diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml index 56a3177b..2f2c7e09 100644 --- a/.github/workflows/run_tests.yml +++ b/.github/workflows/run_tests.yml @@ -43,8 +43,13 @@ jobs: run: working-directory: nuxt-app steps: + # Full history, not the default `fetch-depth: 1`: the fallow step below diffs against the PR's + # base branch, and a depth-1 checkout has neither that branch nor a merge base to diff against. + # The repository is ~11 MB, so fetching all of it costs less than the targeted-fetch dance. - name: Checkout repository uses: actions/checkout@v4 + with: + fetch-depth: 0 # Reads nuxt-app/.nvmrc rather than naming a version here, so CI and local development cannot # drift apart again — there is one file to change, not three. @@ -58,6 +63,22 @@ jobs: - name: Install dependencies run: npm ci + # Dead-code gate: reports unused exports, files, types and unresolved imports as annotations on + # the PR diff. `audit --base` scores only what the PR introduces, so the existing findings do not + # have to be fixed first and there is no baseline file to keep in sync. + # + # `continue-on-error` while the 26 pre-existing findings are still in the tree: a run that turns + # the job red on day one gets switched off rather than used. Remove it once those are cleaned up + # (tracked separately) — from then on a newly introduced dead export fails the job. + # + # Pinned to an exact version and run through npx rather than added to package.json: fallow is a + # ~54 MB platform binary plus a ~27 MB type-aware sidecar, and only CI runs it, so it should not + # land in every `npm ci` (local installs and the Vercel build included). Renovate is scoped to + # `nuxt-app/**`, so this pin is bumped by hand. + - name: Dead-code audit (fallow) + continue-on-error: true + run: npx --yes fallow@3.27.0 audit --base "origin/$GITHUB_BASE_REF" --format github-annotations + # Keep `prettier:check`, not `prettier` — the latter writes, so it would pass by mutating. # Without this step formatting is voluntary, which is how 90 files drifted after the Prettier # 3.2 -> 3.9 bump in Phase 2 with nothing noticing. diff --git a/nuxt-app/.fallowrc.json b/nuxt-app/.fallowrc.json new file mode 100644 index 00000000..2e936db2 --- /dev/null +++ b/nuxt-app/.fallowrc.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://raw.githubusercontent.com/fallow-rs/fallow/main/schema.json", + "minimumVersion": "3.27.0", + + // `shared-code` is a Nuxt alias (see nuxt.config.ts), not a package. fallow does not read + // nuxt.config.ts, so without these two entries every import of it is reported as an unresolved + // import (11 findings) plus one unlisted dependency — all false positives. + "ignoreUnresolvedImports": ["shared-code", "shared-code/**"], + "ignoreDependencies": ["shared-code"], + + "rules": { + // Off pre-emptively: this tree produces no class-member findings today, and the ones seen + // while evaluating fallow on this code were all false positives. + "unused-class-members": "off", + // No architecture boundaries and no rule packs are configured for this project. Saying so + // explicitly is what fallow asks for, instead of it reporting "nothing was measured". + "boundary-violation": "off", + "policy-violation": "off" + }, + + // Complexity is not a gate here: 104 of 1286 functions are already above the default thresholds, + // so a CRAP score would fail a PR for touching an already-complex function rather than for adding + // dead code. Duplication needs no entry — it is reported but never gates (`duplicates.threshold` + // defaults to 0 = no limit). + "health": { + "ignore": ["**"] + } +} diff --git a/nuxt-app/.gitignore b/nuxt-app/.gitignore index 9db7f79a..03c6560b 100644 --- a/nuxt-app/.gitignore +++ b/nuxt-app/.gitignore @@ -9,6 +9,9 @@ node_modules .output dist +# fallow's analysis cache and audit base snapshots +.fallow + # Playwright smoke-test artefacts playwright-report test-results