feat: add cargo xtask lint-extended subcommand for comment/repetition smells - #11
feat: add cargo xtask lint-extended subcommand for comment/repetition smells#11jordigilh wants to merge 1 commit into
Conversation
716066e to
bca579a
Compare
bca579a to
464ce94
Compare
Python is the wrong tool for a Rust-native codebase: it needs its own interpreter/toolchain in CI and locally, has no compile-time checking, and can't share types or test harnesses with the rest of the repo. Introduce a minimal `xtask` binary crate as a new workspace member (this repo had no existing workspace) and port scripts/extended-lint.py to it verbatim as the `lint-extended` subcommand, using regex + anyhow instead of ad hoc string handling. clap was not added as a dependency: it is only ever pulled in transitively (via criterion, a dev-dependency of the main crate's benchmarks), so plain std::env::args() parsing for a single subcommand keeps xtask's own dependency footprint minimal. `make extended-lint` and the CI lint step now run `cargo run -p xtask -- lint-extended` instead of `python3 scripts/extended-lint.py`; the diff-base-fetch CI step is unchanged since the tool still needs a base ref to diff against. The Containerfile's dependency pre-caching stage copies only Cargo.toml manifests before the real source, which broke once the workspace grew a second member: cargo needs every member's manifest (and a target file) present just to resolve the workspace graph, even to build a single package. Give xtask a permanent stub manifest+main.rs in that stage and build with `-p praxis-operator` so the dev-only xtask crate is resolved but never actually compiled into the production image. Porting the checker into a `.rs` file also exposed a new self-reference problem the Python version never had: `*.rs`-scoped diff scanning now matches the tool's own source, whose doc comments and test fixtures spell out the literal TODO/FIXME markers and commented-code shapes it looks for. Exclude `xtask/**` from its own git-diff scan to fix it. Fixes praxis-proxy#10 Signed-off-by: Jordi Gil <jgil@redhat.com>
464ce94 to
420809a
Compare
|
Closing this out without merging. After digging into what actually exists in the Rust ecosystem for this class of check, most of the "extended lint" heuristics either have no reliable off-the-shelf equivalent in any language's tooling (commented-out-code detection, "narrating" comment detection), or only partial overlap that does not justify maintaining bespoke regex/diff-scoped Rust across six repos (e.g. TODO markers are trivially a one-line Decision: we do not want to own and maintain custom heuristic lint logic per-repo. If this capability is worth having, the better path is contributing it upstream to a maintained linter (clippy itself, or a |
|
Follow-up on the reasoning above, now that all six ports are done: implementing this surfaced a concrete illustration of exactly the maintenance burden we did not want to sign up for. Every one of the six independent Rust ports had to hand-write a workaround for the same problem -- the linter's own source (its regex definitions, doc comments, and test fixtures) legitimately contains the words |
Summary
Adds a
cargo xtask lint-extendedsubcommand, a small diff-scopedheuristic checker for low-quality-code patterns that clippy can't catch
structurally: comment content (leftover TODO/FIXME markers,
commented-out code, "what"-narrating comments) and diff-local
repetition (a literal repeated 3+ times instead of a named constant),
plus a couple of lighter-weight signals (weak identifier names, new
clippy suppressions). It only scans lines added/changed versus the diff
base, so pre-existing code is never relitigated.
This originally shipped as a Python script (
scripts/extended-lint.py)-- wrong tool for a Rust-native codebase, since it needs its own
interpreter/toolchain in CI and locally, has no compile-time checking,
and can't share types or test harnesses with the rest of the repo. It's
now a proper
xtaskbinary crate, added as a new workspace member(this repo had no existing workspace; the root
Cargo.tomlgained a[workspace]table withmembers = ["xtask"], with.remaining animplicit member as the workspace's root package). The heuristics
themselves are unchanged -- same regexes, same block/warn split, same
diff-base resolution order (CLI arg, then
$EXTENDED_LINT_BASE, thenorigin/$GITHUB_BASE_REFin a GitHub Actions PR, thenorigin/main).clapwas considered for argument parsing but is only ever pulled intothis workspace transitively (via
criterion, a dev-dependency of themain crate's benchmarks) -- not a direct dependency of the operator's
own CLI, which has none. Since it's not otherwise part of this
workspace,
xtaskparses its one subcommand with plainstd::env::args()to keep its own dependency footprint minimal.anyhowandregexare added as directxtask-only dependencies(
regexwas already present transitively at1.13.1).Wired in as:
make extended-lint(Makefile target now runscargo run -p xtask -- lint-extended)lintjob (.github/workflows/tests.yaml)is unchanged in content -- it still fetches the PR's base branch first,
then runs
make extended-lintdocs/conventions.md("Important Tools") andCONTRIBUTING.md'squick reference now point at
xtask lint-extendedinstead of thePython script
Also fixes a
Containerfilebreak surfaced by CI on this PR's firstpush: its dependency-pre-caching stage only copies
Cargo.tomlmanifests before the real source, and cargo needs every workspace
member's manifest (plus a target file) present just to resolve the
workspace graph, even when building a single package.
xtasknow getsa permanent stub manifest +
src/main.rsin that stage, and bothcargo buildinvocations use-p praxis-operatorso the dev-onlyxtaskcrate is resolved but never actually compiled into theproduction image. Verified with a local
podman build.And a self-reference bug surfaced by CI on the second push: scanning
*.rsfiles now also matcheslint-extended's own source, whose doccomments and test fixtures necessarily spell out the literal
TODO/FIXME markers and commented-code shapes it looks for -- something
the original
.pyscript never hit, since.pyfiles never matchedits
*.rsglob.xtask/**is now excluded from its own git-diff scan(documented as a known, deliberate limitation in the module docs); a
genuine leftover TODO added to
xtaskitself won't be caught by thistool, but everything else in the workspace still is.
Closes #10.
Test plan
cargo clippy --workspace --all-targets -- -D warningspasses(whole workspace, including the new
xtaskmember)cargo +nightly fmt --all -- --checkpassescargo test -p xtask-- 4 unit tests covering the ported regexespass
cargo doc --no-deps --document-private-items --workspacewithRUSTDOCFLAGS="-D warnings"passescargo machetereports no unused dependenciespodman build -f Containerfile .succeeds end-to-endcargo run -p xtask -- lint-extended origin/mainagainst thisPR's full diff -- confirmed no blocking findings from
xtask'sown source after the self-exclusion fix
// TODO: ...commentto
src/lib.rs, rancargo run -p xtask -- lint-extended origin/main-- confirmed it correctly flagged and blocked(exit 1), then reverted the throwaway change
cargo run -p xtask -- lint-extended HEAD(no diff) --confirmed it reports "no added Rust lines" and exits 0
make extended-lint(viaEXTENDED_LINT_BASE=HEAD) invokes thesubcommand correctly
lint,test,coverage,audit,DCOall pass on theupdated push (see checks on this PR)