Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,22 @@ jobs:
working-directory: frontend
run: npm audit --audit-level=high --omit=dev

# ESLint. This step did not exist until 2026-09-11, which made
# `eslint.config.js` decorative: the config was added specifically
# to fix `npm run lint` silently erroring with "couldn't find a
# config", and then nothing ever ran it. Thirteen errors
# accumulated in master unnoticed, and the eslint 9 -> 10 bump was
# reviewed by running the linter by hand because CI could not say
# anything about it.
#
# eslint exits non-zero on errors only, so the ~34 deliberate
# `warn`-level findings (React Compiler advisories, unused-vars)
# stay visible in the log without blocking a deploy. That split is
# the whole point — see the rule notes in eslint.config.js.
- name: Lint (eslint)
working-directory: frontend
run: npm run lint

# Vitest component tests — run BEFORE the build so a regression
# caught by tests doesn't get the chance to ship via a successful
# build. We have ~50 tests today (HelpTooltip, InstallCameraNodeCard,
Expand Down
19 changes: 19 additions & 0 deletions frontend/eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,25 @@ export default [
"react-hooks/purity": "warn",
"react-hooks/refs": "warn",
"react-hooks/preserve-manual-memoization": "warn",
// Same family, same reasoning — these two were missed when the
// list above was written, and they were the only thing keeping
// `npm run lint` at a non-zero exit:
//
// - `immutability` fires 12 times on the shape
// `useEffect(() => { loadThings() }, [...])` where `loadThings`
// is a `const` arrow function declared further down the
// component. It is correct at runtime — effects run after
// render, by which point the binding is initialized — so this
// is the compiler saying it cannot track the value, not a live
// bug. The fix is to hoist each loader above its effect (or
// wrap in useCallback), which is a real change to six files and
// belongs with the next edit to each.
// - `use-memo` fires once, on a non-inline first argument.
//
// Kept at `warn` rather than disabled: the diagnostic stays in
// the CI log, and lint can now be enforcing for everything else.
"react-hooks/immutability": "warn",
"react-hooks/use-memo": "warn",
},
},

Expand Down
Loading