From 66672a2981137038a82e2c6602b4cf6c2e3c9979 Mon Sep 17 00:00:00 2001 From: Ross Cawston Date: Mon, 7 Sep 2026 15:01:36 -0700 Subject: [PATCH] Add Developer ID signed release workflow Set the bundle identifier to com.rcawston.Overlook and add a GitHub Actions workflow that archives, notarizes, and staples a Developer ID build on version tags or manual dispatch. --- .github/workflows/release.yml | 93 ++++++++++++++++++++++++++++++ ExportOptions.plist | 14 +++++ Overlook.xcodeproj/project.pbxproj | 4 +- 3 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 ExportOptions.plist diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..1a88b7e --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,93 @@ +name: Signed Release + +on: + push: + tags: ["v*"] + workflow_dispatch: + +permissions: + contents: write + +jobs: + release: + runs-on: macos-latest + env: + APP_NAME: Overlook + BUNDLE_ID: com.rcawston.Overlook + steps: + - uses: actions/checkout@v4 + + - name: Import Developer ID certificate + uses: apple-actions/import-codesign-certs@v7 + with: + p12-file-base64: ${{ secrets.BUILD_CERTIFICATE_BASE64 }} + p12-password: ${{ secrets.P12_PASSWORD }} + + - name: Write notary API key + env: + API_KEY: ${{ secrets.APPLE_API_KEY_BASE64 }} + run: | + echo -n "$API_KEY" | base64 --decode > "$RUNNER_TEMP/AuthKey.p8" + chmod 600 "$RUNNER_TEMP/AuthKey.p8" + + - name: Point ExportOptions at this team + env: + TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + run: /usr/libexec/PlistBuddy -c "Set :teamID $TEAM_ID" ExportOptions.plist + + - name: Archive + env: + TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} + run: | + set -euo pipefail + xcodebuild archive \ + -project Overlook.xcodeproj \ + -scheme Overlook \ + -configuration Release \ + -destination "generic/platform=macOS" \ + -archivePath "$RUNNER_TEMP/Overlook.xcarchive" \ + DEVELOPMENT_TEAM="$TEAM_ID" \ + PRODUCT_BUNDLE_IDENTIFIER="$BUNDLE_ID" \ + CODE_SIGN_STYLE=Manual \ + CODE_SIGN_IDENTITY="Developer ID Application" \ + CODE_SIGN_INJECT_BASE_ENTITLEMENTS=NO \ + OTHER_CODE_SIGN_FLAGS="--timestamp" + + - name: Export Developer ID app + run: | + xcodebuild -exportArchive \ + -archivePath "$RUNNER_TEMP/Overlook.xcarchive" \ + -exportPath "$RUNNER_TEMP/export" \ + -exportOptionsPlist ExportOptions.plist + + - name: Notarize and staple + env: + KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} + ISSUER: ${{ secrets.APPLE_API_ISSUER_ID }} + run: | + set -euo pipefail + APP="$RUNNER_TEMP/export/${APP_NAME}.app" + ZIP="$RUNNER_TEMP/${APP_NAME}.zip" + ditto -c -k --keepParent "$APP" "$ZIP" + xcrun notarytool submit "$ZIP" \ + --key "$RUNNER_TEMP/AuthKey.p8" \ + --key-id "$KEY_ID" \ + --issuer "$ISSUER" \ + --wait + xcrun stapler staple "$APP" + codesign -dv --verbose=4 "$APP" + spctl --assess --verbose=4 --type execute "$APP" + ditto -c -k --keepParent "$APP" "$GITHUB_WORKSPACE/${APP_NAME}.zip" + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + name: Overlook-signed + path: Overlook.zip + + - name: GitHub Release + if: startsWith(github.ref, 'refs/tags/') + uses: softprops/action-gh-release@v2 + with: + files: Overlook.zip + generate_release_notes: true diff --git a/ExportOptions.plist b/ExportOptions.plist new file mode 100644 index 0000000..0eb271e --- /dev/null +++ b/ExportOptions.plist @@ -0,0 +1,14 @@ + + + + + method + developer-id + signingStyle + manual + signingCertificate + Developer ID Application + teamID + REPLACE_ME + + diff --git a/Overlook.xcodeproj/project.pbxproj b/Overlook.xcodeproj/project.pbxproj index a39d1fa..2ec25e6 100644 --- a/Overlook.xcodeproj/project.pbxproj +++ b/Overlook.xcodeproj/project.pbxproj @@ -371,7 +371,7 @@ "-Xcc", "-Wno-deprecated-declarations", ); - PRODUCT_BUNDLE_IDENTIFIER = com.overlook.app; + PRODUCT_BUNDLE_IDENTIFIER = com.rcawston.Overlook; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = Overlook/Overlook-Bridging-Header.h; SWIFT_EMIT_LOC_STRINGS = YES; @@ -406,7 +406,7 @@ "-Xcc", "-Wno-deprecated-declarations", ); - PRODUCT_BUNDLE_IDENTIFIER = com.overlook.app; + PRODUCT_BUNDLE_IDENTIFIER = com.rcawston.Overlook; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OBJC_BRIDGING_HEADER = Overlook/Overlook-Bridging-Header.h; SWIFT_EMIT_LOC_STRINGS = YES;