diff --git a/scripts/pipeline.py b/scripts/pipeline.py index dfa018ca..dae8c37d 100644 --- a/scripts/pipeline.py +++ b/scripts/pipeline.py @@ -228,9 +228,18 @@ SKIPPED = _Skipped() def _refuse_unapplied_flags(parser: argparse.ArgumentParser, args) -> None: - """--all-variants builds every source itself: a --source beside it is dropped.""" + """A flag the run would drop is refused before any step. + + --all-variants builds every source itself, so a --source beside it is + dropped; --skip-packs builds none, so both are. + """ if args.all_variants and args.source != "full": parser.error("--source is incompatible with --all-variants") + if args.skip_packs: + for flag, on in (("--source", args.source != "full"), + ("--all-variants", args.all_variants)): + if on: + parser.error(f"{flag} is incompatible with --skip-packs") def _truth_steps(args: argparse.Namespace, results: dict) -> bool: diff --git a/tests/test_audit_regressions.py b/tests/test_audit_regressions.py index cc75b8dd..8fceaf89 100644 --- a/tests/test_audit_regressions.py +++ b/tests/test_audit_regressions.py @@ -3332,5 +3332,40 @@ class TheInstallerNamesWhatItSkipped(unittest.TestCase): self.assertIn("and 2 more", many[1]) + +class EveryToolRefusesAFlagItWouldDrop(unittest.TestCase): + """The mode x flag matrix existed for generate_pack only: verify took + --strict in --emulator mode and ignored it, pipeline took --source with + --skip-packs and built nothing. Each pair here must exit non-zero + before doing any work.""" + + REFUSED = { + "scripts/verify.py": [ + ["--list-emulators", "--strict"], + ["--list-emulators", "--verbose"], + ["--list-emulators", "--json"], + ["--list-systems", "--region", "us"], + ["--emulator", "handy", "--target", "switch"], + ["--platform", "retroarch", "--standalone"], + ["--platform", "retroarch", "--include-archived"], + ], + "scripts/pipeline.py": [ + ["--offline", "--skip-packs", "--source", "truth"], + ["--offline", "--skip-packs", "--all-variants"], + ["--offline", "--all-variants", "--source", "platform"], + ], + } + + def test_each_pair_is_refused(self): + for script, cases in self.REFUSED.items(): + for argv in cases: + with self.subTest(script=script, argv=argv): + proc = subprocess.run( + [sys.executable, script, *argv], cwd=ROOT, + capture_output=True, text=True, timeout=120, + ) + self.assertEqual(proc.returncode, 2, proc.stdout + proc.stderr) + + if __name__ == "__main__": unittest.main()