ci(release): create GitHub Release after successful PyPI publish (VER-001)
User description
Why
GA gate criterion VER-001 ("Version and release truth agree from source through
deployment") is a must-pass blocker, currently fail. The measured finding
(governance/ga-gate/evidence/VER-001-release-ledger-2026-09-05.md in
wave-av/claude-workstation) is that no release.yml in any of the four public
release-publishing repos ever creates a GitHub Release — this repo's "latest" Release
is v1.0.0 (2026-04-05) while main/pyproject.toml is already at 2.1.0.
What changed
Adds a release job to .github/workflows/release.yml, after the existing publish
job:
- Gate:
needs: publishwithif: needs.publish.result == 'success'.publish
itself only runsif: startsWith(github.ref, 'refs/tags/v')(never on a
pull_requestdry-run) and already includes its own "Post-publish verification"
step (waits forpip index versions, installs the fresh wheel from PyPI, asserts
wave_sdk.__version__), so this job only ever fires once the artifact is confirmed
live. - Permissions:
contents: writescoped to only this job. Workflow-level
permissions:is unchanged (contents: read). - No untrusted interpolation: the tag name comes in via
env: TAG_NAME: ${{ github.ref_name }}, read as a shell variable; no${{ }}appears inside anyrun:
body in the new job. - Idempotent: a Release that already exists for the tag gets its
dist/artifacts
re-uploaded with--clobberinstead of failing. - Assets: downloads the
distartifact thebuildjob already uploads
(actions/upload-artifact), viaactions/download-artifact@018cc2cf…pinned by full
commit SHA (verified againstgh api repos/actions/download-artifact/git/refs/tags/v6.0.0
—018cc2cf5baa6db3ef3c5f8a56943fffe632ef53), and attaches every file underdist/
to the Release.
Verification performed
python3 -c "import yaml; yaml.safe_load(open('.github/workflows/release.yml'))"—
parses clean, 3 jobs (build, publish, release).actionlint .github/workflows/release.yml— exit 0, no findings.- Confirmed no
${{ }}inside arun:body in the new job (only insideenv:). - Confirmed job-level
permissions:: workflow stayscontents: read;publishkeeps
id-token: write+contents: read; onlyreleaseaddscontents: write. - Verified the
download-artifactSHA pin against the GitHub API directly, rather than
trusting a remembered value — an earlier draft of this pin was wrong.
What this PR does NOT do
This PR does not create any GitHub Release, and there is no back-fill candidate
for this repo today — and the gap here is worse than a missing Release. This repo's
own package (wave-sdk on PyPI) is stuck at 2.0.0
(curl https://pypi.org/pypi/wave-sdk/json → info.version = "2.0.0"), even though
main's pyproject.toml is at 2.1.0 and a v2.1.0 tag already exists. Per the GA
evidence doc, this repo's own release.yml run on v2.1.0 failed with
invalid-publisher — PyPI's registered Trusted Publisher for wave-sdk does not
resolve to this repo. Separately, the different package name wave-av-sdk (currently
3.0.0 on PyPI) carries provenance pointing at wave-av/sdks, not this repo. Neither
v2.1.0 (unpublished here) nor any other tag has an artifact on the registry this repo
actually publishes to, so there is nothing to back-fill: (b) does not apply until the
Trusted Publisher / package-ownership question (item (d) in the evidence doc's remediation
list) is resolved by Jake.
Part of the VER-001 GA burn-down lane (wave-av/claude-workstation
governance/ga-gate/spec/WAVE-GA-burndown-v1.0.0.json).
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
[!NOTE]
Cursor Bugbot is generating a summary for commit 5c8efc071082aa89139374c88ecfc2049a281d8b. Configure here.
Summary by Sourcery
Create a verified, artifact-backed GitHub Release after each successful PyPI publication.
New Features:
- Create or update a GitHub Release for each successfully published and verified version tag, attaching the built distribution artifacts.
Enhancements:
- Make GitHub Release creation idempotent and verify that all distribution artifacts are attached.
- Restrict release-job repository write permissions to the job that creates the release.
CI:
- Extend the release workflow with a post-publish GitHub Release job using a pinned artifact-download action.
Tests:
- Validate the updated workflow syntax and action linting.
CodeAnt-AI Description
Create verified GitHub Releases after successful package publishing
What Changed
- A GitHub Release is created automatically after the package is successfully published to PyPI and verified as installable
- Release pages include the built distribution files and generated release notes
- Existing releases are updated by re-uploading their distribution files instead of failing
- The workflow verifies that every built file is attached before reporting success
Impact
✅ GitHub Releases stay aligned with verified PyPI packages
✅ Downloadable distribution files on every release
✅ Safe retries for interrupted or repeated releases
💡 Usage Guide
Checking Your Pull Request
Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.
Talking to CodeAnt AI
Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:
@codeant-ai ask: Your question here
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
@codeant-ai ask: Can you suggest a safer alternative to storing this secret?
Preserve Org Learnings with CodeAnt
You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:
@codeant-ai: Your feedback here
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
@codeant-ai: Do not flag unused imports.
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
@codeant-ai: review
Check Your Repository Health
To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.