diff --git a/.changeset/integration-skip-unaffected.md b/.changeset/integration-skip-unaffected.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/integration-skip-unaffected.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 650d7e5f916..890b2ea0aa1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -510,9 +510,79 @@ jobs: retention-days: 7 if-no-files-found: warn - integration-tests: - needs: [check-permissions, build-packages] + integration-plan: + needs: [check-permissions] if: ${{ github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository }} + name: Integration Plan + permissions: + contents: read + runs-on: 'blacksmith-8vcpu-ubuntu-2204' + defaults: + run: + shell: bash + timeout-minutes: ${{ vars.TIMEOUT_MINUTES_NORMAL && fromJSON(vars.TIMEOUT_MINUTES_NORMAL) || 10 }} + outputs: + affected: ${{ steps.plan.outputs.affected }} + known: ${{ steps.plan.outputs.known }} + + steps: + - name: Checkout Repo + uses: actions/checkout@v4.4.0 + with: + persist-credentials: false + fetch-depth: 2 + fetch-tags: false + filter: 'blob:none' + show-progress: false + + - name: Setup + uses: $/.github/actions/init-blacksmith + with: + cache-enabled: true + turbo-signature: ${{ secrets.TURBO_REMOTE_CACHE_SIGNATURE_KEY }} + turbo-team: ${{ vars.TURBO_TEAM }} + turbo-token: ${{ secrets.TURBO_TOKEN }} + + - name: Find affected integration suites + id: plan + env: + EVENT_NAME: ${{ github.event_name }} + run: | + mapfile -t TASKS < <(jq -r '.tasks | keys[] | select(startswith("//#test:integration:")) | ltrimstr("//#")' turbo.json) + if [ "${#TASKS[@]}" -eq 0 ]; then + echo "::error::Found no integration tasks in turbo.json, so every integration suite runs." + exit 1 + fi + echo "known=$(printf '%s\n' "${TASKS[@]#test:integration:}" | jq -Rnc '[inputs]')" >> "$GITHUB_OUTPUT" + + if [ "$EVENT_NAME" != "pull_request" ]; then + echo "Running every integration suite for $EVENT_NAME." + echo "affected=all" >> "$GITHUB_OUTPUT" + exit 0 + fi + + if ! git diff --quiet HEAD^1 HEAD -- .github; then + echo "This PR changes .github/, so every integration suite runs." + echo "affected=all" >> "$GITHUB_OUTPUT" + exit 0 + fi + + if ! TURBO_RAW=$(pnpm turbo query affected --base HEAD^1 --head HEAD --tasks "${TASKS[@]}"); then + echo "::error::turbo query affected failed, so every integration suite runs." + exit 1 + fi + TURBO_JSON=$(printf '%s\n' "$TURBO_RAW" | awk '/^\{/{found=1} found') + if ! AFFECTED=$(jq -ec '[.data.affectedTasks.items[] | select(.package.name == "//" and (.name | startswith("test:integration:"))) | .name | ltrimstr("test:integration:")]' <<< "$TURBO_JSON"); then + echo "::error::turbo query affected returned unexpected output, so every integration suite runs." + printf '%s\n' "$TURBO_RAW" + exit 1 + fi + echo "affected=$AFFECTED" >> "$GITHUB_OUTPUT" + echo "Affected integration suites: $AFFECTED" + + integration-tests: + needs: [check-permissions, build-packages, integration-plan] + if: ${{ !cancelled() && needs.check-permissions.result == 'success' && needs.build-packages.result == 'success' && (github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository) }} name: Integration Tests (${{ matrix.test-name }}, ${{ matrix.test-project }}${{ matrix.next-version && format(', {0}', matrix.next-version) || '' }}) permissions: contents: read @@ -572,7 +642,28 @@ jobs: next-version: '16' steps: + - name: Check whether this suite is affected + id: affected + env: + AFFECTED: ${{ needs.integration-plan.outputs.affected }} + KNOWN: ${{ needs.integration-plan.outputs.known }} + PLAN_RESULT: ${{ needs.integration-plan.result }} + SUITE: ${{ matrix.test-name }} + run: | + if [ "$PLAN_RESULT" != "success" ] || [ -z "$AFFECTED" ] || [ "$AFFECTED" = "all" ]; then + echo "run=true" >> "$GITHUB_OUTPUT" + elif [[ "$KNOWN" != *"\"$SUITE\""* ]]; then + echo "::warning::$SUITE is not an integration task in turbo.json, so it runs and the task validation reports it." + echo "run=true" >> "$GITHUB_OUTPUT" + elif [[ "$AFFECTED" == *"\"$SUITE\""* ]]; then + echo "run=true" >> "$GITHUB_OUTPUT" + else + echo "::notice title=Integration suite skipped::Nothing the $SUITE suite uses changed in this PR." + echo "run=false" >> "$GITHUB_OUTPUT" + fi + - name: Checkout Repo + if: steps.affected.outputs.run == 'true' uses: actions/checkout@v4.4.0 with: persist-credentials: false @@ -582,6 +673,7 @@ jobs: show-progress: false - name: Setup + if: steps.affected.outputs.run == 'true' id: config uses: $/.github/actions/init-blacksmith with: @@ -592,6 +684,7 @@ jobs: playwright-enabled: true - name: Verify jq is installed + if: steps.affected.outputs.run == 'true' shell: bash run: | if ! command -v jq &> /dev/null; then @@ -601,6 +694,7 @@ jobs: jq --version - name: Validate turbo task + if: steps.affected.outputs.run == 'true' env: E2E_APP_CLERK_JS_DIR: ${{runner.temp}} E2E_APP_CLERK_UI_DIR: ${{runner.temp}} @@ -610,10 +704,8 @@ jobs: E2E_PROJECT: ${{ matrix.test-project }} INTEGRATION_INSTANCE_KEYS: ${{ secrets.INTEGRATION_INSTANCE_KEYS }} run: | - # Validate the turbo task exists. Turbo's --affected flag is a no-op for - # root-level tasks (//#) — they are always returned as affected. The previous - # --affected check only served to silently skip tests when the task was missing - # from turbo.json, hiding real configuration errors. + # Validate the turbo task exists, so a missing or misnamed task fails here + # instead of silently running nothing. TASK_NAME="test:integration:${{ matrix.test-name }}" TURBO_STDERR=$(mktemp) if ! TURBO_RAW=$(pnpm turbo run "$TASK_NAME" --dry=json 2>"$TURBO_STDERR"); then @@ -640,15 +732,19 @@ jobs: echo "Task '$TASK_NAME' validated ($TASK_COUNT tasks in graph)" - name: Build packages + if: steps.affected.outputs.run == 'true' run: pnpm turbo build $TURBO_ARGS --only - name: Publish to local registry + if: steps.affected.outputs.run == 'true' run: pkglab pub --force - name: Edit .npmrc [link-workspace-packages=false] + if: steps.affected.outputs.run == 'true' run: sed -i -E 's/link-workspace-packages=(deep|true)/link-workspace-packages=false/' .npmrc - name: Install @clerk/clerk-js in os temp + if: steps.affected.outputs.run == 'true' working-directory: ${{runner.temp}} run: | mkdir clerk-js && cd clerk-js @@ -656,6 +752,7 @@ jobs: pkglab add @clerk/clerk-js - name: Install @clerk/ui in os temp + if: steps.affected.outputs.run == 'true' working-directory: ${{runner.temp}} run: | mkdir clerk-ui && cd clerk-ui @@ -663,10 +760,11 @@ jobs: pkglab add @clerk/ui - name: Copy components @clerk/astro - if: ${{ matrix.test-name == 'astro' }} + if: ${{ steps.affected.outputs.run == 'true' && (matrix.test-name == 'astro') }} run: cd packages/astro && pnpm copy:components - name: Write all ENV certificates to files in integration/certs + if: steps.affected.outputs.run == 'true' uses: actions/github-script@v7.1.0 env: INTEGRATION_CERTS: '${{secrets.INTEGRATION_CERTS}}' @@ -684,11 +782,12 @@ jobs: } - name: LS certs + if: steps.affected.outputs.run == 'true' working-directory: ./integration/certs run: ls -la && pwd - name: Ensure Xvfb is installed - if: ${{ matrix.test-name == 'electron' }} + if: ${{ steps.affected.outputs.run == 'true' && (matrix.test-name == 'electron') }} run: | if ! command -v xvfb-run &> /dev/null; then sudo apt-get update @@ -696,6 +795,7 @@ jobs: fi - name: Configure test user cleanup + if: steps.affected.outputs.run == 'true' run: echo "INTEGRATION_TEST_RUN_KEY=${RUN_ID}-${RUN_ATTEMPT}-${TEST_NAME}-${TEST_PROJECT}-${NEXT_VERSION:-default}" >> "$GITHUB_ENV" env: RUN_ID: ${{ github.run_id }} @@ -705,6 +805,7 @@ jobs: NEXT_VERSION: ${{ matrix.next-version }} - name: Run Integration Tests + if: steps.affected.outputs.run == 'true' id: integration-tests timeout-minutes: 25 run: | @@ -728,7 +829,7 @@ jobs: VERCEL_AUTOMATION_BYPASS_SECRET: ${{ secrets.VERCEL_AUTOMATION_BYPASS_SECRET }} - name: Sanitize artifact name - if: ${{ cancelled() || failure() }} + if: ${{ steps.affected.outputs.run == 'true' && (cancelled() || failure()) }} id: sanitize run: | SANITIZED="${TEST_NAME//:/-}" @@ -737,7 +838,7 @@ jobs: TEST_NAME: ${{ matrix.test-name }} - name: Upload test-results - if: ${{ cancelled() || failure() }} + if: ${{ steps.affected.outputs.run == 'true' && (cancelled() || failure()) }} uses: actions/upload-artifact@v4.6.2 with: name: playwright-traces-${{ github.run_id }}-${{ github.run_attempt }}-${{ steps.sanitize.outputs.artifact-suffix }}${{ matrix.next-version && format('-next{0}', matrix.next-version) || '' }} diff --git a/turbo.json b/turbo.json index 461564fd311..99b3832521a 100644 --- a/turbo.json +++ b/turbo.json @@ -4,6 +4,9 @@ "signature": true }, "ui": "tui", + "futureFlags": { + "affectedUsingTaskInputs": true + }, "globalDependencies": [ ".github/.cache-version", ".npmrc",