You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ci: publish a GitHub Release on every release (#52)
* ci: publish a GitHub Release on every release
Releases were tag-only: semantic-release runs with --no-vcs-release, so the
repo had zero GitHub Releases. A published Release is what a Marketplace
listing is cut from, and it is also where users look for notes.
Create the Release explicitly after the tag pushes rather than dropping
--no-vcs-release: semantic-release runs --no-push so the commit can be
amended (uv.lock + the action.yml pin) and the tag re-pointed, which means
the tag is not on the remote at the point semantic-release would publish.
Notes come from the CHANGELOG section semantic-release just generated for
the version, falling back to GitHub's generated notes with a ::warning::
rather than failing a release that has already pushed main and tags. The
step authenticates with the release app token, not GITHUB_TOKEN, so the
workflow's contents: read permission stays as documented.
Also refresh the action.yml `version:` pin, which was stale at 0.8.6 — the
in-release bump step only landed after the last release was cut, so @main
consumers were installing 0.8.6.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: code review fixes
Two findings, each confirmed independently by all three reviewers
(gemini-3.1-pro, gpt-5.6-sol, opus).
Write the release notes under RUNNER_TEMP instead of the repo root. The step
wrote release-notes.md into the working tree two steps before `uv build`, and
hatchling has no [tool.hatch.build.targets.sdist] config, so its default file
selection swept the file into the published sdist. Verified by building:
`coder_eval-0.8.9/release-notes.md` was present in the tarball. Adding the
path to .gitignore would not have been a reliable fix -- the sdist already
ships evalboard/node_modules/** despite that path being git-ignored.
Make the step best-effort. main, the version tag, and the moving major tag are
all pushed by the time it runs, so a transient `gh release create` failure
aborted the job, skipped `Build wheel + sdist`, and left publish-pypi unrun --
stranding `@vN` on an action.yml pin whose version never reached PyPI. This
mirrors the existing precedent in the same file: 522dbc7 ("tag only after PyPI
publishes") made the GHCR steps continue-on-error for exactly this reason.
Also narrows the header comment, which claimed a broader fallback than the
`if m else ""` branch actually provided, and defers an sdist-contents
guardrail to .claude/harness-candidates.md.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
* fix: address PR #52 review feedback on the release-publishing step
Reviewer items acted on:
- Move "Publish GitHub Release" after "Build wheel + sdist" and "Upload dist
for PyPI publish". Those are the last steps that can still fail for an
already-tagged version, so a Release no longer announces a version whose
artifacts never built, and a hung `gh` call can no longer eat the 15-minute
job budget before the artifacts are safe.
- Make the swallowed `continue-on-error` failure loud: a new "Flag missing
GitHub Release" step re-raises it as an ::error annotation plus a
run-summary block with the by-hand recovery command, without failing the job
(which would skip the `needs: release` PyPI publish).
- Extract the CHANGELOG notes slicing out of the `run:` heredoc into
.github/scripts/release_notes.py, covered by tests/test_release_notes.py.
Heredoc code is invisible to ruff, pyright, pytest and coverage, and this
regex has three failure modes on a path that runs once per release against
production main with no rehearsal (the prerelease dispatch skips the step).
Tests pin the load-bearing \b (0.8.1 must not slice the v0.8.10 section),
the \Z branch, re.escape, the empty-file fallback contract, and couple the
regex to semantic-release's real rendering of CHANGELOG.md.
- Pin encoding="utf-8" on every read_text/write_text in workflow-embedded
Python (release.yml, publish-testpypi.yml). CHANGELOG.md carries non-ASCII,
so a non-UTF-8 locale raised UnicodeDecodeError inside a
continue-on-error step: no Release, still green.
- Quote the publish-testpypi.yml heredoc delimiter (<<'PY') and read
DEV_VERSION from os.environ instead of expanding it into the Python source.
- Add tests/test_action_version_pin.py: action.yml's `version:` default must
equal pyproject.toml's version, and the `# <-- kept in sync` sed anchor must
be present and unique. Nothing detected the 0.8.6-vs-0.8.9 drift this PR
hand-fixed, which would have had @v0 consumers installing a version other
than the tag they pinned.
- Fix the misleading step comment ("two steps below", "publishes to PyPI") and
update the workflow header, which still omitted the GitHub Release from both
the outputs list and the PRERELEASE exclusion list.
- Record the accepted risk on the Release body: notes render squashed PR
titles, so a first-party surface carries text reviewed as code, not markdown.
Also note that Marketplace listing needs a one-time manual checkbox.
- Widen the Makefile lint scope to .github/scripts/ so extracted release
tooling is actually linted.
Rescoped the deferred sdist note in .claude/harness-candidates.md: it claimed
the sdist "already ships evalboard/node_modules/**" to PyPI. Verified false for
published artifacts — the 0.8.9 and 0.8.2 sdists on PyPI are ~7.5 MB with zero
node_modules entries, because CI never runs pnpm install. It reproduces only in
a developed local worktree (135 MB, 8520 files), since hatchling honors just the
root .gitignore. The live hazard is untracked files a workflow leaves at the
root, which is what the $RUNNER_TEMP note guards. Also recorded CE032/CE033 and
actionlint/zizmor as deferred candidates.
Declined: swapping the app token for GITHUB_TOKEN + job-level contents: write.
actions/checkout already persists the same app token in .git/config for every
step in the job, so scoping it out of this one step's env buys no isolation
while adding a second write credential. Rationale recorded in the step comment.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
echo "::error title=GitHub Release not published::v${VERSION} was tagged and its artifacts built, but 'gh release create' failed. Create the Release by hand so ${MAJOR} and the Marketplace listing resolve."
336
+
{
337
+
echo "### :x: GitHub Release for \`v${VERSION}\` was NOT created"
338
+
echo
339
+
echo "The version tag, the moving \`${MAJOR}\` tag, and the PyPI artifacts are unaffected —"
340
+
echo "only \`gh release create\` failed. Create it by hand:"
0 commit comments