Skip to content
Open
2 changes: 2 additions & 0 deletions .changeset/integration-skip-unaffected.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
121 changes: 111 additions & 10 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -582,6 +673,7 @@ jobs:
show-progress: false

- name: Setup
if: steps.affected.outputs.run == 'true'
id: config
uses: $/.github/actions/init-blacksmith
with:
Expand All @@ -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
Expand All @@ -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}}
Expand All @@ -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
Expand All @@ -640,33 +732,39 @@ 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
pnpm init
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
pnpm init
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}}'
Expand All @@ -684,18 +782,20 @@ 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
sudo apt-get install -y xvfb
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 }}
Expand All @@ -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: |
Expand All @@ -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//:/-}"
Expand All @@ -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) || '' }}
Expand Down
3 changes: 3 additions & 0 deletions turbo.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@
"signature": true
},
"ui": "tui",
"futureFlags": {
"affectedUsingTaskInputs": true
},
"globalDependencies": [
".github/.cache-version",
".npmrc",
Expand Down
Loading