Git Hooks (Husky)
This repository uses Husky to run Git hooks from the root .husky/ directory. Hooks run automatically at specific points in the Git workflow to keep code style and commit messages consistent across the monorepo.
Hook scripts live in .husky/ (pre-commit, commit-msg).
Setup
Hooks are configured when you run at the repository root:
npm installThe prepare script runs automatically and points Git at .husky/.
NOTE
Husky lives in the root package.json because hooks apply to the entire monorepo. Vue lint still uses zmscitizenview; frontend ESLint uses zmsadmin, zmsstatistic, zmscalldisplay, and zmsticketprinter; docs formatting uses docs/.
After cloning, run npm install once at the repo root (also in the root README). For doc changes, install docs dependencies once: cd docs && npm install.
Hooks
pre-commit
No-op placeholder. Git always runs pre-commit before commit-msg; the real checks are in commit-msg so the commit subject is validated before Vue/docs/ESLint/PHP.
commit-msg
All checks run in this hook, in fail-fast order:
- Commit message — subject line from the message file Git passes to this hook
- Vue code style — Prettier check in
zmscitizenview(npm run lint) - Docs formatting — Prettier check in
docs/(npm run format:check) - Frontend ESLint —
npm run lintin stagedzmsadmin,zmsstatistic,zmscalldisplay, andzmsticketprinterJS (viazms-webwhen that container is running, otherwise on the host) - PHP code style — PHP CodeSniffer (PSR-12) across PHP modules via the
zms-webcontainer - PHP Mess Detector — PHPMD with root
phpmd.rules.xml(complexity, size, unused) viazms-web— same as CIphp-code-quality
Container detection
ESLint and the PHP checks detect your runtime automatically:
- Podman — if a container named
zms-webis running - Docker — fallback when Podman is unavailable
- ESLint fallback — if no container is running, ESLint runs on the host
- PHP skip — if no container is running (warning only, non-blocking)
Behavior
- Commit message, Vue, docs, and ESLint checks block the commit on failure
- ESLint runs only when JS,
eslint.config.*, orpackage.json/package-lock.jsonis staged in those four modules - PHP checks (PHPCS + PHPMD) run only when a
.phpfile orphpmd.rules.xmlis staged andzms-webis up; JS-only files in PHP modules do not trigger phpcs/phpmd
See also Code formatting for manual PHPCS/Prettier commands.
Commit message format (step 1):
type(PROJECT-123): commit message
type(PROJECT): commit message
type(PROJECT-1 PROJECT-2): commit message
type(PROJECT-1 PROJECT-2): type(PROJECT-3): commit messageThe ticket number is optional — use PROJECT-123 or just PROJECT (uppercase). Multiple tickets/projects may be space-separated in one scope; multiple type(scope): prefixes may be chained before the summary.
Merge commits
Git’s default merge subjects (for example Merge branch 'main' into feature-branch) are allowed automatically so git merge can finish without renaming the message. You can still use a conventional subject if you prefer, for example chore(ZMS): merge main into feature-branch.
Full rules, types, projects, and examples: Commit message convention.
Troubleshooting
Vue lint fails
cd zmscitizenview
npm run formatThen commit again.
Docs formatting fails
If Prettier reports issues under docs/:
cd docs
npm run formatInstall dependencies first if needed: cd docs && npm install.
Frontend ESLint fails
Fix the staged module (replace zmsadmin as needed):
podman exec -it zms-web bash -lc "cd zmsadmin && npm run fix"Or on the host: cd zmsadmin && npm run fix. Then commit again.
PHP CodeSniffer fails
The hook prints a fix command for your container engine:
# Podman
podman exec -it zms-web bash -lc "./cli modules loop 'vendor/bin/phpcbf --standard=psr12 src/'"
# Docker
docker exec -it zms-web bash -lc "./cli modules loop 'vendor/bin/phpcbf --standard=psr12 src/'"PHPMD fails
Re-run the same command CI uses (from the repo root inside zms-web):
# Podman
podman exec -it zms-web bash -lc "./cli modules loop 'vendor/bin/phpmd src/ text ../phpmd.rules.xml'"
# Docker
docker exec -it zms-web bash -lc "./cli modules loop 'vendor/bin/phpmd src/ text ../phpmd.rules.xml'"Thresholds and rules live in phpmd.rules.xml.
Container not detected
If you see a warning that zms-web is not running:
podman ps | grep zms-webStart the dev environment if needed (Devcontainer and Podman, Podman and Dev Containers). PHP checks are skipped when the container is down; the commit is not blocked for PHP alone.
Invalid commit message format
Common mistakes:
- Missing project:
feat: add feature - Lowercase project:
feat(zms-123): add feature - Missing colon:
feat(ZMS-123) add feature
Correct examples:
feat(ZMS-123): add featurechore(ZMSKVR): clean up
Merge blocked by commit-msg
If git merge fails with “Invalid commit message format” and a subject like Merge branch 'main' into …, update .husky/commit-msg from the latest main or feature branch (merge subjects should be accepted). As a workaround, finish the merge with a conventional message:
git commit -m "chore(ZMS): merge main into your-branch"Bypassing hooks
In emergencies, use Git’s --no-verify flag:
git commit --no-verify -m "feat(ZMS-123): urgent fix"CAUTION
Use --no-verify only when necessary. Bypassing hooks can hurt code quality and affect other contributors.