Skip to content

Commit c789233

Browse files
committed
fix(hooks): resolve pnpm via mise
1 parent 0b0d392 commit c789233

File tree

3 files changed

+87
-4
lines changed

3 files changed

+87
-4
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,8 +183,8 @@
183183
"zod-to-json-schema": "^3.25.0"
184184
},
185185
"simple-git-hooks": {
186-
"pre-commit": "pnpm lint-staged && pnpm typecheck",
187-
"commit-msg": "node scripts/verify-commit.js"
186+
"pre-commit": "node scripts/pre-commit.mjs",
187+
"commit-msg": "node scripts/verify-commit.js \"$1\""
188188
},
189189
"lint-staged": {
190190
"*.js": [

scripts/pre-commit.mjs

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// @ts-check
2+
import { spawnSync } from 'node:child_process'
3+
4+
const tryCommand = (cmd, args) => {
5+
const result = spawnSync(cmd, args, { stdio: 'ignore' })
6+
if (result.error) {
7+
return false
8+
}
9+
return result.status === 0
10+
}
11+
12+
const resolvePnpm = () => {
13+
if (tryCommand('pnpm', ['--version'])) {
14+
return { cmd: 'pnpm', argsPrefix: [], source: 'PATH' }
15+
}
16+
if (
17+
tryCommand('mise', ['--version']) &&
18+
tryCommand('mise', ['exec', '--', 'pnpm', '--version'])
19+
) {
20+
return { cmd: 'mise', argsPrefix: ['exec', '--', 'pnpm'], source: 'mise' }
21+
}
22+
return null
23+
}
24+
25+
const runner = resolvePnpm()
26+
if (!runner) {
27+
console.error(
28+
[
29+
'ERROR: pnpm not found.',
30+
'Expected to find pnpm on PATH or via "mise exec -- pnpm".',
31+
'Fix one of:',
32+
'- Ensure pnpm is on PATH for git hooks',
33+
'- Or install/configure mise and run "mise install"',
34+
].join('\n'),
35+
)
36+
process.exit(1)
37+
}
38+
39+
const runPnpm = (args) => {
40+
const result = spawnSync(runner.cmd, [...runner.argsPrefix, ...args], {
41+
stdio: 'inherit',
42+
})
43+
if (result.error) {
44+
console.error(`ERROR: failed to run pnpm via ${runner.source}`)
45+
process.exit(1)
46+
}
47+
if (typeof result.status === 'number' && result.status !== 0) {
48+
process.exit(result.status)
49+
}
50+
if (result.signal) {
51+
process.exit(1)
52+
}
53+
}
54+
55+
const args = process.argv.slice(2)
56+
if (args.length > 0) {
57+
runPnpm(args)
58+
} else {
59+
runPnpm(['lint-staged'])
60+
runPnpm(['typecheck'])
61+
}

scripts/verify-commit.js

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
// @ts-check
22
import pico from 'picocolors'
3-
import { readFileSync } from 'node:fs'
3+
import { existsSync, readFileSync } from 'node:fs'
44
import path from 'node:path'
55

6-
const msgPath = path.resolve('.git/COMMIT_EDITMSG')
6+
const resolveMsgPath = () => {
7+
const argPath = process.argv[2]
8+
if (argPath && existsSync(argPath)) {
9+
return argPath
10+
}
11+
12+
const gitPath = path.resolve('.git')
13+
if (existsSync(gitPath)) {
14+
try {
15+
const stat = readFileSync(gitPath, 'utf-8').trim()
16+
if (stat.startsWith('gitdir:')) {
17+
const gitDir = stat.replace('gitdir:', '').trim()
18+
return path.resolve(gitDir, 'COMMIT_EDITMSG')
19+
}
20+
} catch {
21+
// ignore and fall through
22+
}
23+
}
24+
25+
return path.resolve('.git/COMMIT_EDITMSG')
26+
}
27+
28+
const msgPath = resolveMsgPath()
729
const msg = readFileSync(msgPath, 'utf-8').trim()
830

931
const commitRE =

0 commit comments

Comments
 (0)