---
title: "Continuous integration"
description: "Understand the repository gates for types, tests, samples, docs, and releases."
image: "https://adonia.pages.dev/og.png"
version: "next"
---

> Documentation Index
> Fetch the complete documentation index at: https://adonia.pages.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Continuous integration

Workflow: [`.github/workflows/ci.yml`](https://github.com/rikoriswandha/adonia/blob/main/.github/workflows/ci.yml) (single workflow, runs on `push` to `main` and on every PR targeting `main`).

## Jobs

| Job | What it runs |
| --- | --- |
| `lint` | `pnpm lint` — ESLint 10 flat config plus the TSDoc public-export gate — and `pnpm --filter blog-admin lint`, which runs the integration fixture's AdonisJS ESLint config |
| `typecheck` | `pnpm -r typecheck` checks package and docs source, then `pnpm typecheck:tests` runs `tsc --noEmit` with every package's `tsconfig.test.json`. Existing package-level test debt is explicit in `scripts/test-typecheck-baseline.json`; every listed package is still checked, new failing packages fail CI, and a newly passing package fails until its stale baseline entry is removed |
| `unit` | Package Japa suites run under c8 and the UI Vitest suite runs with V8 coverage; LCOV and JSON summaries are retained in the `package-coverage-*` artifact for 30 days. Coverage is informational until the baseline supports defensible thresholds |
| `security` | **Required §19 gate** — `packages/core/tests/security/*.spec.ts` (route sweep, mass-assignment probes, allowlist fuzzing, upload spoofing, the XSS corpus over the persist path, the authorization cross-check, serialization leakage) plus `examples/blog-admin/tests/functional/adonia_security.spec.ts` on sqlite (guest sweep over the committed router, Shield XSRF, compiled SQL). `mapping.spec.ts` fails the job when [`docs/security-conformance.md`](/security-conformance) and the suite drift apart in either direction |
| `build` | `pnpm build` on the supported Node 24 baseline |
| `docs` | `pnpm docs:api:diff` then `pnpm docs:build` — G2-1/G2-2's gate. `docs:api:diff` compares the generated public API inventory with the PR base and requires a new major Changeset for removals. `docs:build` verifies generated references, compiles checked fenced samples, enforces the `no-check` budget, and fails on dead relative links. Neither command needs `pnpm build` |
| `test-blog-admin` | `examples/blog-admin` suite matrixed over `DB_CONNECTION=pg\|mysql\|sqlite`; the pg axis starts `postgres:17`, the mysql axis starts `mysql:8.4` (health-checked), the sqlite axis starts no real services (in-process) |
| `install-from-scratch` | Phase-1 exit gate (never leaves CI): `scripts/test-fresh-install.sh` — packs `@adonia/*` to tarballs, scaffolds a FRESH AdonisJS v7 inertia-react starter, installs the tarballs, runs `node ace add @adonia/core` (configure hook, zero manual edits), adds one `posts` resource, and curl-asserts the CRUD flow (XSRF cookie-jar flow, mass-assignment guard, validation failures) over HTTP; matrixed over `DB_CONNECTION=pg\|mysql\|sqlite` with the same service pattern as `test-blog-admin` |
| `playwright` | caches Chromium and Firefox, maps `lvh.me` test domains, runs both desktop projects, and uploads retained traces and failure screenshots from `test-results/` when the suite fails |
| `bundle-size` | `pnpm build` then `pnpm size` — bundles the scaffolded panel entry with React/Inertia external, gates the base chunks at TECH_SPEC §18's 225 kB gzip, asserts the rich-text/code/image editors stay behind `import()`, and posts a per-chunk report to the job summary and a sticky PR comment. See [bundle budget](/bundle-budget) |
| `performance` | **Required §18 gate** — `pnpm perf` benchmarks validated production descriptor/index/export/render/controller paths, asserts fixed N+1 and widget request counts, enforces cold descriptor p95 plus bundle/lazy-editor budgets, publishes the report to the job summary, and uploads raw JSON/chunks for 90 days. The same raw JSON is committed durably at [`docs/public/performance-report.json`](/performance-report.json) and linked from the generated report |

Notes on design decisions:

- GHA does not support conditional services. The `test-blog-admin` and `install-from-scratch` matrices give a non-matching service a no-op `alpine` image with **no health check**, so GHA never waits on it; only the service matching `matrix.db` is real and health-gated.
- `install-from-scratch` runs the exact `verdaccio@6.9.0` release on `127.0.0.1:54573` because `node ace add @adonia/core` installs from a registry before running the configure hook; the starter kit and `create-adonisjs` are pinned too.
- `/etc/hosts` has no wildcard support, so the Playwright job enumerates the subdomains the domain-mounted/tenant panel tests will use instead of `*.lvh.me`.
- `examples/blog-admin`, the fresh-install script, and `test:e2e` are required inputs. CI invokes them directly, so deleting or renaming any of them fails instead of turning a required job into a green no-op.
- `bundle-size` measures a *bundle*, not a file: `packages/ui` builds with `tsc -b`, so gating `dist/index.js` would gate a barrel of re-export statements. `scripts/panel_bundle.js` bundles the scaffolded panel entry with esbuild instead, and `.size-limit.json` points at the resulting `.size-limit-build/base/*.js` chunks.
- `docs` is separate from `lint`: root ESLint ignores extracted documentation samples, while `docs:build` checks them against the real API. A red docs job therefore reports documentation drift directly instead of hiding it under lint.
- The PR-comment step is skipped for fork PRs (their token is read-only) and is `continue-on-error`, so the required check never goes red over a comment permission. The job summary carries the same report either way.

## Required status checks (branch protection)

Branch protection cannot be configured from this repo — it must be set once in the GitHub UI:
**Settings → Branches → Add branch ruleset** for `main`, enable "Require status checks to pass before merging" and mark **all** of the following as required:

- `Lint (ESLint flat config)`
- `Typecheck`
- `Unit tests`
- `Security conformance (§19)`
- `Build (Node 24)`
- `Docs (samples + site build)`
- `blog-admin tests (pg)`
- `blog-admin tests (mysql)`
- `blog-admin tests (sqlite)`
- `install-from-scratch (pg)`
- `install-from-scratch (mysql)`
- `install-from-scratch (sqlite)`
- `Playwright e2e`
- `Performance (§18)`
- `Bundle size (size-limit)`

Also enable "Require branches to be up to date before merging" so the matrix cannot go stale against `main`.

Source: https://adonia.pages.dev/ci/index.mdx
