fix(ci): list the files to check on the host, not in the container (#190) - #191
Merged
Conversation
`make validate` failed on the monitoring host and passed in CI, which is the wrong way round for a script whose first line claims "everything CI runs, runnable locally". editorconfig-checker is the only linter in the list that decides for itself what to look at: given no arguments it runs `git ls-files`. The comment in runner_for() says that is what makes a local run equal a CI one, because the gitignored backups/, certificates/, .venv/ and .rendered/ trees are untracked either way. That reasoning is right and the mechanism was not working. Inside the container the call fails, and fails silently. A git worktree's .git is a file holding an absolute path to a gitdir outside the bind mount, so git answers "not a git repository: (null)" and the checker falls back to walking the filesystem. It then flagged the four decrypted Alertmanager webhook URLs that render-config.sh writes without a trailing newline — files that are gitignored, that CI never creates because it never renders, and that no amount of reading .gitignore would have excluded, because nothing was consulting it. Mounting the real gitdir does not fix it: the worktree's gitdir holds a back-pointer to the worktree's own .git path, which inside the container is /check, and git rejects the mismatch. So the listing moves to the host, where git resolves a worktree correctly. The checker is now handed the same tracked files whether it runs from the pinned image or a local binary, and cannot substitute a different set without saying so. An empty list fails rather than skips: a skip means the linter was unreachable, and this means it was reachable with no trustworthy answer to what it should check — the state the fallback used to paper over. Two details the fallback was hiding. -z, because a tracked path may contain a space. And an existence test, because a tracked file deleted from the working tree makes the checker panic with a Go stack trace rather than report anything; it now passes. Verified on the deploy host after `make up`, with the rendered files present: `make validate` green end to end, the file set identical to the 114 the container's own listing produces in a normal checkout, a trailing space added to scripts/snmp-verify.sh still caught, and a deleted README.md no longer a panic. Adjacent to #175, which is the opposite asymmetry — validate running fewer checks than CI rather than one CI cannot fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #190.
make validatefailed on the monitoring host and passed in CI — the wrong wayround for a script whose header claims "Everything CI runs, runnable locally".
It was not a missing exclude
scripts/lint.sh:111-119already says those files should be skipped, and sayshow — editorconfig-checker lists files with
git ls-files, so gitignored treesare untracked in both a workstation and a CI checkout and both runs see the same
files. The image is even chosen to make that work: it installs git and marks
/checkasafe.directory.The reasoning is right. The mechanism was not running.
Where it broke
In a git worktree,
.gitis a file holding an absolute path to a gitdiroutside the bind mount:
The checker then silently falls back to walking the filesystem and picks up
every gitignored tree it finds —
backups/,certificates/,.venv/,.rendered/. A normal checkout is unaffected, which is why this only evershowed up in the agent worktrees on this host.
The silent substitution is the real defect: nothing reports that the file set
changed, the check just starts examining something else. Same family as #62 and
#63.
Mounting the real gitdir does not help — the worktree's gitdir holds a
back-pointer to the worktree's own
.gitpath, which inside the container is/check, and git rejects the mismatch. Tested.Fix
Build the list on the host, where git resolves a worktree correctly, and pass it
in. The checker now gets the same tracked files whether it runs from the pinned
image or a local binary, and cannot substitute a different set without saying
so.
An empty list fails rather than skips — a skip means the linter was
unreachable; this means it was reachable with no trustworthy answer to what it
should check, which is exactly the state the fallback used to paper over.
Two details the fallback was hiding:
-z, because a tracked path may contain a space.with a Go stack trace rather than report anything.
Verified on the deploy host, after
make up, with the rendered files presentmain4 errors found/FAILmake validateafter the fixgit ls-files, and the container's own listing in a normal checkoutscripts/snmp-verify.sh→303: Trailing whitespace,FAILPASS, no panic (was a Go stack trace)Not the same as #175
#175 is validate running fewer checks than CI. This is validate running one CI
cannot fail. Both are #68's family, but separate changes in separate files.
🤖 Generated with Claude Code