build: add a browser-test exclusion check and a pre-push static-check hook - #500
Conversation
… hook npm run check:browser-excludes finds tests that import a browser driver and asks `vitest list` whether the CI config still collects them; wired into CI. npm install now also installs a marker-owned pre-push hook that runs the static CI checks (~15s). Skip with CODEMAN_SKIP_PREPUSH=1; hand-written hooks are left alone.
|
Thanks @aakhter, this is a nice piece of tooling: a CI check that asks 1. The hooks dir can resolve outside the repo (must fix)
Please only return a hooks dir that is the repo's own: 2. The hook checks the working tree, not the pushed commit
Small things (I can do these at merge time if you prefer)
Once 1 and 2 are in, I will merge. If you would rather land the checker first, splitting it into its own PR works too and I can merge that part straight away. |
resolveGitHooksDir now returns a directory only when it is the repo's own <git-common-dir>/hooks (compared on canonical paths), so a core.hooksPath elsewhere, global or repo-local, is never written to by postinstall, while a core.hooksPath pointing back at the repo's own .git/hooks still resolves. The pre-push hook skips with a one-line notice when a pushed ref is not the checked-out HEAD (tags peeled) or when git status shows uncommitted or untracked changes under a path the checks read (src, config, scripts, test, package.json, package-lock.json, install.sh), since the checks read the working tree rather than the pushed commit. Also: honest timing (~10-40s instead of ~15s), CLAUDE.md Session Safety note on CODEMAN_SKIP_PREPUSH for another session's WIP, 14 (not 9) Playwright tests, and a note that the browser-excludes check only sees direct imports.
|
Thanks for the careful review and the repro.
I kept it as one PR since both asks were concrete, but happy to split the checker out if you'd still prefer that. |
- pre-push hook: skip with a notice when npm is not on PATH (GUI git clients and IDEs often run hooks with a minimal PATH), instead of blocking every push on "npm: not found"; real-push test with a stripped PATH - test/git-hooks.test.ts: pin GIT_CONFIG_NOSYSTEM=1 and GIT_CONFIG_GLOBAL=/dev/null around the resolveGitHooksDir tests, so an exported global or a system core.hooksPath no longer fails them - watch tsconfig.json, .prettierignore and .editorconfig too: typecheck and format:check read them - check:browser-excludes: fail loudly when the vitest list output and the walked test/**/*.test.ts tree share no path (format drift would otherwise pass vacuously) - Reword the PRE_PUSH_MARKER comment: bumping its version would make every installed v1 hook read as foreign and never refresh again. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
Merged, and it ships in 1.33.2. Thanks @aakhter. Both review points came back exactly as asked, with real-push tests behind them, and asking vitest itself what CI collects (instead of re-implementing the globs) is a nice design. Applied on the way in:
|
What
Two small pieces of developer tooling. Neither changes runtime behaviour.
1.
npm run check:browser-excludes(new CI step in the static job)npm test/test:cimust never collect a test that drives a real browser: a runner with no chromium dies withbrowserType.launch: Executable doesn't exist. The exclusions live inBROWSER_TEST_GLOBS(config/test-suites.ts), which is maintained by hand, so a new browser test only gets excluded if someone remembers. When they don't, the test passes on every machine that has runnpx playwright installand fails only on a clean runner.The checker closes that gap:
playwright,@playwright/test,playwright-core,puppeteerorpuppeteer-core. Several existing browser tests predate the*.browser.test.tsconvention, so a filename match would miss them.vitest list --config config/vitest.ci.config.ts --filesOnly), not by re-implementing glob matching, so it cannot disagree with what CI actually collects. An empty collection is treated as a failure rather than a vacuous pass.On current master it passes: 23 browser-driven files, all excluded, 435 files collected.
2. A pre-push hook installed by
npm installpostinstall.jsnow also installs apre-pushhook that runs the static CI checks before a push:check:lockfile,generate:cli-catalog --check,check:browser-excludes,check:frontend-syntax,format:check,lint,typecheck. That takes about 15s, and failures surface locally instead of after a CI round-trip. It deliberately skips the test suites, which take minutes.# codeman-managed-hookmarker is left alone, so a contributor's own hook survivesnpm install. (The existing pre-commit installer overwrites; that is unchanged.)git rev-parse --git-path hooks, so it works in a worktree, where.gitis a file. The pre-commit installer now uses the same resolution.node_modulesis missing or the push is a branch deletion.CODEMAN_SKIP_PREPUSH=1bypasses it.npm install.Docs: CLAUDE.md (commands table + CI note),
.github/CONTRIBUTING.md,docs/wiki/Contributing.md.Testing
test/check-browser-test-excludes.test.ts(15) andtest/git-hooks.test.ts(29). The installer tests use throwawaygit initrepos, never the checkout they run in. Both files are collected by the CI config.BROWSER_TEST_GLOBSmakes the checker fail and name that file.CODEMAN_SKIP_PREPUSHbypass each fails the hook tests.format:check.CODEMAN_SKIP_PREPUSH=1and a deletion push both skipped.typecheck(includingconfig/tsconfig.scripts.json),lint,format:check,check:frontend-syntaxandcheck:lockfileare clean. This branch's own push went through the installed hook.