diff --git a/scripts/verify_pypi_release.py b/scripts/verify_pypi_release.py index 2785bbd..15cca9d 100644 --- a/scripts/verify_pypi_release.py +++ b/scripts/verify_pypi_release.py @@ -22,6 +22,7 @@ MAX_METADATA_BYTES = 4 * 1024 * 1024 MAX_ARTIFACT_BYTES = 256 * 1024 * 1024 BUILD_TOOL_IGNORE_FILE = ".gitignore" +PUBLISH_ATTESTATION_SUFFIX = ".publish.attestation" class ReleaseVerificationError(RuntimeError): @@ -90,6 +91,12 @@ def _local_artifacts(directory: Path) -> dict[str, Artifact]: # distribution and PyPI never sees it. Anything else hidden in # dist/ is still refused below. continue + if path.name.endswith(PUBLISH_ATTESTATION_SUFFIX): + # pypa/gh-action-pypi-publish writes `.publish.attestation` + # beside each file it uploads. The post-publication verification + # step runs after that, so the sidecar is expected there; it is + # not a distribution and PyPI serves it separately, if at all. + continue if path.name.endswith(".whl"): package_type = "bdist_wheel" elif path.name.endswith(".tar.gz"): diff --git a/tests/test_verify_pypi_release.py b/tests/test_verify_pypi_release.py index 74db270..307c67c 100644 --- a/tests/test_verify_pypi_release.py +++ b/tests/test_verify_pypi_release.py @@ -262,3 +262,14 @@ def test_any_other_hidden_file_in_dist_is_still_refused(tmp_path: Path) -> None: (directory / ".gitignore").write_bytes(b"*.whl\n") with pytest.raises(ReleaseVerificationError, match="unexpected local distribution"): verify_pypi_release(directory, VERSION, fetch=_fetch(bodies)) + + +def test_publish_attestation_sidecars_are_not_distributions(tmp_path: Path) -> None: + # pypa/gh-action-pypi-publish writes .publish.attestation beside + # each uploaded file before the post-publication verification runs. + directory, _, bodies = _fixture(tmp_path) + for name in list(bodies): + filename = name.rsplit("/", 1)[-1] + if filename.endswith((".whl", ".tar.gz")): + (directory / f"{filename}.publish.attestation").write_bytes(b"{}") + verify_pypi_release(directory, VERSION, fetch=_fetch(bodies))