7070 - name : 🔨 Set up Docker Buildx
7171 uses : docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
7272
73- # Logins and metadata are only needed in push mode
73+ # GHCR login runs before the build — needed to pull ghcr.io/astral-sh/uv.
7474 - name : Login to GHCR
7575 if : inputs.push
7676 uses : docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
@@ -79,12 +79,11 @@ jobs:
7979 username : ${{ github.actor }}
8080 password : ${{ github.token }}
8181
82- - name : Login to Docker Hub
83- if : inputs.push
84- uses : docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
85- with :
86- username : ${{ secrets.DOCKERHUB_USERNAME }}
87- password : ${{ secrets.DOCKERHUB_TOKEN }}
82+ # Docker Hub login is deferred until after the build and tests.
83+ # A repo-scoped Docker Hub token (socketdev/socket-basics only) would cause
84+ # 401s if active during the build, since BuildKit uses it for ALL Docker Hub
85+ # requests including pulling public base images (python, trivy, trufflehog).
86+ # Those public images pull fine without auth; only the push needs credentials.
8887
8988 - name : Extract image metadata
9089 if : inputs.push
@@ -124,6 +123,11 @@ jobs:
124123 BUILD_DATE=${{ github.event.repository.updated_at }}
125124 cache-from : type=gha,scope=${{ inputs.name }}
126125 cache-to : type=gha,mode=max,scope=${{ inputs.name }}
126+ # Disable attestations for the test build — provenance/SBOM cause BuildKit
127+ # to pull docker/buildkit-syft-scanner from Docker Hub, which fails with a
128+ # repo-scoped token. Attestations are enabled on the push step only.
129+ provenance : false
130+ sbom : false
127131
128132 # ── Step 2: Smoke test ─────────────────────────────────────────────────
129133 - name : 🧪 Smoke test
@@ -141,6 +145,16 @@ jobs:
141145 --image-tag ${{ inputs.name }}:pipeline-test
142146
143147 # ── Step 4: Push to registries (publish mode only) ─────────────────────
148+ # Docker Hub login happens here — after build and tests, immediately before
149+ # push. Keeping it here prevents the repo-scoped token from interfering
150+ # with public image pulls during the build step.
151+ - name : Login to Docker Hub
152+ if : inputs.push
153+ uses : docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
154+ with :
155+ username : ${{ secrets.DOCKERHUB_USERNAME }}
156+ password : ${{ secrets.DOCKERHUB_TOKEN }}
157+
144158 # All layers are in the GHA cache from step 1 — this is just an upload.
145159 - name : 🚀 Push to registries
146160 if : inputs.push
@@ -157,8 +171,11 @@ jobs:
157171 VCS_REF=${{ github.sha }}
158172 BUILD_DATE=${{ github.event.repository.updated_at }}
159173 cache-from : type=gha,scope=${{ inputs.name }}
160- provenance : true
161- sbom : true
174+ # SBOM and provenance generation pull docker/buildkit-syft-scanner from
175+ # Docker Hub, which fails with a repo-scoped token. Disabled until a
176+ # token with broader Docker Hub read access is available.
177+ provenance : false
178+ sbom : false
162179
163180 # Floating major version tags (v2 → latest v2.x.y) have been intentionally
164181 # removed. Mutable tags are structurally equivalent to :latest and are
0 commit comments