From 5664e09eeaed6a4e40b19cdfde453df6a0d2ddbe Mon Sep 17 00:00:00 2001 From: meh Date: Wed, 29 Jul 2026 17:50:22 +0700 Subject: [PATCH] Make the release tag reachable when it is missing The 0.2.1 publish succeeded and the tag step died with "unable to auto-detect email address": an annotated tag records a tagger and a bare runner has no git identity. Fixed by configuring the identity GitHub uses for its own bot. The larger problem is that the failure was unrepairable. Tagging was gated on `needed == 'true'`, and `needed` comes from asking the registry whether the version is already published. After a successful publish the answer is yes, so re-running skipped every remaining step including the tag. The one recovery path the workflow offers could not fix the one step that had failed. So tagging no longer depends on this run having published. It runs whenever the tag is absent and exits quietly when it is present, which makes a re-run repair a missing tag instead of confirming there is nothing to do. It stays ordered after the publish, so a tag never points at a version that failed to go out. --- .github/workflows/publish.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index f519bba..783a94d 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -107,11 +107,26 @@ jobs: env: CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }} - # After publishing, so a tag never points at a version that failed to go - # out. The tag is what maps a registry version back to a commit. + # Deliberately *not* gated on a publish having happened in this run. It + # was, and that made the failure below unrepairable: the publish + # succeeded, the tag step died, and re-running found the version already + # on crates.io and skipped every remaining step including this one. The + # tag is what maps a registry version back to a commit, so it has to be + # reachable whenever it is missing, not only on the run that published. + # + # Still ordered after the publish, so a tag never points at a version + # that failed to go out. - name: Tag the release - if: steps.check.outputs.needed == 'true' run: | tag="v${{ steps.version.outputs.version }}" + if git ls-remote --exit-code --tags origin "refs/tags/$tag" >/dev/null 2>&1; then + echo "::notice::$tag already exists; nothing to do" + exit 0 + fi + # An annotated tag records a tagger, and a bare runner has no git + # identity: without this the step dies with "unable to auto-detect + # email address". This is the identity GitHub uses for its own bot. + git config user.name 'github-actions[bot]' + git config user.email '41898282+github-actions[bot]@users.noreply.github.com' git tag -a "$tag" -m "$tag" git push origin "$tag"