# CI — the FULL quality gate, so no change lands unverified: formatting, # lint (client + server), typecheck (client + server), server syntax check, # server + client tests, and the Vite build. # # Forgejo Actions reads .forgejo/workflows/. The container image matches the # Dockerfile runtime (node:22) so better-sqlite3 prebuilds resolve identically. name: CI on: push: pull_request: jobs: ci: runs-on: docker container: image: node:22-bookworm steps: - name: Checkout uses: actions/checkout@v4 - name: Install dependencies run: npm ci - name: Secret scan (gitleaks) run: | GITLEAKS_VERSION=8.21.2 curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" \ | tar -xz -C /usr/local/bin gitleaks gitleaks detect --source=. --redact --no-banner - name: Dependency audit (fail on high or critical) # Raised from critical after clearing the nodemailer/xlsx highs # (QA-B0-02) — high vulns must fail CI, not pass silently. run: npm audit --omit=dev --audit-level=high - name: Format check (Prettier) run: npm run format:check - name: Lint (client + server) run: npm run lint - name: Dead code (knip) # Blocking since 2026-07-10 (repo is knip-clean): new unused files, # exports, or dependencies fail CI instead of rotting silently. run: npm run knip - name: Typecheck (client) run: npm run typecheck - name: Typecheck (server) run: npm run typecheck:server - name: Syntax check (server) run: npm run check:server - name: Server tests (node:test) run: npm run test - name: Client tests (Vitest) run: npm run test:client - name: Build (Vite) run: npm run build