Skip to content

fix(go-binary-release): grant packages: write so GHCR pushes can succeed - #1

Merged
juicycleff merged 1 commit into
mainfrom
fix/goreleaser-packages-write
Aug 7, 2026
Merged

fix(go-binary-release): grant packages: write so GHCR pushes can succeed#1
juicycleff merged 1 commit into
mainfrom
fix/goreleaser-packages-write

Conversation

@juicycleff

Copy link
Copy Markdown
Contributor

The failure

Releasing xraph/forge built for six minutes, produced the images, and then died on the push:

docker images: failed to publish artifacts: failed to push ghcr.io/xraph/forge:1.9.2-arm64:
  exit status 1: denied: installation not allowed to Write organization package

Why

The goreleaser job declared:

permissions:
  contents: write

Once a permissions: block exists, everything unlisted is none — so GITHUB_TOKEN had packages: none. Meanwhile the docker: true path logs into the registry as exactly that token (docker/login-action with password: ${{ secrets.GITHUB_TOKEN }}) and then pushes.

The message is misleading: installation not allowed to Write organization package reads like a registry ACL problem. It isn't — the token has no packages scope to exercise. Granting the calling repository write access on the GHCR package does not change the outcome.

Callers could not work around it:

  • A reusable workflow's own permissions: block is authoritative for its jobs, so a caller declaring packages: write on the calling job changes nothing.
  • GORELEASER_TOKEN never reaches the login step, which hardcodes secrets.GITHUB_TOKEN.

The change

Adds packages: write to that job. Harmless when docker is false — nothing authenticates to a registry on that path, so the scope goes unused.

Note for merging

xraph/forge pins this workflow at @v1, so the v1 tag has to move before it picks the fix up. Until then forge skips the docker pipe via goreleaser-args: release --clean --skip=docker, which is marked temporary and references this PR.

🤖 Generated with Claude Code

The job declared `permissions: contents: write` and nothing else. Once any
permissions block exists everything unlisted is `none`, so GITHUB_TOKEN had
`packages: none` -- while the `docker: true` path logs into the registry as
exactly that token and then pushes.

Callers could not work around it. A reusable workflow's own block is the
authoritative one for its jobs, so a caller declaring `packages: write` on the
calling job changed nothing, and GORELEASER_TOKEN never reaches the login step,
which hardcodes secrets.GITHUB_TOKEN.

The result was a release that built for six minutes and then failed with

    denied: installation not allowed to Write organization package

which reads like a registry ACL problem and is not one -- the token has no
packages scope to exercise, so granting the repository write access on the
package does not change the outcome.

Harmless when `docker` is false: nothing authenticates to a registry on that
path, so the scope goes unused.

Found releasing xraph/forge, which is pinned to @v1 and needs that tag moved to
pick this up.
@juicycleff
juicycleff merged commit 9e0edec into main Aug 7, 2026
38 checks passed
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