| name | ci-workflow |
| description | Use when validating website changes before commit, push, or PR โ picking which Makefile suites to run, in what order (make format, then focused tests, then make lint), and how to react to failures. Triggers: "ready to commit", "before PR", "is this CI-green", "which tests do I run", "make lint / make format failed", "make ci-lint", "make ci-test", and Prettier / ESLint / tsc / markdownlint / dependency-cruiser / Jest / Playwright / Stryker failures. |
CI Workflow
How to take a website change from "edited" to "ready to push" without guessing.
Every command here is a Makefile target run from the repo root (this repo has no
package.json scripts โ the Makefile is the command surface). Pair this with the
test-coverage contract in agents.md: that file decides what
to test; this skill decides which suites to run and in what order.
Core rule: format, then test, then lint
Run the one mutating step first, then the read-only gates:
make format
make lint
make format only rewrites files (Prettier). make lint never mutates โ it fails if
anything is off. Running tests between them means you validate already-formatted code,
so a formatting rewrite can never invalidate a green test run.
Locally, prefix any unit suite with CI=1 to run it directly (no Docker):
CI=1 make test-unit-client. E2E, visual, load, memory-leak, and Lighthouse suites
run against the Docker prod/Mockoon stack and are started by their own targets.
Match the change to suites
Pick the smallest set that actually exercises the change, then always finish with
make lint. A single change often needs more than one suite.
- Markdown / docs only โ
make lint-md (then make lint). Note: .claude/skills/**
is not markdownlint-scanned, but it is Prettier-formatted, so still run
make format.
- React component / hook / client logic โ
CI=1 make test-unit-client. Covers
src/features/*/components, src/components, src/hooks,
src/test/testing-library, and src/test/unit.
- Apollo resolver / GraphQL server-mock logic (
src/test/apollo-server) โ
CI=1 make test-unit-server. Touched both layers? CI=1 make test-unit-all.
- User-facing flow end to end โ
make test-e2e (Playwright + Mockoon API mock).
- Rendered UI or styling โ
make test-visual (Playwright snapshots). Only for a
deliberate, reviewed visual change, refresh baselines with make test-visual-update
and inspect the diff before committing.
- Imports, feature public-API barrels, or cross-feature/shared-layer boundaries โ
make lint-deps (dependency-cruiser); it is already inside make lint.
- i18n strings (
src/features/*/i18n/{en,uk}.json) โ client unit tests that assert the
t() output, plus make test-e2e / make test-visual if the string is visible.
- Makefile or CI shell scripts (
scripts/ci/*) โ make test-bats.
- Test strength for new/changed logic โ
make test-mutation (Stryker).
- Performance-sensitive paths โ
make lighthouse-desktop / make lighthouse-mobile,
make load-tests (K6), make test-memory-leak (Memlab).
See examples/validation-sequences.md for copy-paste
command blocks per change kind.
CI phase aliases
The pipeline phases are exposed as targets so you can run the exact CI stages locally:
make ci-lint โ grouped, parallel ESLint + TypeScript + markdownlint with aggregated
output (mirrors the lint stage). make lint additionally runs lint-deps; run the
full make lint before pushing.
make ci-test โ parallel dev-side tests: client unit, server unit, and integration.
make ci โ the whole local CI flow (setup, lint, dev tests, mutation, prod setup,
prod tests). Heavy; use it for a final pre-PR sweep, not per-edit.
Prefer the focused suites during iteration and the ci-* aliases for a final check.
Pre-commit checklist
Pre-PR checklist
When a gate fails
- Formatting diff โ re-run
make format, then review the rewritten files; do not edit
formatting by hand.
- ESLint โ fix the flagged rule. Never add
eslint-disable.
- TypeScript โ fix the type contract. Never add
@ts-ignore, @ts-nocheck, or
@ts-expect-error.
- markdownlint โ keep headings, fences, list markers, and line length compliant.
- dependency-cruiser โ respect feature boundaries: import features via their
index.ts
barrel, keep shared layers from importing features, and avoid cross-feature deep paths.
- Jest โ reproduce the one failing spec before changing code; fix behavior, not the
assertion.
- Playwright visual โ confirm whether the diff is a real, intended UI change. If so,
refresh with
make test-visual-update. If it is only environment drift, see
reference/failure-recovery.md.
- Stryker โ kill survivors by adding a behavior assertion, not by deleting the mutant's
code path.
Deeper, per-gate recovery steps live in
reference/failure-recovery.md.
Never weaken a gate
A passing run achieved by lowering the bar is a failing change. Do not add
eslint-disable, prettier-ignore, @ts-ignore/@ts-nocheck/@ts-expect-error, or
markdownlint
disable directives; do not relax dependency-cruiser rules, lower coverage or mutation
thresholds, or add maxDiffPixels to silence a visual diff. Complexity and metrics
budgets (owned by the complexity-management skill) follow the same no-lowering rule.
Fix the code or document a concrete Not applicable: <reason> per agents.md instead.
Related guides
Before applying this skill, confirm the active task against ../AI-AGENT-GUIDE.md and
../SKILL-DECISION-GUIDE.md so every relevant skill is consulted.