Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,13 @@ updates:
github-actions:
patterns:
- "*"
ignore:
# The action ref is the Rust version to install, not an action release.
# Dependabot otherwise proposes unreleased toolchains such as 1.100.0.
- dependency-name: dtolnay/rust-toolchain
# The v4 ref already follows current v4 security and patch releases.
- dependency-name: github/codeql-action
update-types:
- version-update:semver-minor
- version-update:semver-patch
open-pull-requests-limit: 2
56 changes: 56 additions & 0 deletions tests/test_published_distribution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import unittest

from utils.verify_published_distribution import distribution_files


class PublishedDistributionTests(unittest.TestCase):
def test_registry_attestations_are_not_distribution_archives(self):
payload = {
"urls": [
{
"filename": "vidxp-0.4.0.dev19-py3-none-any.whl",
"digests": {"sha256": "wheel"},
},
{
"filename": (
"vidxp-0.4.0.dev19-py3-none-any.whl.publish.attestation"
),
"digests": {"sha256": "wheel-attestation"},
},
{
"filename": "vidxp-0.4.0.dev19.tar.gz",
"digests": {"sha256": "sdist"},
},
{
"filename": "vidxp-0.4.0.dev19.tar.gz.publish.attestation",
"digests": {"sha256": "sdist-attestation"},
},
]
}

self.assertEqual(
distribution_files(payload),
{
"vidxp-0.4.0.dev19-py3-none-any.whl": "wheel",
"vidxp-0.4.0.dev19.tar.gz": "sdist",
},
)

def test_unknown_registry_files_are_still_compared(self):
payload = {
"urls": [
{
"filename": "unexpected.zip",
"digests": {"sha256": "unexpected"},
}
]
}

self.assertEqual(
distribution_files(payload),
{"unexpected.zip": "unexpected"},
)


if __name__ == "__main__":
unittest.main()
23 changes: 17 additions & 6 deletions tests/test_release_contract.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,18 @@
import unittest
from pathlib import Path

from utils.release_contract import validate
from utils.release_contract import validate, version_sources
from utils.prepare_nightly import prepare


class ReleaseContractTests(unittest.TestCase):
def current_release(self) -> tuple[str, str]:
versions = set(version_sources().values())
self.assertEqual(len(versions), 1)
version = versions.pop()
channel = "beta" if "-b" in version else "stable"
return version, channel

def copy_contract(self, destination: Path) -> None:
root = Path(__file__).resolve().parents[1]
for relative in (
Expand All @@ -22,8 +29,9 @@ def copy_contract(self, destination: Path) -> None:
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes((root / relative).read_bytes())

def test_beta_contract_matches_every_release_source(self):
self.assertEqual(validate("beta", "v0.4.0-b"), "0.4.0-b")
def test_current_contract_matches_every_release_source(self):
version, channel = self.current_release()
self.assertEqual(validate(channel, f"v{version}"), version)

def test_rejects_a_divergent_desktop_version(self):
with tempfile.TemporaryDirectory() as temporary:
Expand All @@ -36,12 +44,15 @@ def test_rejects_a_divergent_desktop_version(self):
validate("beta", None, root)

def test_beta_and_stable_channels_are_not_interchangeable(self):
with self.assertRaisesRegex(ValueError, "stable release version"):
validate("stable", None)
_, channel = self.current_release()
other_channel = "stable" if channel == "beta" else "beta"
with self.assertRaisesRegex(ValueError, f"{other_channel} release version"):
validate(other_channel, None)

def test_tag_must_match_the_combined_version(self):
_, channel = self.current_release()
with self.assertRaisesRegex(ValueError, "does not match"):
validate("beta", "v0.4.0-b.9")
validate(channel, "v999.999.999")

def test_nightly_version_is_unique_without_changing_release_sources(self):
with tempfile.TemporaryDirectory() as temporary:
Expand Down
16 changes: 12 additions & 4 deletions utils/verify_published_distribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
from urllib.request import urlopen


_PUBLISH_ATTESTATION_SUFFIX = ".publish.attestation"


def sha256(path: Path) -> str:
digest = hashlib.sha256()
with path.open("rb") as file:
Expand All @@ -21,6 +24,14 @@ def sha256(path: Path) -> str:
return digest.hexdigest()


def distribution_files(payload: dict[str, object]) -> dict[str, str]:
return {
file["filename"]: file["digests"]["sha256"]
for file in payload.get("urls", [])
if not file["filename"].endswith(_PUBLISH_ATTESTATION_SUFFIX)
}


def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--repository", required=True)
Expand Down Expand Up @@ -50,10 +61,7 @@ def main() -> int:
return 0
raise

remote = {
file["filename"]: file["digests"]["sha256"]
for file in payload.get("urls", [])
}
remote = distribution_files(payload)
if local == remote:
print("identical")
return 0
Expand Down