From d9aee037ad5b3fdeb7013f33791dc6013e5b42ca Mon Sep 17 00:00:00 2001 From: Le Tan Date: Wed, 23 Apr 2025 00:27:13 -0700 Subject: [PATCH] code sign and notarization on macOS(#2605) --- .github/workflows/ci-macos.yml | 66 ++++++++++++++++++++++++++++++++-- package/entitlements.xml | 12 +++++++ src/CMakeLists.txt | 2 +- src/CPackMacDeployQt.cmake.in | 3 +- src/data/core/Info.plist | 8 ++--- 5 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 package/entitlements.xml diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 498681a9..46d1d483 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -21,6 +21,7 @@ env: jobs: build: + environment: Mac-code-sign name: Build On MacOS timeout-minutes: 120 @@ -107,10 +108,69 @@ jobs: - name: Build Project run: | + # Remove the libqsqlmimer.so as libmimerapi.so is not deployed with Qt6 + rm ${{env.Qt6_DIR}}/plugins/sqldrivers/libqsqlmimer.dylib cmake --build . --target pack - ls -ls . - ls -ls src - mv src/VNote.dmg VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg + python3 ${{runner.workspace}}/macdeployqtfix/macdeployqtfix.py ./src/VNote.app/Contents/MacOS/VNote ${{env.Qt6_DIR}}/../.. + working-directory: ${{runner.workspace}}/build + + - name: Codesign Bundle + # Extract the secrets we defined earlier as environment variables + env: + MACOS_CERTIFICATE: ${{ secrets.CLI_MACOS_CERTIFICATE }} + MACOS_CERTIFICATE_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE_PWD }} + MACOS_CERTIFICATE_NAME: ${{ secrets.CLI_MACOS_CERTIFICATE_NAME }} + MACOS_CI_KEYCHAIN_PWD: ${{ secrets.CLI_MACOS_CERTIFICATE }} + run: | + # Turn our base64-encoded certificate back to a regular .p12 file + echo $MACOS_CERTIFICATE | base64 --decode > certificate.p12 + + # We need to create a new keychain, otherwise using the certificate will prompt + # with a UI dialog asking for the certificate password, which we can't + # use in a headless CI environment + security create-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain + security default-keychain -s build.keychain + security unlock-keychain -p "$MACOS_CI_KEYCHAIN_PWD" build.keychain + security import certificate.p12 -k build.keychain -P "$MACOS_CERTIFICATE_PWD" -T /usr/bin/codesign + security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$MACOS_CI_KEYCHAIN_PWD" build.keychain + + # We finally codesign our app bundle, specifying the Hardened runtime option + /usr/bin/codesign --force --deep -s "$MACOS_CERTIFICATE_NAME" --entitlements ${{github.workspace}}/package/entitlements.xml --options runtime ${{runner.workspace}}/build/src/VNote.app -vvv + /usr/bin/codesign -v -vvv ${{runner.workspace}}/build/src/VNote.app + + - name: "Notarize Bundle" + # Extract the secrets we defined earlier as environment variables + env: + PROD_MACOS_NOTARIZATION_APPLE_ID: ${{ secrets.CLI_MACOS_NOTARY_USER }} + PROD_MACOS_NOTARIZATION_TEAM_ID: ${{ secrets.CLI_MACOS_TEAM_ID }} + PROD_MACOS_NOTARIZATION_PWD: ${{ secrets.CLI_MACOS_NOTARY_PWD }} + run: | + # Store the notarization credentials so that we can prevent a UI password dialog + # from blocking the CI + echo "Create keychain profile" + xcrun notarytool store-credentials "notarytool-profile" --apple-id "$PROD_MACOS_NOTARIZATION_APPLE_ID" --team-id "$PROD_MACOS_NOTARIZATION_TEAM_ID" --password "$PROD_MACOS_NOTARIZATION_PWD" + + # We can't notarize an app bundle directly, but we need to compress it as an archive. + # Therefore, we create a zip file containing our app bundle, so that we can send it to the + # notarization service + echo "Creating temp notarization archive" + ditto -c -k --keepParent "${{runner.workspace}}/build/src/VNote.app" "notarization.zip" + + # Here we send the notarization request to the Apple's Notarization service, waiting for the result. + # This typically takes a few seconds inside a CI environment, but it might take more depending on the App + # characteristics. Visit the Notarization docs for more information and strategies on how to optimize it if + # you're curious + echo "Notarize app" + xcrun notarytool submit "notarization.zip" --keychain-profile "notarytool-profile" --wait + + # Finally, we need to "attach the staple" to our executable, which will allow our app to be + # validated by macOS even when an internet connection is not available. + echo "Attach staple" + xcrun stapler staple "${{runner.workspace}}/build/src/VNote.app" + + - name: Create DMG + run: | + hdiutil create -volname "VNote" -srcfolder ./src/VNote.app -ov -format UDZO VNote-${{env.VNOTE_VER}}-mac-${{matrix.config.arch}}.dmg working-directory: ${{runner.workspace}}/build # Enable tmate debugging of manually-triggered workflows if the input option was provided diff --git a/package/entitlements.xml b/package/entitlements.xml new file mode 100644 index 00000000..d58e8aa8 --- /dev/null +++ b/package/entitlements.xml @@ -0,0 +1,12 @@ + + + + + com.apple.security.files.user-selected.read-write + + com.apple.security.cs.allow-unsigned-executable-memory + + com.apple.security.network.client + + + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index feaae5e3..f37430f6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -139,7 +139,7 @@ elseif(APPLE) OUTPUT_NAME "${PROJECT_NAME}" MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}" MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}" - MACOSX_BUNDLE_GUI_IDENTIFIER "fun.vnote.app" + MACOSX_BUNDLE_GUI_IDENTIFIER "fun.vnote.vnote" MACOSX_BUNDLE_LONG_VERSION_STRING "${PROJECT_VERSION}" MACOSX_BUNDLE_SHORT_VERSION_STRING "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}" MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION}" diff --git a/src/CPackMacDeployQt.cmake.in b/src/CPackMacDeployQt.cmake.in index b9003ddf..9a8ced2b 100644 --- a/src/CPackMacDeployQt.cmake.in +++ b/src/CPackMacDeployQt.cmake.in @@ -1,7 +1,6 @@ execute_process(COMMAND "optool" strip -t ${CMAKE_CURRENT_BINARY_DIR}/VNote.app WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY} ) -execute_process(COMMAND "${MACDEPLOYQT_EXECUTABLE}" ${CMAKE_CURRENT_BINARY_DIR}/VNote.app -dmg - -always-overwrite -verbose=1 +execute_process(COMMAND "${MACDEPLOYQT_EXECUTABLE}" ${CMAKE_CURRENT_BINARY_DIR}/VNote.app -always-overwrite -verbose=1 WORKING_DIRECTORY ${CPACK_PACKAGE_DIRECTORY} ) diff --git a/src/data/core/Info.plist b/src/data/core/Info.plist index 156ab841..d409e14b 100644 --- a/src/data/core/Info.plist +++ b/src/data/core/Info.plist @@ -18,22 +18,20 @@ - com.apple.security.cs.disable-library-validation - CFBundleName VNote CFBundleExecutable - vnote + VNote CFBundleShortVersionString 3.19 CFBundleVersion 3.19.1 NSHumanReadableCopyright - Distributed under LGPL-3.0 license. Copyright (c) 2024 app.vnote.fun + Distributed under LGPL-3.0 license. Copyright (c) 2025 app.vnote.fun CFBundleIconFile vnote.icns CFBundleIdentifier - fun.vnote.app + fun.vnote.vnote CFBundlePackageType APPL LSMinimumSystemVersion