Problem
Contributors can push prettier-dirty code that only fails in CI. Concrete example from #988: a local npm run fmt reported the file as clean, but CI's pinned prettier disagreed.
Two root causes:
- No pre-commit guard.
npm run lint is only run explicitly. Forgetting to install/refresh dependencies in the package directory means npm run prettier can resolve to a different prettier binary on PATH (e.g. an npx-cached version) than the one CI uses after npm ci. Different prettier minor versions produce different line-break output.
- Inconsistent devDependency layout.
prettier-plugin-java@2.6.7 is hoisted to root package.json AND duplicated in every package. prettier@3.4.2 is duplicated in every package but not at the root. Same pinning concept, two different layouts.
Proposed solution
A. Add a pre-commit hook (husky + lint-staged)
- Add
husky and lint-staged as root devDependencies.
- Configure
husky to run lint-staged on pre-commit.
- Configure
lint-staged to run prettier (and eslint) on staged files using the workspace-local pinned prettier.
- Add a
prepare script in root package.json so npm install wires up the hook automatically.
This makes it physically impossible to push prettier-dirty code without --no-verify.
B. Consolidate the prettier devDependency
- Move
prettier@<version> from every packages/*/package.json into the root package.json devDependencies (next to the already-hoisted prettier-plugin-java).
- Optionally bump to the latest 3.x while we're at it.
- Per-package
npm run prettier scripts stay; they'll resolve prettier from the hoisted node_modules/.bin since npm workspaces hoist by default.
Single source of truth for the version; no more drift between packages.
Out of scope
- Bumping prettier itself (can be a follow-up to keep this change reviewable).
Problem
Contributors can push prettier-dirty code that only fails in CI. Concrete example from #988: a local
npm run fmtreported the file as clean, but CI's pinned prettier disagreed.Two root causes:
npm run lintis only run explicitly. Forgetting to install/refresh dependencies in the package directory meansnpm run prettiercan resolve to a different prettier binary on PATH (e.g. an npx-cached version) than the one CI uses afternpm ci. Different prettier minor versions produce different line-break output.prettier-plugin-java@2.6.7is hoisted to rootpackage.jsonAND duplicated in every package.prettier@3.4.2is duplicated in every package but not at the root. Same pinning concept, two different layouts.Proposed solution
A. Add a pre-commit hook (
husky+lint-staged)huskyandlint-stagedas root devDependencies.huskyto runlint-stagedonpre-commit.lint-stagedto run prettier (and eslint) on staged files using the workspace-local pinned prettier.preparescript in rootpackage.jsonsonpm installwires up the hook automatically.This makes it physically impossible to push prettier-dirty code without
--no-verify.B. Consolidate the prettier devDependency
prettier@<version>from everypackages/*/package.jsoninto the rootpackage.jsondevDependencies (next to the already-hoistedprettier-plugin-java).npm run prettierscripts stay; they'll resolve prettier from the hoistednode_modules/.binsince npm workspaces hoist by default.Single source of truth for the version; no more drift between packages.
Out of scope