name: CI on: push: branches: [master, main] pull_request: jobs: ci: name: Typecheck & Lint runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: 22 cache: 'npm' - name: Install dependencies run: npm ci - name: Check package-lock.json version sync run: npm run check:lockfile - name: Type check run: npm run typecheck - name: Lint run: npm run lint - name: Frontend JS syntax check run: npm run check:frontend-syntax - name: Format check run: npm run format:check - name: Server boot smoke test run: | set -u if ! command -v tmux >/dev/null; then sudo apt-get update -qq sudo apt-get install -y tmux fi npx tsx src/index.ts web --port 3151 > /tmp/boot.log 2>&1 & SERVER_PID=$! trap "kill $SERVER_PID 2>/dev/null || true" EXIT for i in $(seq 1 30); do if curl -fsS http://localhost:3151/api/status -o /dev/null; then echo "Server booted in ${i}s" exit 0 fi if ! kill -0 $SERVER_PID 2>/dev/null; then echo "Server exited before becoming ready. Logs:" cat /tmp/boot.log exit 1 fi sleep 1 done echo "Server did not respond on /api/status within 30s. Logs:" cat /tmp/boot.log exit 1 test: name: Unit & integration tests runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - name: Setup Node.js uses: actions/setup-node@v6 with: node-version: 22 cache: 'npm' - name: Install dependencies run: npm ci - name: Install tmux run: | if ! command -v tmux >/dev/null; then sudo apt-get update -qq sudo apt-get install -y tmux fi - name: Run unit & integration tests # Excludes the browser-driven mobile suite (test/mobile/**); see config/vitest.ci.config.ts. # Safe in CI: TmuxManager no-ops all shell commands under VITEST (test/setup.ts). run: npm run test:ci # Note: The browser-driven mobile suite (test/mobile/**) is excluded from CI — # it needs a live server + chromium + environment-specific PNG baselines. # Run it locally/manually. All other tests run via the `test` job above.