diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 43d182c6..f02adcee 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -56,6 +56,14 @@ jobs: publish: needs: build + # Publishing happens on merge to main (stable.yml), so this path stays + # off: the tags stable.yml pushes would otherwise start a second upload + # of a version PyPI already has. The build job above still runs on every + # v* tag — it verifies the tag matches pyproject, smoke-tests the wheel + # and attests provenance. To go back to tag-driven releases, register a + # PyPI trusted publisher for release.yml, drop this condition, and put + # stable.yml's publish job back behind `if: ${{ false }}`. + if: ${{ false }} runs-on: ubuntu-latest environment: name: pypi diff --git a/.github/workflows/stable.yml b/.github/workflows/stable.yml index 06e6e1e1..02b068cd 100644 --- a/.github/workflows/stable.yml +++ b/.github/workflows/stable.yml @@ -118,8 +118,12 @@ jobs: publish: needs: test - # Publishing moved to release.yml: immutable v* tags + Trusted Publishing. - if: ${{ false }} + # Releases ride on merges to main: this job bumps the patch version, + # uploads to PyPI with the PYPI_API_TOKEN secret, then pushes the bump + # commit (marked [skip ci]) and its v* tag. The guard is what keeps it + # off pull requests and the nightly schedule, which the same workflow + # also triggers on — without it every PR would cut a release. + if: github.event_name == 'push' && github.ref == 'refs/heads/main' runs-on: ubuntu-latest permissions: contents: write