#!/usr/bin/env python3 """Offline checks for track selection, release identity, dependency metadata and server exclusion.""" import argparse from pathlib import Path import tempfile import unittest import zipfile from changed_targets import affected from publish_mod_sites import release_identity, release_metadata, verify_artifact from server_test_lock import server_test_lock class WorkflowChecks(unittest.TestCase): def test_changes_stay_on_their_track(self): self.assertEqual(affected(["src/main/java/net/dnorberg/rivencraft/Rivencraft.java"]), ["mc1211"]) self.assertEqual(affected(["ports/mc263/src/main/java/Example.java"]), ["mc263"]) self.assertEqual(affected(["src/main/resources/assets/rivencraft/sounds.json"]), ["mc1211", "mc263"]) self.assertEqual(affected(["README.md", "scripts/publish_mod_sites.py"]), []) def test_release_identity_rejects_mislabeled_channels(self): self.assertEqual(release_identity("26.3.0.3", "26.3", "release"), ("V26.3.0.3", "rivencraft-26.3.0.3.jar")) self.assertEqual(release_identity("1.21.1.0.1", "1.21.1", "release"), ("V1.21.1.0.1", "rivencraft-1.21.1.0.1.jar")) for version, channel in [("26.3.0.3-beta.1", "release"), ("26.3.0.3", "beta")]: with self.assertRaises(RuntimeError): release_identity(version, "26.3", channel) def test_required_dependencies_follow_minecraft(self): with tempfile.TemporaryDirectory() as work: notes = Path(work) / "notes.md" notes.write_text("Release notes") args = argparse.Namespace(changelog=notes, name="Rivencraft", version="1.21.1.0.1", minecraft="1.21.1", java="21", channel="release") mr, cf = release_metadata(args) self.assertEqual(len(mr["dependencies"]), 2) self.assertTrue(all(d["dependency_type"] == "required" for d in mr["dependencies"])) self.assertEqual(len(cf["relations"]["projects"]), 2) args.minecraft, args.java, args.version = "26.3", "25", "26.3.0.3" mr, cf = release_metadata(args) self.assertEqual(mr["dependencies"], []) self.assertNotIn("relations", cf) def test_wrong_track_and_fixture_jars_are_rejected(self): with tempfile.TemporaryDirectory() as work: jar = Path(work) / "rivencraft-26.3.0.3.jar" metadata = ( '[[mods]]\nmodId="rivencraft"\nversion="26.3.0.3"\n' '[[dependencies.rivencraft]]\nmodId="minecraft"\nversionRange="[26.3]"\n' ) with zipfile.ZipFile(jar, "w") as archive: archive.writestr("META-INF/neoforge.mods.toml", metadata) verify_artifact(jar, "26.3.0.3", "26.3", "25", "release") with self.assertRaises(RuntimeError): verify_artifact(jar, "26.3.0.3", "26.3", "21", "release") with self.assertRaises(RuntimeError): verify_artifact(jar, "1.21.1.0.1", "1.21.1", "21", "release") with zipfile.ZipFile(jar, "a") as archive: archive.writestr("net/dnorberg/rivencraft/regression/Fixture.class", b"test") with self.assertRaises(RuntimeError): verify_artifact(jar, "26.3.0.3", "26.3", "25", "release") def test_server_lock_refuses_overlap_and_releases(self): with server_test_lock(): with self.assertRaises(SystemExit): with server_test_lock(): self.fail("overlapping server admitted") with server_test_lock(): pass if __name__ == "__main__": unittest.main()