Jelajahi Sumber

code sign and notarization on macOS(#2605)

Le Tan 6 bulan lalu
induk
melakukan
d9aee037ad

+ 63 - 3
.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

+ 12 - 0
package/entitlements.xml

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+    <dict>
+        <key>com.apple.security.files.user-selected.read-write</key>
+        <true/>
+        <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
+        <true/>
+        <key>com.apple.security.network.client</key>
+        <true/>
+    </dict>
+</plist>

+ 1 - 1
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}"

+ 1 - 2
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}
 )

+ 3 - 5
src/data/core/Info.plist

@@ -18,22 +18,20 @@
             </array>
         </dict>
     </array>
-    <key>com.apple.security.cs.disable-library-validation</key>
-    <true/>
     <key>CFBundleName</key>
     <string>VNote</string>
     <key>CFBundleExecutable</key>
-    <string>vnote</string>
+    <string>VNote</string>
     <key>CFBundleShortVersionString</key>
     <string>3.19</string>
     <key>CFBundleVersion</key>
     <string>3.19.1</string>
     <key>NSHumanReadableCopyright</key>
-    <string>Distributed under LGPL-3.0 license. Copyright (c) 2024 app.vnote.fun</string>
+    <string>Distributed under LGPL-3.0 license. Copyright (c) 2025 app.vnote.fun</string>
     <key>CFBundleIconFile</key>
     <string>vnote.icns</string>
     <key>CFBundleIdentifier</key>
-    <string>fun.vnote.app</string>
+    <string>fun.vnote.vnote</string>
     <key>CFBundlePackageType</key>
     <string>APPL</string>
     <key>LSMinimumSystemVersion</key>