ci(cli): dispatch Homebrew tap via primitive-ci GitHub App, not PAT#214
Conversation
Greptile SummaryThis PR replaces the broken
Confidence Score: 4/5Safe to merge once the two open thread issues are resolved: confirm the correct SM path for production credentials, and verify the role ARN is registered as a repository Variable (not a Secret) so OIDC assumption doesn't silently fail. The credential-fetch chain is well-structured and the PAT removal solves the confirmed 403. However, two defects flagged in prior threads are still present in the code: if .github/workflows/cli-release.yml — specifically the Important Files Changed
Reviews (3): Last reviewed commit: "ci(cli): source role ARN from a non-secr..." | Re-trigger Greptile |
| JSON=$(aws secretsmanager get-secret-value \ | ||
| --secret-id staging/github-ci-app \ | ||
| --query SecretString --output text) |
There was a problem hiding this comment.
Staging secret in production release workflow
The secret path staging/github-ci-app is used to mint the GitHub App token for a production CLI release. If this is intentional (i.e., staging/ is just an AWS Secrets Manager namespace convention shared with the tap workflow), it's fine — but if there's a separate production/github-ci-app secret with different credentials or a scoped installation, this step would silently authenticate with the wrong App and could produce a token that lacks contents:write on homebrew-tap. Is staging/github-ci-app the correct Secrets Manager path for a production release, or does this workflow need a production-scoped credential (e.g., production/github-ci-app)?
The CLI Release "Trigger Homebrew tap update" step authenticated to the homebrew-tap repo with the HOMEBREW_TAP_BOT_TOKEN PAT, which lacks the contents:write / repository_dispatch permission on the tap. The release publishes to npm and tags GitHub fine, then 403s on the dispatch: gh: Resource not accessible by personal access token (HTTP 403) Switch to the org's blessed App-token path, mirroring homebrew-tap's own update-formula workflow (PR #15): OIDC -> assume AWS role -> pull the primitive-ci App credentials from Secrets Manager -> mint a short-lived installation token scoped to homebrew-tap -> POST the cli-release dispatch with it. Drops the silent "PAT not configured -> skip" branch so a misconfigured dispatch now fails loudly instead of being masked. New actions pinned to SHA per repo convention. Requires (org/AWS admin, not in this PR): - AWS_HOMEBREW_TAP_ROLE_ARN secret on this repo - the IAM role trust policy to permit this repo's OIDC subject Then the HOMEBREW_TAP_BOT_TOKEN secret can be deleted. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The OIDC role ARN cannot live in Secrets Manager: the role must be assumed before SM is reachable. An ARN is an identifier, not a credential, so use a non-secret Actions variable (vars.) rather than a secret. No credentials are stored on the GitHub side; the App key stays in SM. Keeps the AWS account ID out of the public workflow source. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
099835c to
ac9d768
Compare
Why
The
CLI Releaseworkflow's Trigger Homebrew tap update step authenticates toprimitivedotdev/homebrew-tapwith theHOMEBREW_TAP_BOT_TOKENPAT. That PAT lacks thecontents:write/repository_dispatchpermission on the tap, so every release publishes to npm and creates the GitHub tag/release fine, then 403s on the dispatch:Observed on the 1.2.0 release: run 27247901978. npm publish + GH release succeeded; only the tap bump was lost.
What
Switch the dispatch to the org's blessed App-token path, mirroring the tap's own
update-formula.yml(homebrew-tap PR #15 — "use GitHub App via OIDC+SM instead of PAT"):vars.AWS_HOMEBREW_TAP_ROLE_ARN)primitive-ciApp credentials from Secrets Manager (staging/github-ci-app)create-github-app-token, scoped torepositories: homebrew-tapcli-releasedispatch with that tokenAlso drops the silent "PAT not configured → skip" branch, so a misconfigured dispatch fails loudly instead of being masked (which is how this bug went unnoticed). The two new actions are pinned to SHA per repo convention. The workflow already declares
id-token: write.No GitHub secrets
The only sensitive material — the
primitive-ciApp private key — is pulled from AWS Secrets Manager at runtime; nothing credential-bearing is stored on the GitHub side. The role ARN cannot come from SM (the role must be assumed before SM is reachable), but an ARN is an identifier, not a credential, so it's supplied as a non-secret Actions variable (vars.AWS_HOMEBREW_TAP_ROLE_ARN) rather than a secret. This also keeps the AWS account ID out of the public workflow source.Required before this can pass (org/AWS admin — not in this PR)
AWS_HOMEBREW_TAP_ROLE_ARNvariable (not secret) on this reporepo:primitivedotdev/sdks:*)primitive-ciApp is installed onhomebrew-tapwithcontents: write(it already makes the formula PRs, so this should already hold)Once green, delete the now-unused
HOMEBREW_TAP_BOT_TOKENsecret.🤖 Generated with Claude Code