Skip to content

fix(uncheck): write the pre-commit hook husky 9 and Vite+ actually run - #9

Merged
dinwwwh merged 2 commits into
mainfrom
claude/pensive-robinson-58ed93
Sep 23, 2026
Merged

dinwwwh merged 2 commits into
mainfrom
claude/pensive-robinson-58ed93

Conversation

@dinwwwh

@dinwwwh dinwwwh commented Sep 23, 2026

Copy link
Copy Markdown
Member

With husky 9 or Vite+ (vp config) managing git hooks, uncheck prepare --pre-commit now writes to .husky/pre-commit or .vite-hooks/pre-commit, the file their dispatcher runs. Before, it appended to the generated shim in .husky/_ or .vite-hooks/_ and reported the hook as written, but the line never ran: the dispatcher h the shim sources always exits first, and the next husky or vp config run wiped the line anyway. In those repos, commits were never checked.

Fixes

  • When the configured hooks folder holds the h dispatcher, the hook goes into the folder above it, next to the user's own commands. Lines added by hand stay, monorepo packages each keep their own line, and rerunning prepare stays idempotent.
  • A committed .husky/pre-commit keeps its file mode, so installs no longer leave a mode change in git status. The dispatcher runs the file with sh -e, so it doesn't need to be executable.
  • A core.hooksPath set by hand, such as .githooks, and the default .git/hooks work as before, including the executable bit.

Testing

  • New test sets core.hooksPath=.husky/_ with a stand-in dispatcher based on husky 9 and prepares from the root and from a nested package. Real git commits run every line through the dispatcher, and a failing line blocks the commit. The shim is left untouched. This test fails on the previous version.
  • The same test checks that a new .vite-hooks/pre-commit gets the #!/bin/sh header, and that an existing hook only gets the line appended.
  • New test checks that a hand-set core.hooksPath still gets the hook, executable, in the folder as configured.
  • The README section on prepare now describes the husky 9 and Vite+ behavior.

@pkg-pr-new

pkg-pr-new Bot commented Sep 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/uncheck@9

commit: 9ed89c4

@codecov

codecov Bot commented Sep 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.33333% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
packages/uncheck/src/commands/prepare.ts 83.33% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ No new issues found.

Reviewed changes

  • prepare.ts picks the file the dispatcher actually runs (prepare.ts:112-141) — when the configured hooks folder contains the h dispatcher, pre-commit is written one level up (.husky/ / .vite-hooks/) instead of the generated _/ shim that the dispatcher exits past. Covers husky 9 and Vite+, while default .git/hooks and hand-set core.hooksPath behave as before.
  • No chmod when dispatched — both dispatchers execute the project hook with sh -e, so the executable bit is unnecessary and preserving a committed hook's mode avoids a spurious git status entry. The default/hand-set paths still get 0o755.
  • Regression tests (command.test.ts:1418-1556) — real git commits through a faithful husky dispatcher from the root and a nested package, failing line blocks the commit, shim untouched, non-executable hook, Vite+ creates the parent-folder hook, and hand-set core.hooksPath=.githooks stays executable and in place.
  • README (README.md:135) documents the husky 9 / Vite+ behavior.

I verified the load-bearing external assumptions against vendor source rather than the repo's stand-ins. Husky v9.1.7 h computes s=$(dirname "$(dirname "$0")")/$n and runs sh -e "$s"; Vite+ packages/cli/src/config/hooks.ts installs _/h (mode 0o755), dispatches with "$__vp_shell" -e "$s", and itself treats _/h as the dispatcher marker. The h-existence heuristic therefore matches both tools' own contracts, and skipping chmod is correct for both. I also confirmed git rev-parse --git-path hooks returns a cwd-relative ../../.husky/_ from a nested package, so the existing path.resolve(cwd, hooks) resolution already lands correctly — the nested-package test exercises this. The new tests pass on head and, after reverting prepare.ts to the pre-fix commit, fail by writing .husky/_/pre-commit, so they are genuine regression coverage. The full uncheck prepare block passes (8/8), and oxfmt --check / oxlint are clean on both changed TS files.

One non-blocking observation, not a required change: if uncheck's prepare runs before the tool has generated _/h (e.g. a fresh clone with scripts ordered the other way), it will append to the shim for that run; once h exists the next install moves the line to the right folder, so the documented prepare: "husky && uncheck prepare --pre-commit" ordering keeps this from happening. No action needed.

Pullfrog  | View workflow run | Using DeepSeek Flash (default — pick a model for stronger reviews) | 𝕏

@dinwwwh
dinwwwh merged commit c00bd76 into main Sep 23, 2026
7 of 8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant