diff --git a/main.py b/main.py index 77a2c0a..ad7f76e 100755 --- a/main.py +++ b/main.py @@ -511,7 +511,7 @@ def _relay_cli_notices(text: str) -> None: def run_check_json( - args: list[str], input_text: str | None = None + args: list[str], input_text: str | None = None, cwd: str | None = None ) -> tuple[int, dict[str, Any] | None, str]: """Run ``commit-check --format json`` and return (exit code, parsed JSON, raw output). @@ -526,6 +526,12 @@ def run_check_json( The parsed JSON is ``None`` when the CLI did not produce valid JSON; the raw output is kept so callers can fall back to showing it as text, and in that case it carries both streams so nothing the CLI said is lost. + + ``cwd`` picks the directory the CLI runs from -- left at ``None`` (the + caller's own cwd) for the real action, where that directory is the + checked-out repository on purpose. A caller that wants no config file, + no ``ignore_authors``, and no ``git`` state to leak in (the unmocked + binary test, notably) passes an isolated directory instead. """ command = ["commit-check", "--format", "json"] + args result = subprocess.run( @@ -536,6 +542,7 @@ def run_check_json( text=True, encoding="utf-8", check=False, + cwd=cwd, ) out = result.stdout or "" err = result.stderr or "" diff --git a/main_test.py b/main_test.py index 8b0be1f..9b2cd6f 100644 --- a/main_test.py +++ b/main_test.py @@ -2800,10 +2800,29 @@ class TestRealCommitCheckBinary(unittest.TestCase): for every value. This is the one place that drift can fail a build. CI installs requirements.txt, so the binary is always present there; the skip only spares a contributor running the suite without it. + + Run from an isolated, empty directory rather than the checked-out repo: + this repo's own ``commit-check.toml`` inherits the org's shared config + over the network, and a message piped in here is deliberately unrelated + to any real commit, so neither that config nor ``git``'s notion of the + current author (nor, through it, ``ignore_authors``) belongs in a test + about the CLI's JSON contract. A previous version of this test ran from + the repo as checked out, so it inherited both -- and, having no git + identity of its own, additionally fell back to HEAD's actual author to + weigh against ``ignore_authors``. On a Dependabot PR that author is + ``dependabot[bot]``, which the org config ignores, so the message check + silently skipped instead of running, regardless of the message. """ + def setUp(self): + tmpdir = tempfile.TemporaryDirectory() + self.addCleanup(tmpdir.cleanup) + self._cwd = tmpdir.name + def _run(self, message: str) -> tuple[int, dict]: - rc, data, raw = main.run_check_json(["--message"], input_text=message) + rc, data, raw = main.run_check_json( + ["--message"], input_text=message, cwd=self._cwd + ) self.assertIsInstance(data, dict, f"CLI did not emit JSON:\n{raw}") assert data is not None # for the type checker; asserted above self.assertIn("checks", data)