From d48b0f1d7f46888c62b7c8876f92abae8a2cbf77 Mon Sep 17 00:00:00 2001 From: halprin Date: Thu, 27 Feb 2025 08:18:07 -0700 Subject: [PATCH] macOS Code Signing and Notarization (#669) * Code sign the macOS binaries that go into d3-osx.hog * Code sign the netcon clients for macOS * Update Build GitHub Action to support macOS signing, package, and notarization * Update secret name * try using glob syntax to sign everything in netgames * Clean the installed folder after making disk image and move disk image into installed folder * Remove all references to the macOS binary not being signed in USAGE.md readme * Split the PR workflow from the main build workflow to be explicit * Test passing in secrets into PR * Remove test of putting secrets into PR workflow * Try DescentDevelopers version of GitHub Actions * test fake secret to test * Remove fake secret, test was successful * Set CODESIGN_IDENTITY in the top level CMakeLists.txt * Create macos_sign CMake function * Update BUILD.md wih the new description of CODESIGN_IDENTITY * Test using a combined variable * Remove test secret * Indent only two spaces --- .github/workflows/build.yml | 58 ++++++++++++++++++---- .github/workflows/cd.yml | 23 +++++++++ .github/workflows/ci.yml | 18 +++++++ BUILD.md | 1 + CMakeLists.txt | 9 ++++ USAGE.md | 7 +-- netcon/descent3onlineclient/CMakeLists.txt | 1 + netcon/lanclient/CMakeLists.txt | 1 + netcon/mtclient/CMakeLists.txt | 1 + scripts/CMakeLists.txt | 1 + 10 files changed, 103 insertions(+), 17 deletions(-) create mode 100644 .github/workflows/cd.yml create mode 100644 .github/workflows/ci.yml diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5523bcc7..6f33ff4b 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,18 +1,25 @@ name: Descent 3 Build + on: - workflow_dispatch: - push: - branches: [ "main" ] - paths-ignore: - - '**/*.md' - pull_request: - branches: [ "main" ] - paths-ignore: - - '**/README.md' - - '**/LICENSE' + workflow_call: + secrets: + MACOS_SIGNING_IDENTITY: + required: false + MACOS_SIGNING_CERTIFICATE_P12: + required: false + MACOS_SIGNING_CERTIFICATE_P12_PASSWORD: + required: false + MACOS_APP_STORE_CONNECT_KEY: + required: false + MACOS_APP_STORE_CONNECT_KEY_ID: + required: false + MACOS_APP_STORE_CONNECT_ISSUER_ID: + required: false + jobs: + build: name: ${{ matrix.os.name }}, ${{ matrix.build_type }} strategy: @@ -50,6 +57,9 @@ jobs: runs-on: ${{ matrix.os.runner }} + env: + MACOS_AND_CODE_SIGNING: ${{ matrix.os.preset == 'mac' && secrets.MACOS_SIGNING_IDENTITY != '' }} + steps: - uses: actions/checkout@v4 with: @@ -103,12 +113,19 @@ jobs: cp ./arm64-osx.cmake ./community/universal-osx.cmake sed -i '' 's/^set(VCPKG_OSX_ARCHITECTURES.*$/set(VCPKG_OSX_ARCHITECTURES "arm64;x86_64")/' ./community/universal-osx.cmake + - name: Import macOS code signing certificate + if: ${{ env.MACOS_AND_CODE_SIGNING == 'true' }} + uses: DescentDevelopers/import-codesign-certs@v1 + with: + p12-file-base64: ${{ secrets.MACOS_SIGNING_CERTIFICATE_P12 }} + p12-password: ${{ secrets.MACOS_SIGNING_CERTIFICATE_P12_PASSWORD }} + - name: Configure CMake if: ${{ matrix.os.preset != 'linux-cross-arm64' }} env: CC: ${{ matrix.os.cc }} CXX: ${{ matrix.os.cxx }} - run: cmake --preset ${{ matrix.os.preset }} -DBUILD_TESTING=ON -DENABLE_LOGGER=ON -DFORCE_PORTABLE_INSTALL=ON -DBUILD_EDITOR=ON -DUSE_EXTERNAL_PLOG=ON + run: cmake --preset ${{ matrix.os.preset }} -DCODESIGN_IDENTITY=${{ secrets.MACOS_SIGNING_IDENTITY }} -DBUILD_TESTING=ON -DENABLE_LOGGER=ON -DFORCE_PORTABLE_INSTALL=ON -DBUILD_EDITOR=ON -DUSE_EXTERNAL_PLOG=ON - name: Build ${{ matrix.build_type }} run: cmake --build --preset ${{ matrix.os.preset }} --config ${{ matrix.build_type }} --verbose @@ -121,6 +138,25 @@ jobs: # There no cmake install presets so install in traditional way run: cmake --install builds/${{ matrix.os.preset }}/ --config ${{ matrix.build_type }} + - name: Sign, package, and notarize for macOS + if: ${{ env.MACOS_AND_CODE_SIGNING == 'true' }} + uses: DescentDevelopers/macos-sign-package-notarize@v1 + with: + path-to-binaries: builds/${{ matrix.os.preset }}/installed/Descent3.app builds/${{ matrix.os.preset }}/installed/netgames/* + signing-identity: ${{ secrets.MACOS_SIGNING_IDENTITY }} + app-store-connect-key: ${{ secrets.MACOS_APP_STORE_CONNECT_KEY }} + app-store-connect-key-id: ${{ secrets.MACOS_APP_STORE_CONNECT_KEY_ID }} + app-store-connect-issuer-id: ${{ secrets.MACOS_APP_STORE_CONNECT_ISSUER_ID }} + archive-files: builds/${{ matrix.os.preset }}/installed/* + archive-disk-name: Descent 3 + archive-file-path: builds/${{ matrix.os.preset }}/Descent3-${{ matrix.build_type }}-${{ matrix.os.name }}.dmg + + - name: Swap macOS DMG disk image into installed folder + if: ${{ env.MACOS_AND_CODE_SIGNING == 'true' }} + run: | + rm -rf builds/${{ matrix.os.preset }}/installed/* + mv builds/${{ matrix.os.preset }}/Descent3-${{ matrix.build_type }}-${{ matrix.os.name }}.dmg builds/${{ matrix.os.preset }}/installed/ + - name: Upload Artifacts uses: actions/upload-artifact@v4 with: diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml new file mode 100644 index 00000000..8cf1b61b --- /dev/null +++ b/.github/workflows/cd.yml @@ -0,0 +1,23 @@ +name: Continuous Delivery + + +on: + push: + branches: + - main + paths-ignore: + - '**/*.md' + + +jobs: + + build: + name: Build for main branch + uses: ./.github/workflows/build.yml + secrets: + MACOS_SIGNING_IDENTITY: ${{ secrets.MACOS_SIGNING_IDENTITY }} + MACOS_SIGNING_CERTIFICATE_P12: ${{ secrets.MACOS_SIGNING_CERTIFICATE_P12 }} + MACOS_SIGNING_CERTIFICATE_P12_PASSWORD: ${{ secrets.MACOS_SIGNING_CERTIFICATE_P12_PASSWORD }} + MACOS_APP_STORE_CONNECT_KEY: ${{ secrets.MACOS_APP_STORE_CONNECT_KEY }} + MACOS_APP_STORE_CONNECT_KEY_ID: ${{ secrets.MACOS_APP_STORE_CONNECT_KEY_ID }} + MACOS_APP_STORE_CONNECT_ISSUER_ID: ${{ secrets.MACOS_APP_STORE_CONNECT_ISSUER_ID }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 00000000..73fa2eda --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,18 @@ +name: Continuous Integration + + +on: + pull_request: + branches: + - main + paths-ignore: + - '**/README.md' + - '**/LICENSE' + + +jobs: + + build: + name: Build for PR + uses: ./.github/workflows/build.yml + # explicitly not passing secrets into the build diff --git a/BUILD.md b/BUILD.md index f824f410..7a6a0ad0 100644 --- a/BUILD.md +++ b/BUILD.md @@ -206,3 +206,4 @@ You can also use the [cmake-gui](https://cmake.org/cmake/help/latest/manual/cmak | `FORCE_PORTABLE_INSTALL` | Install all files into local directory defined by `CMAKE_INSTALL_PREFIX`. | `ON` | | `OFF` | | `USE_VCPKG` | Explicitly control whether or not to use vcpkg for dependency resolution. `ON` requires the environment variable `VCPKG_ROOT` to be set. | Determined by the existence of `VCPKG_ROOT` in the environment: If it exists, vcpkg is used. | +| `CODESIGN_IDENTITY` | Sets the macOS code signing identity. If set to something besides the empty string, then the dynamic libraries put into the hog files will be signed using this identity. | The empty string, `""`. | diff --git a/CMakeLists.txt b/CMakeLists.txt index 59a0bafc..43737294 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,6 +5,15 @@ if(NOT CMAKE_BUILD_TYPE AND NOT DEFINED ENV{CMAKE_BUILD_TYPE}) set(CMAKE_BUILD_TYPE "Debug" CACHE STRING "default build type") endif() +set(CODESIGN_IDENTITY "" CACHE STRING "Sets the macOS code signing identity. If set to something besides the empty string, then the dynamic libraries put into the hog files will be signed using this identity.") +function (macos_sign target) + if(DEFINED CODESIGN_IDENTITY AND NOT "${CODESIGN_IDENTITY}" STREQUAL "") + message(STATUS "Code signing ${target}") + add_custom_command(TARGET ${target} POST_BUILD + COMMAND codesign --verbose --sign "${CODESIGN_IDENTITY}" --force --timestamp --deep -o runtime $) + endif() +endfunction() + # toolchain setup for vcpkg must be done before the 'project' call set(USE_VCPKG "DEFAULT" CACHE STRING "Use vcpkg for dependency management. DEFAULT defers to existence of $VCPKG_ROOT environment variable.") set_property(CACHE USE_VCPKG PROPERTY STRINGS "DEFAULT" "ON" "OFF") diff --git a/USAGE.md b/USAGE.md index 5d600356..2e05307a 100644 --- a/USAGE.md +++ b/USAGE.md @@ -63,12 +63,7 @@ conflicts. - On Linux, `cd` to `D3-open-source` and run `./Descent3`. Wayland users may need to set environment variable `SDL_VIDEODRIVER=wayland` before launching the game. - - On macOS, the `.app` bundle is currently not signed, so your operating - system will not let you run it by double-clicking it. To remediate that, - open your terminal and `cd` to `D3-open-source`. Run - `xattr -c ./Descent3.app`, `xattr -c ./netgames/*`, - `chmod +x ./Descent3.app/Contents/MacOS/Descent3`, and then run the game - using `./Descent3.app/Contents/MacOS/Descent3` + - On macOS, open the terminal, `cd` to `D3-open-source`, and run `./Descent3.app/Contents/MacOS/Descent3`. ## Troubleshooting diff --git a/netcon/descent3onlineclient/CMakeLists.txt b/netcon/descent3onlineclient/CMakeLists.txt index d6262a7d..7f81572b 100644 --- a/netcon/descent3onlineclient/CMakeLists.txt +++ b/netcon/descent3onlineclient/CMakeLists.txt @@ -27,6 +27,7 @@ target_link_libraries(Descent3_Online_TCP_IP PRIVATE target_include_directories(Descent3_Online_TCP_IP PRIVATE ${SDL3_INCLUDE_DIRS}) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set_target_properties(Descent3_Online_TCP_IP PROPERTIES SUFFIX ".dylib") + macos_sign(Descent3_Online_TCP_IP) endif() include(HogMaker) diff --git a/netcon/lanclient/CMakeLists.txt b/netcon/lanclient/CMakeLists.txt index 82ca3da6..799d6021 100644 --- a/netcon/lanclient/CMakeLists.txt +++ b/netcon/lanclient/CMakeLists.txt @@ -19,6 +19,7 @@ target_link_libraries(Direct_TCP_IP PRIVATE target_include_directories(Direct_TCP_IP PRIVATE ${SDL3_INCLUDE_DIRS}) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set_target_properties(Direct_TCP_IP PROPERTIES SUFFIX ".dylib") + macos_sign(Direct_TCP_IP) endif() include(HogMaker) diff --git a/netcon/mtclient/CMakeLists.txt b/netcon/mtclient/CMakeLists.txt index a1480164..72c04a41 100644 --- a/netcon/mtclient/CMakeLists.txt +++ b/netcon/mtclient/CMakeLists.txt @@ -29,6 +29,7 @@ target_link_libraries(Parallax_Online PRIVATE target_include_directories(Parallax_Online PRIVATE ${SDL3_INCLUDE_DIRS}) if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set_target_properties(Parallax_Online PROPERTIES SUFFIX ".dylib") + macos_sign(Parallax_Online) endif() include(HogMaker) diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 039a6424..d836ce5d 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -87,6 +87,7 @@ foreach(SCRIPT ${SCRIPTS}) set_target_properties(${SCRIPT} PROPERTIES CXX_VISIBILITY_PRESET "hidden") if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") set_target_properties(${SCRIPT} PROPERTIES SUFFIX ".dylib") + macos_sign(${SCRIPT}) endif() endforeach()