ci(packaging): validate sdist+wheel metadata with twine on every PR#1355
Conversation
The 2026.5.5.1 release upload to PyPI failed with ``400 License-File LICENSE does not exist in distribution file mergify_cli-2026.5.5.1.tar.gz at mergify_cli-2026.5.5.1/LICENSE``. Maturin auto-derives a ``License-File: LICENSE`` PEP 639 metadata field from ``license = "Apache-2.0"`` plus the project root ``LICENSE`` file, but the sdist tarball (``maturin sdist``) packs the cargo workspace and the Python source dir without picking up the project root ``LICENSE`` itself. PyPI's upload validator cross-checks the metadata against the tarball contents and 400s when they disagree. Listing ``LICENSE`` in ``[tool.maturin].include`` puts it back in both the wheel and the sdist, so the metadata claim is honored and PyPI accepts the upload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Change-Id: Ie45717750af52467929600966592cb8453d3b4d2
Without this, packaging-metadata bugs only surface at ``release: published`` time — release 2026.5.5.1 was rejected by PyPI's upload validator with ``400 License-File LICENSE does not exist in distribution file`` because the LICENSE auto-bundling hadn't been wired up. PR CI couldn't have caught it: ``build-sdist`` was gated on ``inputs.stamp-version``, so PR runs skipped the sdist entirely, and there was no twine invocation anywhere. Two changes: 1. ``build-sdist`` now runs on every PR. The version-stamping step and the artifact upload still gate on ``inputs.stamp-version`` (PR builds keep the placeholder version and skip the upload — the artifact is only useful for the publish job in ``release.yml``). The Python toolchain is provisioned the same way as the wheel jobs. 2. ``twine check --strict`` runs against both the wheel (per matrix target) and the sdist immediately after each is built. Strict mode applies the same metadata rules PyPI's upload validator does — README rendering, ``Description-Content-Type``, ``License-File`` presence — so a mismatch fails PR CI instead of the next release. The cost is one extra ubuntu-24.04 job (~30s for sdist + twine check) and a few seconds per wheel-matrix shard for the twine install + check. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Change-Id: I0f7338df02bbf600804a58bcb996bcb882de6010
|
This pull request is part of a Mergify stack:
|
Merge ProtectionsYour pull request matches the following merge protections and will not be merged until they are valid. 🟢 ⛓️ Depends-On RequirementsWonderful, this rule succeeded.Requirement based on the presence of
🟢 🤖 Continuous IntegrationWonderful, this rule succeeded.
🟢 👀 Review RequirementsWonderful, this rule succeeded.
🟢 Enforce conventional commitWonderful, this rule succeeded.Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/
🟢 🔎 ReviewsWonderful, this rule succeeded.
🟢 📕 PR descriptionWonderful, this rule succeeded.
|
There was a problem hiding this comment.
Pull request overview
Adds packaging validation to PR CI so metadata problems are caught before release publishing, aligning the reusable wheel/sdist workflow with the packaging fix from #1354.
Changes:
- Add
LICENSEto the maturin package include list so built artifacts match the emittedLicense-Filemetadata. - Run the reusable
build-sdistjob on every PR instead of only on release builds. - Run
twine check --strictafter building each wheel and the sdist to validate publish-time metadata rules in CI.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
pyproject.toml |
Includes LICENSE in maturin-built distributions to keep packaged contents aligned with metadata. |
.github/workflows/build-wheels.yml |
Expands reusable packaging CI to always build the sdist on PRs and validates both wheel and sdist metadata with Twine. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Merge Queue Status
This pull request spent 12 minutes 22 seconds in the queue, including 11 minutes 56 seconds running CI. Required conditions to merge
|
Without this, packaging-metadata bugs only surface at
release: publishedtime — release 2026.5.5.1 was rejected byPyPI's upload validator with
400 License-File LICENSE does not exist in distribution filebecause the LICENSE auto-bundlinghadn't been wired up. PR CI couldn't have caught it:
build-sdistwas gated on
inputs.stamp-version, so PR runs skipped the sdistentirely, and there was no twine invocation anywhere.
Two changes:
build-sdistnow runs on every PR. The version-stamping stepand the artifact upload still gate on
inputs.stamp-version(PR builds keep the placeholder version and skip the upload —
the artifact is only useful for the publish job in
release.yml). The Python toolchain is provisioned the sameway as the wheel jobs.
twine check --strictruns against both the wheel (permatrix target) and the sdist immediately after each is built.
Strict mode applies the same metadata rules PyPI's upload
validator does — README rendering,
Description-Content-Type,License-Filepresence — so amismatch fails PR CI instead of the next release.
The cost is one extra ubuntu-24.04 job (~30s for sdist + twine
check) and a few seconds per wheel-matrix shard for the twine
install + check.
Co-Authored-By: Claude Opus 4.7 (1M context) noreply@anthropic.com
Depends-On: #1354