-
Sign builds and releases with a stable code identity
released this
2026-08-05 13:23:09 +06:00 | 10 commits to main since this releaseswiftc linker-signs only the inner binary, leaving the bundle unsigned
and its codesign identifier as "launcher" rather than the bundle id. More
importantly it leaves the app ad-hoc signed, and macOS pins an ad-hoc
app's Accessibility grant to its exact cdhash instead of to a designated
requirement. Every build mints a new cdhash, so each rebuild-and-replace
silently revoked the permission while the app stayed listed and ticked
under Privacy & Security — and every release did the same to everyone who
updated. That was the root cause of the window tags never appearing.- build.sh signs the bundle with its real identifier, honours
SHANNONCOAT_SIGN_IDENTITY, and fails outright rather than falling back
to ad-hoc when an identity was asked for explicitly. - The identity is read from a gitignored .env, so it doesn't have to be
retyped every build. Parsed rather than sourced, so a stray command in
the file can't execute as a side effect of building, and so an existing
environment variable still wins. .env.example carries the full one-time
setup. - release.yml imports the certificate into a throwaway keychain, builds,
verifies, and deletes the keychain on if: always(). It stays inert
until the three secrets exist, and fails the release rather than
shipping ad-hoc. - Guards the empty-password case explicitly: macOS cannot import an
OpenSSL-produced PKCS#12 with an empty password, and reports it as "MAC
verification failed (wrong password?)", which sends you hunting for a
wrong password rather than a missing one. Nothing local catches this,
since the login keychain imports the PEM pair and needs no password. - Ignores *.p12 and *.pem as a backstop; the certificate belongs outside
the working tree entirely.
Verified end-to-end: two from-scratch builds produce byte-identical
designated requirements where ad-hoc differs every time, and six
rebuild-reinstall cycles under a real certificate kept the Accessibility
grant with no System Settings interaction.This buys permission persistence, not Gatekeeper approval — a
self-signed certificate isn't notarized, so downloads still need
System Settings -> Privacy & Security -> Open Anyway.Downloads
- build.sh signs the bundle with its real identifier, honours