@@ -11,10 +11,15 @@ name: Native release candidate
1111# its build provenance. The PHP image and its Release workflow are unchanged.
1212#
1313# Its credentials are its own: the dockerhub-native Environment and the
14- # NATIVE_DOCKERHUB_* secret names. While they are absent the workflow fails
15- # closed: each job signs in to Docker Hub before it builds anything, so a
16- # dispatch stops there and pushes nothing. It can never resolve the PHP
17- # release's Environment or repository credentials.
14+ # NATIVE_DOCKERHUB_* secret names. It can never resolve the PHP release's
15+ # Environment or repository credentials.
16+ #
17+ # A release candidate (a version with a -rc.N suffix) publishes to GHCR only,
18+ # so candidates can be qualified before Docker Hub credentials exist
19+ # (operator decision, October 30). Any other version publishes to both
20+ # registries: each job then signs in to Docker Hub before it builds anything,
21+ # so while the credentials are absent a dispatch stops there and pushes
22+ # nothing.
1823
1924run-name : Native ${{ inputs.tag }} at ${{ inputs.release_commit }}
2025
4045 GHCR_IMAGE : ghcr.io/durable-workflow/server-native
4146
4247jobs :
48+ plan :
49+ name : Choose the registries for this tag
50+ if : github.ref == 'refs/heads/main'
51+ runs-on : ubuntu-latest
52+ timeout-minutes : 5
53+ outputs :
54+ dockerhub : ${{ steps.plan.outputs.dockerhub }}
55+ steps :
56+ - name : Publish a release candidate to GHCR only
57+ id : plan
58+ env :
59+ RELEASE_TAG : ${{ inputs.tag }}
60+ run : |
61+ set -euo pipefail
62+ [[ "$RELEASE_TAG" =~ ^native-[0-9]+\.[0-9]+\.[0-9]+(-rc\.[0-9]+)?$ ]] \
63+ || { echo 'tag must be native-X.Y.Z or native-X.Y.Z-rc.N' >&2; exit 1; }
64+ if [[ -n "${BASH_REMATCH[1]}" ]]; then echo dockerhub=false; else echo dockerhub=true; fi >> "$GITHUB_OUTPUT"
65+
4366 build-amd64 :
4467 name : Build and smoke linux/amd64
68+ needs : plan
4569 if : github.ref == 'refs/heads/main'
4670 runs-on : ubuntu-latest
4771 timeout-minutes : 75
81105 uses : docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
82106
83107 - name : Log in to Docker Hub
108+ if : needs.plan.outputs.dockerhub == 'true'
84109 uses : docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
85110 with :
86111 username : ${{ secrets.NATIVE_DOCKERHUB_USERNAME }}
@@ -107,7 +132,7 @@ jobs:
107132 org.opencontainers.image.revision=${{ inputs.release_commit }}
108133 dev.durable-workflow.release.tag=${{ inputs.tag }}
109134 dev.durable-workflow.release.run-id=${{ github.run_id }}
110- outputs : type=image,"name=${{ env.GHCR_IMAGE }}, ${{ env.DOCKERHUB_IMAGE }}",push-by-digest=true,name-canonical=true,push=true
135+ outputs : type=image,"name=${{ env.GHCR_IMAGE }}${{ needs.plan.outputs.dockerhub == 'true' && format(',{0}', env.DOCKERHUB_IMAGE) || '' }}",push-by-digest=true,name-canonical=true,push=true
111136
112137 - name : Smoke-test the pushed linux/amd64 digest on its own architecture
113138 env :
@@ -131,6 +156,7 @@ jobs:
131156
132157 build-arm64 :
133158 name : Build and smoke linux/arm64
159+ needs : plan
134160 if : github.ref == 'refs/heads/main'
135161 runs-on : ubuntu-24.04-arm
136162 timeout-minutes : 75
@@ -170,6 +196,7 @@ jobs:
170196 uses : docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
171197
172198 - name : Log in to Docker Hub
199+ if : needs.plan.outputs.dockerhub == 'true'
173200 uses : docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
174201 with :
175202 username : ${{ secrets.NATIVE_DOCKERHUB_USERNAME }}
@@ -196,7 +223,7 @@ jobs:
196223 org.opencontainers.image.revision=${{ inputs.release_commit }}
197224 dev.durable-workflow.release.tag=${{ inputs.tag }}
198225 dev.durable-workflow.release.run-id=${{ github.run_id }}
199- outputs : type=image,"name=${{ env.GHCR_IMAGE }}, ${{ env.DOCKERHUB_IMAGE }}",push-by-digest=true,name-canonical=true,push=true
226+ outputs : type=image,"name=${{ env.GHCR_IMAGE }}${{ needs.plan.outputs.dockerhub == 'true' && format(',{0}', env.DOCKERHUB_IMAGE) || '' }}",push-by-digest=true,name-canonical=true,push=true
200227
201228 - name : Smoke-test the pushed linux/arm64 digest on its own architecture
202229 env :
@@ -220,7 +247,7 @@ jobs:
220247
221248 publish :
222249 name : Tag, verify and attest the native index
223- needs : [build-amd64, build-arm64]
250+ needs : [plan, build-amd64, build-arm64]
224251 if : github.ref == 'refs/heads/main'
225252 runs-on : ubuntu-latest
226253 timeout-minutes : 20
@@ -240,6 +267,7 @@ jobs:
240267 uses : docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4
241268
242269 - name : Log in to Docker Hub
270+ if : needs.plan.outputs.dockerhub == 'true'
243271 uses : docker/login-action@af1e73f918a031802d376d3c8bbc3fe56130a9b0 # v4
244272 with :
245273 username : ${{ secrets.NATIVE_DOCKERHUB_USERNAME }}
@@ -252,12 +280,13 @@ jobs:
252280 username : ${{ github.actor }}
253281 password : ${{ secrets.GITHUB_TOKEN }}
254282
255- - name : Tag and verify the index in both registries
283+ - name : Tag and verify the index in each registry
256284 id : index
257285 env :
258286 RELEASE_TAG : ${{ inputs.tag }}
259287 DIGEST_AMD64 : ${{ needs.build-amd64.outputs.digest }}
260288 DIGEST_ARM64 : ${{ needs.build-arm64.outputs.digest }}
289+ PUBLISH_DOCKERHUB : ${{ needs.plan.outputs.dockerhub }}
261290 run : bash scripts/ci/native-release-publish.sh
262291
263292 - name : Attest the index's build provenance in GHCR
@@ -268,6 +297,7 @@ jobs:
268297 push-to-registry : true
269298
270299 - name : Attest the index's build provenance in Docker Hub
300+ if : needs.plan.outputs.dockerhub == 'true'
271301 uses : actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4
272302 with :
273303 subject-name : index.docker.io/${{ env.DOCKERHUB_IMAGE }}
0 commit comments