name: CI on: pull_request: # Cancel in-progress runs when a new commit is pushed to the same PR concurrency: group: ci-${{ github.event.pull_request.number || github.ref }} cancel-in-progress: true env: CI: true jobs: # First, install dependencies once and cache them install: name: Install Dependencies runs-on: blacksmith-2vcpu-ubuntu-2404 timeout-minutes: 5 steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 2 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 9.15.0 - name: Setup Node.js uses: useblacksmith/setup-node@v5 with: node-version: 22 cache: 'pnpm' - name: Fix pnpm store permissions run: | STORE_PATH=$(pnpm store path --silent) if [ -d "$STORE_PATH" ]; then sudo chown -R $(whoami):$(whoami) "$STORE_PATH" || true chmod -R u+rw "$STORE_PATH" || true fi - name: Check if lockfile changed id: lockfile-check run: | if git diff HEAD~1 HEAD --name-only | grep -q "pnpm-lock.yaml"; then echo "changed=true" >> $GITHUB_OUTPUT else echo "changed=false" >> $GITHUB_OUTPUT fi - name: Fetch dependencies (if lockfile changed) if: steps.lockfile-check.outputs.changed == 'true' run: pnpm fetch --frozen-lockfile - name: Install dependencies run: pnpm install --frozen-lockfile --prefer-offline # Build job - runs in parallel build: name: Build needs: install runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 9.15.0 - name: Setup Node.js uses: useblacksmith/setup-node@v5 with: node-version: 22 - name: Get pnpm store directory shell: bash run: | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Mount pnpm store sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-pnpm-store path: ${{ env.STORE_PATH }} - name: Mount Turbo cache sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-turbo-cache path: ./.turbo - name: Install dependencies run: | rm -rf node_modules pnpm install --frozen-lockfile --prefer-offline - name: Build all packages (excluding web) run: pnpm build --filter='!@buster-app/web' env: NODE_ENV: production # Lint job - runs in parallel lint: name: Lint needs: install runs-on: blacksmith-2vcpu-ubuntu-2404 timeout-minutes: 5 steps: - name: Checkout code uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 9.15.0 - name: Setup Node.js uses: useblacksmith/setup-node@v5 with: node-version: 22 - name: Get pnpm store directory shell: bash run: | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Mount pnpm store sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-pnpm-store path: ${{ env.STORE_PATH }} - name: Mount Turbo cache sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-turbo-cache path: ./.turbo - name: Install dependencies run: | rm -rf node_modules pnpm install --frozen-lockfile --prefer-offline - name: Lint all packages (excluding web) run: pnpm lint --filter='!@buster-app/web' # Test job - runs in parallel test: name: Test needs: install runs-on: blacksmith-4vcpu-ubuntu-2404 timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@v4 - name: Install pnpm uses: pnpm/action-setup@v2 with: version: 9.15.0 - name: Setup Node.js uses: useblacksmith/setup-node@v5 with: node-version: 22 - name: Get pnpm store directory shell: bash run: | echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV - name: Mount pnpm store sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-pnpm-store path: ${{ env.STORE_PATH }} - name: Mount Turbo cache sticky disk uses: useblacksmith/stickydisk@v1 with: key: ${{ github.repository }}-turbo-cache path: ./.turbo - name: Install dependencies run: | rm -rf node_modules pnpm install --frozen-lockfile --prefer-offline - name: Run all unit tests (excluding web) run: pnpm test:unit --filter='!@buster-app/web' - name: Upload test coverage uses: actions/upload-artifact@v4 if: always() with: name: coverage path: | **/coverage/** !**/coverage/tmp/** retention-days: 7 # Final status check - ensures all parallel jobs pass ci-status: name: CI Status needs: [build, lint, test] runs-on: blacksmith-2vcpu-ubuntu-2404 if: always() timeout-minutes: 1 steps: - name: Check CI Status run: | if [[ "${{ needs.build.result }}" != "success" || "${{ needs.lint.result }}" != "success" || "${{ needs.test.result }}" != "success" ]]; then echo "❌ CI failed" echo "Build: ${{ needs.build.result }}" echo "Lint: ${{ needs.lint.result }}" echo "Test: ${{ needs.test.result }}" exit 1 fi echo "✅ All CI checks passed!"