import os from pathlib import Path import subprocess import unittest import yaml class PruningContract(unittest.TestCase): @classmethod def setUpClass(cls): cls.action = yaml.safe_load((Path(__file__).resolve().parents[1] / "action.yaml").read_text()) cls.steps = cls.action["runs"]["steps"] def test_default_preserves_existing_callers_and_only_prune_is_conditional(self): self.assertEqual(self.action["inputs"]["prune"]["default"], "true") gated = [step for step in self.steps if "if" in step] self.assertEqual(len(gated), 1) self.assertEqual(gated[0]["name"], "Prune old tags") self.assertEqual(gated[0]["if"], "${{ inputs.prune == 'true' }}") remote = [step for step in self.steps if "/packages/" in step.get("run", "")] self.assertEqual(remote, gated) self.assertIn("docker push", next(step for step in self.steps if step["name"] == "Push")["run"]) self.assertNotIn("if", next(step for step in self.steps if step["name"] == "Untag local image")) def test_invalid_policy_stops_before_credential_step(self): validation = self.steps[0] self.assertEqual(validation["name"], "Validate pruning policy") self.assertEqual(validation["env"], {"PRUNE": "${{ inputs.prune }}"}) self.assertNotIn("uses", validation) for value, success in (("true", True), ("false", True), ("False", False), ("", False), ("yes", False), ("false\ntrue", False)): with self.subTest(value=value): result = subprocess.run(["bash", "-c", validation["run"]], env={"PATH": os.defpath, "PRUNE": value}, capture_output=True) self.assertEqual(result.returncode == 0, success) if __name__ == "__main__": unittest.main()