-
Notifications
You must be signed in to change notification settings - Fork 300
fix(macos): configure release signing and notarization #422
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -855,6 +855,33 @@ jobs: | |
| if: ${{ env.RELEASE_DRY_RUN != 'true' }} | ||
| uses: sigstore/cosign-installer@d7d6bc7722e3daa8354c50bcb52f4837da5e9b6a # v3.8.1 | ||
|
|
||
| - name: Import Apple certificate | ||
| if: ${{ env.RELEASE_DRY_RUN != 'true' }} | ||
| env: | ||
| APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }} | ||
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | ||
| run: | | ||
| CERTIFICATE_PATH="$RUNNER_TEMP/certificate.p12" | ||
| KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db" | ||
| KEYCHAIN_PASSWORD="$(openssl rand -hex 16)" | ||
|
|
||
| echo "$APPLE_CERTIFICATE_BASE64" | base64 --decode > "$CERTIFICATE_PATH" | ||
|
|
||
| security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | ||
| security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" | ||
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | ||
|
|
||
| security import "$CERTIFICATE_PATH" \ | ||
| -P "$APPLE_CERTIFICATE_PASSWORD" \ | ||
| -A -t cert -f pkcs12 \ | ||
| -k "$KEYCHAIN_PATH" | ||
|
|
||
| security set-key-partition-list \ | ||
| -S apple-tool:,apple: \ | ||
| -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | ||
|
|
||
| security list-keychain -d user -s "$KEYCHAIN_PATH" | ||
|
|
||
| - name: Determine package version | ||
| id: version | ||
| run: | | ||
|
|
@@ -864,7 +891,6 @@ jobs: | |
| VERSION="0.0.0-dev" | ||
| fi | ||
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | ||
|
|
||
| - name: Build Swift bridge artifacts and generate Xcode project | ||
| env: | ||
| MOLTIS_VERSION: ${{ steps.version.outputs.version }} | ||
|
|
@@ -875,13 +901,18 @@ jobs: | |
| - name: Build macOS app | ||
| env: | ||
| DERIVED_DATA_DIR: apps/macos/.derivedData-ci | ||
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||
| run: | | ||
| xcodebuild \ | ||
| -project apps/macos/Moltis.xcodeproj \ | ||
| -scheme Moltis \ | ||
| -configuration Release \ | ||
| -destination "platform=macOS" \ | ||
| -derivedDataPath "$DERIVED_DATA_DIR" \ | ||
| CODE_SIGN_STYLE=Manual \ | ||
| CODE_SIGN_IDENTITY="Developer ID Application" \ | ||
| DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \ | ||
| OTHER_CODE_SIGN_FLAGS="--options runtime" \ | ||
| build | ||
|
Comment on lines
901
to
916
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Signing parameters applied unconditionally while certificate import is conditional The "Import Apple certificate" step is gated on You should guard the signing parameters with the same condition, or add a separate code path that builds with - name: Build macOS app (dry run – no signing)
if: ${{ env.RELEASE_DRY_RUN == 'true' }}
env:
DERIVED_DATA_DIR: apps/macos/.derivedData-ci
run: |
xcodebuild \
-project apps/macos/Moltis.xcodeproj \
-scheme Moltis \
-configuration Release \
-destination "platform=macOS" \
-derivedDataPath "$DERIVED_DATA_DIR" \
CODE_SIGNING_ALLOWED=NO \
build
- name: Build macOS app (release – signed)
if: ${{ env.RELEASE_DRY_RUN != 'true' }}
env:
DERIVED_DATA_DIR: apps/macos/.derivedData-ci
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
run: |
xcodebuild \
-project apps/macos/Moltis.xcodeproj \
-scheme Moltis \
-configuration Release \
-destination "platform=macOS" \
-derivedDataPath "$DERIVED_DATA_DIR" \
CODE_SIGN_STYLE=Manual \
CODE_SIGN_IDENTITY="Developer ID Application" \
DEVELOPMENT_TEAM="$APPLE_TEAM_ID" \
OTHER_CODE_SIGN_FLAGS="--options runtime" \
build |
||
|
|
||
| - name: Package macOS app | ||
|
|
@@ -895,6 +926,28 @@ jobs: | |
| fi | ||
| ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "moltis-${VERSION}-macos.app.zip" | ||
|
|
||
| - name: Notarize macOS app | ||
| if: ${{ env.RELEASE_DRY_RUN != 'true' }} | ||
| env: | ||
| VERSION: ${{ steps.version.outputs.version }} | ||
| APPLE_ID: ${{ secrets.APPLE_ID }} | ||
| APPLE_ID_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }} | ||
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | ||
| run: | | ||
| xcrun notarytool submit "moltis-${VERSION}-macos.app.zip" \ | ||
| --apple-id "$APPLE_ID" \ | ||
| --password "$APPLE_ID_PASSWORD" \ | ||
| --team-id "$APPLE_TEAM_ID" \ | ||
| --wait | ||
|
|
||
| # Staple the notarization ticket to the app bundle | ||
| APP_PATH="apps/macos/.derivedData-ci/Build/Products/Release/Moltis.app" | ||
| xcrun stapler staple "$APP_PATH" | ||
|
|
||
| # Re-package with the stapled ticket | ||
| rm "moltis-${VERSION}-macos.app.zip" | ||
| ditto -c -k --sequesterRsrc --keepParent "$APP_PATH" "moltis-${VERSION}-macos.app.zip" | ||
|
|
||
| - name: Sign with Sigstore and generate checksums | ||
| if: ${{ env.RELEASE_DRY_RUN != 'true' }} | ||
| uses: ./.github/actions/sign-artifacts | ||
|
|
@@ -913,6 +966,14 @@ jobs: | |
| *.app.zip.sig | ||
| *.app.zip.crt | ||
|
|
||
| - name: Clean up keychain | ||
| if: always() | ||
| run: | | ||
| KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db" | ||
| if [ -f "$KEYCHAIN_PATH" ]; then | ||
| security delete-keychain "$KEYCHAIN_PATH" | ||
| fi | ||
|
|
||
| build-windows-exe: | ||
| needs: [clippy, test, e2e] | ||
| runs-on: windows-latest | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| <?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/> | ||
| </plist> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,13 +28,18 @@ targets: | |
| sources: | ||
| - path: Sources | ||
| - path: Assets.xcassets | ||
| entitlements: | ||
| path: Moltis.entitlements | ||
| settings: | ||
| base: | ||
| PRODUCT_BUNDLE_IDENTIFIER: org.moltis.app | ||
| GENERATE_INFOPLIST_FILE: YES | ||
| SWIFT_EMIT_LOC_STRINGS: NO | ||
| ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon | ||
| SWIFT_OBJC_BRIDGING_HEADER: Sources/Bridging-Header.h | ||
| ENABLE_HARDENED_RUNTIME: YES | ||
| CODE_SIGN_STYLE: Manual | ||
| CODE_SIGN_IDENTITY: "Developer ID Application" | ||
|
Comment on lines
+40
to
+42
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Manual signing identity in
Consider scoping these signing settings to the settings:
base:
PRODUCT_BUNDLE_IDENTIFIER: org.moltis.app
GENERATE_INFOPLIST_FILE: YES
SWIFT_EMIT_LOC_STRINGS: NO
ASSETCATALOG_COMPILER_APPICON_NAME: AppIcon
SWIFT_OBJC_BRIDGING_HEADER: Sources/Bridging-Header.h
ENABLE_HARDENED_RUNTIME: YES
OTHER_LDFLAGS:
...
configs:
Release:
CODE_SIGN_STYLE: Manual
CODE_SIGN_IDENTITY: "Developer ID Application"
Comment on lines
+41
to
+42
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Adding manual signing at the target base settings level applies it to all generated macOS builds, not just release packaging. Local developer workflows ( Useful? React with 👍 / 👎. |
||
| OTHER_LDFLAGS: | ||
| - "-lmoltis_bridge" | ||
| - "-lsqlite3" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In
.github/workflows/release.yml, this step now always forces manual Developer ID signing, but the certificate import is gated behindif: ${{ env.RELEASE_DRY_RUN != 'true' }}. Forworkflow_dispatchdry runs, no signing cert is installed whilexcodebuildstill requires one, so the macOS job fails before packaging/notarization logic can be exercised. This makes the workflow’s dry-run mode effectively unusable.Useful? React with 👍 / 👎.