@@ -564,8 +564,22 @@ jobs:
564564 EXISTING_SHA="${REMOTE_PEELED:-${REMOTE_RAW}}"
565565 SHORT_SHA=$(echo "$EXISTING_SHA" | head -c 8)
566566
567- # Fail-fast on wrong-target. A wrong-target tag means
568- # create-git-tag would hard-fail 20-40 minutes later after
567+ # Auto-publish (create_edge_docker_tag=true) runs on every push
568+ # to master, but component versions only change when a human
569+ # bumps them. So the same immutable tag (e.g. server-0.8.1-edge.1)
570+ # is re-seen on every run after the one that first created it.
571+ # That is the expected steady state, not an error: the version
572+ # is already released. The run still refreshes the rolling :edge
573+ # Docker image; it just skips the versioned git tag / crate /
574+ # :version manifest for that component. An existing tag here - at
575+ # ANY commit - is therefore informational, never fatal.
576+ # WRONG_TARGET_TAGS stays empty in this mode so the fail-fast
577+ # exit 1 below cannot trigger.
578+ if [ "${{ inputs.create_edge_docker_tag }}" = "true" ]; then
579+ echo "ℹ️ $NAME: $TAG already exists at $SHORT_SHA - already released, run will refresh :edge only"
580+ echo "| $NAME | $VERSION | $TAG | ℹ️ Already released ($SHORT_SHA) - :edge refresh only |" >> $GITHUB_STEP_SUMMARY
581+ # Fail-fast on wrong-target for MANUAL publish. A wrong-target tag
582+ # means create-git-tag would hard-fail 20-40 minutes later after
569583 # publishing artifacts to crates.io / PyPI / npm / Maven /
570584 # NuGet / DockerHub. Catching it at check-tags converts that
571585 # into a fast, cheap failure at the top of the run.
@@ -579,7 +593,7 @@ jobs:
579593 # manually or run a follow-up without skip_tag_creation to
580594 # converge. The fail-fast exit 1 below is gated on
581595 # skip_tag_creation != true.
582- if [ "$EXISTING_SHA" != "${{ needs.validate.outputs.commit }}" ]; then
596+ elif [ "$EXISTING_SHA" != "${{ needs.validate.outputs.commit }}" ]; then
583597 WRONG_TARGET_TAGS+=("$TAG|$SHORT_SHA")
584598 if [ "${{ inputs.skip_tag_creation }}" = "true" ]; then
585599 echo "⚠️ Tag exists on remote at WRONG target: $TAG (points to $SHORT_SHA, not enforced: skip_tag_creation=true)"
@@ -879,6 +893,19 @@ jobs:
879893 SHOULD_TAG=false
880894 fi
881895
896+ # Git tags are immutable. A component version is bumped by a human;
897+ # auto-publish then re-runs on every subsequent master push with that
898+ # same version until the next bump. Once the tag exists the versioned
899+ # release (git tag + :version manifest) is already done - this run
900+ # only refreshes the rolling :edge image. Querying the remote (not the
901+ # shallow local clone) so this agrees with create-git-tag's own
902+ # authoritative ls-remote check.
903+ if [ "$SHOULD_TAG" = "true" ] && [ -n "$TAG" ] \
904+ && git ls-remote --tags --exit-code origin "refs/tags/${TAG}" >/dev/null 2>&1; then
905+ echo "ℹ️ $TAG already exists on remote - versioned release already done, refreshing :edge only"
906+ SHOULD_TAG=false
907+ fi
908+
882909 {
883910 echo "version=$VERSION"
884911 echo "tag=$TAG"
@@ -924,59 +951,63 @@ jobs:
924951
925952 - name: Create and push manifest
926953 working-directory: ${{ runner.temp }}/digests
954+ env:
955+ SHOULD_TAG: ${{ steps.ver.outputs.should_tag }}
927956 run: |
928957 IMAGE="${{ steps.config.outputs.image }}"
929958 VERSION="${{ steps.ver.outputs.version }}"
930959
931960 echo "Creating manifests for $IMAGE from digests:"
932961 ls -la
933962
934- # Create :edge tag if requested (for auto-publish from post-merge)
935963 if [ "${{ inputs.create_edge_docker_tag }}" = "true" ]; then
964+ # Auto-publish: :edge is the rolling tag and is ALWAYS refreshed.
936965 docker buildx imagetools create \
937966 -t "${IMAGE}:edge" \
938967 $(printf "${IMAGE}@sha256:%s " *)
939968 echo "✅ Pushed manifest: ${IMAGE}:edge"
940- fi
941969
942- # Create versioned tag
943- # When called from auto-publish (create_edge_docker_tag=true), only create
944- # versioned tag for pre-release versions to match original post-merge behavior.
945- # Manual publish always creates versioned tag.
946- if [ "${{ inputs.create_edge_docker_tag }}" = "true" ]; then
947- if [[ "$VERSION " =~ -(edge|rc) ] ]; then
970+ # The versioned :version manifest is part of the immutable release
971+ # and ships only alongside a new git tag. should_tag is false when
972+ # the version is stable (versioned release is manual-only) OR when
973+ # the tag already exists (already released). In both cases this run
974+ # refreshes :edge and nothing else.
975+ if [ "$SHOULD_TAG " = "true" ]; then
948976 docker buildx imagetools create \
949977 -t "${IMAGE}:${VERSION}" \
950978 $(printf "${IMAGE}@sha256:%s " *)
951979 echo "✅ Pushed manifest: ${IMAGE}:${VERSION}"
952980 else
953- echo "ℹ️ Skipping versioned tag for stable version in auto-publish mode "
981+ echo "ℹ️ should_tag=false - :edge refreshed, skipping versioned :${VERSION} manifest "
954982 fi
955983 else
984+ # Manual publish: always push the versioned manifest, plus :latest
985+ # for stable (non edge/rc) releases.
956986 docker buildx imagetools create \
957987 -t "${IMAGE}:${VERSION}" \
958988 $(printf "${IMAGE}@sha256:%s " *)
959989 echo "✅ Pushed manifest: ${IMAGE}:${VERSION}"
960- fi
961990
962- # Create :latest for stable releases (not edge/rc)
963- # Only create :latest in manual publish mode - auto-publish should never update :latest
964- if [ "${{ inputs.create_edge_docker_tag }}" != "true" ] && [[ ! "$VERSION" =~ -(edge|rc) ]]; then
965- echo "Creating 'latest' manifest"
966- docker buildx imagetools create \
967- -t "${IMAGE}:latest" \
968- $(printf "${IMAGE}@sha256:%s " *)
969- echo "✅ Pushed manifest: ${IMAGE}:latest"
991+ if [[ ! "$VERSION" =~ -(edge|rc) ]]; then
992+ echo "Creating 'latest' manifest"
993+ docker buildx imagetools create \
994+ -t "${IMAGE}:latest" \
995+ $(printf "${IMAGE}@sha256:%s " *)
996+ echo "✅ Pushed manifest: ${IMAGE}:latest"
997+ fi
970998 fi
971999
9721000 - name: Inspect manifest
1001+ env:
1002+ SHOULD_TAG: ${{ steps.ver.outputs.should_tag }}
9731003 run: |
9741004 IMAGE="${{ steps.config.outputs.image }}"
9751005 VERSION="${{ steps.ver.outputs.version }}"
9761006
977- # In auto-publish mode with stable version, we only pushed :edge
978- if [ "${{ inputs.create_edge_docker_tag }}" = "true" ] && [[ ! "$VERSION" =~ -(edge|rc) ]]; then
979- echo "Inspecting :edge manifest (versioned tag was skipped for stable version)"
1007+ # Auto-publish pushed :version only when should_tag was true; in
1008+ # every other auto-publish case (:edge-only) inspect :edge instead.
1009+ if [ "${{ inputs.create_edge_docker_tag }}" = "true" ] && [ "$SHOULD_TAG" != "true" ]; then
1010+ echo "Inspecting :edge manifest (versioned manifest was skipped: should_tag=false)"
9801011 docker buildx imagetools inspect "${IMAGE}:edge"
9811012 else
9821013 docker buildx imagetools inspect "${IMAGE}:${VERSION}"
0 commit comments