Ship MetersApp as a notarized download on every merge - #3
Closed
gotwalt wants to merge 1 commit into
Closed
Conversation
SwiftPM builds a bare executable, which Gatekeeper will not accept and which macOS 15 will not grant local-network access to. Scripts/build_app.sh wraps the same product in a universal .app with an Info.plist that carries NSLocalNetworkUsageDescription, so discovery keeps working once the app is bundled. The new workflow builds that bundle on every push to main, signs it with a Developer ID under the hardened runtime, notarizes it, staples the ticket, and republishes the rolling metersapp-latest prerelease at that commit, so the download URL is stable. Until the six signing secrets are configured it skips signing and uploads an unsigned workflow artifact rather than failing the run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FUC9inEb9CrygvatVez5qD
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Every merge to
mainnow produces a signed, notarized, stapled download ofMetersApp.What lands
swift/Scripts/build_app.sh— SwiftPM only emits a bare executable, so this wraps the same product in a real.app:--arch arm64 --arch x86_64), so one download runs on Apple silicon and IntelInfo.plistwith bundle idcom.gotwalt.libkp.MetersApp, display name "KP Meters",LSMinimumSystemVersion 13.0NSLocalNetworkUsageDescription— without it macOS 15+ silently drops the discovery broadcast once the app is bundledspec/version.toml;MARKETING_VERSION/BUILD_NUMBER/BUNDLE_IDoverrideswift/Scripts/build_app.sh # -> swift/.build/dist/MetersApp.app.github/workflows/metersapp-release.yml— on every push tomain(plusworkflow_dispatch), onmacos-15:build the bundle → import the Developer ID cert into a throwaway keychain →
codesign --options runtime --timestamp→dittozip →notarytool submit --wait→stapler staple+stapler validate+spctl --assess→ re-zip the stapled app → delete and recreate themetersapp-latestprerelease at that commit.The tag rolls, so the download URL is stable:
A
.sha256is published alongside it, and the zip is uploaded as a workflow artifact on every run.concurrency: metersapp-releasekeeps two merges from racing on the rolling tag; the keychain and the.p8are torn down in analways()step.Before this does anything
Six repository secrets:
MACOS_CERT_P12_BASE64base64 -i DeveloperID.p12MACOS_CERT_PASSWORD.p12exportMACOS_SIGNING_IDENTITYDeveloper ID Application: Your Name (TEAMID)APP_STORE_CONNECT_KEY_IDAPP_STORE_CONNECT_ISSUER_IDAPP_STORE_CONNECT_KEY_CONTENTAuthKey_<KEY_ID>.p8contentsUntil they exist the job still builds and uploads an unsigned artifact and emits a warning rather than failing — so merging this will not turn
mainred.Verification
Locally: the script builds a working universal bundle (
lipo -archs→x86_64 arm64,plutil -lintclean); an ad-hoccodesign --options runtimerun binds the Info.plist and reportsIdentifier=com.gotwalt.libkp.MetersAppwith the runtime flag set;dittoproduces a 762K zip. The workflow YAML parses and everyrunblock passesbash -n.The signing and notarization steps themselves are untested — they need the real secrets, and the first merge to
mainis what exercises them.Not done here
.icnsinContents/Resources+CFBundleIconFile).workflow_runon CI success would publish only builds that passed.🤖 Generated with Claude Code
https://claude.ai/code/session_01FUC9inEb9CrygvatVez5qD