fix(ci): pypi publish skip-existing to unblock idempotent re-runs

Every push to main since v0.21.5 was first published has failed the
publish-pypi job with `400 File already exists`. The workflow's
detect-version step has been computing v0.21.5 repeatedly (the
canonical+commit-height algorithm hasn't bumped past it for the
recent fix-only commits), so each run rebuilds the same wheels with
the same version and twine rejects the duplicates.

Failed runs:
- 25443521479 (PR #406 merge, 15:04 UTC)
- 25452026402 (PR #409 merge, 17:55 UTC)
- 25452038283 (next push, 17:56 UTC)

PyPA's recommended pattern for this scenario is `skip-existing: true`
on the publish action — duplicate uploads become no-ops, fresh
versions still publish normally. Idempotent.

This unblocks main without touching the version-detection algorithm.
A follow-up audit of `headroom/release_version.py` is the right
deeper fix (so a series of `fix:` commits between releases produces
a sequence of patch bumps), but that's a deeper investigation; this
patch just stops the publish job from going red on every push.

Effect after this lands:
- Push to main → wheels rebuilt with whatever version detect-version
  computes
- If that version's wheels are already on PyPI → twine skips them,
  exit 0, downstream jobs (publish-npm, publish-docker, create-release)
  run normally
- If detect-version computes a NEW version not on PyPI → wheels
  publish as before, no behaviour change
This commit is contained in:
chopratejas 2026-05-06 14:04:00 -07:00
parent 1050e00241
commit 6a191b405b

View file

@ -616,6 +616,15 @@ jobs:
- name: Publish ${{ env.PYPI_PACKAGE }} to PyPI
id: pypi-publish
uses: pypa/gh-action-pypi-publish@release/v1
with:
# Idempotent re-runs: when a wheel filename for the computed
# version is already on PyPI (e.g. a previous push to main
# already published this version, or this run's computed
# semver hasn't bumped past the last release), treat the
# existing file as a no-op instead of a hard failure. PyPA's
# recommended pattern for release workflows that may run
# multiple times against the same version.
skip-existing: true
publish-npm:
needs: [detect-version, build]