diff --git a/quest/m0/ci/README.md b/quest/m0/ci/README.md index 5ae13f591b6..41b4fcba540 100644 --- a/quest/m0/ci/README.md +++ b/quest/m0/ci/README.md @@ -165,6 +165,5 @@ The historical samples locate candidates; they are not controlled benchmarks. - [Release credentials off main](/quest/m0/ci/publish-release-only.md) - `publish` admits only `release` and release tags once its `workflow_run` publishers run on their tag - [The queue host keeps the queue's disk](/quest/m0/ci/queue-host-disk.md) - agent sessions can't starve the queue runner of disk, and a crashed runner restarts - [Biome checks every file it can parse](/quest/m0/ci/biome-whole-repo.md) - Biome runs over the whole repository and main is clean under it -- [Dispatcher tool changes run the dispatcher tests](/quest/m0/ci/dispatch-selection-gaps.md) - a tool-list change runs `sh/dispatch-query.test.py` in CI, and `sh/rs/uring.test.py` stops printing jq errors - [dispatch.sh's tests pass without KVM](/quest/m0/ci/dispatch-test-kvm.md) - `sh/dispatch-query.test.py` fakes the KVM probe instead of failing 20 tests on hosts without `/dev/kvm` - [mbx launches Cargo with any argument length](/quest/m0/ci/mbx-arg-max.md) - no "Argument list too long" in `sh/rs/select.test.py`'s recipe test diff --git a/quest/m0/ci/dispatch-selection-gaps.md b/quest/m0/ci/dispatch-selection-gaps.md deleted file mode 100644 index 430879cc10c..00000000000 --- a/quest/m0/ci/dispatch-selection-gaps.md +++ /dev/null @@ -1,36 +0,0 @@ -# [S] Dispatcher tool changes run the dispatcher tests - -## Goal - -A change to the dispatcher's tool lists (`sh/dispatch.sh` and the files it -reads them from) runs `sh/dispatch-query.test.py` in CI, so a tool added to a -module can't break that suite on `main` unnoticed. `sh/rs/uring.test.py` -runs without the repeated `jq: error ... null (null) cannot be matched` -lines. - -## Plan - -Decided 2026-10-31 (maintainer, the /quest-complete requeue session), from -[moq-dev/moq#7432](https://github.com/moq-dev/moq/pull/7432). - -- **Selection.** [6633d2f2e2](https://github.com/moq-dev/moq/commit/6633d2f2e2) - added `zizmor` to the `gh` module's tools in `sh/dispatch.sh`, and every - `CI_STRICT` case of `sh/dispatch-query.test.py` then failed with "these - tools are missing: zizmor" on `main`; #7432 fixes the stub. `run_lane` in - `sh/dispatch.sh` says gh's tests run on every `check` diff, and a change to - `sh/dispatch.sh` selects everything, so find why the commit's CI didn't run - or didn't fail on the suite (`.github/justfile` `test`, the CI lane that - runs it, the land gate) and fix that gap rather than adding a path rule. -- **jq noise.** `python3 sh/rs/uring.test.py` passes but prints - `jq: error (at :36): null (null) cannot be matched, as it is not a - string` four times. Its cargo-metadata fixture has no `workspace_root` or - `targets`, which the seed filter in `sh/rs/select.sh` (around line 66) - reads. Make the fixture complete, or make the filter tolerate their - absence, whichever matches real `cargo metadata` output. - -Public API: none. Wire: none. - -## Related - -- [workspace.test.py ignores the caller's gate filter](https://github.com/moq-dev/moq/pull/7432) - #7432's quest, the same dispatcher test environment -- [moq-dev/moq#7440](https://github.com/moq-dev/moq/pull/7440) - plans `quest/m0/ci/check-selection.md`, which makes a jq error in Rust selection fail the run; that turns this jq noise into a failure, so land the fixture fix first or together. It does not cover the tool-list selection gap diff --git a/sh/dispatch-query.test.py b/sh/dispatch-query.test.py index da809764f2c..5fbfbb1a193 100644 --- a/sh/dispatch-query.test.py +++ b/sh/dispatch-query.test.py @@ -10,6 +10,7 @@ import time import unittest from pathlib import Path +from unittest.mock import patch from test_env import dispatch_env @@ -27,13 +28,14 @@ def setUp(self): shutil.copy(ROOT / "sh" / script, self.repo / "sh" / script) self.bin = self.root / "bin" self.bin.mkdir() - for command in ("bash", "git", "sort", "mktemp", "rm", "grep"): + for command in ("bash", "git", "sort", "mktemp", "rm", "grep", "cat", "sed", "tr", "xargs", "sleep"): (self.bin / command).symlink_to(shutil.which(command)) self.env = dispatch_env( LOCAL_SUPERVISED="1", PATH=str(self.bin), GIT_CONFIG_NOSYSTEM="1", GIT_CONFIG_GLOBAL=os.devnull, + BASH_ENV=os.devnull, CI_STRICT="1", ) self.git("init", "-q", "-b", "main") @@ -224,6 +226,7 @@ def stub_ci(self, just=""): "quest", "nix", "c++", + "cc", "clang-format", "cmake", "dart", @@ -257,7 +260,6 @@ def stub_ci(self, just=""): nix.chmod(0o755) self.env.update(IN_MOQ_DEV_SHELL="1", CALLS=str(self.root / "calls")) (self.root / "calls").unlink(missing_ok=True) - self.env["PATH"] = f"{self.bin}:{os.environ['PATH']}" for script in ("markdown.sh", "shell.sh", "large-files.sh"): path = self.repo / "sh" / script path.write_text("#!/bin/sh\nexit 0\n") @@ -271,6 +273,25 @@ def run_ci(self, base="origin/main"): self.assertEqual(result.returncode, 0, result.stderr) return (self.root / "calls").read_text().splitlines() + def test_ci_requires_its_tool_stubs_even_when_the_host_has_them(self): + host = self.root / "host" + host.mkdir() + tool = host / "zizmor" + tool.write_text("#!/bin/sh\nexit 0\n") + tool.chmod(0o755) + with patch.dict(os.environ, PATH=str(host)): + self.stub_ci() + (self.bin / "zizmor").unlink() + result = subprocess.run( + ["bash", "sh/dispatch.sh", "ci", "origin/main"], + cwd=self.repo, + env=self.env, + text=True, + capture_output=True, + ) + self.assertEqual(result.returncode, 1, result.stdout + result.stderr) + self.assertIn("these tools are missing: zizmor", result.stderr) + def test_failure_keeps_running_lanes_and_starts_remaining_modules(self): # The failed lane finishes before go releases the two parked lanes. # No timing assumption can make cancellation look like completion. diff --git a/sh/rs/uring.test.py b/sh/rs/uring.test.py index fe8c4347962..d645d015a27 100644 --- a/sh/rs/uring.test.py +++ b/sh/rs/uring.test.py @@ -19,11 +19,13 @@ def test_selection_follows_shared_dependencies(self): just.write_text('#!/bin/sh\nprintf "%s\\n" "$*" >> "$SELECT_CALLS"\n') just.chmod(0o755) metadata = { + "workspace_root": "/", "packages": [ { "name": name, "id": f"path+file:///rs/{name}#1.0.0", "manifest_path": f"/rs/{name}/Cargo.toml", + "targets": [{"src_path": f"/rs/{name}/src/lib.rs"}], "dependencies": [{"name": dep} for dep in deps], } for name, deps in ( @@ -32,7 +34,7 @@ def test_selection_follows_shared_dependencies(self): ("kio", []), ("moq-unrelated", []), ) - ] + ], } fixture = scratch / "metadata" fixture.write_text(json.dumps(metadata)) @@ -44,6 +46,7 @@ def test_selection_follows_shared_dependencies(self): os.environ, LOCAL_SUPERVISED="1", PATH=f"{scratch}:{os.environ['PATH']}", + BASH_ENV=os.devnull, SELECT_CALLS=str(calls), TEST_METADATA=str(fixture), ) @@ -59,7 +62,15 @@ def test_selection_follows_shared_dependencies(self): with self.subTest(path=path): changed.write_text(path + "\n") calls.write_text("") - subprocess.run(["bash", "sh/rs/select.sh", "uring", str(changed)], cwd=ROOT, env=env, check=True) + result = subprocess.run( + ["bash", "sh/rs/select.sh", "uring", str(changed)], + cwd=ROOT, + env=env, + text=True, + capture_output=True, + ) + self.assertEqual(result.returncode, 0, result.stdout + result.stderr) + self.assertEqual(result.stderr, "") self.assertEqual("rs uring" in calls.read_text().splitlines(), passes)