name: CI Pipeline on: pull_request: types: [opened, synchronize, reopened] concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true jobs: check_changes: name: Check Changes runs-on: ubuntu-latest permissions: contents: read outputs: exists: ${{ steps.filter.outputs.exists }} steps: - uses: actions/checkout@v4 - name: Filter changes uses: yumemi-inc/path-filter@v2 id: filter with: patterns: | ** !**.md !.gitignore !.gitattributes !.vscode/** !.env.example setup: name: Setup Dependencies needs: [check_changes] if: ${{ needs.check_changes.outputs.exists == 'true' }} runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Check if node_modules cache exists id: check-node-modules-cache uses: actions/cache@v4 with: path: | node_modules */node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles('**/pnpm-lock.yaml') }} lookup-only: true - name: Setup Node.js if: steps.check-node-modules-cache.outputs.cache-hit != 'true' uses: actions/setup-node@v4 with: node-version: lts/* - name: Setup pnpm if: steps.check-node-modules-cache.outputs.cache-hit != 'true' uses: pnpm/action-setup@v4 with: run_install: false - name: Install dependencies if: steps.check-node-modules-cache.outputs.cache-hit != 'true' run: pnpm install --frozen-lockfile quality_checks: name: ${{ matrix.name }} needs: [setup] if: ${{ needs.check_changes.outputs.exists == 'true' }} runs-on: ubuntu-latest strategy: matrix: include: - name: Lint check: lint - name: Format check: format - name: Test check: test - name: Build check: build - name: TypeScript check: typecheck - name: Spell Check check: spell steps: - uses: actions/checkout@v4 - name: Restore Turborepo Cache uses: actions/cache@v4 with: path: .turbo key: ${{ runner.os }}-turbo-${{ matrix.check }}-${{ github.sha }} restore-keys: ${{ runner.os }}-turbo-${{ matrix.check }}- - name: Restore node_modules cache id: cache uses: actions/cache/restore@v4 with: path: | node_modules */node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: ${{ runner.os }}-node-modules- - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: lts/* - name: Setup pnpm uses: pnpm/action-setup@v4 with: run_install: false - name: Install dependencies if: steps.cache.outputs.cache-hit != 'true' run: pnpm install --frozen-lockfile - name: Run ${{ matrix.name }} run: pnpm exec turbo run ${{ matrix.check }} - name: Upload Build Artifact if: matrix.name == 'Build' uses: actions/upload-artifact@v4 with: name: build-dist-${{ github.sha }} path: dist/ # We should depend on quality checks to save CI running time. playwright: name: Playwright Tests needs: [setup, quality_checks] if: ${{ needs.check_changes.outputs.exists == 'true' }} runs-on: ubuntu-latest container: image: mcr.microsoft.com/playwright:v1.54.1-noble options: --user 1001 steps: - uses: actions/checkout@v4 with: fetch-depth: 0 - name: Restore Turborepo Cache uses: actions/cache@v4 with: path: .turbo key: ${{ runner.os }}-turbo-${{ github.sha }} restore-keys: ${{ runner.os }}-turbo- - name: Restore node_modules cache id: cache uses: actions/cache/restore@v4 with: path: | node_modules */node_modules key: ${{ runner.os }}-node-modules-${{ hashFiles('**/pnpm-lock.yaml') }} restore-keys: ${{ runner.os }}-node-modules- - name: Download Build Artifact uses: actions/download-artifact@v4 with: path: dist/ pattern: build-dist* merge-multiple: true - name: Setup pnpm uses: pnpm/action-setup@v4 with: run_install: false - name: Install dependencies if: steps.cache.outputs.cache-hit != 'true' run: pnpm install --frozen-lockfile - name: Run Playwright Tests run: pnpm exec turbo run test:playwright timeout-minutes: 10 verify: name: Verify needs: [check_changes, quality_checks, playwright] runs-on: ubuntu-latest if: always() outputs: success: ${{ steps.set-result.outputs.success }} steps: - name: Set Result id: set-result run: | # Check if changes exist but no jobs ran, or if any job failed or was cancelled if [[ "${{ needs.check_changes.outputs.exists }}" != "true" ]]; then echo "success=true" >> $GITHUB_OUTPUT echo "No relevant changes detected - pipeline passed" elif [[ "${{ contains(needs.*.result, 'failure') }}" == "true" || "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then echo "success=false" >> $GITHUB_OUTPUT echo "Pipeline failed - some jobs failed or were cancelled" exit 1 else echo "success=true" >> $GITHUB_OUTPUT echo "All jobs completed successfully" fi