# Console CI Contract (DEVOPS-CONSOLE-23-001) ## Scope Define a deterministic, offline-friendly CI pipeline for the Console web app covering lint, type-check, unit, Storybook a11y, Playwright smoke, Lighthouse perf/a11y, and artifact retention. ## Stages & Gates 1. **Setup** - Node 20.x, pnpm 9.x from cached tarball (`tools/cache/node20.tgz`, `tools/cache/pnpm-9.tgz`). - Restore `node_modules` from `.pnpm-store` cache key `console-${{ hashFiles('pnpm-lock.yaml') }}`; fallback to offline tarball `local-npm-cache.tar.zst`. - Export `PLAYWRIGHT_BROWSERS_PATH=./.playwright` and hydrate from `tools/cache/playwright-browsers.tar.zst`. 2. **Lint/Format/Types** (fail-fast) - `pnpm lint` - `pnpm format:check` - `pnpm typecheck` 3. **Unit Tests** - `pnpm test -- --runInBand --reporter=junit --outputFile=.artifacts/junit.xml` - Collect coverage to `.artifacts/coverage` (lcov + summary). 4. **Storybook a11y** - `pnpm storybook:build` (static export) - `pnpm storybook:a11y --ci --output .artifacts/storybook-a11y.json` 5. **Playwright Smoke** - `pnpm playwright test --config=playwright.config.ci.ts --reporter=list,junit=.artifacts/playwright.xml` - Upload `playwright-report/` and `.artifacts/playwright.xml`. 6. **Lighthouse (CI mode)** - Serve built app with `pnpm serve --port 4173` and run `pnpm lhci autorun --config=lighthouserc.ci.js --upload.target=filesystem --upload.outputDir=.artifacts/lhci` - Enforce budgets: performance >= 0.80, accessibility >= 0.90, best-practices >= 0.90, seo >= 0.85. 7. **SBOM/Provenance** - `pnpm exec syft packages dir:dist --output=spdx-json=.artifacts/console.spdx.json` - Attach `.artifacts/console.spdx.json` and provenance attestation from release job. ## Determinism & Offline - No network fetches after cache hydrate; fail if `pnpm install` hits the network (set `PNPM_FETCH_RETRIES=0`, `PNPM_OFFLINE=1`). - All artifacts written under `.artifacts/` and uploaded as CI artifacts. - Timestamps normalized via `SOURCE_DATE_EPOCH=${{ github.run_id }}` for reproducible Storybook/LH builds. ## Inputs/Secrets - Required only for Playwright auth flows: `CONSOLE_E2E_USER`, `CONSOLE_E2E_PASS` (scoped to non-prod tenant). Pipeline must soft-skip auth tests when unset. - No signing keys required in CI; release handles signing separately. ## Outputs - `.artifacts/junit.xml` (unit) - `.artifacts/playwright.xml`, `playwright-report/` - `.artifacts/storybook-a11y.json` - `.artifacts/lhci/` (Lighthouse reports) - `.artifacts/coverage/` - `.artifacts/console.spdx.json` ## Example Gitea workflow snippet ```yaml - name: Console CI (DEVOPS-CONSOLE-23-001) uses: actions/setup-node@v4 with: node-version: '20' - name: Prep pnpm run: | corepack enable corepack prepare pnpm@9 --activate - name: Cache pnpm store uses: actions/cache@v4 with: path: | ~/.pnpm-store ./node_modules key: console-${{ hashFiles('pnpm-lock.yaml') }} - name: Install (offline) env: PNPM_FETCH_RETRIES: 0 PNPM_OFFLINE: 1 run: pnpm install --frozen-lockfile - name: Lint/Types run: pnpm lint && pnpm format:check && pnpm typecheck - name: Unit run: pnpm test -- --runInBand --reporter=junit --outputFile=.artifacts/junit.xml - name: Storybook a11y run: pnpm storybook:build && pnpm storybook:a11y --ci --output .artifacts/storybook-a11y.json - name: Playwright run: pnpm playwright test --config=playwright.config.ci.ts --reporter=list,junit=.artifacts/playwright.xml - name: Lighthouse run: pnpm serve --port 4173 & pnpm lhci autorun --config=lighthouserc.ci.js --upload.target=filesystem --upload.outputDir=.artifacts/lhci - name: SBOM run: pnpm exec syft packages dir:dist --output=spdx-json=.artifacts/console.spdx.json - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: console-ci-artifacts path: .artifacts ``` ## Acceptance to mark blocker cleared - Pipeline executes fully in a clean runner with network blocked after cache hydrate. - All artefacts uploaded and budgets enforced; failing budgets fail the job. - Soft-skip auth-dependent tests when secrets are absent, without failing the pipeline.