CI ran lint with continue-on-error because 23 errors predated it. All are fixed, so the flag is gone and a typecheck step is added beside it — nothing else in CI compiles the test files, so a type error in a fixture could only ever be found on a developer's machine. Real fixes, no blanket disables and no suppressions: - react-hooks/set-state-in-effect (6): each was "reset or seed state when an input changes", so each becomes a state adjustment during render behind a previous-value guard — the documented React pattern for it. Two were also latent bugs. transactions/page.tsx depended on `others`, rebuilt by .filter() every render, so the effect already ran every render, one commit late. shared/page.tsx depended on the `tagIds` array identity, so the row window was reset more often than "changing any filter" claims — including after "Show more", the one interaction it must not undo; the key now joins by value. csv-import-modal reads localStorage once at mount, which is a lazy useState initializer, not an effect (SSR-guarded, though the modal is mounted from client state and never prerenders). - react-hooks/static-components (3): SortIcon was declared inside SharedPage, making it a new component type on every render. Hoisted to module scope with the sort state passed as props. - @typescript-eslint/no-explicit-any (9): the dynamically imported route handlers in two integration tests. Typed as their real signatures with one `as unknown as NextRequest` cast at the fixture boundary, so the call sites and response bodies get checked instead of opted out. - react/no-unescaped-entities (5): exact-equivalent entities (', "), so no rendered text changes. Also fixes the one pre-existing tsc error (unit/order-ingestion.test.ts:511): `options` is optional, and `?? 0` keeps the assertion failing on an absent list rather than silencing it with a non-null bang. 9 warnings remain (no-unused-vars, exhaustive-deps). eslint exits 0 on warnings, so lint blocks on errors only — deliberately, since none of the remaining warnings should stop a push.
40 lines
1.5 KiB
YAML
40 lines
1.5 KiB
YAML
name: ci
|
|
on:
|
|
push:
|
|
pull_request:
|
|
|
|
jobs:
|
|
lint-test:
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- uses: actions/checkout@v4
|
|
- uses: actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
- name: Install
|
|
run: npm ci
|
|
# The Prisma client is generated into src/generated/prisma, which is
|
|
# gitignored — so a fresh checkout has no client and every test that
|
|
# reaches src/lib/db.ts dies on "Cannot find package
|
|
# '@/generated/prisma/client'". Schema-only, so it needs no database.
|
|
# Without this the pipeline had been red on every run since at least
|
|
# ae0c34f, which is how the failure stayed invisible: it looked like
|
|
# the normal colour.
|
|
- name: Generate Prisma client
|
|
run: npx prisma generate
|
|
# Blocking since #79. It was advisory from 2026-07-19 while 23 errors sat
|
|
# across the pages and the integration tests; those are now fixed, so a
|
|
# new one must not be able to slip in behind a green tick. Warnings are
|
|
# still allowed (eslint exits 0 on them) — there are 9 left, all
|
|
# `no-unused-vars` or `exhaustive-deps` advisories, none of which should
|
|
# stop a push.
|
|
- name: Lint
|
|
run: npm run lint
|
|
# Typecheck is separate from `next build`: nothing else in CI compiles the
|
|
# test files, so a type error in a fixture could only ever be found on a
|
|
# developer's machine.
|
|
- name: Typecheck
|
|
run: npx tsc --noEmit
|
|
- name: Unit tests
|
|
run: npm test
|