You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ci: enforce unit and e2e test coverage for apps/website (#15274)
*PR Created by the Glary-Bot Agent*
---
## Problem
`apps/website` sits outside every test-enforcement mechanism in this
repo. Three independent gaps, each sufficient on its own:
1. **Unit tests never run.** `changes-filter` computes `should-run` by
excluding `apps/**`, and `ci-tests-unit.yaml` is gated on it. A
website-only PR runs no unit tests at all. The **423 tests already
committed** under `apps/website/src` have therefore never executed in CI
— and one was **already failing on `main`** (`IMAGE_URL` accepted `jpg`
but not `jpeg`; the asset is `16x9-thumb-01.jpeg`). Nobody knew.
2. **Codecov cannot see the website.** Root Vitest coverage is scoped to
`src/**`, so website files appear in no report. Untested website code
cannot lower any number, and `codecov/patch` is `informational: true`
(passes unconditionally) regardless.
3. **CodeRabbit explicitly exempts it.** The e2e regression check says
verbatim: *"Do not fail if the changes are exclusively in
`apps/website`"*, and its path matcher only covers `src/`/`packages/`.
Net effect: an agent could add an entire untested, un-e2e'd website
feature and every check would be green.
## Changes
**`ci-website-unit.yaml`** (new) — runs the website Vitest suite with
coverage, uploads under a new `website-unit` flag. Includes an
always-running gate job so branch protection has a context that still
posts when the test job is legitimately skipped.
**`apps/website/vitest.config.ts`** — adds coverage config. Vitest 4
removed `coverage.all`, so an explicit `coverage.include` is what pulls
never-imported files into the report. Without it, a wholly untested new
module is *absent* from the report rather than counted as 0%, and patch
coverage passes on it.
> Real website coverage is **22%**, not the **89%** the default
tests-touched-only report advertises. The denominator quadruples (1,246
→ 4,992 statements) once all sources count. `.astro` is excluded (V8
cannot instrument it); so are content collections and translation maps.
**`codecov.yml`** — adds an 80% patch gate ("is the code you just wrote
tested?") plus a 1% project ratchet, both scoped to
`apps/website/src/**` via the `website-unit` flag. `carryforward:
false`, because a missing upload must never be papered over with stale
coverage.
> Also **scopes the existing project status to `unit`/`e2e`**. Without
this, the incoming 22% website report drags aggregate coverage down and
fails `codecov/project` on PRs that never touched the website.
**`.coderabbit.yaml`** — adds a website e2e check pointing at
`apps/website/e2e/` (`mode: error`). The existing exemption is kept but
clarified: removing it would demand a `browser_tests/` file for website
fixes, which is the wrong directory. Adds path instructions for the unit
gate and for the `.astro` blind spot (nudging frontmatter logic into
testable `.ts`).
## Staged rollout — please read
The two **Codecov statuses ship `informational: true` on purpose.** This
is the one deliberate gap, and I want it called out rather than buried:
- Codecov path mapping (`network_prefix`) cannot be verified until a
real upload lands on `main`. If it is wrong, patch coverage reads 0% on
*every* website PR and blocks everyone — precisely the friction this is
meant to avoid.
- Flipping straight to blocking turns every open website PR red with no
warning.
**What already blocks on day one** (no Codecov dependency): the 423 unit
tests now actually run and fail the build; `website-unit-gate` is a hard
context; the CodeRabbit e2e check is `mode: error`.
**To promote** (remove `informational: true` from both `website`
statuses in `codecov.yml`):
1. Merge, then confirm the first `main` upload maps files to
`apps/website/src/...` and not the root `src/`.
2. Watch ~10 website PRs for `.vue` source-map false positives; tune the
80% target if needed.
3. Mark the contexts required in branch protection *before* flipping, to
prove they always post.
## Verification
- 423/423 unit tests pass; `pnpm typecheck` + `pnpm typecheck:website` +
eslint + oxlint + oxfmt + `yamllint` all clean (pre-commit hooks ran the
full gate).
- **Enforcement proven end-to-end.** Added a bespoke untested module,
then the same module with a test:
| Scenario | Coverage | Gate |
|---|---|---|
| Untested logic added | `0 \| 0 \| 0 \| 0` (`LF:3, LH:0` in LCOV) |
**fails** 80% patch |
| Same logic + colocated test | `100 \| 100 \| 100 \| 100` | **passes**
|
Before this PR that file would have been absent from the report entirely
and passed.
- Gate job shell logic exercised across all 7 job-state combinations,
including `changes=failure` and `website-changed + skipped` — both
correctly fail.
*No screenshots: this is CI/config only and changes no UI surface.*
## Review feedback addressed
- `network_filter` + `network_prefix` double-prefixed paths
(`apps/website/apps/website/src/...`). Now uploads from the package
directory with `network_prefix` alone.
- The gate accepted *any* skipped test job, so a failed `changes` job
left the required context green. Only a deliberate skip passes now.
---------
Co-authored-by: Glary-Bot <glary-bot@users.noreply.github.com>
Copy file name to clipboardExpand all lines: .coderabbit.yaml
+52-1Lines changed: 52 additions & 1 deletion
Original file line number
Diff line number
Diff line change
@@ -43,12 +43,40 @@ reviews:
43
43
2. The PR changes files under `src/` or `packages/` related to the main frontend application but the PR does not change at least one file under `browser_tests/`.
44
44
3. The PR description lacks a concrete explanation of why an end-to-end regression test was not added.
45
45
46
-
Do not fail if the changes are exclusively in `apps/website`, just documentation changes, or changes related to CI processes.
46
+
Do not fail if the changes are exclusively in `apps/website` (that package has its own check, "Website end-to-end regression coverage", because its Playwright specs live in `apps/website/e2e/` rather than `browser_tests/`), just documentation changes, or changes related to CI processes.
47
47
The goal is to make sure that fixes include End-to-End regression tests. Do not insist on tests when the PR is not fixing a bug.
48
48
49
49
Pass otherwise.
50
50
When failing, mention which bug-fix signal you found and ask the author to either add or update a Playwright regression test under `browser_tests/` or add a concrete explanation in the PR description of why an end-to-end regression test is not practical.
51
51
52
+
- name: Website end-to-end regression coverage
53
+
mode: error
54
+
instructions: |
55
+
Use only PR metadata already available in the review context:
56
+
- the PR title
57
+
- commit subjects in this PR
58
+
- the files changed in this PR relative to the PR base (equivalent to `base...head`)
59
+
- the PR description
60
+
- the diff content.
61
+
Do not rely on shell commands.
62
+
Do not inspect reverse diffs, files changed only on the base branch, or files outside this PR.
63
+
If the changed-file list or commit subjects are unavailable, mark the check inconclusive instead of guessing.
64
+
65
+
This check applies ONLY when the PR changes website runtime files under `apps/website/src/` or `apps/website/public/`. If no such files changed, pass immediately — that includes PRs touching only `apps/website/e2e/`, tooling, config, or CI.
66
+
67
+
Changes confined to `packages/` are deliberately out of scope here, even though the website consumes those packages: the generic "End-to-end regression coverage for fixes" check already requires a `browser_tests/` regression test for them. Do not demand a second website-specific test for a shared-package change.
68
+
69
+
Fail if all of the following are true:
70
+
1. The diff itself changes observable website runtime behavior — fixes a user-visible bug, adds a page or route, or changes an interactive flow, form, or navigation. A `fix`/`bugfix`/`hotfix` style title or commit subject is only a hint: confirm it against the diff, and never treat the wording alone as qualifying.
71
+
2. The PR does not add or update a Playwright assertion under `apps/website/e2e/**/*.spec.ts` that actually exercises the route, flow, or behavior this PR changed. An unrelated assertion elsewhere in the suite does not satisfy this.
72
+
3. The PR description lacks a concrete explanation of why an end-to-end regression test was not added.
73
+
74
+
Do not fail for text/copy-only edits, translation-only changes, static asset swaps, styling-only changes, generated files, dependency metadata, refactors that preserve behavior, or changes confined to tests, tooling, or CI.
75
+
A reformatted or whitespace-only edit to an existing spec does not count as adding coverage.
76
+
77
+
Pass otherwise.
78
+
When failing, name the behavior-changing signal you found and ask the author to either add or update a Playwright regression test under `apps/website/e2e/` or record in the PR description why an end-to-end test is not practical.
79
+
52
80
- name: ADR compliance for entity/litegraph changes
53
81
mode: warning
54
82
instructions: |
@@ -97,6 +125,29 @@ reviews:
97
125
`docs/guidance/vitest.md`, `docs/testing/vitest-patterns.md`, and
98
126
`docs/testing/litegraph-testing.md` as required review context for
99
127
every changed LiteGraph Vitest test file.
128
+
- path: 'apps/website/src/**/*.{ts,vue}'
129
+
instructions: |
130
+
Changed lines here are measured by the `website-unit` Codecov patch
131
+
status, so new behavior needs a colocated Vitest test. Treat
132
+
`docs/guidance/vitest.md` as required review context. Flag new
133
+
exported logic that no test exercises.
134
+
This glob is wider than the gate: `coverage.exclude` in
135
+
`apps/website/vitest.config.ts` is the source of truth, and anything
136
+
it lists is unmeasured. At time of writing that is `*.test.ts`,
0 commit comments