Skip to content

fix(release): create the draft release in one step - #130

Merged
TranBaDat2607 merged 1 commit into
mainfrom
fix/release-single-writer
Oct 19, 2026
Merged

TranBaDat2607 merged 1 commit into
mainfrom
fix/release-single-writer

Conversation

@TranBaDat2607

Copy link
Copy Markdown
Owner

The bug

The v1.3.1 draft came out of release.yml with both installers attached but an empty description. The workflow had three writers, all softprops/action-gh-release with draft: true: each build job attached its own file, and release-notes wrote the body. The action finds a draft by looking it up by tag, and GitHub's get-release-by-tag endpoint doesn't return drafts. On v1.3.1 the description job's lookup missed. From its log:

👩‍🏭 Creating new GitHub release for tag v1.3.1...
↪️ Using release 417469754 for tag v1.3.1 instead of duplicate draft 417475586
🧹 Removing duplicate draft release 417475586 for tag v1.3.1...

It wrote the description to a new draft, then deleted that draft as "the duplicate" and kept the older one, which had the installers but no text. (v1.3.1's notes were added by hand afterwards.)

Fix

One writer.

  • windows-installer and linux-bundles no longer touch the release. They already upload their installers as workflow artifacts, so their attach steps are gone and their permissions drop to contents: read.
  • release (renamed from release-notes, still tag-only and run after both builds) downloads both artifacts and runs a single gh release create "$TAG" installers/* --draft --verify-tag --title "$TAG" --notes-file … --generate-notes. Files, description and GitHub's generated PR summary all land in one call.
  • Re-runs refuse instead of duplicating. GitHub allows any number of drafts per tag, so the job first lists releases (drafts included) for the tag. If one exists, it fails with that release's URL: delete the stale draft and re-run.
  • --verify-tag stops it inventing a tag.
  • The description text is unchanged. The new step's heredoc produces output byte-identical to the old body: (2,800 bytes, checked by running the step locally).
  • docs/architecture/packaging.md describes the new shape and why.

Verified

  • The workflow parses. Job and step layout and permissions checked with PyYAML.
  • The "Write the description" step, run locally, produces exactly the old body.
  • The create script passes bash -n.
  • The guard's query, run against this repo: finds v1.3.1, finds nothing for an unused tag.
  • gh release create docs confirm --notes-file text goes above the --generate-notes summary, as softprops did before.

Not verified

  • The tag-triggered run itself. The release job only runs on a v* tag push, and there's no way to dry-run that without creating a tag and a draft. The next real release (v1.3.2 or later) is the first live run.
  • If the job fails there, both installers are still in that run's workflow artifacts. Fix and re-run the release job alone; there's no need to rebuild.

🤖 Generated with Claude Code

Three jobs wrote the release through softprops/action-gh-release, which
finds its draft by tag. On v1.3.1 the description job's lookup missed:
it created a second draft holding the description, then removed "the
duplicate" (the new one), leaving the release with both installers and
an empty body.

The build jobs now only upload workflow artifacts (and drop to
contents: read). A single `release` job downloads both and runs one
`gh release create --draft --verify-tag` with the files, the
description and GitHub's generated notes. It refuses to run if a
release for the tag already exists, since GitHub allows any number of
drafts per tag and a re-run would otherwise leave two.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@TranBaDat2607
TranBaDat2607 merged commit 6587426 into main Oct 19, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant