Skip to content

Create the GitHub release even when the publish fails - #38

Merged
wtgee merged 2 commits into
mainfrom
fix/release-independent-of-pypi
Sep 16, 2026
Merged

wtgee merged 2 commits into
mainfrom
fix/release-independent-of-pypi

Conversation

@wtgee

@wtgee wtgee commented Sep 16, 2026

Copy link
Copy Markdown
Member

Two outputs that depend on different things were failing together.

What happened on v0.5.0

The retagged run got further than the last one — the annotated-tag fix from #37 worked:

# Step
3 Restore the annotated tag object ✅
4 Require an annotated tag ✅
7 Build package with Hatch ✅
8 Publish package ❌
9 Create the GitHub release skipped

The build and the tag were both fine. PyPI refused the token exchange:

invalid-publisher: valid token, but no corresponding publisher
  sub:          repo:panoptes/panoptes-data:ref:refs/tags/v0.5.0
  workflow_ref: …/create-release.yml@refs/tags/v0.5.0
  environment:  MISSING

The release step was last and ran only if everything before it had, so a PyPI configuration problem cost the GitHub release too — even though the release is built from the tag and the dists and has nothing to do with PyPI.

The change

  • The release step is keyed on the build step's outcome rather than the job's, so it runs whenever there are dists to attach. If the build fails there is nothing to release, and it correctly stays skipped.
  • Fixing a publish means re-running the job, so the step has to be repeatable. gh release create refuses a tag that already has a release, which would turn every retry into a second failure — it now updates an existing release and clobbers its assets instead.

Both paths and the empty-tag-message refusal were exercised against a stub gh:

=== first run (no release exists) ===
    gh release create v0.5.0 --title v0.5.0 --notes-file notes.md dist/…whl dist/…tar.gz
=== re-run after fixing PyPI (release exists) ===
    gh release edit v0.5.0 --title v0.5.0 --notes-file notes.md
    gh release upload v0.5.0 dist/…whl dist/…tar.gz --clobber
=== empty tag message still refuses ===
    ERROR empty → exit non-zero

What this does not fix

The publish itself. invalid-publisher is configuration on PyPI, not in this repository — worth checking under Manage project → Publishing that the entry still exists, that its workflow filename is create-release.yml, and whether it expects an environment (the claim is MISSING, so an environment requirement there would never match). v0.4.0 published fine on Sept 14 with the same repo and workflow name, and PyPI matches on owner + repo + workflow + environment rather than on the tag, so something changed on that side.

With this merged, re-running the job produces the v0.5.0 release whether or not the publish is fixed first.

The missing v0.4.0 release. Its run had no release step at all — that step arrived later, in #33 — so it built, published, and stopped. Backfilling it is a manual gh release create v0.4.0 from that tag's message; nothing in this workflow will do it retroactively.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AnfKKSA7RyCwvsWhzyZ8zj


Generated by Claude Code

The release step was last and ran only if every step before it had, so the
v0.5.0 run produced no release: the build was fine and the tag was fine, but
PyPI refused the trusted-publisher exchange and the release went with it. The
two outputs depend on different things -- one on the build and the tag, the
other on PyPI's configuration -- so they should fail apart.

It now runs whenever there are dists to attach, keyed on the build step's
outcome rather than the job's.

Fixing a publish means re-running the job, so creating the release has to be
repeatable. `gh release create` refuses a tag that already has a release, which
would have turned every retry into a second failure; the step updates an
existing release and clobbers its assets instead. Both paths, and the empty-tag
-message refusal, were exercised against a stub `gh`.

This does not fix the v0.5.0 publish, which is a trusted-publisher claim PyPI
has no match for -- `sub: repo:panoptes/panoptes-data:ref:refs/tags/v0.5.0`,
`environment: MISSING`. That is configuration on PyPI, not in this repository.
It does mean the release will be created when the job is re-run, whether or not
the publish is fixed first.

Note that v0.4.0 has no GitHub release because the release step did not exist
when it was tagged; its run built and published and stopped there. Backfilling
it is a separate manual step.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnfKKSA7RyCwvsWhzyZ8zj
Thirteen comment lines for three changes, and several of them described the
incident that prompted the change rather than the code: a trusted-publisher
claim that stopped matching is this week's reason, not a property of the
workflow, and it reads as noise once the configuration is fixed.

Seven lines now, each saying something the code cannot: that `actions/checkout`
rewrites the tag ref, that the release is keyed on the build rather than the
job, and that `gh release create` refuses a tag that already has a release.

Same rule CLAUDE.md states for comments, which applies here too.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AnfKKSA7RyCwvsWhzyZ8zj
@wtgee
wtgee merged commit e829754 into main Sep 16, 2026
4 checks passed
@wtgee wtgee mentioned this pull request Sep 16, 2026
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.

2 participants