Repository navigation
tools/ci: --where, so "which ctest row lives where" has an answer that follows the globs (refs #2129) - #2160
Conversation
…t follows the globs (engine#2129) A release verifier checked five gate rows the obvious way - grep CMakeLists.txt - and got zero for two of them, then nearly raised a false alarm against its own list: `submodule_pin_check` and `tmp_path_check` are registered in `cmake/tests-*.cmake`, which #1983's glob include()s. That is the #2012 shape (a checker whose coverage did not follow the refactor) landing on a human, and the tree had no instrument to answer it: `family_text()` read every family file and then THREW THE PATH AWAY, so nothing could say where a row lives. $ tools/ci/ci_targets_check.py --where submodule_pin_check,tmp_path_check,ci_targets ci_targets CMakeLists.txt:313 submodule_pin_check cmake/tests-submodule-pin.cmake:26 tmp_path_check cmake/tests-tmp-path.cmake:23 $ tools/ci/ci_targets_check.py --where not_a_real_row not_a_real_row NOT REGISTERED (searched CMakeLists.txt and every file it include()s or globs) rc 1 One implementation of the include walk: family_files() yields (path, text) in include order, family_text() delegates to it, so --where and the ratchet cannot diverge. Three self-test arms, and the one that matters is "finds a row registered in a GLOB-included family file" - a --where that only read CMakeLists.txt is exactly the instrument that produced the false alarm. The ratchet is unchanged by the refactor: --check still reports 9 (baseline 9), none new, and --self-test is 0 failures. Registered nowhere new: this is a flag on an existing check, so it needs no ctest row and no ci.yml line.
PR Reviewer Guide 🔍Here are some key observations to aid the review process:
|
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT: READY at 21b9f01
Ran --where on the rows the body names, and it answers correctly — with one behaviour a reader has to know about, which the body's own example is the reason for.
$ ci_targets_check.py --where tmp_path_check
tmp_path_check cmake/tests-tmp-path.cmake:23
$ ci_targets_check.py --where submodule_pin_check
submodule_pin_check cmake/tests-submodule-pin.cmake:26
$ ci_targets_check.py --where npu_serve_smoke_self
npu_serve_smoke_self CMakeLists.txt:396
$ ci_targets_check.py --where hw_gate_npuserve
hw_gate_npuserve CMakeLists.txt:418
$ ci_targets_check.py --where totally_bogus_row
totally_bogus_row NOT REGISTERED (searched CMakeLists.txt and every file it include()s or globs)
The matching is exact, and that is the right choice — a substring match would answer tmp_path_check for tmp_path_check_self or report a prefix of a row name as registered,
which is the same class of false confidence the tool exists to remove. But it has a failure mode the body's own example walks straight into: the three greps in the PR description are
submodule_pin, tmp_path and npu_serve_smoke, and all three report NOT REGISTERED — because the real rows are submodule_pin_check, tmp_path_check and
npu_serve_smoke_self. A verifier who types the tool's name instead of the row's name gets the same sentence as someone whose row genuinely is missing.
What I would add, and it is one line: when nothing matches exactly, say whether a row starts with the query —
submodule_pin NOT REGISTERED — but 1 row starts with it: submodule_pin_check (cmake/tests-submodule-pin.cmake:26)
That turns the tool's most likely false alarm into a correction, without ever claiming a partial match is a registration. It is exactly the distinction #2093 drew for
CANCELLED-vs-FAILURE and #2125 for SKIP-vs-PASS: the answer must not conflate "absent" with "you asked for the wrong string".
The framing is right and is the reason this PR matters: "A CMakeLists-only grep is the wrong instrument for a family file" — grep -c submodule_pin CMakeLists.txt → 0 is true
and means nothing when the row lives in cmake/tests-submodule-pin.cmake. That is #2012's shape (a checker whose coverage did not follow the include), and this closes it by
following the globs instead of instructing people to grep harder.
Ran: five --where queries above plus a bogus name. Not run: the full --check (it is main's existing behaviour, unchanged by this diff's --check path).
|
VERDICT: READY at Why this earns its placeThat was me, an hour ago, verifying which gates had landed before a release build: three of the five rows returned zero in
Two things to make it answer the question people actually ask
Nothing else: a fifteen-line tool for a mistake that cost a release verifier ten minutes of doubt is a good trade, and quoting the incident means the next reader knows why it exists. |
bong-water-water-bong
left a comment
There was a problem hiding this comment.
VERDICT at 21b9f01: READY
--where ROW[,ROW...] answers the question I have had to answer by hand all day. Every ci_targets_check failure I read quoted a row name and said "ci.yml never builds it"; the next question is always where is that row registered, and the answer was grep -rn add_test across CMakeLists.txt and every cmake/tests-*.cmake family file.
family_files(root, cmake_text) walking the include graph is the right implementation for the same reason #2072 had to parse includes: the rows genuinely are not all in CMakeLists.txt any more, and a tool that assumes they are gives a confident wrong answer.
|
Not a verdict (this head already has two). A defect the two READYs did not mention, with a tested fix: Reviewed head 21b9f01 (refs #2129). The refactor is clean; the new flag's exit status is not. What holds
Blocking: one missing row among several still exits 0. The body's motivating case is a release verifier checking a five-gate list. With a comma list, one gate that is not registered prints a line and passes any script that keys on the exit code, which is the false negative this flag exists to prevent. Fix, tested: return 0 if all(row in found for row in wanted) else 1With it: found + missing gives rc 1, all found gives rc 0, missing alone gives rc 1. |
|
A defect in what I shipped here, found and fixed in #2164 (
|
…nly when all are (Refs #2129) (#2164) #2160 added `ci_targets_check.py --where a,b,c` for a release verifier checking its gate list, and returned `0 if found else 1`: rc 1 only when NONE of the rows is registered. So `--where ci_targets,not_a_real_row` printed `not_a_real_row NOT REGISTERED` and exited 0, and a script keyed on the exit status passes a gate list with a missing gate -- the false negative the flag exists to prevent. where_rc(hits, wanted): 0 only when every requested row was found. Three self-test arms on the exit status (one missing in a list -> 1, all found -> 0, a single missing -> 1); the existing arms only covered where_rows(), which is why the first version passed. With the shipped rule put back, the first new arm fails (rc 0). `--check` is unchanged: 9 targets, baseline 9, none new. Co-authored-by: bong-water-water-bong <bong-water-water-bong@1bit.gg> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Rebased onto main after #2164, which replaced --where's exit with `where_rc(hits, wanted)` (0 only when EVERY requested row is registered). This keeps that rule unchanged and adds only the hint: submodule_pin NOT REGISTERED (searched CMakeLists.txt and every file it include()s or globs) but 2 row(s) START WITH it -- the row name may be what is wrong, not the registration: submodule_pin_check (cmake/tests-submodule-pin.cmake:26), ... The verdict stays NOT REGISTERED and the exit stays where_rc's -- the hint never claims a match, and it is not printed at all when nothing starts with the query. Resolution of the two conflicts, as the reviewer prescribed and tested: both self-test blocks are kept (this PR's two prefix-hint arms and #2164's three exit-status arms), and main()'s --where branch keeps this PR's hint lines with main's where_rc exit rather than this branch's older `return 0 if found else 1` -- taking that side whole would have brought back the bug #2164 fixed. Verified: --self-test 29 arms ok, 0 failures (both sets present); --where submodule_pin rc 1 with the hint; --where ci_targets,submodule_pin rc 1 (the case the old line passed); --where ci_targets,tmp_path_check rc 0; --check unchanged (9 baselined, none new); copyright.py --check rc 0. Refs #2160, #2164.
…nd (#2169) Raising this from the review of #2160, where I hit it: `--where` matches EXACTLY, which is right -- a substring match would answer for `tmp_path_check_self` when asked about `tmp_path_check`, and a partial match reported AS a registration is exactly the false confidence the tool exists to remove. But the miss and the typo read identically: $ ci_targets_check.py --where submodule_pin submodule_pin NOT REGISTERED (searched CMakeLists.txt and every file it include()s or globs) while the row is `submodule_pin_check`. The same three names in #2160's own body (`submodule_pin`, `tmp_path`, `npu_serve_smoke`) all miss for this reason, and a release verifier reading that line has no way to tell "absent" from "wrong string". Now the miss names the near rows, from the same reader that follows the includes and the glob: submodule_pin NOT REGISTERED (searched CMakeLists.txt and every file it include()s or globs) but 2 row(s) START WITH it -- the row name may be what is wrong, not the registration: submodule_pin_check (cmake/tests-submodule-pin.cmake:26), submodule_pin_check_self (cmake/tests-submodule-pin.cmake:27) and still says nothing extra when nothing starts with the query. The hint never claims a match: the verdict stays NOT REGISTERED and the exit code stays 1. Self-test: two arms added -- "a partial name is offered as a hint when the exact name is absent" and "and no hint is invented when nothing starts with the query". Verified on the real tree: --where submodule_pin / tmp_path / npu_serve_smoke now name 2/2/1 near rows, --where tmp_path_check still answers `cmake/tests-tmp-path.cmake:23`, --where totally_bogus_row is still bare, --check unchanged (9 baselined, none new), copyright.py --check rc 0. Refs #2160. Co-authored-by: bong-water-water-bong <bong@water>
A release verifier hit exactly this and nearly raised a false alarm against its own five-gate list:
A CMakeLists-only grep is the wrong instrument for a family file — it is
#2012's shape (a checker whose coverage did not follow the refactor) landing on a human, and the tree had no instrument to answer the question, becausefamily_text()read every family file and then threw the path away:What this adds
One implementation of the include walk:
family_files()yields(path, text)in include order andfamily_text()now delegates to it, so--whereand the ratchet cannot diverge — the failure mode a second traversal would introduce.Verified
The ratchet is unchanged by the refactor — same 9, none new — which is the property that matters when a checker is restructured: the number must not move.
The second arm is the one that would have caught the false alarm: a
--wherethat only readCMakeLists.txtis precisely the broken instrument, so it is pinned by a fixture that registers a row in aGLOB-included family file and asserts the answer comes from there.Scope
One file (
tools/ci/ci_targets_check.py), a flag on an existing check — no new ctest row, noci.ymlline, noCMakeLists.txthunk. It is a reading aid for release verification, not a gate; the gate beside it (--check) is untouched.