diff --git a/.gitattributes b/.gitattributes index c543351f6..c9944983b 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,4 +1,6 @@ # Sourced by /bin/sh inside the Lite container image: CRLF would break it. *.envsh text eol=lf +# Run by sh from Git Bash on Windows, which does not strip CR. +.husky/* text eol=lf # Demo fixtures record exact byte sizes of these files; never normalise them. public/demo/** -text diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 8042e79eb..002bd8a76 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -34,3 +34,28 @@ jobs: # from timing out on the shared runners; the longer per-test timeout # covers the jsdom-heavy suites. run: npx vitest run --pool=forks --maxWorkers=2 --testTimeout=15000 + + # The pre-commit hook lints only staged files and never runs on fork PRs, + # so this is the one place the whole tree is checked. + lint: + name: Lint and typecheck + runs-on: ubuntu-latest + timeout-minutes: 15 + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Node + uses: actions/setup-node@v4 + with: + node-version: 22 + cache: npm + + - name: Install dependencies + run: npm ci + + - name: Typecheck + run: npm run typecheck + + - name: Lint + run: npm run lint diff --git a/.husky/pre-commit b/.husky/pre-commit index 58f8aa205..5b09e6120 100644 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1 +1,6 @@ -npx tsc --noEmit && npx eslint . --ext .ts,.tsx +#!/bin/sh +# Typecheck the project (incremental, a few seconds warm) and lint only the +# staged files. The full lint and typecheck run in CI for every push and PR. +npx tsc --noEmit || exit 1 +files=$(git diff --cached --name-only --diff-filter=ACM -- '*.ts' '*.tsx' '*.js' '*.mjs') +[ -z "$files" ] || echo "$files" | xargs npx eslint --no-warn-ignored