From 3c743cc17750bccdb9a5df12d9cc61ec34f6eb82 Mon Sep 17 00:00:00 2001 From: Erik Osterman Date: Fri, 4 Sep 2026 16:57:27 -0500 Subject: [PATCH] fix: re-mint GitHub App token before goreleaser to avoid mid-run expiry GitHub App installation tokens are hard-capped at 1 hour and cannot be extended. The goreleaser job minted its token once at job start, then handed it straight to a `goreleaser release --timeout 180m` invocation whose own runtime (build + sign + SBOM + publish across every platform target) has been climbing past 1 hour on recent atmos runs (44m -> 53m -> 1h5m52s), so the token is already expired by the time goreleaser reaches its final publish-phase API calls. That surfaces as an unrelated-looking `401 Bad credentials` when goreleaser tries to list/delete existing draft releases, not an error about the release content itself. Mint a second, fresh App token immediately before the "Run GoReleaser" step (after all the setup/GPG/disk-cleanup steps that otherwise eat into the original token's lifetime before goreleaser even starts), and use it for both the GoReleaser invocation and the immediately-following build-provenance attestation step. --- .github/workflows/shared-go-auto-release.yml | 24 ++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/.github/workflows/shared-go-auto-release.yml b/.github/workflows/shared-go-auto-release.yml index 78bc991e..cd00b23b 100644 --- a/.github/workflows/shared-go-auto-release.yml +++ b/.github/workflows/shared-go-auto-release.yml @@ -243,6 +243,26 @@ jobs: df -h + # Re-minted immediately before the long-running goreleaser invocation: + # GitHub App installation tokens are hard-capped at 1 hour (not + # configurable), and the goreleaser step below (build + sign + SBOM + + # publish, across every platform target) has been taking 45-65+ + # minutes on its own and trending upward. The original `github-app` + # token from the top of this job has already burned several minutes on + # setup (git/gpg install, harden-runner init, syft install, checkout, + # unshallow, go setup, gpg import, disk-space checks, apt cleanup) + # before goreleaser even starts, so by the time goreleaser reaches its + # final publish-phase API calls (listing/deleting existing drafts) the + # original token can already be expired, failing with a `401 Bad + # credentials` that has nothing to do with the release content itself. + # Minting a fresh token right here maximizes the runway goreleaser gets + # before its own token goes stale. + - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 + id: github-app-release + with: + app-id: ${{ vars.BOT_GITHUB_APP_ID }} + private-key: ${{ secrets.BOT_GITHUB_APP_PRIVATE_KEY }} + - name: Run GoReleaser uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7.2.3 id: releaser @@ -252,7 +272,7 @@ jobs: args: release --config ${{ steps.go-releaser-config.outputs.path }} --clean --timeout 180m env: GPG_FINGERPRINT: ${{ steps.import_gpg.outputs.fingerprint }} - GITHUB_TOKEN: ${{ steps.github-app.outputs.token }} + GITHUB_TOKEN: ${{ steps.github-app-release.outputs.token }} GO_RELEASER_TARGET_COMMITISH: ${{ github.event_name == 'pull_request' && github.head_ref || github.ref_name }} GO_RELEASER_DRAFT_MODE: ${{ inputs.draft }} @@ -264,7 +284,7 @@ jobs: - name: "Attest build provenance" uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 with: - github-token: ${{ steps.github-app.outputs.token }} + github-token: ${{ steps.github-app-release.outputs.token }} subject-path: 'source/dist/*' - name: "Resolve checksums file"