Skip to content

Fix Publish to PyPI step being silently skipped on tag push#229

Merged
alexlib merged 2 commits into
masterfrom
copilot/fix-pypi-publish-action
Mar 1, 2026
Merged

Fix Publish to PyPI step being silently skipped on tag push#229
alexlib merged 2 commits into
masterfrom
copilot/fix-pypi-publish-action

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 1, 2026

upload_pypi was silently skipped whenever any single build_wheels matrix combination failed, because GitHub Actions propagates a failed needs dependency as a skip to downstream jobs. With 9 matrix combinations (3 OS × 3 Python), a single flaky build or test was enough to block all PyPI releases entirely.

Changes

upload_pypi job condition

  • Added always() so the job evaluates its own condition even when build_wheels has failures
  • Explicitly gates on needs.build_sdist.result == 'success' (sdist required) and needs.build_wheels.result == 'success' || 'failure' (at least attempted, not cancelled/skipped)
# Before
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/')

# After
if: |
  always() &&
  github.event_name == 'push' &&
  startsWith(github.ref, 'refs/tags/') &&
  needs.build_sdist.result == 'success' &&
  (needs.build_wheels.result == 'success' || needs.build_wheels.result == 'failure')

This pairs correctly with the existing skip-existing: true on the publish step — partial wheel sets can be published and completed on re-run.

Permissions

  • Added attestations: write and contents: read required by pypa/gh-action-pypi-publish >= v1.12, which generates Sigstore attestations by default

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…ttestation permissions

Co-authored-by: alexlib <747110+alexlib@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix PyPI publish action skipping issue Fix Publish to PyPI step being silently skipped on tag push Mar 1, 2026
@alexlib alexlib marked this pull request as ready for review March 1, 2026 22:44
Copilot AI review requested due to automatic review settings March 1, 2026 22:44
@alexlib alexlib closed this Mar 1, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a long-standing silent skip of the upload_pypi job on tag pushes. Previously, a single failed matrix combination in build_wheels (out of 9: 3 OS × 3 Python) would cause GitHub Actions to propagate a skipped status to upload_pypi, silently preventing any PyPI release. The fix introduces always() and explicit result checks in the job condition, and adds attestations: write / contents: read permissions required by newer versions of pypa/gh-action-pypi-publish.

Changes:

  • Updated the upload_pypi job if condition to use always() and explicitly check needs.build_sdist.result == 'success' and needs.build_wheels.result being either 'success' or 'failure'
  • Added attestations: write and contents: read permissions to the upload_pypi job

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

github.event_name == 'push' &&
startsWith(github.ref, 'refs/tags/') &&
needs.build_sdist.result == 'success' &&
(needs.build_wheels.result == 'success' || needs.build_wheels.result == 'failure')
Copy link

Copilot AI Mar 1, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The condition needs.build_wheels.result == 'failure' is satisfied both when only one matrix leg fails (the intended partial-failure case) and when every single wheel build fails (all 9 matrix jobs fail). In the total-failure case, upload_pypi will still run and attempt to publish — but only the sdist artifact will exist, with no wheels at all.

While skip-existing: true prevents duplicate uploads, publishing a tag release to PyPI with zero wheels is likely unintentional and could result in an incomplete release reaching users.

Consider adding an explicit guard against a complete wheel build failure, for example by restricting the condition to needs.build_wheels.result == 'success' only, and relying on re-runs with skip-existing: true to handle truly flaky partial failures. Alternatively, if partial-failure publishing is genuinely desired, the PR description and/or a workflow comment should document this tradeoff explicitly.

Suggested change
(needs.build_wheels.result == 'success' || needs.build_wheels.result == 'failure')
needs.build_wheels.result == 'success'

Copilot uses AI. Check for mistakes.
@alexlib alexlib reopened this Mar 1, 2026
@alexlib alexlib merged commit 7e111bd into master Mar 1, 2026
15 of 25 checks passed
@alexlib alexlib deleted the copilot/fix-pypi-publish-action branch March 1, 2026 22:46
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.

3 participants