codegen-check fails on any unstaged change, and blames the code generators #131

Closed
opened 2026-08-19 14:42:01 +00:00 by logan · 1 comment
Collaborator

Report

The codegen-check pre-commit hook fails on a commit whose staged changes are
perfectly fine, if the working tree has any unrelated unstaged change. It
reports:

Generated code is out of date. Run 'make generate' and stage the changes.

and then prints a diffstat of the unstaged files — which in my case were
CLAUDE.md, .planning/NOTES.md and a plan document. Running make generate
does nothing, because nothing generated is stale, so the message sends you
looking for a codegen problem that does not exist.

Findings

lefthook.yml:

codegen-check:
  glob: "*.{go,sql,templ}"
  run: |
    go generate ./...
    if [ -n "$(git diff --name-only)" ]; then

git diff --name-only is the whole unstaged worktree, not the generated
output, so the check conflates two different things: "generation produced a
change" and "you have unstaged edits". The glob means it only fires when a
.go/.sql/.templ file is staged, which is why it does not bite constantly —
it needs a staged Go file and an unstaged anything.

Splitting one piece of work into separate commits is exactly the shape that
triggers it, since the later commits' files sit unstaged while the earlier ones
land. The workaround is to order commits so the tree is clean by the time a Go
file is staged, which is a constraint on commit order for no real reason.

Direction

Diff only what generation can actually produce, so the check answers the
question it names. Either restrict the paths:

if [ -n "$(git diff --name-only -- '*_templ.go' 'backend/database/sql/sqlcgen' 'frontend/src/events.ts')" ]; then

or capture the tree state before go generate and compare against it, which
keeps working when a new generator is added.

Worth checking whether the CI step has the same shape; there the tree is clean
by construction, so it would never have shown up.

**Report** The `codegen-check` pre-commit hook fails on a commit whose *staged* changes are perfectly fine, if the working tree has **any** unrelated unstaged change. It reports: ``` Generated code is out of date. Run 'make generate' and stage the changes. ``` and then prints a diffstat of the unstaged files — which in my case were `CLAUDE.md`, `.planning/NOTES.md` and a plan document. Running `make generate` does nothing, because nothing generated is stale, so the message sends you looking for a codegen problem that does not exist. **Findings** `lefthook.yml`: ```yaml codegen-check: glob: "*.{go,sql,templ}" run: | go generate ./... if [ -n "$(git diff --name-only)" ]; then ``` `git diff --name-only` is the *whole unstaged worktree*, not the generated output, so the check conflates two different things: "generation produced a change" and "you have unstaged edits". The glob means it only fires when a `.go`/`.sql`/`.templ` file is staged, which is why it does not bite constantly — it needs a staged Go file *and* an unstaged anything. Splitting one piece of work into separate commits is exactly the shape that triggers it, since the later commits' files sit unstaged while the earlier ones land. The workaround is to order commits so the tree is clean by the time a Go file is staged, which is a constraint on commit order for no real reason. **Direction** Diff only what generation can actually produce, so the check answers the question it names. Either restrict the paths: ```sh if [ -n "$(git diff --name-only -- '*_templ.go' 'backend/database/sql/sqlcgen' 'frontend/src/events.ts')" ]; then ``` or capture the tree state before `go generate` and compare against it, which keeps working when a new generator is added. Worth checking whether the CI step has the same shape; there the tree is clean by construction, so it would never have shown up.
logan added the
Reviewed
Confirmed
1
Kind/Bug
Priority
Low
4
labels 2026-08-19 14:42:01 +00:00
yonlu self-assigned this 2026-08-19 17:18:23 +00:00
yonlu added the
Status
In Progress
label 2026-08-19 17:18:24 +00:00
Owner

Scoping the codegen-check hook to the files go generate actually writes, so an unrelated unstaged edit stops being reported as stale generated code.

Scoping the codegen-check hook to the files `go generate` actually writes, so an unrelated unstaged edit stops being reported as stale generated code.
logan closed this issue 2026-08-19 19:08:46 +00:00
gitea-actions bot removed the
Status
In Progress
label 2026-08-19 19:09:03 +00:00
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: yonlu/yellowjacket#131