ci(release): repair orphaned draft tag_name on retag

When the git tag was deleted and re-created between draft creation
and merge, GitHub orphaned the draft release: tag_name became
"untagged-<hash>" while `name` was preserved. The finalize step
looked up the draft by tag_name and threw `Draft release for <tag>
not found`, blocking the release.

Fall back to matching by `name` only when the candidate is the
GitHub-orphaned form (tag_name matches /^untagged-/), repair the
draft's tag_name via updateRelease, then publish. Hard-fail is
preserved when neither lookup matches.

Same failure recurred on the v1.4.1 finalize run; this commit
prevents recurrence but does not auto-recover the stuck v1.4.2
draft.

Assisted-By: Claude <noreply@anthropic.com>
Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
(cherry picked from commit 22187e069d)
This commit is contained in:
Myasnikov Daniil authored and github-actions[bot] committed 2026-06-05 08:54:15 +00:00
1 parent 7e91f1ba3b
commit e437cf2e3d
1 file changed
+24 -3
+24 -3
View File
@@ -159,9 +159,30 @@ jobs:
per_page: 100
});
// Find draft release to publish
const draft = releases.data.find(r => r.tag_name === tag && r.draft);
if (!draft) throw new Error(`Draft release for ${tag} not found`);
// Find draft release to publish.
//
// Normally the draft was created by tags.yaml with tag_name === tag.
// But if the git tag was deleted and re-created between draft creation
// and merge (e.g. the release branch was force-updated), GitHub orphans
// the draft: tag_name becomes "untagged-<hash>" while `name` is kept.
// Fall back to matching by `name` and repair the draft's tag_name
// before publishing — otherwise the published release would not point
// at the real git tag.
let draft = releases.data.find(r => r.draft && r.tag_name === tag);
if (!draft) {
const orphan = releases.data.find(r =>
r.draft && r.name === tag && /^untagged-/.test(r.tag_name)
);
if (!orphan) throw new Error(`Draft release for ${tag} not found`);
console.log(`🔧 Repairing orphaned draft ${orphan.id}: tag_name '${orphan.tag_name}' -> '${tag}'`);
const repaired = await github.rest.repos.updateRelease({
owner: context.repo.owner,
repo: context.repo.repo,
release_id: orphan.id,
tag_name: tag
});
draft = repaired.data;
}
// Find max semver among published releases (excluding current draft)
const publishedReleases = releases.data