Summary
src/config/release-tag-check/action.yml decides whether a release was published by comparing the latest semver tag against a pre-release snapshot:
git fetch --tags origin
NEW_TAG=$(git tag -l 'v*' --sort=-v:refname | head -1)
if [ "$NEW_TAG" != "$PREVIOUS_TAG" ] && [ -n "$NEW_TAG" ]; then
echo "release_published=true" >> "$GITHUB_OUTPUT"
...
git tag --sort=-v:refname without versionsort.suffix configured orders a prerelease tag above its stable counterpart. So with tags v2.0.0 and v2.0.0-beta.2, head -1 returns v2.0.0-beta.2, not v2.0.0.
Impact
In release.yml, when the post-publish backmerge fails (steps.semantic.outcome == 'failure', e.g. a dirty working tree breaks @saithodev/semantic-release-backmerge's git rebase), release-tag-check runs to recover. Because the snapshot PREVIOUS_TAG was also computed the same way (it was already v2.0.0-beta.2), NEW_TAG == PREVIOUS_TAG ⇒ release_published=false, even though v2.0.0 was published.
That false false then:
- skips the
Backmerge PR fallback step (its if requires release-published == 'true'), and
- runs
Fail if release itself failed, killing the job with the misleading message "Semantic release failed before publishing a new version".
Net result: the stable release is published (GitHub release + tag + PR labels all created), the backmerge silently does not happen, and the job goes red with a message that says the opposite of what occurred.
This action is byte-identical across @v1.21.0 and the current @v1 / @v1.31.0, so bumping the shared-workflows version does not help. It affects any consumer repo using prereleases (e.g. develop → beta, release-candidate → rc).
Reproduce
printf 'v2.0.0\nv2.0.0-beta.2\nv2.0.0-beta.1\nv1.14.1\n' | xargs -n1 -I{} git tag {} 2>/dev/null
git tag -l 'v*' --sort=-v:refname | head -1 # => v2.0.0-beta.2 (expected: v2.0.0)
Real occurrence: LerianStudio/tenant-manager release run #26594352945 (published v2.0.0, job failed).
Proposed fix
Configure git's version-sort suffix so prereleases sort below the stable tag, e.g. in the action step:
git config versionsort.suffix '-' # any tag containing '-' sorts before the bare version
# or, more explicit:
git -c versionsort.suffix=-alpha -c versionsort.suffix=-beta -c versionsort.suffix=-rc \
tag -l 'v*' --sort=-v:refname | head -1
Alternatively, drop git sorting and select the newest tag with a semver-aware comparison (e.g. semver via node, already available in the release job), or compare creation time of the tag created by this run rather than "latest tag overall".
Adjacent note
In the tenant-manager case the trigger for the failed backmerge was a stray tracked package-lock.json dirtying the working tree; that is a consumer-repo bug (fixed there). But release-tag-check should still report the truth when any post-publish step fails — hence this issue.
Summary
src/config/release-tag-check/action.ymldecides whether a release was published by comparing the latest semver tag against a pre-release snapshot:git tag --sort=-v:refnamewithoutversionsort.suffixconfigured orders a prerelease tag above its stable counterpart. So with tagsv2.0.0andv2.0.0-beta.2,head -1returnsv2.0.0-beta.2, notv2.0.0.Impact
In
release.yml, when the post-publish backmerge fails (steps.semantic.outcome == 'failure', e.g. a dirty working tree breaks@saithodev/semantic-release-backmerge'sgit rebase),release-tag-checkruns to recover. Because the snapshotPREVIOUS_TAGwas also computed the same way (it was alreadyv2.0.0-beta.2),NEW_TAG == PREVIOUS_TAG⇒release_published=false, even thoughv2.0.0was published.That false
falsethen:Backmerge PR fallbackstep (itsifrequiresrelease-published == 'true'), andFail if release itself failed, killing the job with the misleading message "Semantic release failed before publishing a new version".Net result: the stable release is published (GitHub release + tag + PR labels all created), the backmerge silently does not happen, and the job goes red with a message that says the opposite of what occurred.
This action is byte-identical across
@v1.21.0and the current@v1/@v1.31.0, so bumping the shared-workflows version does not help. It affects any consumer repo using prereleases (e.g.develop→ beta,release-candidate→ rc).Reproduce
Real occurrence:
LerianStudio/tenant-managerrelease run #26594352945 (published v2.0.0, job failed).Proposed fix
Configure git's version-sort suffix so prereleases sort below the stable tag, e.g. in the action step:
Alternatively, drop git sorting and select the newest tag with a semver-aware comparison (e.g.
semvervia node, already available in the release job), or compare creation time of the tag created by this run rather than "latest tag overall".Adjacent note
In the tenant-manager case the trigger for the failed backmerge was a stray tracked
package-lock.jsondirtying the working tree; that is a consumer-repo bug (fixed there). Butrelease-tag-checkshould still report the truth when any post-publish step fails — hence this issue.