Skip to content

chore: add pre-commit hook using nx format + affected lint - #282

Merged
konowrockis merged 1 commit into
mainfrom
chore/pre-commit-lint-staged
Jun 24, 2026
Merged

konowrockis merged 1 commit into
mainfrom
chore/pre-commit-lint-staged

Conversation

@claude

@claude claude Bot commented Jun 24, 2026 •

Copy link
Copy Markdown

Requested by Sebastian Konowrocki · Slack thread

Before: Husky was installed and only enforced commit-message linting (.husky/commit-msg → commitlint). Nothing checked the staged code itself before a commit, so lint/format issues were only caught later in CI.

After: Committing formats and lints what you are committing using the repo's existing nx tooling — no new dependency is added. Formatting fixes are re-staged so they land in the commit, and only the affected projects are linted, keeping it fast.

How:

  • .husky/pre-commit (same shebang-less Husky v9 style as .husky/commit-msg) runs:
    • npx nx format:write --uncommitted — formats the changed files via nx's built-in Prettier.
    • git add -u — re-stages those formatting fixes, because nx format:write rewrites files but does not git add them, so without this the fixes would not be part of the commit.
    • npx nx affected -t lint --uncommitted — runs the lint target for the projects affected by the changes.
  • Drops the lint-staged devDependency and its package.json config block; package-lock.json is regenerated accordingly.

Verified locally: nx format:write --uncommitted and nx affected -t lint --uncommitted run cleanly, and a staged-edit dry run confirmed formatting fixes are re-staged and lint errors block the commit.


Generated by Claude Code

Comment thread package.json Outdated
"jsdom": "~22.1.0",
"jsonc-eslint-parser": "^2.1.0",
"lerna": "^8.0.0",
"lint-staged": "^15.0.0",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a separate package for that? Couldn't we do nx affected --uncommited?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dobre pytanie. Sprawdziłem konkretnie, jak to wygląda w tym repo:

  • nx affected -t lint używa targetu lint, który jest zdefiniowany jako eslint . z cwd ustawionym na katalog projektu. Czyli działa na granularności całego projektu — przy zmianie jednego pliku przelintowałby cały affected package, a nie tylko zastagowane pliki.
  • Nie mamy w ogóle targetu prettier/format na projektach. Formatowanie przez nx jest dostępne tylko jako wbudowane nx format:write (i tak, --uncommitted istnieje). Warto zauważyć, że CI w ogóle nie odpala prettiera — leci tylko nx affected:lint.
  • --uncommitted działa na całym working tree, łącznie ze zmianami niezastagowanymi, i nie re-staguje auto-fixów. lint-staged działa dokładnie na zastagowanych plikach i dostawia poprawki z powrotem do indeksu.
  • Caveat z częściowym stagowaniem (git add -p): lint-staged stashuje niezastagowaną resztę i operuje tylko na zastagowanym fragmencie; nx ... --uncommitted ruszyłby też niezastagowaną resztę pliku, co przy częściowym commicie potrafi zaskoczyć.

Tradeoff w skrócie:

  • lint-staged — precyzja na poziomie zastagowanych plików + auto-re-stage, kosztem jednej devDependency.
  • nx (format:write --uncommitted + affected -t lint --uncommitted) — bez nowej zależności i spójne z konwencją CI (nx affected), ale granularność na poziomie projektu, formatowanie tylko whole-file, brak re-stage i niezgrabne zachowanie przy częściowo zastagowanych plikach.

Moim zdaniem dla hooka pre-commit (gdzie chodzi właśnie o "popraw dokładnie to, co commituję") lint-staged lepiej pasuje do use case'u i ta jedna zależność się broni. Ale jest to realny wybór projektowy — jeśli wolicie zero nowych zależności i trzymanie się nx affected, chętnie przepiszę hooka na podejście oparte na nx format:write --uncommitted + nx affected -t lint --uncommitted. Którą wersję wolisz?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wolimy wersję z nx

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A są jeszcze jakieś inne opcje w nxie?

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DXXPnGepYUGie3we1X9PTR
@claude
claude Bot force-pushed the chore/pre-commit-lint-staged branch from f24f2a6 to 041c9cf Compare June 24, 2026 14:55
@claude claude Bot changed the title chore: add pre-commit hook running lint-staged chore: add pre-commit hook using nx format + affected lint Jun 24, 2026
@claude

claude Bot commented Jun 24, 2026

Copy link
Copy Markdown
Author

Przerobiłem hook na wariant oparty o nx — bez dodawania nowej zależności (lint-staged usunięty z package.json i z lockfile'a).

Hook (.husky/pre-commit):

npx nx format:write --uncommitted
git add -u
npx nx affected -t lint --uncommitted

Re-staging: nx format:write poprawia pliki, ale ich nie dodaje do indexu, więc bez git add -u poprawki formatowania nie trafiłyby do commita. Dlatego po formatowaniu re-stage'uję zmiany. Sprawdzone lokalnie na próbnym, zastage'owanym edycie: formatowanie ląduje w commicie, a błąd lintu blokuje commit.

@Komoszek — co do innych opcji w nx (v22), menu pod pre-commit wygląda tak:

  • nx format:write (fix) / nx format:check (tylko weryfikacja, fail bez zmian) — wbudowany Prettier. Źródła zmian: --uncommitted, --untracked, --files=<lista>, albo --base=X --head=Y.
  • nx affected -t <target> z tymi samymi źródłami zmian: --uncommitted, --untracked, --files=<lista>, --base/--head.
  • Najbardziej precyzyjnie (najbliżej lint-staged, ale wciąż w nx): zawężenie do dokładnie zastage'owanych plików przez --files, np.:
    nx format:write --files="$(git diff --cached --name-only --diff-filter=ACMR | paste -sd, -)"
    W odróżnieniu od --uncommitted, które łapie też niezastage'owane zmiany w working tree.

Dlaczego --uncommitted, a nie --files: prostszy i bardziej odporny hook (brak kombinowania z subshellem/listą plików w shellu), a różnica jest istotna tylko gdy ktoś świadomie commit'uje część zmian z pliku — wtedy i tak chcemy mieć cały plik sformatowany. Jeśli wolicie maksymalną precyzję (format/lint wyłącznie zastage'owanych plików), mogę bez problemu przełączyć na wariant z --files + git add -u.

Jedna uwaga praktyczna: target lint to eslint . na poziomie projektu, więc nx affected -t lint lintuje cały affected projekt, nie pojedyncze pliki — granularność per-plik w nx jest natywna tylko dla format.

@konowrockis
konowrockis merged commit 07a3ddf into main Jun 24, 2026
1 check passed
@konowrockis
konowrockis deleted the chore/pre-commit-lint-staged branch June 24, 2026 18:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants