Repository navigation
Conversation
`gh release view "$TAG"` resolves a tag through the get-release-by-tag endpoint, and that endpoint does not return drafts. So the final step of the release job never looked at the draft it had just created -- it read whatever published release the tag pointed at, diffed five expected asset names against nothing, and failed. Every tag since v0.1.1 died there with the build green and a complete draft sitting beside it. Capture what `gh release create` prints instead: its stdout is the new release's URL, unique to that draft. Trade it once for the numeric release id, and read the assets and publish by id through the documented REST endpoints. The draft's `untagged-<hash>` slug does resolve through `gh release view`, but that fallback is undocumented -- `gh release view [<tag>]` promises a tag -- and this job is built as a bet against unpinned gh behaviour. The asset-set assertion is unchanged. It was reading the wrong release, not asking the wrong question. Refuse a tag that already carries a release in the preflight, where it costs seconds rather than three runners. A draft is not bound to a tag ref, so `gh release create` will not refuse a claimed tag -- it adds a second draft beside the first, which is how v0.1.3 came to name three releases.
chrisuthe
marked this pull request as ready for review
August 24, 2026 16:50
chrisuthe
deleted the
chrisuthe/task/publish-the-draft-the-release-job-created-not-the
branch
August 24, 2026 16:54
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
release.ymlhas not published a release since v0.1.0. Everyv*tag since v0.1.1 failed inthe
releasejob's last step, Assert every asset arrived, then publish, withthe draft v0.1.3 is missing assets and will not be publishedand a diff reading@@ -1,5 +0,0 @@--five expected names against nothing read back.
The build was never the problem. Every leg was green, the pre-create assertion passed on a
complete
dist/, andgh release create --draftuploaded all five files. The failure wasentirely in the read-back:
gh release view "$TAG"resolves a tag through theget-release-by-tag endpoint, and that endpoint does not return drafts. So the step read
whichever published release the tag pointed at -- on v0.1.1 and v0.1.3, an asset-less one --
and never looked at the draft it had just made.
What changed
Publish the release the create step made, by id.
gh release createprints the newrelease's URL on stdout, unique to that draft. That URL is traded once for the numeric
release id, and the read-back and the publish both go through the documented REST endpoints
for a release by id.
The draft's
untagged-<hash>slug does resolve throughgh release view-- I confirmed itagainst the live API -- but the behaviour is undocumented (
gh release view [<tag>]promisesa tag), and this job's whole shape is a bet against unpinned
ghbehaviour. The id route isthe one that keeps the guarantee in this file.
The asset-set assertion is untouched. It was reading the wrong release, not asking the
wrong question.
A tag that already carries a release is now refused in
preflight, where it costsseconds instead of three runners. This is what should have stopped v0.1.3: a draft is not
bound to a tag ref, so
gh release createdoes not refuse a claimed tag -- it adds anotherdraft beside it, which is how one tag came to name three releases.
Both comment blocks in the create/publish steps are rewritten. The
--clobberblockdescribed the old model and was wrong; the still-accurate part of it -- re-run the failed
jobs, because re-running all of them repeats the build and
upload-artifactrefuses anartifact name the run already has -- is kept.
How this was verified
No tag was pushed. Everything below is read-only against the live API:
gh release view v0.1.3(old code)gh api .../releases/375836659(new code)create's URLuntagged-4d8f...->375836659, and each draft's URL resolves to its own distinct idactionlint1.7.12, all four workflowsshellcheck0.11.0, everyrun:block +scripts/*.shThe C++ suite was not run locally --
cmakeis not installed on that machine -- but no C++file is touched here, and CI runs it on this PR.
Needs a hand, deliberately not done here
Four stale releases want deleting, and that is your call rather than this PR's:
The v0.1.3 tag itself is fine and does not need re-cutting. Once the empty release is gone and
this is merged, re-running the failed jobs on run 32750006763 should publish it -- note
that re-running only the failed jobs does not re-run
preflight, so the new guard will notstand in the way of that recovery.
Open in Codrasil:
codrasil://task/tsk_01M0T9QBPBKNVATD8J7FK2FHD0