scripts/test_release_compliance.py
Rama main · réplica de lectura del repositorio original.
import json
import sys
import tempfile
import unittest
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent))
import release_compliance as rc
def package(
pid,
name,
version="1.0.0",
*,
license="MIT",
kinds=None,
manifest_path=None,
):
return {
"id": pid,
"name": name,
"version": version,
"license": license,
"license_file": None,
"source": f"registry+https://example/{name}",
"repository": None,
"manifest_path": manifest_path or f"/missing/{name}/Cargo.toml",
"targets": [{"kind": kinds or ["lib"]}],
}
class ReleaseComplianceTests(unittest.TestCase):
def cargo_fixture(self, root: Path):
api_dir = root / "api"
dep_dir = root / "runtime"
dev_dir = root / "dev"
proc_dir = root / "macro"
for directory in (api_dir, dep_dir, dev_dir, proc_dir):
directory.mkdir()
(directory / "Cargo.toml").write_text(
"[package]\nname='x'\nversion='0.1.0'\n", encoding="utf-8"
)
(dep_dir / "LICENSE-MIT").write_text("MIT text\n", encoding="utf-8")
return {
"packages": [
package(
"api",
"firecrab-api",
manifest_path=str(api_dir / "Cargo.toml"),
),
package(
"runtime",
"runtime-dep",
manifest_path=str(dep_dir / "Cargo.toml"),
),
package(
"dev",
"dev-dep",
manifest_path=str(dev_dir / "Cargo.toml"),
),
package(
"macro",
"macro-dep",
kinds=["proc-macro"],
manifest_path=str(proc_dir / "Cargo.toml"),
),
],
"workspace_members": ["api"],
"resolve": {
"nodes": [
{
"id": "api",
"deps": [
{
"pkg": "runtime",
"dep_kinds": [{"kind": None, "target": None}],
},
{
"pkg": "dev",
"dep_kinds": [{"kind": "dev", "target": None}],
},
{
"pkg": "macro",
"dep_kinds": [{"kind": None, "target": None}],
},
],
},
{"id": "runtime", "deps": []},
{"id": "dev", "deps": []},
{"id": "macro", "deps": []},
]
},
}
def test_cargo_sets_separate_runtime_from_dev_and_proc_macro(self):
with tempfile.TemporaryDirectory() as tmp:
runtime, build = rc.cargo_sets(self.cargo_fixture(Path(tmp)))
self.assertEqual(runtime, {"runtime"})
self.assertEqual(build, {"dev", "macro"})
def test_cargo_workspace_runtime_dependencies_are_included(self):
with tempfile.TemporaryDirectory() as tmp:
metadata = self.cargo_fixture(Path(tmp))
metadata["packages"][0]["name"] = "firecrab-api"
runtime, build = rc.cargo_sets(metadata)
self.assertEqual(runtime, {"runtime"})
self.assertEqual(build, {"dev", "macro"})
def test_npm_sets_use_lockfile_dev_flag(self):
lock = {
"packages": {
"": {"name": "app"},
"node_modules/react": {
"version": "19.0.0",
"license": "MIT",
},
"node_modules/vite": {
"version": "8.0.0",
"license": "MIT",
"dev": True,
},
}
}
runtime, build = rc.npm_sets(lock)
self.assertEqual([item["name"] for item in runtime], ["react"])
self.assertEqual([item["name"] for item in build], ["vite"])
def test_license_policy_rejects_gpl_only_but_accepts_dual_and_lgpl(self):
self.assertFalse(rc.license_allowed("GPL-2.0-only"))
self.assertFalse(rc.license_allowed("AGPL-3.0-only"))
self.assertTrue(rc.license_allowed("MIT OR GPL-2.0-only"))
self.assertTrue(rc.license_allowed("LGPL-2.1-only"))
self.assertTrue(rc.license_allowed("Apache-2.0"))
self.assertFalse(rc.license_allowed(None))
def test_license_policy_fails_closed_on_unreviewed_declarations(self):
for expression in (
"Proprietary",
"GPLv2",
"LicenseRef-file:COPYING",
"SEE LICENSE IN LICENSE",
"Unknown-License-1.0",
):
with self.subTest(expression=expression):
self.assertFalse(rc.license_allowed(expression))
self.assertFalse(rc.license_allowed("MIT AND GPL-2.0-only"))
self.assertTrue(rc.license_allowed("MIT AND BSD-3-Clause"))
self.assertTrue(rc.license_allowed("MIT/Apache-2.0"))
self.assertTrue(rc.license_allowed("Apache-2.0/MIT"))
self.assertTrue(
rc.license_allowed("Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT")
)
def test_cargo_records_keep_packaged_license_text(self):
with tempfile.TemporaryDirectory() as tmp:
metadata = self.cargo_fixture(Path(tmp))
runtime, build = rc.cargo_sets(metadata)
runtime_records, _ = rc.cargo_records([metadata], runtime, build)
self.assertEqual(runtime_records[0]["name"], "runtime-dep")
self.assertEqual(runtime_records[0]["notices"][0]["name"], "LICENSE-MIT")
self.assertIn("MIT text", runtime_records[0]["notices"][0]["text"])
def test_render_notices_distinguishes_runtime_and_build_only(self):
runtime = [
{
"ecosystem": "npm",
"name": "react",
"version": "19",
"license": "MIT",
"source": None,
"notices": [],
}
]
build = [
{
"ecosystem": "npm",
"name": "vite",
"version": "8",
"license": "MIT",
"source": None,
"notices": [],
}
]
text = rc.render_notices(runtime, build)
self.assertIn("Runtime dependencies: 1", text)
self.assertIn("Build/test-only dependencies: 1", text)
self.assertIn("npm :: react 19", text)
self.assertIn("Build/test-only inventory", text)
self.assertIn("npm :: vite 8 :: MIT", text)
def test_main_writes_inventory_and_fails_on_incompatible_runtime_license(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
metadata = self.cargo_fixture(root)
for item in metadata["packages"]:
if item["id"] == "runtime":
item["license"] = "GPL-2.0-only"
cargo = root / "cargo.json"
lock = root / "package-lock.json"
frontend = root / "frontend"
frontend.mkdir()
cargo.write_text(json.dumps(metadata), encoding="utf-8")
lock.write_text(
json.dumps({"packages": {"": {"name": "app"}}}),
encoding="utf-8",
)
notices = root / "out" / "THIRD_PARTY_NOTICES.txt"
inventory = root / "out" / "release-license-inventory.json"
code = rc.main(
[
"--cargo-metadata",
str(cargo),
"--frontend-lock",
str(lock),
"--frontend-root",
str(frontend),
"--notices-out",
str(notices),
"--inventory-out",
str(inventory),
"--deny-incompatible",
]
)
self.assertEqual(code, 1)
self.assertTrue(notices.is_file())
data = json.loads(inventory.read_text(encoding="utf-8"))
self.assertEqual(len(data["runtime"]), 1)
def test_multi_target_union_keeps_target_only_runtime_packages(self):
with tempfile.TemporaryDirectory() as tmp:
root = Path(tmp)
def target_metadata(label: str, dep_id: str):
api_dir = root / f"api-{label}"
dep_dir = root / dep_id
api_dir.mkdir()
dep_dir.mkdir()
(api_dir / "Cargo.toml").write_text(
"[package]\nname='firecrab-api'\nversion='0.1.0'\n",
encoding="utf-8",
)
(dep_dir / "Cargo.toml").write_text(
f"[package]\nname='{dep_id}'\nversion='1.0.0'\n",
encoding="utf-8",
)
return {
"packages": [
package(
"api",
"firecrab-api",
manifest_path=str(api_dir / "Cargo.toml"),
),
package(
dep_id,
dep_id,
manifest_path=str(dep_dir / "Cargo.toml"),
),
],
"workspace_members": ["api"],
"resolve": {
"nodes": [
{
"id": "api",
"deps": [
{
"pkg": dep_id,
"dep_kinds": [{"kind": None, "target": None}],
}
],
},
{"id": dep_id, "deps": []},
]
},
}
x86 = target_metadata("x86", "x86-runtime")
arm = target_metadata("arm", "arm-runtime")
runtime, build = rc.merge_cargo_sets([x86, arm])
runtime_records, build_records = rc.cargo_records(
[x86, arm], runtime, build
)
self.assertEqual(runtime, {"x86-runtime", "arm-runtime"})
self.assertEqual(build, set())
self.assertEqual(
{item["name"] for item in runtime_records},
{"x86-runtime", "arm-runtime"},
)
self.assertEqual(build_records, [])
if __name__ == "__main__":
unittest.main()