From 6c7fbc7b948438b73106e04dd80a6d27c8458d36 Mon Sep 17 00:00:00 2001 From: Alpha Diop <90140491+alphajoop@users.noreply.github.com> Date: Sat, 19 Apr 2025 14:18:36 +0000 Subject: [PATCH] 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 --- .husky/pre-commit | 1 + codex-cli/.husky/_/husky.sh | 32 -------------------------------- codex-cli/.husky/pre-commit | 5 ----- codex-cli/.husky/pre-push | 5 ----- codex-cli/.lintstagedrc.json | 9 --------- codex-cli/package.json | 7 ++----- lint-staged.config.mjs | 4 ---- package.json | 13 ++++++++++++- pnpm-lock.yaml | 30 +++++++++++++++--------------- 9 files changed, 30 insertions(+), 76 deletions(-) create mode 100644 .husky/pre-commit delete mode 100644 codex-cli/.husky/_/husky.sh delete mode 100644 codex-cli/.husky/pre-commit delete mode 100644 codex-cli/.husky/pre-push delete mode 100644 codex-cli/.lintstagedrc.json delete mode 100644 lint-staged.config.mjs diff --git a/.husky/pre-commit b/.husky/pre-commit new file mode 100644 index 00000000..e02c24e2 --- /dev/null +++ b/.husky/pre-commit @@ -0,0 +1 @@ +pnpm lint-staged \ No newline at end of file diff --git a/codex-cli/.husky/_/husky.sh b/codex-cli/.husky/_/husky.sh deleted file mode 100644 index a09c6caf..00000000 --- a/codex-cli/.husky/_/husky.sh +++ /dev/null @@ -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 diff --git a/codex-cli/.husky/pre-commit b/codex-cli/.husky/pre-commit deleted file mode 100644 index f052379f..00000000 --- a/codex-cli/.husky/pre-commit +++ /dev/null @@ -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 diff --git a/codex-cli/.husky/pre-push b/codex-cli/.husky/pre-push deleted file mode 100644 index 33915254..00000000 --- a/codex-cli/.husky/pre-push +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env sh -. "$(dirname -- "$0")/_/husky.sh" - -# Run tests and type checking before pushing -npm test && npm run typecheck diff --git a/codex-cli/.lintstagedrc.json b/codex-cli/.lintstagedrc.json deleted file mode 100644 index 54b8b062..00000000 --- a/codex-cli/.lintstagedrc.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "*.{ts,tsx}": [ - "eslint --fix", - "prettier --write" - ], - "*.{json,md,yml}": [ - "prettier --write" - ] -} diff --git a/codex-cli/package.json b/codex-cli/package.json index d5c99c4d..b0a005d0 100644 --- a/codex-cli/package.json +++ b/codex-cli/package.json @@ -22,10 +22,8 @@ "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: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": "pnpm run release:readme && pnpm run release:version && pnpm install && pnpm run release:build-and-publish", - "prepare": "husky", - "pre-commit": "lint-staged" + "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" }, "files": [ "README.md", @@ -73,7 +71,6 @@ "eslint-plugin-react-refresh": "^0.4.19", "husky": "^9.1.7", "ink-testing-library": "^3.0.0", - "lint-staged": "^15.5.1", "prettier": "^2.8.7", "punycode": "^2.3.1", "ts-node": "^10.9.1", diff --git a/lint-staged.config.mjs b/lint-staged.config.mjs deleted file mode 100644 index 85af6291..00000000 --- a/lint-staged.config.mjs +++ /dev/null @@ -1,4 +0,0 @@ -export default { - "*.{js,jsx,ts,tsx}": ["pnpm prettier --write", "pnpm eslint --fix"], - "*.{json,md,yml,yaml}": ["pnpm prettier --write"], -}; diff --git a/package.json b/package.json index b6ce8ee4..a54db4ad 100644 --- a/package.json +++ b/package.json @@ -10,12 +10,14 @@ "test": "pnpm --filter @openai/codex run test", "lint": "pnpm --filter @openai/codex run lint", "typecheck": "pnpm --filter @openai/codex run typecheck", + "changelog": "git-cliff --config cliff.toml --output CHANGELOG.ignore.md $LAST_RELEASE_TAG..HEAD", "prepare": "husky", - "changelog": "git-cliff --config cliff.toml --output CHANGELOG.ignore.md $LAST_RELEASE_TAG..HEAD" + "husky:add": "husky add" }, "devDependencies": { "git-cliff": "^2.8.0", "husky": "^9.1.7", + "lint-staged": "^15.5.1", "prettier": "^3.5.3" }, "resolutions": { @@ -30,5 +32,14 @@ "node": ">=22", "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" } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d4bee57d..1539652c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,6 +19,9 @@ importers: husky: specifier: ^9.1.7 version: 9.1.7 + lint-staged: + specifier: ^15.5.1 + version: 15.5.1 prettier: specifier: ^3.5.3 version: 3.5.3 @@ -88,7 +91,7 @@ importers: devDependencies: '@eslint/js': specifier: ^9.22.0 - version: 9.25.0 + version: 9.24.0 '@types/diff': specifier: ^7.0.2 version: 7.0.2 @@ -137,9 +140,6 @@ importers: ink-testing-library: specifier: ^3.0.0 version: 3.0.0(@types/react@18.3.20) - lint-staged: - specifier: ^15.5.1 - version: 15.5.1 prettier: specifier: ^2.8.7 version: 2.8.8 @@ -344,8 +344,8 @@ packages: resolution: {integrity: sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} - '@eslint/js@9.25.0': - resolution: {integrity: sha512-iWhsUS8Wgxz9AXNfvfOPFSW4VfMXdVhp1hjkZVhXCrpgh/aLcc45rX6MPu+tIVUWDw0HfNwth7O28M1xDxNf9w==} + '@eslint/js@9.24.0': + resolution: {integrity: sha512-uIY/y3z0uvOGX8cp1C2fiC4+ZmBhp6yZWkojtHL1YEMnRt1Y63HB9TM17proGEmeG7HeUY+UP36F0aknKYTpYA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@humanwhocodes/config-array@0.13.0': @@ -2304,8 +2304,8 @@ packages: engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true - vite@6.3.2: - resolution: {integrity: sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg==} + vite@6.3.1: + resolution: {integrity: sha512-kkzzkqtMESYklo96HKKPE5KKLkC1amlsqt+RjFMlX2AvbRB/0wghap19NdBxxwGZ+h/C6DLCrcEphPIItlGrRQ==} engines: {node: ^18.0.0 || ^20.0.0 || >=22.0.0} hasBin: true peerDependencies: @@ -2595,7 +2595,7 @@ snapshots: '@eslint/js@8.57.1': {} - '@eslint/js@9.25.0': {} + '@eslint/js@9.24.0': {} '@humanwhocodes/config-array@0.13.0': dependencies: @@ -2851,13 +2851,13 @@ snapshots: chai: 5.2.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: '@vitest/spy': 3.1.1 estree-walker: 3.0.3 magic-string: 0.30.17 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': dependencies: @@ -4753,7 +4753,7 @@ snapshots: debug: 4.4.0 es-module-lexer: 1.6.0 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: - '@types/node' - jiti @@ -4768,7 +4768,7 @@ snapshots: - tsx - 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: esbuild: 0.25.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): dependencies: '@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/runner': 3.1.1 '@vitest/snapshot': 3.1.1 @@ -4800,7 +4800,7 @@ snapshots: tinyexec: 0.3.2 tinypool: 1.0.2 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) why-is-node-running: 2.3.0 optionalDependencies: