Repository navigation
ci(dogfood): make the invisible-character gate fail closed #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -128,9 +128,22 @@ jobs: | |
| run: | | ||
| # Inline invisible character detection (from empty-linter's core patterns). | ||
| # Checks for: zero-width spaces, zero-width joiners, BOM, soft hyphens, | ||
| # non-breaking spaces, null bytes, and other invisible Unicode in source files. | ||
| set +e | ||
| # non-breaking spaces, null bytes, C0 controls and other invisible | ||
| # Unicode in source files. | ||
| # | ||
| # `(*UTF)` makes PCRE match code points, not bytes, whatever the | ||
| # runner locale is; `-a` stops grep treating a NUL-bearing file as | ||
| # binary and silently matching nothing. Both were missing before | ||
| # #90 and the gate had matched nothing in its life. | ||
| PATTERNS='(*UTF)[\x00-\x08\x0B\x0C\x0E-\x1F\x{a0}\x{ad}\x{200b}-\x{200f}\x{202a}-\x{202f}\x{2060}\x{2066}-\x{2069}\x{feff}]' | ||
|
|
||
| # Planted positive: the pattern must fire on a known NBSP, or this | ||
| # gate cannot fire at all and must fail closed rather than pass. | ||
| if ! printf 'x\xc2\xa0y' | grep -aqP "$PATTERNS"; then | ||
| echo "::error::invisible-character pattern did not match a planted NBSP; the gate cannot fire, failing closed" | ||
| exit 1 | ||
| fi | ||
|
|
||
| find "$GITHUB_WORKSPACE" \ | ||
| -not -path '*/.git/*' -not -path '*/node_modules/*' \ | ||
| -not -path '*/.deno/*' -not -path '*/target/*' \ | ||
|
|
@@ -141,23 +154,27 @@ jobs: | |
| -o -name '*.yml' -o -name '*.yaml' -o -name '*.md' -o -name '*.adoc' \ | ||
| -o -name '*.idr' -o -name '*.zig' -o -name '*.v' -o -name '*.jl' \ | ||
| -o -name '*.gleam' -o -name '*.hs' -o -name '*.ml' -o -name '*.sh' \) \ | ||
| -exec grep -aPrl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt 2>/dev/null | ||
| EL_EXIT=$? | ||
| set -e | ||
| -exec grep -aPrl "$PATTERNS" {} \; > /tmp/empty-lint-results.txt | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win ✅ Runtime observed🏁 Script executed: #!/usr/bin/env bash
set -u
PATTERNS='(*UTF)[\x00-\x08\x0B\x0C\x0E-\x1F\x{a0}\x{ad}\x{200b}-\x{200f}\x{202a}-\x{202f}\x{2060}\x{2066}-\x{2069}\x{feff}]'
tmpdir="$(mktemp -d)"
trap 'rm -rf "$tmpdir"' EXIT
printf '\xff' > "$tmpdir/sample.rs"
grep -aPl "$PATTERNS" "$tmpdir/sample.rs" >/dev/null
grep_status=$?
find "$tmpdir" -type f -name '*.rs' \
-exec grep -aPrl "$PATTERNS" {} \; > "$tmpdir/results"
find_status=$?
if [ "$grep_status" -lt 2 ]; then
echo "The probe did not produce a grep scan error." >&2
exit 2
fi
if [ "$find_status" -eq 0 ]; then
echo "find masked grep's scan error."
exit 0
fi
echo "find propagated grep's scan error." >&2
exit 1Repository: hyperpolymath/double-track-browser Length of output: 327 Propagate scan errors from the At 🤖 Prompt for AI Agents |
||
|
|
||
| FINDINGS=$(wc -l < /tmp/empty-lint-results.txt 2>/dev/null || echo 0) | ||
| FINDINGS=$(grep -c . /tmp/empty-lint-results.txt || true) | ||
| echo "findings=$FINDINGS" >> "$GITHUB_OUTPUT" | ||
| echo "exit_code=$EL_EXIT" >> "$GITHUB_OUTPUT" | ||
| echo "ready=true" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Emit annotations for each file with invisible chars | ||
| # One annotation per offending file, then FAIL: a gate that only | ||
| # warns is not a gate. | ||
| while IFS= read -r filepath; do | ||
| [ -z "$filepath" ] && continue | ||
| REL_PATH="${filepath#$GITHUB_WORKSPACE/}" | ||
| echo "::warning file=${REL_PATH}::Invisible Unicode characters detected (zero-width space, BOM, NBSP, etc.)" | ||
| echo "::error file=${REL_PATH}::Invisible Unicode characters detected (zero-width space, BOM, NBSP, soft hyphen, C0 control, NUL)" | ||
| done < /tmp/empty-lint-results.txt | ||
|
|
||
| if [ "$FINDINGS" -gt 0 ]; then | ||
| echo "::error::${FINDINGS} file(s) contain invisible Unicode characters (listed above). This gate fails the job." | ||
| exit 1 | ||
| fi | ||
|
|
||
| - name: Write summary | ||
| if: always() | ||
| run: | | ||
| if [ "${{ steps.lint.outputs.ready }}" = "true" ]; then | ||
| FINDINGS="${{ steps.lint.outputs.findings }}" | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🔎 Supported by static analysis
🏁 Script executed:
Repository: hyperpolymath/double-track-browser
Length of output: 5322
🏁 Script executed:
Repository: hyperpolymath/double-track-browser
Length of output: 5385
Initialise the lint status before the planted-pattern guard.
When the
grep -aqPcheck fails,exit 1runs beforefindingsandreadyare written to$GITHUB_OUTPUT. Thealways()summary then reportsSkipped: empty-linter not availableinstead of the guard failure.🤖 Prompt for AI Agents