Add lint-eol; lint-yaml reports how many files it checked #2

Merged
Aareon merged 2 commits from claude/lint-eol into main 2026-09-24 11:01:41 -05:00
Member

Adds lint-eol and makes lint-yaml report how many files it checked.

lint-eol

Fails unless every tracked text file is:

  1. stored as LF. Catches files committed with CRLF (i/crlf or i/mixed).
  2. covered by an eol=lf attribute. Without it, a Windows checkout or git archive with core.autocrlf=true writes CRLF. That's how prodesk-2's /etc/network/interfaces got CRLF on 2026-09-24 (Homelab/infra#21, #22).
  • Binary and empty files are skipped.
  • allow-crlf takes globs, space- or newline-separated, for files that really need CRLF (e.g. *.ps1 *.bat).
  • Each problem is reported as an ::error file=… annotation, followed by the one-line fix: * text=auto eol=lf in the root .gitattributes, then git add --renormalize .

Tested locally:

Target Result
infra origin/main ❌ 158 of 213 text files lack the attribute (expected)
infra #22 branch (root .gitattributes) ✅ 208 files, 0 problems
this repo ✅ 8 files, 0 problems
Synthetic repo files stored as CRLF caught; binary and empty skipped; allowlist works (space- or newline-separated, nested paths)

It's also added to this repo's own CI.

lint-yaml

It printed nothing on success, so a pass looked the same as a skip. It now prints Checked N YAML files: M problem(s).

Adoption

  • Homelab/agents: can adopt it as soon as this merges, since it already has a root LF rule.
  • Homelab/infra: would fail on main until infra#22 merges, which is by design. After that, I'll bump both repos' pins.

Merge method: Squash. The second commit is a README fix-up to the first. Consumers pin the resulting commit on main.

🤖 Generated with Claude Code

Adds **`lint-eol`** and makes `lint-yaml` report how many files it checked. ## `lint-eol` Fails unless every tracked text file is: 1. **stored as LF.** Catches files committed with CRLF (`i/crlf` or `i/mixed`). 2. **covered by an `eol=lf` attribute.** Without it, a Windows checkout or `git archive` with `core.autocrlf=true` writes CRLF. That's how prodesk-2's `/etc/network/interfaces` got CRLF on 2026-09-24 (Homelab/infra#21, #22). - Binary and empty files are skipped. - `allow-crlf` takes globs, space- or newline-separated, for files that really need CRLF (e.g. `*.ps1 *.bat`). - Each problem is reported as an `::error file=…` annotation, followed by the one-line fix: `* text=auto eol=lf` in the root `.gitattributes`, then `git add --renormalize .` **Tested locally:** | Target | Result | |---|---| | infra `origin/main` | ❌ 158 of 213 text files lack the attribute (expected) | | infra #22 branch (root `.gitattributes`) | ✅ 208 files, 0 problems | | this repo | ✅ 8 files, 0 problems | | Synthetic repo | files stored as CRLF caught; binary and empty skipped; allowlist works (space- or newline-separated, nested paths) | It's also added to this repo's own CI. ## `lint-yaml` It printed nothing on success, so a pass looked the same as a skip. It now prints `Checked N YAML files: M problem(s).` ## Adoption - **`Homelab/agents`:** can adopt it as soon as this merges, since it already has a root LF rule. - **`Homelab/infra`:** would fail on `main` until infra#22 merges, which is by design. After that, I'll bump both repos' pins. **Merge method:** Squash. The second commit is a README fix-up to the first. Consumers pin the resulting commit on `main`. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
lint-eol fails unless every tracked text file is stored as LF and has
eol=lf from .gitattributes. Without the attribute, git archive on a Windows
box with core.autocrlf=true writes CRLF; that put CRLF into prodesk-2's
/etc/network/interfaces on 2026-09-24. Binary and empty files are skipped;
`allow-crlf` takes globs for files that really need CRLF.

Tested: infra origin/main fails (158 files without the attribute); infra's
root-.gitattributes branch and this repo pass (208 / 8 files); a synthetic
repo catches CRLF-stored files and honours the allowlist (space- or
newline-separated, nested paths).

lint-yaml printed nothing on success, so a pass looked like a skip.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
README: lint-eol needs only git, not apt
All checks were successful
ci / test (pull_request) Successful in 9s
40f36c1e3c
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Author
Member

Merge method: Squash. 40f36c1 only fixes the README from b038804, so one commit on main is cleaner. Callers will pin the squashed commit's ID on main, never a branch commit.

**Merge method:** Squash. `40f36c1` only fixes the README from `b038804`, so one commit on `main` is cleaner. Callers will pin the squashed commit's ID on `main`, never a branch commit.
Aareon merged commit 39f9fdc786 into main 2026-09-24 11:01:41 -05:00
Aareon deleted branch claude/lint-eol 2026-09-24 11:01:42 -05:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ci/actions!2
No description provided.