Skip to content

Add publish-release command to flip draft releases to published - #294

Merged
jeduden merged 4 commits into
mainfrom
claude/fix-workflow-env-vars-g582P
May 15, 2026
Merged

Add publish-release command to flip draft releases to published#294
jeduden merged 4 commits into
mainfrom
claude/fix-workflow-env-vars-g582P

Conversation

@jeduden

@jeduden jeduden commented May 15, 2026

Copy link
Copy Markdown
Owner

Summary

Adds a new mdsmith-release publish-release command 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/release package with PublishRelease() function that:

    • Looks up a release by tag with configurable retry logic (handles GitHub's eventual consistency)
    • Checks if the release is already published (idempotent)
    • Patches the release to set draft: false if needed
    • Uses proper GitHub API headers (Bearer token auth, API version pinning)
  • New cmd/mdsmith-release/publishrelease.go subcommand that:

    • Reads GITHUB_REPOSITORY, RELEASE_TAG, GITHUB_TOKEN, and GITHUB_API_URL from environment
    • Delegates to the PublishRelease() function
    • Integrates with existing mdsmith-release CLI structure
  • Updated .github/workflows/release.yml:

    • Changed softprops/action-gh-release to always create releases as drafts (draft: true)
    • Added checkout and Go setup steps to the publish job
    • Added new "Publish release" step that runs go run ./cmd/mdsmith-release publish-release only on tag pushes (not UI-created drafts)
    • Updated smoke-test to skip mise channel on UI-draft path (assets not publicly downloadable until published)
  • Comprehensive test coverage (internal/release/publishrelease_test.go):

    • Happy path: draft → published with retries
    • Already-published releases are no-op
    • Retry exhaustion errors appropriately
    • Validation of required options
    • HTTP error handling (unexpected status codes, JSON parse errors, transport errors)
    • Default API base URL behavior
    • Custom HTTP client support
  • Documentation updates in docs/development/release.md and docs/development/release-tooling.md explaining the two-phase release strategy (draft upload + atomic publish).

Implementation Details

  • Retry logic with configurable attempts and delay handles GitHub's eventual consistency when looking up newly-created releases
  • Idempotent design: already-published releases are left untouched
  • Proper HTTP client lifecycle management with request/response cleanup
  • GitHub API v2022-11-28 with Bearer token authentication
  • Separates draft creation (always happens) from publishing (conditional on tag push vs. UI draft)

https://claude.ai/code/session_014crGVw5Bwiv3nv4EoBimbz

claude added 2 commits May 15, 2026 17:30
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
Copilot AI review requested due to automatic review settings May 15, 2026 18:09
@codecov

codecov Bot commented May 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 96.09%. Comparing base (41e61a5) to head (df0e8be).

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              
Flag Coverage Δ
go 96.05% <100.00%> (+0.01%) ⬆️
typescript 99.35% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 a cmd/mdsmith-release/publishrelease.go CLI wrapper that reads GITHUB_REPOSITORY, RELEASE_TAG, GITHUB_TOKEN, GITHUB_API_URL.
  • release.yml always drafts via softprops/action-gh-release, adds checkout/Go setup + a new Publish release step, and skips the mise smoke-test channel via a YAML anchor when the release stays a draft.
  • Documentation updates in release.md and release-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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.

Comment thread internal/release/publishrelease.go
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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 9 out of 9 changed files in this pull request and generated no new comments.

@jeduden
jeduden merged commit d5d4174 into main May 15, 2026
22 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.

3 participants