Skip to content

ci: one token, one publishing environment, SHA-pinned actions - #145

Merged
UltimaPhoenix merged 2 commits into
developfrom
ci/publishing-environment
Nov 8, 2026
Merged

UltimaPhoenix merged 2 commits into
developfrom
ci/publishing-environment

Conversation

@UltimaPhoenix

@UltimaPhoenix UltimaPhoenix commented Nov 8, 2026 •

Copy link
Copy Markdown
Owner

What

The pipeline's credentials, consolidated after the Scoop bucket joined the destinations.

  • One secret, CI_DEVCOACH_TOKEN — the admin's fine-grained PAT (Contents RW on dev-coach and
    on homebrew-tap, scoop-bucket, claude-plugins-marketplace, claude-plugins-marketplace-beta). It
    replaces RELEASE_TOKEN in bump and HOMEBREW_TAP_TOKEN / SCOOP_BUCKET_TOKEN /
    CLAUDE_PLUGIN_MARKETPLACE / BETA_MARKETPLACE_DEPLOY_KEY in the four publishing jobs, which now
    all clone and push the same way (the beta job leaves its ssh deploy key behind).
  • One publishing environment for bump, marketplace-beta, homebrew, scoop, marketplace,
    holding the secret, with a deployment branch policy — develop, main, v* tags — that refuses
    those jobs on any other ref before they start. This is the control that keeps the token off PR branches; a fork's
    pull_request run never had secrets, and the one pull_request_target (CLA) runs a fixed action
    without checking out PR code.
  • Token in the step, not the job: read in the single step that pushes (job-level HAS_TOKEN
    boolean, since secrets is not available in a step's if), and handed to git as an HTTP header by
    scripts/ci/git-token-auth.sh — never in a clone URL, never in the clone's .git/config, base64
    form masked in the log.
  • Every action pinned to a commit SHA (version kept as a comment) in all four workflows;
    Dependabot's github-actions ecosystem bumps pin and comment together. A moved tag is how CI
    secrets were actually stolen in 2025 (tj-actions/changed-files).

No user-facing change; CHANGELOG untouched.

Before merging

  1. The PAT CI-DEVCOACH-TOKEN exists with the five repos and Contents RW, and is stored as the
    secret CI_DEVCOACH_TOKEN of the publishing environment (done 2026-11-08) — the beta job reads
    it on the first push to develop after the merge, bump on the next release.

After the first green run

  • Delete the old secrets RELEASE_TOKEN, HOMEBREW_TAP_TOKEN, CLAUDE_PLUGIN_MARKETPLACE, the
    environment secret BETA_MARKETPLACE_DEPLOY_KEY, the deploy key on the beta repo, and the two old
    PATs; the environments homebrew-tap, scoop-bucket, claude-marketplace are unreferenced.
  • Optionally turn on Require actions to be pinned to a full-length commit SHA in Settings → Actions
    (only after this PR is on develop, or the running workflows fail).

Verification

  • All four workflows parse as YAML; every uses: resolves to the SHA its tag pointed at on
    2026-11-08 (11 actions, exact versions in the comments); no old secret name remains in .github/.
  • The marketplace-beta job runs on every push to develop, so the merge itself exercises the new
    token path end to end.

The pipeline's credentials, consolidated after the Scoop bucket joined the destinations:

- ONE secret, CI_DEVCOACH_TOKEN (the admin's fine-grained PAT: Contents RW on dev-coach and on
  homebrew-tap, scoop-bucket, claude-plugins-marketplace, claude-plugins-marketplace-beta). It
  replaces RELEASE_TOKEN in `bump` and HOMEBREW_TAP_TOKEN / SCOOP_BUCKET_TOKEN /
  CLAUDE_PLUGIN_MARKETPLACE / the BETA_MARKETPLACE_DEPLOY_KEY in the four publishing jobs, which
  now all clone and push the same way.
- The four publishing jobs run in a single `publishing` environment whose deployment branch
  policy (develop, main, v* tags) refuses them on any other ref — the control that keeps the
  token away from PR branches. The per-destination environments are no longer referenced.
- The token is read in the one step that pushes (job-level HAS_TOKEN boolean, since `secrets`
  is not available in a step's `if`) and reaches git as an HTTP header through
  scripts/ci/git-token-auth.sh: never in a clone URL, never in the clone's .git/config, base64
  form masked in the log.
- Every `uses:` in the four workflows is pinned to a full commit SHA with the version as a
  comment; Dependabot's github-actions ecosystem bumps pin and comment together.

Claude-Session: https://claude.ai/code/session_01LWas1iLGAaSFTxXrcucoSr
The token was stored as an environment secret, which is the tighter place for it; the bump
job had no environment and would have read an empty token at the next release. It now runs in
`publishing` like the four publishing jobs — one secret, one place, and the branch policy
(develop, main, v*) is exactly where a release is dispatched from.

Claude-Session: https://claude.ai/code/session_01LWas1iLGAaSFTxXrcucoSr
@UltimaPhoenix
UltimaPhoenix merged commit 26377e1 into develop Nov 8, 2026
15 checks passed
@UltimaPhoenix
UltimaPhoenix deleted the ci/publishing-environment branch November 8, 2026 16:08
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.

1 participant