name: CI on: push: branches: [main, dev] pull_request: branches: [main, dev] schedule: - cron: '0 8 * * 1' # Weekly Monday 08:00 UTC — smoke tests workflow_dispatch: concurrency: group: ci-${{ github.ref }} cancel-in-progress: true jobs: # ── Fast gate: typecheck + build ── build: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: [ubuntu-latest, macos-latest, windows-latest] steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'npm' - name: Install dependencies run: npm ci - name: Type check run: npx tsc --noEmit - name: Build run: npm run build # Guard: committed cli-manifest.json must match the one build regenerates. # Prevents silent drift where unrelated adapter entries vanish or change # across PRs (agent hits unexpected manifest diff → surgical-merge churn). - name: Check cli-manifest.json is up-to-date if: runner.os == 'Linux' shell: bash run: | if ! git diff --exit-code -- cli-manifest.json; then echo "::error::cli-manifest.json is out of sync with the source. Run 'npm run build' and commit the result." exit 1 fi # Guard: adapter rows must not silently emit keys omitted from `columns`. # Existing findings are tracked in scripts/silent-column-drop-baseline.json; # this gate rejects newly introduced drops while allowing incremental cleanup. - name: Check silent column drops if: runner.os == 'Linux' run: npm run check:silent-column-drop # Guard: adapters should fail with typed errors instead of silently # returning empty arrays, clamping user input, or inventing sentinel data. # Existing findings are tracked in scripts/typed-error-lint-baseline.json. - name: Check typed-error lint baseline if: runner.os == 'Linux' run: npm run check:typed-error-lint # ── Unit tests (vitest shard) ── # PR: ubuntu + Node 22 only (fast feedback, 2 jobs). # Push to main/dev: full matrix for cross-platform/cross-version coverage (12 jobs). unit-test: runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: os: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && fromJSON('["ubuntu-latest","macos-latest","windows-latest"]') || fromJSON('["ubuntu-latest"]') }} node-version: ${{ (github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && fromJSON('["22"]') || fromJSON('["22"]') }} shard: [1, 2] steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: ${{ matrix.node-version }} cache: 'npm' - name: Install dependencies run: npm ci - name: Run unit tests (Node ${{ matrix.node-version }}, shard ${{ matrix.shard }}/2) run: npx vitest run --project unit --project extension --reporter=verbose --shard=${{ matrix.shard }}/2 # ── Bun compatibility check ── bun-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v6 - uses: oven-sh/setup-bun@v2 with: bun-version: 1.3.5 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'npm' - name: Install dependencies run: npm ci - name: Run unit tests under Bun run: bun vitest run --project unit --reporter=verbose # Adapter tests are pure unit tests — OS doesn't affect results. Gated off # `pull_request` to keep PR CI under ~2 minutes; adapter authors run focused # tests locally before pushing, and `push` to main / nightly cron / manual # dispatch still guard the merged state. adapter-test: if: github.event_name == 'push' || github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' runs-on: ubuntu-latest needs: build steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'npm' - name: Install dependencies run: npm ci - name: Run focused adapter tests run: npm run test:adapter -- --reporter=verbose # ── Smoke tests (scheduled / manual only) ── smoke-test: if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' needs: build runs-on: ${{ matrix.os }} strategy: fail-fast: false matrix: # NOTE: Windows excluded — browser-actions/setup-chrome hangs during # Chrome MSI installation on Windows runners (known issue). os: [ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v6 - uses: actions/setup-node@v6 with: node-version: '22' cache: 'npm' - name: Install dependencies run: npm ci - name: Setup Chrome uses: ./.github/actions/setup-chrome id: setup-chrome - name: Build run: npm run build - name: Run smoke tests (Linux, via xvfb) if: runner.os == 'Linux' run: | xvfb-run --auto-servernum --server-args="-screen 0 1280x720x24" \ npx vitest run tests/smoke/ --reporter=verbose - name: Run smoke tests (macOS / Windows) if: runner.os != 'Linux' run: npx vitest run tests/smoke/ --reporter=verbose timeout-minutes: 15