From 15e3bc75cfbde4c88e48fc0aa6d5d6d16ae6d6b7 Mon Sep 17 00:00:00 2001 From: Blair Hamilton Date: Sat, 22 Aug 2026 08:30:23 -0400 Subject: [PATCH] fix(docker-release): export GH_TOKEN so stevedore can cut the GitHub Release MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The stevedore step passed REGISTRY, STEVEDORE_CACHE_* and GH_PRIVATE_TOKEN but no GH_TOKEN. stevedore's publish path shells out to `gh release create` (internal/publish/publish.go) and takes no token flag, so gh found no credentials and exited 4 — after the image had already been built, pushed and marker-ref'd. The failure mode is worse than a red check, because it straddles a completed publish: on understudy v0.0.140 the run reports failure while understudy:0.0.140 and :31434f0 are both live in ECR, the generated dist/CHANGELOG.md is discarded with the job, and the tag ends up with no Release for a consumer to read. Every v* tag since v0.0.135 has had its Release created by hand. `contents: write` was already declared on the job for the marker refs, so github.token can create the release as-is; no new permission or secret. Env set on a `uses:` step reaches a composite action's own steps — REGISTRY and GH_PRIVATE_TOKEN travel that same path today and demonstrably arrive. Not fixed here: docker-release-split.yml has the same missing env on its `Stevedore merge` step, and additionally its per-platform legs run plain `release` (no --skip-publish), which reaches publishRelease too — so each leg would race to create the same tag's Release. Handing the legs a token without first skipping publish there would turn one clear failure into a flaky one, so split mode is left alone and tracked separately. Refs pinpredict/.github#63, understudy#225 --- .github/workflows/docker-release.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.github/workflows/docker-release.yml b/.github/workflows/docker-release.yml index a797c37..cc50ea3 100644 --- a/.github/workflows/docker-release.yml +++ b/.github/workflows/docker-release.yml @@ -203,6 +203,16 @@ jobs: # entries simply ignore these. STEVEDORE_CACHE_FROM: "type=gha,scope=stevedore" STEVEDORE_CACHE_TO: "type=gha,mode=max,scope=stevedore" + # stevedore's release step shells out to `gh release create`, which + # authenticates from GH_TOKEN and takes no token flag. Without it the + # image publishes and the job THEN dies on `gh: exit status 4`, so a + # red run sits behind a completed push and the tag gets no GitHub + # Release (pinpredict/.github#63, understudy#225). The job's + # `contents: write` above is what lets this token create the release. + # Not to be confused with GH_PRIVATE_TOKEN below: that one is a minted + # App token with contents:read, for fetching private modules inside + # the BUILD, and it cannot create a release. + GH_TOKEN: ${{ github.token }} # Empty unless private-modules minted a token above. The repo's # .stevedore.yaml declares `secrets: [{id: gh_token, env: # GH_PRIVATE_TOKEN}]`; when private-modules is true this is populated,