From 1a6c6c0dd5f491b54f8cdb302f4e1f30142e412c Mon Sep 17 00:00:00 2001 From: FredApps <153173854+FredApps@users.noreply.github.com> Date: Tue, 10 Nov 2026 11:10:27 +0100 Subject: [PATCH] fix(docker-build): scope packages: write to the pushing jobs --- .github/workflows/docker-build.yml | 8 +++++++- tests/test_docker_build.py | 9 +++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/.github/workflows/docker-build.yml b/.github/workflows/docker-build.yml index 194b1da..d6c58e2 100644 --- a/.github/workflows/docker-build.yml +++ b/.github/workflows/docker-build.yml @@ -93,13 +93,16 @@ on: DOCKERHUB_TOKEN: description: "Docker Hub token for dhi.io base images and docker.io pushes; only read when configured" +# Read-only by default; each job that pushes to GHCR asks for `packages: write` itself. permissions: contents: read - packages: write jobs: build: name: Build ${{ matrix.platform.platform }} + permissions: + contents: read + packages: write strategy: fail-fast: true matrix: @@ -243,6 +246,9 @@ jobs: merge: name: Publish multi-arch manifests needs: build + permissions: + contents: read + packages: write runs-on: ubuntu-24.04 timeout-minutes: 15 steps: diff --git a/tests/test_docker_build.py b/tests/test_docker_build.py index 1d83ab1..c94e259 100644 --- a/tests/test_docker_build.py +++ b/tests/test_docker_build.py @@ -17,6 +17,15 @@ class DockerBuildWorkflowTests(unittest.TestCase): self.assertIn("DOCKERHUB_TOKEN", call["secrets"]) self.assertNotIn("DIGITALOCEAN_TOKEN", call["secrets"]) + def test_write_permission_is_job_scoped(self): + """Only the pushing jobs get `packages: write` (SonarCloud githubactions:S8233).""" + self.assertEqual(WORKFLOW["permissions"], {"contents": "read"}) + for job in ("build", "merge"): + self.assertEqual( + WORKFLOW["jobs"][job]["permissions"], + {"contents": "read", "packages": "write"}, + ) + def test_dockerhub_login_in_build_job(self): steps = WORKFLOW["jobs"]["build"]["steps"] dh_step = next(