Repository navigation
fork-ci: fail clippy only on files the PR changes - #11
Conversation
thedancingdeveloper
left a comment
There was a problem hiding this comment.
Review: blocker (head 83364de). The logic is fine; the branch base isn't.
-
The branch is based on the pre-merge
fork/cihistory.git merge-basewith fork/main is c138238, and the PR carries 472cc14, 8e7029c and 27bc640 again, which #4 already landed as a77b522, 1aa8ff2 and 08f5389. Rebase onto origin/fork/main so the PR is one commit: the clippy-step change and thefilesoutput.git diff origin/fork/main..HEADshould then show only fork-ci.yml (+ the script if it changed). -
The requested self-test is missing. Link two runs:
- (a) a probe branch that adds one clippy lint in a changed file, and fork-ci fails on it;
- (b) #6 rebased without 72e7308, and fork-ci passes despite the upstream
let_and_returnin message_processor.rs:371.
Those two runs are the test of this file.
Logic checked:
- JSON clippy with no
-D; - only diagnostics whose primary span is in a changed file fail the job;
- paths are stripped of
codex-rs/to match clippy's workspace-relativefile_name; || trueon clippy is fine, because compile errors are already fatal incargo check.
Non-blocking: errors from upstream deny lints in unchanged files are now ignored too. That's correct, but say so in the comment.
cargo clippy -p <pkg> -- -D warnings fails a PR on upstream lint debt in files it never touched: a change to codex-app-server flagged a redundant binding in message_processor.rs that is already on fork/main, and a fork patch must not have to fix upstream debt. Clippy now runs without -D and emits JSON. The step fails only when a warning or error has its primary span in a file the PR changed, and it prints each matching diagnostic. Compile errors stay fatal everywhere, which the workspace cargo check already enforces.
83364de to
5f9d3ef
Compare
thedancingdeveloper
left a comment
There was a problem hiding this comment.
Review: no blockers in the code (head 5f9d3ef)
It's now one commit on fork/main (c8a5628) that touches only fork-ci.yml (+25/-1), so blocker 1 is resolved. The logic is as reviewed before.
Merge conditions (blocker 2, the self-test):
- (a) the
fork/ci-lintprobe run exists and fails, namingcodex-rs/cli/src/main.rs. No fork-ci run exists for that branch yet; - (b) this PR's own run 37937522191 is green.
After merge, #6 is rebased without 72e7308, and its green run is the second half of the test.
|
Epic lead, on the self-test: probe run 37937788126 failed at cargo check (E0308 in cli/src/main.rs:4970: |
thedancingdeveloper
left a comment
There was a problem hiding this comment.
Review: blocker, the gate never fires (head 5f9d3ef).
The corrected probe (run 37940613906, probe head 16f7723, fn _fork_ci_lint_probe() -> i32 { let value = 1; value }) got through cargo check and the clippy step, then failed in cargo test. So the clippy gate passed a real let_and_return in a changed file.
Root cause, reproduced in scratch (clippy 1.95 on a one-file crate, jq 1.8.1):
- Clippy does emit
warning clippy::let_and_return src/main.rs:6in the JSON stream. --slurpfile changed <(jq -R . /tmp/changed-files)makes$changedan array of strings, so[$changed[][]]tries to iterate a string:jq: error: Cannot iterate over string ("src/main.rs").- jq exits 0 after that runtime error, so
offendersis empty and the step passes. Every PR passes this gate regardless of its lints.
Fix (verified both ways in scratch: the changed file is reported, an unchanged file isn't):
select(any($changed[]; . == $s.file_name))
And make a jq failure fail the step. jq exited 0 here, so capture its stderr and fail if it's non-empty, or run it as its own command before the offenders= assignment and check that.
Then re-run the probe: it must fail at the cargo clippy step, naming cli/src/main.rs:4970 and let_and_return.
Separate finding, not this PR's logic: cargo test -p codex-cli failed on packaged_daemon_bootstrap_seeds_local_package in the probe run. Check whether it also fails on a fork/main baseline dispatch. If it's environment-dependent upstream behaviour (the daemon/package bootstrap on a hosted runner), skip that one test in fork-ci with --skip, and say why in a comment. Otherwise every PR touching codex-cli will be red.
--slurpfile yields an array of strings, so `[$changed[][]]` was a jq runtime
error ("Cannot iterate over string"). jq exits 0 on a runtime error, so the
filter matched nothing and every PR passed the clippy step. Compare the file
names with `any($changed[]; . == $s.file_name)`, and fail the step on any jq
stderr so a broken filter cannot pass silently again.
cargo test -p codex-cli fails packaged_daemon_bootstrap_seeds_local_package on
unmodified fork/main: it asserts autoUpdateEnabled == false while
default_auto_update_enabled() returns true. Skip it with that reason rather
than carry a fix for upstream drift.
thedancingdeveloper
left a comment
There was a problem hiding this comment.
Review (head 8c64e9b): the filter fix is right; one small blocker; the probe still needs a run.
Resolved: select(any($changed[]; . == $s.file_name)), the same filter I verified in scratch. The codex-cli skip of packaged_daemon_bootstrap_seeds_local_package (upstream asserts autoUpdateEnabled == false while default_auto_update_enabled() is true) is acceptable with that comment. Non-blocking: link the fork/main baseline run that shows it failing unmodified.
- Blocker:
2> >(tee /tmp/jq-err >&2)is asynchronous. The process substitution can still be writing when[[ -s /tmp/jq-err ]]runs, so a jq error can again pass unnoticed, the same fail-open class as before. Use a synchronous redirect,2>/tmp/jq-err, thencat /tmp/jq-err >&2and fail if it's non-empty. Also clear/tmp/jq-errat the top of each loop iteration (or use one file per crate). - Merge condition: rebase the
fork/ci-lintprobe onto this head and re-run. It must fail at thecargo clippystep, printingcli/src/main.rs:4970and thelet_and_returnmessage. The last probe run (37940613906, 16f7723) used the broken filter.
thedancingdeveloper
left a comment
There was a problem hiding this comment.
Review: no blockers (head 285c950)
Both merge conditions are verified:
- (a) The gate fires on a real lint. Probe run 37944444440 (fork/ci-lint at ed1bca1, descended from 285c950) fails at the
cargo clippystep withclippy findings in files this PR changesandcli/src/main.rs:4970:5: warning: returning the result of a \let` binding from a block(let_and_return). It's listed twice because clippy checks the bin and test targets.cargo check` passed first, so this is a lint, not a compile error. - (b) This PR's own run 37944232480 on 285c950 is green.
Code:
select(any($changed[]; . == $s.file_name));- a synchronous
2>/tmp/jq-err, cleared per iteration, where any jq stderr fails the step; - clippy without
-D, judged only on files the PR changed; - compile errors stay fatal via
cargo check --workspace; - the commented skip for the upstream-drifted
packaged_daemon_bootstrap_seeds_local_package.
After merge, re-run fork-ci on #10 and #12 and rebase #6 (without 72e7308). Delete the fork/ci-lint probe branch; its job is done.
Summary
Test plan