Skip to content

Documentation

Validation Pipeline

SveltyCMS tiered validation architecture for contributors — fast commits, safe pushes, deterministic CI

10/17/2026
3 min read Edit on GitHub

SveltyCMS uses a three-tier validation architecture that balances developer velocity with code safety. Every tier catches a different class of defect at the right stage of the development lifecycle.

Tip

New to the repo? Run bun run test:doctor --list for the live gate map, or bun run test:doctor to run unit + SQLite integration. Live dashboard: Test Status.

Tier 1 — Pre-commit (~40–60s)

Hook: .githooks/pre-commit · Manual: bun run precommit

  1. scripts/check/check-test-db-safety.ts — never point tests at a live DB name
  2. bun run check — format (oxfmt) + lint (oxlint)
  3. bun run gate:fast — lint-staged
  4. bun run risk:audit — 6 parallel gates: global security-risk scan (all 4 adapters + loopback/tenant/test-mode/AST batch guards) + secret misuse + slop + tenant-isolation API hygiene (lint-tenant-api) + bun audit + OSV.dev (skipped if only docs changed; pass --full to force non-incremental scanning)
  5. bun run test:unit — full Vitest suite (skipped if only docs changed)
  6. SBOM sync — bun run audit:sbom when bun.lock / package.json changed

Tier 2 — Pre-push (~5–8 min)

Hook: .githooks/pre-push · Manual: bun run gate or bun run prepush

  1. Production build with COMPILE_ALL_ADAPTERS=true
  2. Prod build backdoor verify — scripts/security/verify-prod-build-backdoor.ts --mode=bench
  3. Bundle size gate — scripts/check/check-bundle-size.ts
  4. bun run check — TypeScript / Svelte quality gate
  5. Secret misuse scan — scripts/security/scan-secret-misuse.ts --strict
  6. Tenant isolation — bun run test:tenant
  7. SQLite integration: bun test --timeout 300000 tests/integration/
    (in-suite harness starts preview + config/private.test.ts)

Docs-only pushes skip build + integration. Multi-DB matrix, benchmarks, and Playwright E2E are not on pre-push — they run in CI.

Release preparation — --release[=kind] runs scripts/version.ts after a green gate, commits the manifest as chore(release): bump version to vX.Y.Z and prints the push that publishes it. Reaches the hook two ways: bun run gate --release, or bun run git push --release … (the wrapper consumes the flag and exports SVELTY_RELEASE, since git never forwards hook arguments). Skipped on the docs-only and --only-failures paths — a release commit is only prepared behind a full gate. Details: Release Pipeline.

Important

No double-run rule: full unit suite runs on pre-commit only. Pre-push does not re-run all unit tests.

Tier 3 — GitHub Actions

Workflow: .github/workflows/ci.yml

bootstrap → whitebox ×2 (policy/quality + unit) → build → db-tests × 4 → bench-core × 4 → e2e-prep → e2e × 8 named groups → all-green

Manual commands

Command Purpose
bun run test:doctor Gate map + unit + SQLite integration
bun run test:security Focused hooks security suite
bun run risk:audit Full pre-commit security scanners
bun run test:smart Git-diff suite picker
bun run test:e2e CI-parity Playwright
bun run gate Same as pre-push

Private config safety

Local automated runs use config/private.test.ts only. Never read or write the developer’s live config/private.ts. CI may create an ephemeral private.ts on the runner only.

Full detail: docs/tests/git-workflow.mdx · docs/tests/index.mdx · AGENTS.md technical standards

validationci-cdgit-hooksquality-gate
Was this page helpful?