fix: configure husky and lint-staged for pnpm monorepo (#384)
# Improve Developer Experience with Husky and lint-staged for pnpm Monorepo ## Summary This PR enhances the developer experience by configuring Husky and lint-staged to work properly with our pnpm monorepo structure. It centralizes Git hooks at the root level and ensures consistent code quality across the project. ## Changes - Centralized Husky and lint-staged configuration at the monorepo root - Added pre-commit hook that runs lint-staged to enforce code quality - Configured lint-staged to: - Format JSON, MD, and YAML files with Prettier - Lint and typecheck TypeScript files before commits - Fixed release script in codex-cli package.json (changed "pmpm" to "npm publish") - Removed duplicate Husky and lint-staged configurations from codex-cli package.json ## Benefits - **Consistent Code Quality**: Ensures all committed code meets project standards - **Automated Formatting**: Automatically formats code during commits - **Early Error Detection**: Catches type errors and lint issues before they're committed - **Centralized Configuration**: Easier to maintain and update in one place - **Improved Collaboration**: Ensures consistent code style across the team ## Future Improvements We could further enhance this setup by **Commit Message Validation**: Add commitlint to enforce conventional commit messages --------- Co-authored-by: Thibault Sottiaux <tibo@openai.com>
This commit is contained in:
1
.husky/pre-commit
Normal file
1
.husky/pre-commit
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pnpm lint-staged
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
if [ -z "$husky_skip_init" ]; then
|
|
||||||
debug () {
|
|
||||||
if [ "$HUSKY_DEBUG" = "1" ]; then
|
|
||||||
echo "husky (debug) - $1"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
readonly hook_name="$(basename -- "$0")"
|
|
||||||
debug "starting $hook_name..."
|
|
||||||
|
|
||||||
if [ "$HUSKY" = "0" ]; then
|
|
||||||
debug "HUSKY env variable is set to 0, skipping hook"
|
|
||||||
exit 0
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -f ~/.huskyrc ]; then
|
|
||||||
debug "sourcing ~/.huskyrc"
|
|
||||||
. ~/.huskyrc
|
|
||||||
fi
|
|
||||||
|
|
||||||
readonly husky_skip_init=1
|
|
||||||
export husky_skip_init
|
|
||||||
sh -e "$0" "$@"
|
|
||||||
exitCode="$?"
|
|
||||||
|
|
||||||
if [ $exitCode != 0 ]; then
|
|
||||||
echo "husky - $hook_name hook exited with code $exitCode (error)"
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $exitCode
|
|
||||||
fi
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
# Run lint-staged to check files that are about to be committed
|
|
||||||
npm run pre-commit
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
. "$(dirname -- "$0")/_/husky.sh"
|
|
||||||
|
|
||||||
# Run tests and type checking before pushing
|
|
||||||
npm test && npm run typecheck
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
{
|
|
||||||
"*.{ts,tsx}": [
|
|
||||||
"eslint --fix",
|
|
||||||
"prettier --write"
|
|
||||||
],
|
|
||||||
"*.{json,md,yml}": [
|
|
||||||
"prettier --write"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@@ -22,10 +22,8 @@
|
|||||||
"build:dev": "NODE_ENV=development node build.mjs --dev && NODE_OPTIONS=--enable-source-maps node dist/cli-dev.js",
|
"build:dev": "NODE_ENV=development node build.mjs --dev && NODE_OPTIONS=--enable-source-maps node dist/cli-dev.js",
|
||||||
"release:readme": "cp ../README.md ./README.md",
|
"release:readme": "cp ../README.md ./README.md",
|
||||||
"release:version": "TS=$(date +%y%m%d%H%M) && sed -E -i'' -e \"s/\\\"0\\.1\\.[0-9]{10}\\\"/\\\"0.1.${TS}\\\"/g\" package.json src/utils/session.ts",
|
"release:version": "TS=$(date +%y%m%d%H%M) && sed -E -i'' -e \"s/\\\"0\\.1\\.[0-9]{10}\\\"/\\\"0.1.${TS}\\\"/g\" package.json src/utils/session.ts",
|
||||||
"release:build-and-publish": "pmpm run build && pmpm publish",
|
"release:build-and-publish": "pnpm run build && npm publish",
|
||||||
"release": "pnpm run release:readme && pnpm run release:version && pnpm install && pnpm run release:build-and-publish",
|
"release": "pnpm run release:readme && pnpm run release:version && pnpm install && pnpm run release:build-and-publish"
|
||||||
"prepare": "husky",
|
|
||||||
"pre-commit": "lint-staged"
|
|
||||||
},
|
},
|
||||||
"files": [
|
"files": [
|
||||||
"README.md",
|
"README.md",
|
||||||
@@ -73,7 +71,6 @@
|
|||||||
"eslint-plugin-react-refresh": "^0.4.19",
|
"eslint-plugin-react-refresh": "^0.4.19",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
"ink-testing-library": "^3.0.0",
|
"ink-testing-library": "^3.0.0",
|
||||||
"lint-staged": "^15.5.1",
|
|
||||||
"prettier": "^2.8.7",
|
"prettier": "^2.8.7",
|
||||||
"punycode": "^2.3.1",
|
"punycode": "^2.3.1",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
export default {
|
|
||||||
"*.{js,jsx,ts,tsx}": ["pnpm prettier --write", "pnpm eslint --fix"],
|
|
||||||
"*.{json,md,yml,yaml}": ["pnpm prettier --write"],
|
|
||||||
};
|
|
||||||
13
package.json
13
package.json
@@ -10,12 +10,14 @@
|
|||||||
"test": "pnpm --filter @openai/codex run test",
|
"test": "pnpm --filter @openai/codex run test",
|
||||||
"lint": "pnpm --filter @openai/codex run lint",
|
"lint": "pnpm --filter @openai/codex run lint",
|
||||||
"typecheck": "pnpm --filter @openai/codex run typecheck",
|
"typecheck": "pnpm --filter @openai/codex run typecheck",
|
||||||
|
"changelog": "git-cliff --config cliff.toml --output CHANGELOG.ignore.md $LAST_RELEASE_TAG..HEAD",
|
||||||
"prepare": "husky",
|
"prepare": "husky",
|
||||||
"changelog": "git-cliff --config cliff.toml --output CHANGELOG.ignore.md $LAST_RELEASE_TAG..HEAD"
|
"husky:add": "husky add"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"git-cliff": "^2.8.0",
|
"git-cliff": "^2.8.0",
|
||||||
"husky": "^9.1.7",
|
"husky": "^9.1.7",
|
||||||
|
"lint-staged": "^15.5.1",
|
||||||
"prettier": "^3.5.3"
|
"prettier": "^3.5.3"
|
||||||
},
|
},
|
||||||
"resolutions": {
|
"resolutions": {
|
||||||
@@ -30,5 +32,14 @@
|
|||||||
"node": ">=22",
|
"node": ">=22",
|
||||||
"pnpm": ">=9.0.0"
|
"pnpm": ">=9.0.0"
|
||||||
},
|
},
|
||||||
|
"lint-staged": {
|
||||||
|
"*.json": "prettier --write",
|
||||||
|
"*.md": "prettier --write",
|
||||||
|
".github/workflows/*.yml": "prettier --write",
|
||||||
|
"**/*.{js,ts,tsx}": [
|
||||||
|
"pnpm --filter @openai/codex run lint",
|
||||||
|
"pnpm --filter @openai/codex run typecheck"
|
||||||
|
]
|
||||||
|
},
|
||||||
"packageManager": "pnpm@10.8.1"
|
"packageManager": "pnpm@10.8.1"
|
||||||
}
|
}
|
||||||
|
|||||||
30
pnpm-lock.yaml
generated
30
pnpm-lock.yaml
generated
@@ -19,6 +19,9 @@ importers:
|
|||||||
husky:
|
husky:
|
||||||
specifier: ^9.1.7
|
specifier: ^9.1.7
|
||||||
version: 9.1.7
|
version: 9.1.7
|
||||||
|
lint-staged:
|
||||||
|
specifier: ^15.5.1
|
||||||
|
version: 15.5.1
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.5.3
|
specifier: ^3.5.3
|
||||||
version: 3.5.3
|
version: 3.5.3
|
||||||
@@ -88,7 +91,7 @@ importers:
|
|||||||
devDependencies:
|
devDependencies:
|
||||||
'@eslint/js':
|
'@eslint/js':
|
||||||
specifier: ^9.22.0
|
specifier: ^9.22.0
|
||||||
version: 9.25.0
|
version: 9.24.0
|
||||||
'@types/diff':
|
'@types/diff':
|
||||||
specifier: ^7.0.2
|
specifier: ^7.0.2
|
||||||
version: 7.0.2
|
version: 7.0.2
|
||||||
@@ -137,9 +140,6 @@ importers:
|
|||||||
ink-testing-library:
|
ink-testing-library:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0(@types/react@18.3.20)
|
version: 3.0.0(@types/react@18.3.20)
|
||||||
lint-staged:
|
|
||||||
specifier: ^15.5.1
|
|
||||||
version: 15.5.1
|
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^2.8.7
|
specifier: ^2.8.7
|
||||||
version: 2.8.8
|
version: 2.8.8
|
||||||
@@ -344,8 +344,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
|
resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
|
||||||
'@eslint/js@9.25.0':
|
'@eslint/js@9.24.0':
|
||||||
resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==}
|
resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@humanwhocodes/config-array@0.13.0':
|
'@humanwhocodes/config-array@0.13.0':
|
||||||
@@ -2304,8 +2304,8 @@ packages:
|
|||||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
vite@6.3.2:
|
vite@6.3.1:
|
||||||
resolution: {integrity: sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==}
|
resolution: {integrity: sha512-kkzzkqtMESYklo96HKKPE5KKLkC1amlsqt+RjFMlX2AvbRB/0wghap19NdBxxwGZ+h/C6DLCrcEphPIItlGrRQ==}
|
||||||
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -2595,7 +2595,7 @@ snapshots:
|
|||||||
|
|
||||||
'@eslint/js@8.57.1': {}
|
'@eslint/js@8.57.1': {}
|
||||||
|
|
||||||
'@eslint/js@9.25.0': {}
|
'@eslint/js@9.24.0': {}
|
||||||
|
|
||||||
'@humanwhocodes/config-array@0.13.0':
|
'@humanwhocodes/config-array@0.13.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -2851,13 +2851,13 @@ snapshots:
|
|||||||
chai: 5.2.0
|
chai: 5.2.0
|
||||||
tinyrainbow: 2.0.0
|
tinyrainbow: 2.0.0
|
||||||
|
|
||||||
'@vitest/mocker@3.1.1(vite@6.3.2(@types/node@22.14.1)(yaml@2.7.1))':
|
'@vitest/mocker@3.1.1(vite@6.3.1(@types/node@22.14.1)(yaml@2.7.1))':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/spy': 3.1.1
|
'@vitest/spy': 3.1.1
|
||||||
estree-walker: 3.0.3
|
estree-walker: 3.0.3
|
||||||
magic-string: 0.30.17
|
magic-string: 0.30.17
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
vite: 6.3.2(@types/node@22.14.1)(yaml@2.7.1)
|
vite: 6.3.1(@types/node@22.14.1)(yaml@2.7.1)
|
||||||
|
|
||||||
'@vitest/pretty-format@3.1.1':
|
'@vitest/pretty-format@3.1.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -4753,7 +4753,7 @@ snapshots:
|
|||||||
debug: 4.4.0
|
debug: 4.4.0
|
||||||
es-module-lexer: 1.6.0
|
es-module-lexer: 1.6.0
|
||||||
pathe: 2.0.3
|
pathe: 2.0.3
|
||||||
vite: 6.3.2(@types/node@22.14.1)(yaml@2.7.1)
|
vite: 6.3.1(@types/node@22.14.1)(yaml@2.7.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/node'
|
- '@types/node'
|
||||||
- jiti
|
- jiti
|
||||||
@@ -4768,7 +4768,7 @@ snapshots:
|
|||||||
- tsx
|
- tsx
|
||||||
- yaml
|
- yaml
|
||||||
|
|
||||||
vite@6.3.2(@types/node@22.14.1)(yaml@2.7.1):
|
vite@6.3.1(@types/node@22.14.1)(yaml@2.7.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
esbuild: 0.25.2
|
esbuild: 0.25.2
|
||||||
fdir: 6.4.3(picomatch@4.0.2)
|
fdir: 6.4.3(picomatch@4.0.2)
|
||||||
@@ -4784,7 +4784,7 @@ snapshots:
|
|||||||
vitest@3.1.1(@types/node@22.14.1)(yaml@2.7.1):
|
vitest@3.1.1(@types/node@22.14.1)(yaml@2.7.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@vitest/expect': 3.1.1
|
'@vitest/expect': 3.1.1
|
||||||
'@vitest/mocker': 3.1.1(vite@6.3.2(@types/node@22.14.1)(yaml@2.7.1))
|
'@vitest/mocker': 3.1.1(vite@6.3.1(@types/node@22.14.1)(yaml@2.7.1))
|
||||||
'@vitest/pretty-format': 3.1.1
|
'@vitest/pretty-format': 3.1.1
|
||||||
'@vitest/runner': 3.1.1
|
'@vitest/runner': 3.1.1
|
||||||
'@vitest/snapshot': 3.1.1
|
'@vitest/snapshot': 3.1.1
|
||||||
@@ -4800,7 +4800,7 @@ snapshots:
|
|||||||
tinyexec: 0.3.2
|
tinyexec: 0.3.2
|
||||||
tinypool: 1.0.2
|
tinypool: 1.0.2
|
||||||
tinyrainbow: 2.0.0
|
tinyrainbow: 2.0.0
|
||||||
vite: 6.3.2(@types/node@22.14.1)(yaml@2.7.1)
|
vite: 6.3.1(@types/node@22.14.1)(yaml@2.7.1)
|
||||||
vite-node: 3.1.1(@types/node@22.14.1)(yaml@2.7.1)
|
vite-node: 3.1.1(@types/node@22.14.1)(yaml@2.7.1)
|
||||||
why-is-node-running: 2.3.0
|
why-is-node-running: 2.3.0
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
|||||||
Reference in New Issue
Block a user