name: CI on: pull_request: branches: [main, dev] # Design notes: # - Matrix parallelism cuts wall time from ~3-4min to ~60-90s (cache warm). # - Concurrency group cancels superseded runs on the same ref (saves runner time on rapid pushes). # - Build leg produces dist/ artifact; test leg downloads it instead of rebuilding (DRY). # - fail-fast: false so every failure is visible in one run (no re-pushing to see the next failure). concurrency: group: ci-${{ github.ref }} cancel-in-progress: true jobs: validate: if: >- contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.pull_request.author_association) runs-on: [self-hosted, linux, x64] env: # Keep Bun cache isolated per job workspace so parallel self-hosted runs # do not race on ~/.bun/install/cache and corrupt restore/install state. BUN_INSTALL_CACHE_DIR: ${{ github.workspace }}/.bun/install/cache strategy: fail-fast: false matrix: check: - { name: typecheck, cmd: 'bun run typecheck' } - { name: lint, cmd: 'bun run lint' } - { name: format, cmd: 'bun run format:check' } name: ${{ matrix.check.name }} steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: '1.3.9' - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' - name: Restore bun package cache uses: actions/cache@v4 with: path: | ${{ env.BUN_INSTALL_CACHE_DIR }} key: ${{ runner.os }}-bun-cache-v2-${{ hashFiles('bun.lock', 'ui/bun.lock') }} - name: Ensure dependencies run: bash scripts/ensure-deps.sh - name: Run ${{ matrix.check.name }} run: ${{ matrix.check.cmd }} build: if: >- contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.pull_request.author_association) runs-on: [self-hosted, linux, x64] name: build env: BUN_INSTALL_CACHE_DIR: ${{ github.workspace }}/.bun/install/cache steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: '1.3.9' - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' - name: Restore bun package cache uses: actions/cache@v4 with: path: | ${{ env.BUN_INSTALL_CACHE_DIR }} key: ${{ runner.os }}-bun-cache-v2-${{ hashFiles('bun.lock', 'ui/bun.lock') }} - name: Ensure dependencies run: bash scripts/ensure-deps.sh - name: Build run: bun run build:all - name: Upload dist artifact uses: actions/upload-artifact@v4 with: name: dist path: dist/ retention-days: 1 if-no-files-found: error test: if: >- contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.pull_request.author_association) runs-on: [self-hosted, linux, x64] name: test needs: [build] env: BUN_INSTALL_CACHE_DIR: ${{ github.workspace }}/.bun/install/cache steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup Bun uses: oven-sh/setup-bun@v2 with: bun-version: '1.3.9' - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '22' - name: Restore bun package cache uses: actions/cache@v4 with: path: | ${{ env.BUN_INSTALL_CACHE_DIR }} key: ${{ runner.os }}-bun-cache-v2-${{ hashFiles('bun.lock', 'ui/bun.lock') }} - name: Ensure dependencies run: bash scripts/ensure-deps.sh - name: Download dist artifact uses: actions/download-artifact@v4 with: name: dist path: dist/ - name: Test run: bun run test:all - name: Test CLI e2e env: CCS_E2E_SKIP_BUILD: '1' run: bun run test:e2e compose-parity: if: >- contains(fromJSON('["COLLABORATOR","MEMBER","OWNER"]'), github.event.pull_request.author_association) runs-on: [self-hosted, linux, x64, cliproxy] name: compose-parity steps: - name: Checkout code uses: actions/checkout@v4 with: persist-credentials: false - name: Assert compose parity (compose.yaml vs docker-compose.integrated.yml) run: bash tests/docker/compose-parity.sh