ci(triage): detect harness test attributes, not just #[test] - #277
ci(triage): detect harness test attributes, not just #[test]#277beardthelion wants to merge 1 commit into
Conversation
The needs-tests detector matched an added `#[test]` or `#[cfg(test)]` line and nothing else, so it missed every test written with a harness attribute. That is most of this repo: 345 `#[tokio::test]` and 189 `#[sqlx::test]` against 540 bare `#[test]`. Any PR whose tests are all DB or async tests got labeled needs-tests, which is what happened on #275 (three added `#[sqlx::test]` functions) and #262 (eight). Match an added attribute whose last path component contains `test`, followed by `]` or `(`. That covers the four forms in the tree today and the harnesses a contributor might reach for later (`#[rstest]`, `#[test_case]`, `#[wasm_bindgen_test]`) without enumerating them. Deliberately not keying on an added `assert!`: a production assertion is ordinary Rust, so that signal would let a testless PR clear the label silently. The label is a nudge, so it should fail loud. Labeling a PR that did add tests gets corrected by the author; clearing one that did not is invisible. Anchoring to the start of the added line also drops three false positives the old `.*` prefix accepted: a comment, a string literal, and a doc example that merely mention `#[test]`. Verified against the real patches of 14 open PRs: #275 and #262 stop being labeled, both of which do add tests, and no other verdict changes.
📝 WalkthroughWalkthroughThe PR triage workflow updates its Rust inline test heuristic to detect qualified and parameterized test attributes while requiring the attribute to appear at the start of an added line. ChangesRust inline test detection
Estimated code review effort: 2 (Simple) | ~10 minutes Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/pr-triage.yml:
- Around line 85-89: Update addsInlineTest to detect Rust test attributes only
in code, not inside multiline comments or raw strings, by tracking lexical state
across patch lines or using a Rust-aware parser. Preserve the existing
added-line and Rust-file filtering, and add regressions covering multiline
comments and raw strings containing lines beginning with #[test].
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 95aa1bd2-8355-4c96-8f60-8dfbf80f9296
📒 Files selected for processing (1)
.github/workflows/pr-triage.yml
| // Anchored to the start of the added line, so a comment or a string that | ||
| // merely mentions #[test] does not count. | ||
| const addsInlineTest = files.some(f => | ||
| f.filename.endsWith(".rs") && f.patch && | ||
| /^\+.*#\[(test\]|cfg\(test\))/m.test(f.patch)); | ||
| /^\+\s*#\[(cfg\(test\)|(?:\w+::)*\w*test\w*[\](])/m.test(f.patch)); |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift
The line anchor does not exclude multiline comments or raw strings.
A production-only change such as /*\n#[test]\n*/ or a raw string containing a line beginning with #[test] still produces a matching +#[test] patch line, so needs-tests is incorrectly omitted. Track Rust lexical state across patch lines (or use a Rust-aware parser), and add regressions for these cases.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/pr-triage.yml around lines 85 - 89, Update addsInlineTest
to detect Rust test attributes only in code, not inside multiline comments or
raw strings, by tracking lexical state across patch lines or using a Rust-aware
parser. Preserve the existing added-line and Rust-file filtering, and add
regressions covering multiline comments and raw strings containing lines
beginning with #[test].
jatmn
left a comment
There was a problem hiding this comment.
I found one item that needs maintainer input before this merges.
Findings
- [P2] Resolve overlap with open PR #202 before merging
.github/workflows/pr-triage.yml(same file, competing fix)
Open PR #202 (fix/pr-triage-async-test-detection, +208/−4) fixes the sameneeds-testsinline-test detector, closes #201, and already went through multiple review rounds (lexical stripping of comments/strings/raw literals, head-file lexing across hunks, blob API fetch, bounded-scan inconclusive handling,#[r#test]/#[::tokio::test]). This PR (+15/−1) is a regex-only subset of that work. Only one should land; merging both would conflict. Please close or supersede #202 explicitly, or close this PR in favor of #202 if the fuller approach is preferred.
Summary
The
needs-teststriage label fires on PRs that do add tests. The detector matched an added#[test]or#[cfg(test)]line and nothing else, so it missed every test written with a harness attribute. That is most of this repo: 345#[tokio::test]and 189#[sqlx::test]against 540 bare#[test]. A PR whose tests are all DB or async tests got told it had none.It caught #275 (three added
#[sqlx::test]functions) and #262 (eight) while I was reviewing them.What changed
One regex. It now matches an added attribute whose last path component contains
test, followed by]or(:/^\+\s*#\[(cfg\(test\)|(?:\w+::)*\w*test\w*[\](])/mThat covers the four forms in the tree today and the harnesses someone might reach for later (
#[rstest],#[test_case],#[wasm_bindgen_test]) without enumerating them one by one.Anchoring to the start of the added line also drops three false positives the old
.*prefix accepted: a comment, a string literal, and a doc example that merely mention#[test].What it deliberately does not do
An earlier cut of this also counted an added
assert!, on the theory that it catches any test regardless of how it was declared. That is wrong in the direction that matters. A production assertion is ordinary Rust, so a PR addingassert!(!input.is_empty())to a handler and no tests at all would have cleared the label silently.The two failure directions are not symmetric here. Labeling a PR that did add tests is loud and the author corrects it. Clearing a PR that added none is invisible. For an advisory nudge, the heuristic should fail loud, so the assertion signal is out.
Test plan
There is no harness for workflow JS, so this was verified by running the regex directly.
#[rstest],#[test_case],#[wasm_bindgen_test],#[proptest], and an#[rstest]asserting only viaunwrap()are detected. Productionassert!/assert_eq!alone, a doc-comment assert, a removed-line,#[derive(Debug)],#[serde(rename = "test")],#[attest::verify], and comment/string mentions of#[test]are all correctly not.#[rstest]withunwrap()goes undetected to detected on the broadened path component, and a production-assert-only diff goes cleared to labeled when the assertion signal comes out.pr-triage.ymlparses, andnode --checkis clean on the extractedgithub-scriptbody, so the regex survives the YAML block scalar.Nothing else in the workflow changes. It still adds and removes labels only, with no
setFailed.Summary by CodeRabbit
#[test]and#[tokio::test(...)].