Repository navigation
Shared node-repo workflows: mint the stage-repo token from a GitHub App (#2249) - #2310
Conversation
…pp (#2249) Every dependabot PR in MeshWeaver.SocialMedia and MeshWeaver.Reinsurance is permanently RED, so the automated bumps of these very workflows' pins can never merge. The preflight is behaving correctly and must not be "fixed" with a dependabot exemption — that would reintroduce the skip-trapdoor, and a dependency bump is precisely when you want the compile gate to run. The cause is a store split, not a missing value: GitHub hands a dependabot-triggered run the DEPENDABOT secret store, never the Actions one. `MESHWEAVER_REPO_TOKEN` exists for normal runs and is simply absent for dependabot ones. Copying the PAT into the second store would fix today and rot tomorrow — the same PAT class that left Chart Drift at HTTP 401 for nine consecutive runs (#1709). So the credential stops being a stored token: - `stage-repo-token` is replaced by `stage-repo-app-id` + `stage-repo-app-private-key`. - Both workflows mint an installation token per run, scoped by `owner`/`repositories` to the stage repo alone with `permission-contents: read` — narrower than the PAT it replaces. - The App id + private key are provisioned in BOTH stores of every calling repo, so a dependabot run resolves them exactly like a push run. The bake preflight keeps asserting RED when `stage-modules` is set and the credentials are absent, and now adds the one line that turns a confusing red into an actionable one: if the run's actor is dependabot, it says the secret source was the Dependabot store. That is the fact the last person had to infer. Callers are SHA-pinned, so this lands without touching them; the satellite callers switch to the new secrets in the same change set as their pin bump. Category: none — CI credential plumbing, no user-visible effect.
There was a problem hiding this comment.
Pull request overview
This PR updates the shared reusable node-repo CI workflows to stop relying on a long-lived PAT for staging cross-repo modules, and instead mint a short-lived, repo-scoped installation token via a GitHub App—addressing the Dependabot secret-store split described in #2249 and reducing credential-rot risk.
Changes:
- Replace
stage-repo-token(PAT) withstage-repo-app-id+stage-repo-app-private-keyinputs on the reusable workflows. - Mint a per-run installation token using
actions/create-github-app-token@v2, scoped to the configured stage repo, and use it for the staging checkout. - Add an additional Dependabot-focused diagnostic warning in the publish-bake preflight when stage-module staging is enabled.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| .github/workflows/node-repo-publish-bake.yml | Switches staging checkout auth from PAT to GitHub App installation token; updates workflow-call secret contract and preflight diagnostics accordingly. |
| .github/workflows/node-repo-gate.yml | Switches staging checkout auth from PAT to GitHub App installation token; updates workflow-call secret contract accordingly. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
|
CI red here is not this PR — filed as #2319 and investigated before re-running, not after.
Control: #2312, same base, unrelated diff, passed the identical shard 2 (run 32938049737). Worth reading #2319 rather than treating it as noise: the test's own docstring says a red there is "a permanent miss dressed as a timeout, which is why raising a budget could never fix it" — so by its author's reasoning this is a residual hole in the early→live handoff fix ( Re-running the failed jobs now to unblock this unrelated change. The defect is tracked in #2319, not buried here. |
…before minting Two findings from the automatic review, both real. 1. The Dependabot-store hint fired whenever `missing[]` was non-empty — including for a missing acr-password or azure-tenant-id. A hint that names ONE cause must only fire for the input that has that cause; otherwise it sends the next person to the wrong settings page while the actual missing secret sits in the list above it. Now gated on a `stage_missing` flag set only by the two stage-repo credential checks. 2. node-repo-gate.yml minted the token with no assertion on its inputs, so a missing app-id, a missing private key, or a malformed stage-repo surfaced as an opaque create-github-app-token or checkout failure two steps later. It now carries the same shape publish-bake has: fail RED naming exactly what to provision, plus the dependabot-store line when the actor is dependabot. Both `if:`s are on the declared INPUT `stage-modules` — whether staging was requested at all — never on whether a secret happens to be set. That distinction is the whole point of AGENTS.md's "a gate NEVER tests its own inputs": an input-shaped `if:` renders a skipped job identically to a passed one, and these two must fail loudly instead. Category: none — CI credential plumbing, no user-visible effect.
Platform half of #2249. The satellite callers follow in their own PRs, together with their pin bump.
The cause is a store split, not a missing value
Every dependabot PR in
MeshWeaver.SocialMediaandMeshWeaver.Reinsuranceis permanently red, so the automated bumps of these very workflows' pins can never merge. GitHub hands a dependabot-triggered run the Dependabot secret store, never the Actions one —MESHWEAVER_REPO_TOKENexists for push runs and is simply absent for dependabot ones.The preflight is behaving correctly and is not changed to skip. A dependency bump is precisely when you want the compile gate to run.
Why not just copy the PAT into the second store
That fixes today and rots tomorrow. It is the same credential class that left
Chart Driftat HTTP 401 for nine consecutive runs while reporting a missing secret (#1709). So the credential stops being stored:stage-repo-token(PAT)stage-repo-app-id+stage-repo-app-private-keyowner/repositories= the stage repo alone,permission-contents: readMESHWEAVER_APP_ID/MESHWEAVER_APP_PRIVATE_KEYare provisioned in the Actions and Dependabot stores of SocialMedia, Reinsurance and Plugins.One diagnostic added
The bake preflight still fails RED when
stage-modulesis set and the credentials are absent. It now also says, when the actor is dependabot, that the secret source for this run was the Dependabot store — the fact the last person had to infer from a bare 'not provisioned'.Scope note
The issue lists Plugins among the affected repos. It is not affected by this mechanism: Plugins does not pass
stage-repo-tokenand its ci.yml records that it no longer checks out the private core repo. Its one open dependabot PR (#629,actions/setup-node6→7) is unrelated.Safety of landing this alone
Callers are SHA-pinned, so nothing moves until a caller bumps — and the currently-open bump PRs are red and cannot merge, so there is no window in which a caller lands on this workflow while still passing the old secret name.
Verified:
UpstreamBuildGateGuard4/4 passed against the edited workflow (fresh trx); both files parse as YAML.What's New: skipped — CI credential plumbing, no user-visible effect.