Add publish-release command to flip draft releases to published - #294
Conversation
The smoke-test and pages-deploy jobs redefined VERSION via
${{ env.VERSION }} in their job-level env: blocks, but the env
context is not available there, failing workflow validation.
The workflow-level env.VERSION is already inherited by all jobs
and steps, so the redundant redefinitions are removed.
https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz
The release job created the release already-published and then uploaded assets, which fails once immutable releases are enforced (post-publish asset uploads are rejected). Every asset now uploads to a draft release first; a new `mdsmith-release publish-release` subcommand flips the fully-populated draft to published as the final atomic step, but only on the tag-push path. The maintainer's UI-created draft path is left as a draft for manual publish. The mise smoke-test is gated to the non-draft path since it resolves the binary off the public GitHub release, which is not downloadable while the release is still a draft. https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #294 +/- ##
==========================================
+ Coverage 96.07% 96.09% +0.01%
==========================================
Files 201 203 +2
Lines 25812 25929 +117
==========================================
+ Hits 24800 24917 +117
Misses 622 622
Partials 390 390
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Pull request overview
Adds a new mdsmith-release publish-release subcommand and updates the release workflow to upload assets to a draft release first and then atomically flip it to published, satisfying GitHub's immutable-releases enforcement. The softprops/action-gh-release step now always creates a draft, and a follow-up step calls the new command on tag pushes (UI-created drafts are left for manual review).
Changes:
- New
internal/release.PublishRelease(with retry/idempotency) plus acmd/mdsmith-release/publishrelease.goCLI wrapper that readsGITHUB_REPOSITORY,RELEASE_TAG,GITHUB_TOKEN,GITHUB_API_URL. release.ymlalways drafts viasoftprops/action-gh-release, adds checkout/Go setup + a newPublish releasestep, and skips themisesmoke-test channel via a YAML anchor when the release stays a draft.- Documentation updates in
release.mdandrelease-tooling.md; comprehensive table-style tests covering happy path, idempotency, retry exhaustion, validation, HTTP errors, default base URL, and JSON parse failures.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
| internal/release/publishrelease.go | Implements PublishRelease (lookup with retries + PATCH draft:false). |
| internal/release/publishrelease_test.go | Unit tests for happy path, idempotency, retries, validation, and error paths. |
| cmd/mdsmith-release/publishrelease.go | New subcommand wiring env vars to PublishRelease. |
| cmd/mdsmith-release/main.go | Registers publish-release in dispatcher and help text. |
| .github/workflows/release.yml | Always-draft upload + new publish step + mise smoke-test skip via YAML anchor. |
| docs/development/release.md | Documents two-phase draft-then-publish flow. |
| docs/development/release-tooling.md | Adds publish-release to the runtime-logic table. |
Add unit tests for runPublishRelease (was 0% covered) and the PATCH transport / response-body read error branches in PublishRelease, bringing patch coverage above the Codecov gate. https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz
Extract newGitHubRequest so the lookup and publish calls share one request builder, drop the impossible json.Marshal error branch, and add an Op label to releaseLookupError so a failed publish PATCH no longer reports as "lookup ... unexpected status" (per review). Adds white-box tests for the request-build error path; added Go lines in the PR are now fully covered. https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz
Summary
Adds a new
mdsmith-release publish-releasecommand that flips GitHub draft releases to published state. This enables the release workflow to upload all assets to a mutable draft release first, then atomically publish it as the final step — required for GitHub's immutable releases enforcement.Changes
New
internal/releasepackage withPublishRelease()function that:draft: falseif neededNew
cmd/mdsmith-release/publishrelease.gosubcommand that:GITHUB_REPOSITORY,RELEASE_TAG,GITHUB_TOKEN, andGITHUB_API_URLfrom environmentPublishRelease()functionUpdated
.github/workflows/release.yml:softprops/action-gh-releaseto always create releases as drafts (draft: true)go run ./cmd/mdsmith-release publish-releaseonly on tag pushes (not UI-created drafts)Comprehensive test coverage (
internal/release/publishrelease_test.go):Documentation updates in
docs/development/release.mdanddocs/development/release-tooling.mdexplaining the two-phase release strategy (draft upload + atomic publish).Implementation Details
https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz