Run the pre-commit hooks in CI (#58) #108

Merged
claude-bot merged 1 commit from feat/pre-commit-in-ci into main 2026-09-01 19:01:55 +00:00
Contributor

Closes #58.

.pre-commit-config.yaml existed but nothing ran it. Five of its seven hooks have no equivalent anywhere else in the pipelinetrailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict, check-added-large-files — so they were enforced only on machines where someone had run pre-commit install. The issue offered "verify the existing CI jobs cover every hook" as an alternative; they cover two of eight, so that route was closed.

Three problems surfaced on first execution

1. check-yaml was failing.

could not determine a constructor for the tag '!reset'
  in "docker-compose.registry.yml", line 28, column 12

Compose's !reset tag is valid Compose but not standard YAML, so safe_load can't construct it. Excluded — Compose validates that file on every deploy anyway.

2. The ruff hook pinned v0.6.9; uv sync resolves 0.15.21. That skew produces the worst kind of failure: one job failing on formatting another job considers clean, with no obvious cause. Pinned to the resolved version, and Renovate's pre-commit manager (off by default) is now enabled so the two keep moving together — otherwise this silently re-drifts.

3. The prettier hook would have reformatted 62 files / ~4,950 lines. It had never run, prettier is not a frontend dependency, and mirrors-prettier is archived upstream. Removed. Frontend style is already gated by ESLint with --max-warnings 0. Adopting prettier deliberately — devDependency, eslint-config-prettier to stop rule conflicts, one reformat commit — is separate work, not a side effect of this issue.

One trap worth flagging

trailing-whitespace needed --markdown-linebreak-ext=md. Two trailing spaces are a hard line break in Markdown, and without the flag the hook stripped them and silently reflowed the docs — it merged consecutive lines of iris-spec.md's schema list into a single paragraph:

**`scheme_segments`** — per-segment config rows, FK to schemes␠␠
**`segments`** — segment configuration (name, WLED index, mode, static config)␠␠

I nearly committed that. It was only visible by reading the fixer's actual diff rather than trusting that a whitespace hook does something harmless.

Net effect

After that, the accumulated debt is two lines: a stray blank line at the end of iris-spec.md, and a missing final newline in DayCell.test.tsx. The repo was in better shape than #41's history suggested.

Also

CONTRIBUTING.md moves pre-commit install to a first-time setup step ahead of the backend/frontend sections, and corrects Prerequisites from "Python 3.12+" to 3.14+ — what requires-python has demanded since #37, and a version that would have sent a new contributor into a broken environment.

Verification

  • uvx pre-commit run --all-files — all seven hooks pass with no modifications.
  • Backend: 291 passed, ruff, ruff format, mypy clean.
  • ci.yml and renovate.json parse; the new job needs only setup-python + uv, no Node.

🤖 Generated with Claude Code

Closes #58. `.pre-commit-config.yaml` existed but nothing ran it. **Five of its seven hooks have no equivalent anywhere else in the pipeline** — `trailing-whitespace`, `end-of-file-fixer`, `check-yaml`, `check-merge-conflict`, `check-added-large-files` — so they were enforced only on machines where someone had run `pre-commit install`. The issue offered "verify the existing CI jobs cover every hook" as an alternative; they cover two of eight, so that route was closed. ## Three problems surfaced on first execution **1. `check-yaml` was failing.** ``` could not determine a constructor for the tag '!reset' in "docker-compose.registry.yml", line 28, column 12 ``` Compose's `!reset` tag is valid Compose but not standard YAML, so `safe_load` can't construct it. Excluded — Compose validates that file on every deploy anyway. **2. The ruff hook pinned `v0.6.9`; `uv sync` resolves `0.15.21`.** That skew produces the worst kind of failure: one job failing on formatting another job considers clean, with no obvious cause. Pinned to the resolved version, and **Renovate's `pre-commit` manager (off by default) is now enabled** so the two keep moving together — otherwise this silently re-drifts. **3. The prettier hook would have reformatted 62 files / ~4,950 lines.** It had never run, `prettier` is **not a frontend dependency**, and `mirrors-prettier` is archived upstream. Removed. Frontend style is already gated by ESLint with `--max-warnings 0`. Adopting prettier deliberately — devDependency, `eslint-config-prettier` to stop rule conflicts, one reformat commit — is separate work, not a side effect of this issue. ## One trap worth flagging `trailing-whitespace` needed `--markdown-linebreak-ext=md`. **Two trailing spaces are a hard line break in Markdown**, and without the flag the hook stripped them and silently reflowed the docs — it merged consecutive lines of `iris-spec.md`'s schema list into a single paragraph: ``` **`scheme_segments`** — per-segment config rows, FK to schemes␠␠ **`segments`** — segment configuration (name, WLED index, mode, static config)␠␠ ``` I nearly committed that. It was only visible by reading the fixer's actual diff rather than trusting that a whitespace hook does something harmless. ## Net effect After that, the accumulated debt is **two lines**: a stray blank line at the end of `iris-spec.md`, and a missing final newline in `DayCell.test.tsx`. The repo was in better shape than #41's history suggested. ## Also `CONTRIBUTING.md` moves `pre-commit install` to a first-time setup step ahead of the backend/frontend sections, and corrects Prerequisites from "Python 3.12+" to **3.14+** — what `requires-python` has demanded since #37, and a version that would have sent a new contributor into a broken environment. ## Verification - `uvx pre-commit run --all-files` — all seven hooks pass with no modifications. - Backend: **291 passed**, `ruff`, `ruff format`, `mypy` clean. - `ci.yml` and `renovate.json` parse; the new job needs only `setup-python` + `uv`, no Node. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Run the pre-commit hooks in CI (#58)
All checks were successful
CI / Alembic migration check (pull_request) Successful in 1m17s
CI / Pre-commit hooks (pull_request) Successful in 1m30s
CI / Python lint & type-check (pull_request) Successful in 1m45s
CI / Frontend lint, test & build (pull_request) Successful in 1m56s
CI / Python tests (pull_request) Successful in 4m3s
CI / Docker build, health smoke & E2E (pull_request) Successful in 3m47s
0351fd4b40
`.pre-commit-config.yaml` existed but nothing ran it. Five of its seven hooks
-- trailing-whitespace, end-of-file-fixer, check-yaml, check-merge-conflict,
check-added-large-files -- have no equivalent anywhere else in the pipeline,
so they were enforced only on machines where someone had run
`pre-commit install`. That is how the config drifted.

First execution surfaced three problems:

- check-yaml failed on docker-compose.registry.yml. Compose's `!reset` tag is
  valid Compose but not standard YAML, so safe_load cannot construct it.
  Excluded; Compose validates that file on every deploy anyway.

- The ruff hook pinned v0.6.9 while `uv sync` resolved 0.15.21. That skew
  produces the worst kind of failure -- one job failing on formatting another
  job considers clean. Pinned to the resolved version, and Renovate's
  `pre-commit` manager (off by default) is now enabled so the two keep moving
  together.

- The prettier hook would have reformatted 62 files / ~4950 lines. It had
  never run, prettier is not a frontend dependency, and `mirrors-prettier` is
  archived upstream. Removed: frontend style is already gated by ESLint with
  --max-warnings 0. Adopting prettier deliberately -- devDependency,
  eslint-config-prettier, one reformat -- is separate work.

trailing-whitespace also needed `--markdown-linebreak-ext=md`. Two trailing
spaces are a hard line break in Markdown, and without the flag the hook
reflowed the docs, merging consecutive lines of iris-spec.md's schema list
into one paragraph.

Remaining fixes are two lines: a stray blank line at the end of iris-spec.md
and a missing final newline in DayCell.test.tsx.

CONTRIBUTING.md moves `pre-commit install` to a first-time setup step ahead of
the backend/frontend sections, and corrects Prerequisites from "Python 3.12+"
to 3.14+, which is what `requires-python` has demanded since #37.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude-bot deleted branch feat/pre-commit-in-ci 2026-09-01 19:01:56 +00:00
Sign in to join this conversation.
No description provided.