test_q3_release_desktop_unit.py
python
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
12 hours ago
| 1 | """Unit tests for Q3-release desktop installers (§QR.13).""" |
| 2 | |
| 3 | from __future__ import annotations |
| 4 | |
| 5 | import hashlib |
| 6 | from pathlib import Path |
| 7 | |
| 8 | import pytest |
| 9 | |
| 10 | from tests.fixtures.desktop_release import GIT_SHA_FIXTURE, sample_signed_artifacts |
| 11 | from tools.desktop_release.allowlist import AllowlistError, is_allowed_release_asset, refuse_disallowed_asset |
| 12 | from tools.desktop_release.checksums import sha256_file |
| 13 | from tools.desktop_release.manifest import ManifestError, build_manifest, validate_manifest |
| 14 | from tools.desktop_release.refuse import ( |
| 15 | RefuseError, |
| 16 | refuse_private_key_under_desktop_keys, |
| 17 | scan_text_for_secret_patterns, |
| 18 | ) |
| 19 | from tools.desktop_release.version_align import VersionAlignError, check_version_alignment |
| 20 | from tests.support import KIT_ROOT |
| 21 | |
| 22 | |
| 23 | def test_version_align_accepts_kit_tree() -> None: |
| 24 | version = check_version_alignment(KIT_ROOT) |
| 25 | assert version == (KIT_ROOT / "VERSION").read_text(encoding="utf-8").strip() |
| 26 | |
| 27 | |
| 28 | def test_version_align_refuses_mismatch(tmp_path: Path) -> None: |
| 29 | (tmp_path / "VERSION").write_text("0.1.0\n", encoding="utf-8") |
| 30 | desktop = tmp_path / "desktop" |
| 31 | (desktop / "src-tauri").mkdir(parents=True) |
| 32 | (desktop / "package.json").write_text('{"version":"0.1.0"}\n', encoding="utf-8") |
| 33 | (desktop / "src-tauri" / "Cargo.toml").write_text( |
| 34 | '[package]\nname="x"\nversion="0.1.0"\n', |
| 35 | encoding="utf-8", |
| 36 | ) |
| 37 | (desktop / "src-tauri" / "tauri.conf.json").write_text( |
| 38 | '{"version":"9.9.9"}\n', |
| 39 | encoding="utf-8", |
| 40 | ) |
| 41 | with pytest.raises(VersionAlignError, match="mismatch"): |
| 42 | check_version_alignment(tmp_path) |
| 43 | |
| 44 | |
| 45 | def test_version_align_tag_and_dispatch() -> None: |
| 46 | version = check_version_alignment(KIT_ROOT, tag="v0.1.0", dispatch_version="0.1.0") |
| 47 | assert version == "0.1.0" |
| 48 | with pytest.raises(VersionAlignError): |
| 49 | check_version_alignment(KIT_ROOT, tag="v9.9.9") |
| 50 | |
| 51 | |
| 52 | def test_manifest_accepts_valid_fixture() -> None: |
| 53 | doc = build_manifest( |
| 54 | version="0.1.0", |
| 55 | git_sha=GIT_SHA_FIXTURE, |
| 56 | artifacts=sample_signed_artifacts(), |
| 57 | ) |
| 58 | validate_manifest(doc) |
| 59 | assert doc["schema_version"] == 1 |
| 60 | assert doc["product"] == "Overseer Kit" |
| 61 | |
| 62 | |
| 63 | @pytest.mark.parametrize( |
| 64 | ("field", "bad"), |
| 65 | [ |
| 66 | ("platform", "freebsd"), |
| 67 | ("status", "notarized"), |
| 68 | ("method", "cloudflare"), |
| 69 | ], |
| 70 | ) |
| 71 | def test_manifest_refuses_unknown_enums(field: str, bad: str) -> None: |
| 72 | arts = sample_signed_artifacts() |
| 73 | if field == "platform": |
| 74 | arts[0]["platform"] = bad |
| 75 | elif field == "status": |
| 76 | arts[0]["signing"]["status"] = bad |
| 77 | else: |
| 78 | arts[0]["signing"]["method"] = bad |
| 79 | with pytest.raises(ManifestError): |
| 80 | build_manifest(version="0.1.0", git_sha=GIT_SHA_FIXTURE, artifacts=arts) |
| 81 | |
| 82 | |
| 83 | def test_manifest_refuses_signed_with_method_none() -> None: |
| 84 | arts = sample_signed_artifacts() |
| 85 | arts[0]["signing"] = {"status": "signed", "method": "none"} |
| 86 | with pytest.raises(ManifestError, match="method none"): |
| 87 | build_manifest(version="0.1.0", git_sha=GIT_SHA_FIXTURE, artifacts=arts) |
| 88 | |
| 89 | |
| 90 | def test_secret_scanner_flags_pem_and_passes_clean_workflow() -> None: |
| 91 | dirty = "-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBg\n-----END PRIVATE KEY-----\n" |
| 92 | assert "pem_private_key" in scan_text_for_secret_patterns(dirty) |
| 93 | clean = (KIT_ROOT / ".github" / "workflows" / "desktop-release.yml").read_text(encoding="utf-8") |
| 94 | assert scan_text_for_secret_patterns(clean) == [] |
| 95 | |
| 96 | |
| 97 | def test_checksum_helper_known_vector(tmp_path: Path) -> None: |
| 98 | path = tmp_path / "blob.bin" |
| 99 | data = b"overseer-kit-desktop-release" |
| 100 | path.write_bytes(data) |
| 101 | expected = hashlib.sha256(data).hexdigest() |
| 102 | assert sha256_file(path) == expected |
| 103 | |
| 104 | |
| 105 | def test_public_key_path_rules() -> None: |
| 106 | refuse_private_key_under_desktop_keys(Path("desktop/keys/release.minisign.pub")) |
| 107 | refuse_private_key_under_desktop_keys(Path("desktop/keys/README.md")) |
| 108 | with pytest.raises(RefuseError): |
| 109 | refuse_private_key_under_desktop_keys(Path("desktop/keys/release.private.key")) |
| 110 | with pytest.raises(RefuseError): |
| 111 | refuse_private_key_under_desktop_keys(Path("desktop/keys/secret.pem")) |
| 112 | |
| 113 | |
| 114 | def test_allowlist_accepts_and_rejects() -> None: |
| 115 | assert is_allowed_release_asset("Overseer Kit_0.1.0_aarch64.dmg", version="0.1.0") |
| 116 | assert is_allowed_release_asset("SHA256SUMS.txt") |
| 117 | assert is_allowed_release_asset("overseer-kit-desktop-0.1.0-manifest.json", version="0.1.0") |
| 118 | with pytest.raises(AllowlistError): |
| 119 | refuse_disallowed_asset("Overseer Kit_0.1.0_amd64.deb") |
| 120 | with pytest.raises(AllowlistError): |
| 121 | refuse_disallowed_asset("app-unsigned.AppImage") |
File History
1 commit
sha256:a78e7e5a8740e03315f325d19edeb3aa1b306b3337d04abbaa9a9e0f3bbeb7a1
docs: MuseHub-first before ISR #74 — staging solidify NEXT
Human
12 hours ago