diff --git a/.github/workflows/gated-pipeline.yml b/.github/workflows/gated-pipeline.yml index 348470038..ed3ded945 100644 --- a/.github/workflows/gated-pipeline.yml +++ b/.github/workflows/gated-pipeline.yml @@ -661,6 +661,43 @@ jobs: # GATE 2: Testing Gates (runs after container images are published to GHCR) # ============================================================================ + # Detect which test suites need to run based on changed paths + check-app-changes: + name: "Check: App source changes" + runs-on: ubuntu-latest + needs: gate-1-complete + if: github.event_name != 'issues' && github.event_name != 'issue_comment' + outputs: + e2e_changed: ${{ steps.diff.outputs.e2e_changed }} + unit_changed: ${{ steps.diff.outputs.unit_changed }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Detect changed paths + id: diff + shell: bash + run: | + BEFORE="${{ github.event.before }}" + if [ -z "$BEFORE" ] || [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then + echo "e2e_changed=true" >> "$GITHUB_OUTPUT" + echo "unit_changed=true" >> "$GITHUB_OUTPUT" + echo "No before SHA — marking all changed" + exit 0 + fi + + git fetch --depth=1 origin "$BEFORE" 2>/dev/null || true + + E2E=$(git diff --name-only "$BEFORE" "${{ github.sha }}" -- \ + frontends e2e packages components 2>/dev/null || echo "") + UNIT=$(git diff --name-only "$BEFORE" "${{ github.sha }}" -- \ + frontends/nextjs/src 2>/dev/null || echo "") + + [ -n "$E2E" ] && echo "e2e_changed=true" >> "$GITHUB_OUTPUT" || echo "e2e_changed=false" >> "$GITHUB_OUTPUT" + [ -n "$UNIT" ] && echo "unit_changed=true" >> "$GITHUB_OUTPUT" || echo "unit_changed=false" >> "$GITHUB_OUTPUT" + echo "E2E paths changed: ${E2E:-none}" + echo "Unit paths changed: ${UNIT:-none}" + gate-2-start: name: "Gate 2: Testing - Starting" runs-on: ubuntu-latest @@ -688,18 +725,46 @@ jobs: test-unit: name: "Gate 2.1: Unit Tests" runs-on: ubuntu-latest - needs: gate-2-start + needs: [gate-2-start, check-app-changes] if: ${{ !inputs.skip_tests }} steps: - name: Checkout code uses: actions/checkout@v6 + - name: Restore cached coverage report + id: cache-restore + if: needs.check-app-changes.outputs.unit_changed == 'false' + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + LAST_RUN=$(gh run list \ + --repo "${{ github.repository }}" \ + --workflow gated-pipeline.yml \ + --branch "${{ github.ref_name }}" \ + --status success \ + --limit 1 \ + --json databaseId \ + --jq '.[0].databaseId' 2>/dev/null || echo "") + if [ -n "$LAST_RUN" ] && [ "$LAST_RUN" != "null" ]; then + gh run download "$LAST_RUN" \ + --repo "${{ github.repository }}" \ + --name coverage-report \ + --dir frontends/nextjs/coverage/ 2>/dev/null \ + && echo "hit=true" >> "$GITHUB_OUTPUT" \ + || echo "hit=false" >> "$GITHUB_OUTPUT" + else + echo "hit=false" >> "$GITHUB_OUTPUT" + fi + - name: Setup npm with Nexus + if: steps.cache-restore.outputs.hit != 'true' uses: ./.github/actions/setup-npm with: node-version: '20' - name: Run unit tests with coverage + if: steps.cache-restore.outputs.hit != 'true' run: | set -o pipefail cd frontends/nextjs @@ -760,13 +825,41 @@ jobs: test-e2e: name: "Gate 2.2: E2E Tests" runs-on: ubuntu-latest - needs: gate-2-start + needs: [gate-2-start, check-app-changes] if: ${{ !inputs.skip_tests }} steps: - name: Checkout code uses: actions/checkout@v6 + - name: Restore cached test results + id: cache-restore + if: needs.check-app-changes.outputs.e2e_changed == 'false' + shell: bash + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + LAST_RUN=$(gh run list \ + --repo "${{ github.repository }}" \ + --workflow gated-pipeline.yml \ + --branch "${{ github.ref_name }}" \ + --status success \ + --limit 1 \ + --json databaseId \ + --jq '.[0].databaseId' 2>/dev/null || echo "") + if [ -n "$LAST_RUN" ] && [ "$LAST_RUN" != "null" ]; then + gh run download "$LAST_RUN" \ + --repo "${{ github.repository }}" \ + --name playwright-report \ + --dir playwright-report/ 2>/dev/null \ + && echo "hit=true" >> "$GITHUB_OUTPUT" \ + || echo "hit=false" >> "$GITHUB_OUTPUT" + echo "Using cached results from run $LAST_RUN" + else + echo "hit=false" >> "$GITHUB_OUTPUT" + fi + - name: Log in to GitHub Container Registry + if: steps.cache-restore.outputs.hit != 'true' uses: docker/login-action@v4 with: registry: ${{ env.REGISTRY }} @@ -774,17 +867,21 @@ jobs: password: ${{ secrets.GITHUB_TOKEN }} - name: Setup npm with Nexus + if: steps.cache-restore.outputs.hit != 'true' uses: ./.github/actions/setup-npm with: node-version: '20' - name: Build workspace packages + if: steps.cache-restore.outputs.hit != 'true' run: npm run build --workspaces --if-present 2>&1 - name: Install Playwright Browsers + if: steps.cache-restore.outputs.hit != 'true' run: npx playwright install --with-deps chromium - name: Run Playwright tests + if: steps.cache-restore.outputs.hit != 'true' run: | if [ -f e2e/playwright.config.ts ]; then npx playwright test --config=e2e/playwright.config.ts 2>&1