Skip to content

chore: migrate release to reusable macos-sparkle-release workflow - #16

Merged
AdamXweb merged 2 commits into
mainfrom
chore/reusable-release-workflow
Aug 6, 2026
Merged

chore: migrate release to reusable macos-sparkle-release workflow#16
AdamXweb merged 2 commits into
mainfrom
chore/reusable-release-workflow

Conversation

@adamXbot

@adamXbot adamXbot commented Aug 6, 2026

Copy link
Copy Markdown
Collaborator

Migrates the release pipeline to the shared reusable workflow at privacykey/gh-workflows@v1, replacing the 270-line copy-pasted release.yml with a ~40-line caller.

What changed

  • .github/workflows/release.yml — now a thin caller of macos-sparkle-release.yml@v1 with secrets: inherit. Inherit is required, not stylistic: the reusable workflow's release job declares environment: macos-signing, and environment-scoped secrets only resolve inside that job — an explicit secrets: mapping resolves in this caller's context (no environment) and comes back empty. workflow_dispatch re-releases are preserved via the release_tag input. publish_dsym: true keeps this repo's historical behaviour of attaching the dSYM to the public Release (the shared default is private-only).
  • .github/workflows/app-ci.yml (new) — calls macos-app-ci.yml@v1 on push/PR to main. Note: the existing ci.yml covers the SPM targets (Core, auditctlKit, auditctl, guest agent) and is deliberately kept. What it never covered: the Xcode app target (privacycommand.app + privacycommandTests) first compiled on release day. This PR is the first time the actual app builds and tests on every push/PR.
  • packaging/homebrew/privacycommand.rb (new) — cask template with @@VERSION@@/@@SHA256@@/@@URL@@ placeholders. The tap cask (privacykey/homebrew-tap/Casks/privacycommand.rb) has been bumped manually until now; with cask_name/tap_repo wired, the shared workflow renders and pushes it automatically. The step skips cleanly until a tap token is configured.
  • scripts/release.sh — smallest-diff alignment with the shared env contract: the direct codesign of the DMG now passes --keychain "$KEYCHAIN_PATH" when set (CI's ephemeral keychain), falling back to the default keychain search list locally. Everything else (APPLE_SIGNING_IDENTITY, APPLE_API_KEY_PATH/_ID/_ISSUER, SCHEME, dist/privacycommand-<version>.dmg, symbols/privacycommand-<version>.app.dSYM.zip) already matched.
  • scripts/generate-appcast.sh — no longer invoked by CI (the shared workflow has a built-in appcast step with the same key-format validation and a pinned, checksummed Sparkle CLI instead of an unpinned tarball fetch). Kept for local use; can be deleted once the built-in path is proven.

Also new for free from the shared pipeline: a secret-free test job (unit tests + unsigned Release build) runs before the macos-signing gate and before any signing secret is read; a .sha256 sidecar is published next to the DMG; the tag↔MARKETING_VERSION check is unchanged.

Secrets required before the next v* tag

The workflow reads: APPLE_CERTIFICATE, APPLE_CERTIFICATE_PASSWORD, APPLE_SIGNING_IDENTITY, APPLE_API_KEY, APPLE_API_KEY_ID, APPLE_API_ISSUER, SPARKLE_PRIVATE_KEY, plus optional HOMEBREW_TAP_TOKEN (fine-grained PAT scoped to the tap only; the cask step skips cleanly without it). See the gh-workflows README for details, and verify presence with gh secret list before tagging.

Recommended hardening (compatible with this PR as-is thanks to secrets: inherit): give the macos-signing environment a required-reviewers rule so releases pause for human approval before any secret is read (tests run before that gate), and keep SPARKLE_PRIVATE_KEY scoped to that environment (per-app key, never shared).

⚠️ The first tag push after merge is the live test

Nothing in this PR runs the release pipeline — the first v* tag push after merging exercises it end to end (signing, notarization, appcast, Release, cask). To de-risk:

  • Dry-run via workflow_dispatch: the caller keeps the manual trigger — run the Release workflow from the Actions tab with an existing tag to exercise the pipeline against a known-good version. Note this is a real run (it will re-publish assets for that tag), so prefer:
  • Tag an -rc prerelease: bump MARKETING_VERSION, push e.g. v0.1.6-rc.1, and let the whole pipeline run on a throwaway version before the real v0.1.6. (The tag must match MARKETING_VERSION — the verify step enforces v1.2.3 ⇔ 1.2.3, so use a matching prerelease marketing version or expect the check to fail fast, which is itself a cheap smoke test of the plumbing.)
  • The test job runs with zero secrets, so a broken build fails before anything is signed or published.

Rollback

git revert of this PR's merge commit restores the previous self-contained release.yml, scripts/release.sh behaviour, and removes the caller — the old pipeline needed no secrets that have been removed, so a revert is immediately releasable. (app-ci.yml and the cask template are additive and harmless either way.)

🤖 Generated with Claude Code

claude and others added 2 commits August 6, 2026 22:31
Replace the 270-line copy-pasted release pipeline with a thin caller of
privacykey/gh-workflows/.github/workflows/macos-sparkle-release.yml@v1
(secrets: inherit — required for the macos-signing environment scope).

- publish_dsym: true preserves this repo's public-dSYM behaviour
- cask_name/tap_repo + packaging/homebrew/privacycommand.rb template
  automate the previously-manual cask bump in privacykey/homebrew-tap
  (skips cleanly until HOMEBREW_TAP_TOKEN exists)
- scripts/release.sh now pins its direct DMG codesign call to
  KEYCHAIN_PATH when set (shared-workflow env contract), with a local
  fallback to the default keychain search list
- app-ci.yml calls macos-app-ci.yml@v1 so the Xcode app target builds
  and tests on push/PR — previously it only compiled on release day
  (ci.yml keeps covering the SPM targets)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@AdamXweb
AdamXweb merged commit 44182de into main Aug 6, 2026
2 checks passed
@AdamXweb
AdamXweb deleted the chore/reusable-release-workflow branch August 6, 2026 14:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants