Skip to content

CRLF files on main make the changes job fail with a misleading "trailing whitespace" error #9798

Description

@JSONbored

Problem

20 files are committed on main with CRLF line endings, and the repo has no .gitattributes to stop
more from landing. The changes CI job runs:

git diff --check "$BASE_SHA" HEAD

Git's default core.whitespace is blank-at-eol,space-before-tab,blank-at-eof with cr-at-eol
off
, so a carriage return at end-of-line is trailing whitespace as far as --check is concerned.
Any PR that adds a line to one of these files therefore fails CI with an error pointing at lines whose
visible content is spotless, and nothing in the output ever says "CRLF".

This is not hypothetical — it already produced a red changes job on #9787
(run 30436384202):

src/review/inline-suggestion-anchor.ts:13: trailing whitespace.
+  for (const raw of patch.split("\n")) {
src/review/inline-suggestion-anchor.ts:21: trailing whitespace.
+    if (marker === undefined || marker === "-" || marker === "\\") continue;
##[error]Process completed with exit code 2.

Neither line has trailing whitespace. The author did nothing wrong; their editor preserved the file's
existing CRLF convention on the lines they added. There is no way to work that out from the log — it
takes cloning the branch and hexdumping the file.

The whitespace step only started catching this recently: it used to run git diff --check with no
arguments against a shallow single-commit checkout, where working tree and index are always identical,
so it unconditionally passed. Fixing that false-green turned these pre-existing CRLF files into a live
CI trap.

Affected files

Eleven under src/, test/ and packages/:

  • packages/loopover-engine/src/signals/issue-quality-report.ts
  • src/review/changed-files-diff-link.ts
  • src/review/inline-comment-label.ts
  • src/review/inline-comment-range.ts
  • src/review/inline-suggestion-anchor.ts
  • test/unit/changed-files-diff-link.test.ts
  • test/unit/inline-comment-label.test.ts
  • test/unit/inline-comment-range.test.ts
  • test/unit/inline-comments-select.test.ts
  • test/unit/inline-suggestion-anchor.test.ts
  • test/unit/issue-quality-report-package.test.ts

…plus nine more under review-enrichment/ with the same defect:

  • review-enrichment/src/analyzers/binary-extensions.ts
  • review-enrichment/test/binary-extensions.test.ts
  • review-enrichment/test/codeowners.test.ts
  • review-enrichment/test/debug-leftover.test.ts
  • review-enrichment/test/dependency-diff.test.ts
  • review-enrichment/test/floating-promise.test.ts
  • review-enrichment/test/hardcoded-url.test.ts
  • review-enrichment/test/i18n-regression.test.ts
  • review-enrichment/test/size-smell.test.ts

Four are mixedsrc/review/inline-comment-range.ts is 36 CRLF lines out of 54, test/unit/inline-comment-range.test.ts 66 of 97 — so which lines trip the check depends on where in the file you edit.

Reproduce:

git grep -lI $'\r' origin/main -- .

Expected

  1. All 20 files converted to LF, content otherwise byte-identical (git diff -w shows no substantive
    change) and their unit tests still passing.
  2. A root .gitattributes pinning the repo to LF so this cannot recur. It must be * text=auto eol=lf,
    not * text eol=lf — five .ts files embed NUL bytes on purpose as untrusted-text/sanitizer
    fixtures (test/unit/mcp-untrusted-text.test.ts, src/services/maintainer-recap-routing.ts,
    review-enrichment/src/analyzers/ci-check-signals.ts, scripts/counterfactual-replay-core.ts,
    packages/loopover-engine/test/governor-ledger.test.ts). text=auto leaves git's binary detection
    in charge and passes them through untouched; forcing text would rewrite them.
  3. The changes job should say CRLF when it means CRLF. .gitattributes stops CRLF entering
    through git add, but checkin filters don't run on blobs written directly (GitHub web editor, the
    Contents API) or on a merge of a branch cut before .gitattributes landed, so the diagnostic is
    still worth having — and "trailing whitespace" on a clean-looking line is the single hardest CI
    failure in this repo to diagnose.

Metadata

Metadata

Assignees

Labels

maintainer-onlyOwner-only work — yields no Gittensor points.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions