Skip to content

lint-rust-cache-guard: here-strings, not printf | grep -q — pipefail makes the membership test lie - #22

Merged
noahgift merged 1 commit into
mainfrom
fix/lint-piped-membership-test
Sep 20, 2026
Merged

noahgift merged 1 commit into
mainfrom
fix/lint-piped-membership-test

Conversation

@noahgift

Copy link
Copy Markdown
Member

Follow-up to the rust-cache guard landed earlier today. A correctness fix to the lint itself, found by another repo's policy.

The defect

The guard sets set -uo pipefail, and two of its predicates were written as printf ... | grep -q:

has_self_hosted_job()    { printf '%s\n' "$1" | grep -qE 'runs-on:.*(self-hosted|clean-room)'; }
has_private_cargo_home() { printf '%s\n' "$1" | grep -E 'CARGO_HOME:' | grep -qvE '...'; }

Under pipefail, grep -q exits at the first match and SIGPIPEs the writer, so the pipeline's status can be 141 even though the test matched. Both predicates are load-bearing: the first decides whether a workflow is judged at all, and the second is the only exoneration from a BLOCK. Either one answering the opposite of the truth — silently — is worse than not having the lint.

How it was found

paiml/rmedia bans the shape repo-wide with scripts/falsify-pipefail-contains.sh, and its CI failed the sibling copy of this same lint on its first run:

FAIL  no-piped-membership-tests  reintroduced in: scripts/lint-rust-cache-guard.sh

This copy was written from the same source and carries the same defect, so it is fixed here rather than left for someone to rediscover.

Change

All three sites use here-strings. has_private_cargo_home splits its two greps so an empty match is an explicit return 1 rather than a pipeline status. The header names the shape it bans and explains why — rmedia's scanner strips comments before matching, which its own case 7 pins.

Measured: --selftest 4/4, the scan reports its usual denominator, bashrs lint 0 errors.

🤖 Generated with Claude Code

Under `set -o pipefail` — which this script sets — `grep -q` exits at the first
match and SIGPIPEs the writer, so the PIPELINE's status can be 141 even though
the test matched. Both membership tests here are load-bearing: one decides
whether a workflow is judged at all, the other is the ONLY exoneration from a
BLOCK. Either answering the opposite of the truth, silently, is worse than not
having the lint at all.

Found by rmedia, which bans the shape repo-wide (falsify-pipefail-contains.sh)
and whose CI failed the sibling copy of this lint on its first run. This copy
was written from the same source and carries the same defect, so it is fixed
here rather than left to be discovered separately.

All three sites now use here-strings, and has_private_cargo_home splits its two
greps so an empty match is an explicit `return 1` rather than a pipeline status.

Measured after: selftest 4/4 and the scan reports its usual denominator.
@noahgift
noahgift merged commit 9e8a0ae into main Sep 20, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant