From f9b354e1cde669a18157f81d2e2e9448d2582532 Mon Sep 17 00:00:00 2001 From: Arnon Rotem-Gal-Oz Date: Tue, 8 Sep 2026 21:17:40 +0300 Subject: [PATCH] ci: validate the tap token before publishing anything Both v0.8.1 and v0.8.2 published complete releases and then failed at the cask with `401 Bad credentials` on mondaycom/homebrew-tap. Because releases here are immutable and the cask pipe runs after the release pipe, neither could be repaired -- each attempt cost a version to discover the same broken credential. Check the token before the release exists. If it cannot read the tap, or can read but not push, the job stops in seconds having published nothing, so fixing the secret and re-running is enough; no new tag needed. gh puts a one-line summary on stderr and the JSON body on stdout, so the annotation reports stderr -- 401 distinguishes an invalid or truncated token from a 404 for a token with no access to the repository. Bumps flake.nix to 0.8.3, which the preceding version guard requires. Co-Authored-By: Claude Opus 5 --- .github/workflows/release.yml | 30 ++++++++++++++++++++++++++++++ flake.nix | 2 +- 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bc0d270..e49e1bc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -40,6 +40,36 @@ jobs: fi echo "flake.nix and tag agree on $want" + # The cask publishes after the GitHub release, and releases here are + # immutable, so a tap token that does not work means a release that can + # never get its cask -- only a new tag can fix it. That is what cost both + # v0.8.1 and v0.8.2. Validating the credential before anything is + # published turns that into a recoverable failure: nothing exists yet, so + # fixing the secret and re-running this job is enough. + - name: Check the tap token + env: + GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }} + # Kept in step with the repository under homebrew_casks in + # .goreleaser.yaml. + TAP: mondaycom/homebrew-tap + run: | + if [ -z "$GH_TOKEN" ]; then + echo "::error::HOMEBREW_TAP_TOKEN is not set. It needs a PAT with Contents: read and write on $TAP." + exit 1 + fi + # gh puts a one-line summary ("gh: Bad credentials (HTTP 401)") on + # stderr and the raw JSON body on stdout, so report the former. + if ! push="$(gh api "repos/$TAP" -q .permissions.push 2>"$RUNNER_TEMP/tap-err")"; then + echo "::error::HOMEBREW_TAP_TOKEN cannot read $TAP -- $(head -1 "$RUNNER_TEMP/tap-err")" + echo "::error::HTTP 401 means the token is invalid, expired, or was pasted incompletely; HTTP 404 means it is valid but has no access to that repository." + exit 1 + fi + if [ "$push" != "true" ]; then + echo "::error::HOMEBREW_TAP_TOKEN can read $TAP but cannot push to it. Grant Contents: read and write." + exit 1 + fi + echo "tap token can push to $TAP" + - name: Set up Go uses: actions/setup-go@v7 with: diff --git a/flake.nix b/flake.nix index b3865c3..810747c 100644 --- a/flake.nix +++ b/flake.nix @@ -10,7 +10,7 @@ # workflow before anything is published. Nix builds from a source tree with # no .git, so `git describe` is unavailable here and the version has to be # stated literally. - version = "0.8.2"; + version = "0.8.3"; systems = [ "x86_64-linux"