diff --git a/.changeset/wicked-regions-help.md b/.changeset/wicked-regions-help.md new file mode 100644 index 00000000000..a845151cc84 --- /dev/null +++ b/.changeset/wicked-regions-help.md @@ -0,0 +1,2 @@ +--- +--- diff --git a/.github/workflows/mobile-e2e.yml b/.github/workflows/mobile-e2e.yml index 5c75f37af06..9c3c8788318 100644 --- a/.github/workflows/mobile-e2e.yml +++ b/.github/workflows/mobile-e2e.yml @@ -1,101 +1,80 @@ -# Manual mobile e2e for @clerk/expo native components. -# Clones clerk-expo-quickstart, builds the NativeComponentQuickstart app, -# and runs Maestro flows on iOS simulator and Android emulator. -# -# Secrets: -# INTEGRATION_STAGING_INSTANCE_KEYS — JSON map of named staging test instances -# ({ "": { "pk": "pk_test_...", "sk": "sk_test_..." } }). -# Same secret used by /integration (Playwright) staging jobs. We read the -# entry named EXPO_INSTANCE_NAME (set in env: below). -# -# Test users are provisioned per-run via Clerk Backend API and deleted at -# teardown — same pattern as /integration's createBapiUser. -name: "Mobile e2e (@clerk/expo)" +name: 'Mobile e2e smoke (@clerk/expo)' on: workflow_dispatch: inputs: - quickstart_ref: - description: "clerk-expo-quickstart git ref (branch, tag, or SHA)" + platform: + description: 'Platform to run' required: false - default: "main" - exclude_tags: - description: "Maestro tags to exclude (comma-separated)" + default: 'android' + type: choice + options: + - android + - ios + - all + expo_sdk: + description: 'Expo SDK fixture version' required: false - default: "manual,skip" + default: '56' + type: choice + options: + - '54' + - '55' + - '56' -env: - EXPO_INSTANCE_NAME: clerkstage-with-native-components +permissions: + contents: read concurrency: - group: mobile-e2e-${{ github.ref }} + group: mobile-e2e-smoke-${{ github.ref }}-${{ inputs.platform }}-${{ inputs.expo_sdk }} cancel-in-progress: true +env: + FIXTURE_DIR: integration/templates/expo-native + FIXTURE_PUBLISHABLE_KEY: pk_test_ZHVtbXkuY2xlcmsuYWNjb3VudHMuZGV2JA + SDK_PACK_DIR: /tmp/clerk-expo-pack + jobs: android: - name: Android - runs-on: 'blacksmith-8vcpu-ubuntu-2204' + if: ${{ inputs.platform == 'android' || inputs.platform == 'all' }} + name: Android / Expo SDK ${{ inputs.expo_sdk }} + runs-on: blacksmith-8vcpu-ubuntu-2204 timeout-minutes: 45 - defaults: - run: - working-directory: . steps: - - name: Checkout @clerk/javascript - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - persist-credentials: false - - - name: Checkout clerk-expo-quickstart + - name: Checkout repo uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: persist-credentials: false - repository: clerk/clerk-expo-quickstart - ref: ${{ inputs.quickstart_ref }} - path: clerk-expo-quickstart - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: 20 + node-version: 24.15.0 cache: pnpm - - name: Install monorepo deps + - name: Install monorepo dependencies run: pnpm install --frozen-lockfile - - name: Build @clerk/expo - run: pnpm turbo build --filter=@clerk/expo... - - - name: Install quickstart deps - working-directory: clerk-expo-quickstart/NativeComponentQuickstart - run: pnpm install - - - name: Resolve Clerk instance keys - id: keys - env: - INTEGRATION_STAGING_INSTANCE_KEYS: ${{ secrets.INTEGRATION_STAGING_INSTANCE_KEYS }} - run: node scripts/resolve-instance-keys.mjs INTEGRATION_STAGING_INSTANCE_KEYS "$EXPO_INSTANCE_NAME" - - - name: Write quickstart .env - working-directory: clerk-expo-quickstart/NativeComponentQuickstart + - name: Build and pack @clerk/expo run: | - echo "EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=${{ steps.keys.outputs.pk }}" > .env + pnpm --filter @clerk/expo... build + mkdir -p "$SDK_PACK_DIR" + pnpm --filter @clerk/expo pack --pack-destination "$SDK_PACK_DIR" - - name: Provision test user via BAPI - id: user + - name: Install fixture dependencies + working-directory: ${{ env.FIXTURE_DIR }} env: - CLERK_SECRET_KEY: ${{ steps.keys.outputs.sk }} + EXPO_SDK: ${{ inputs.expo_sdk }} run: | - email="ci-${GITHUB_RUN_ID}-${RANDOM}+clerk_test@clerkcookie.com" - password="ClerkCI!$(openssl rand -hex 8)Aa1" - response=$(curl -fsS -X POST https://api.clerk.com/v1/users \ - -H "Authorization: Bearer $CLERK_SECRET_KEY" \ - -H "Content-Type: application/json" \ - -d "{\"email_address\":[\"$email\"],\"password\":\"$password\"}") - user_id=$(echo "$response" | jq -er '.id') - echo "::add-mask::$password" - echo "email=$email" >> "$GITHUB_OUTPUT" - echo "password=$password" >> "$GITHUB_OUTPUT" - echo "user_id=$user_id" >> "$GITHUB_OUTPUT" + cp "package.sdk-$EXPO_SDK.json" package.json + pnpm install --no-frozen-lockfile + SDK_TARBALL="$(ls "$SDK_PACK_DIR"/clerk-expo-*.tgz)" + pnpm add "$SDK_TARBALL" -w + pnpm expo install expo-auth-session expo-constants expo-crypto expo-dev-client expo-secure-store expo-web-browser + + - name: Write fixture .env + working-directory: ${{ env.FIXTURE_DIR }} + run: echo "EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=$FIXTURE_PUBLISHABLE_KEY" > .env - name: Set up JDK 17 uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4 @@ -107,141 +86,84 @@ jobs: run: | curl -Ls "https://get.maestro.mobile.dev" | bash echo "$HOME/.maestro/bin" >> "$GITHUB_PATH" + "$HOME/.maestro/bin/maestro" --version - - name: Run Android e2e + - name: Run Android smoke test uses: reactivecircus/android-emulator-runner@e89f39f1abbbd05b1113a29cf4db69e7540cae5a # v2 - env: - CLERK_TEST_EMAIL: ${{ steps.user.outputs.email }} - CLERK_TEST_PASSWORD: ${{ steps.user.outputs.password }} - EXCLUDE_TAGS: ${{ inputs.exclude_tags }} with: api-level: 34 target: google_apis arch: x86_64 script: | - cd clerk-expo-quickstart/NativeComponentQuickstart - npx expo prebuild --clean - npx expo run:android --variant release --no-bundler - cd ../../integration-mobile - # Maestro doesn't auto-recurse into subdirectories; pass each flow explicitly. - find flows -type f -name "*.yaml" ! -path "*/common/*" -print0 | \ - xargs -0 maestro test --exclude-tags "$EXCLUDE_TAGS" + cd "$FIXTURE_DIR" + pnpm expo prebuild --clean --platform android + pnpm expo run:android --variant release --no-bundler + maestro test --test-output-dir artifacts/maestro .maestro/smoke.yaml - name: Upload Maestro artifacts on failure if: failure() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: - name: maestro-android - path: ~/.maestro/tests - - - name: Cleanup test user - if: always() && steps.user.outputs.user_id != '' - env: - CLERK_SECRET_KEY: ${{ steps.keys.outputs.sk }} - USER_ID: ${{ steps.user.outputs.user_id }} - run: | - curl -fsS -X DELETE "https://api.clerk.com/v1/users/$USER_ID" \ - -H "Authorization: Bearer $CLERK_SECRET_KEY" || true + name: maestro-android-sdk-${{ inputs.expo_sdk }} + path: ${{ env.FIXTURE_DIR }}/artifacts/maestro ios: - name: iOS + if: ${{ inputs.platform == 'ios' || inputs.platform == 'all' }} + name: iOS / Expo SDK ${{ inputs.expo_sdk }} runs-on: macos-15 timeout-minutes: 60 steps: - - name: Checkout @clerk/javascript - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - with: - persist-credentials: false - - - name: Checkout clerk-expo-quickstart + - name: Checkout repo uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 with: persist-credentials: false - repository: clerk/clerk-expo-quickstart - ref: ${{ inputs.quickstart_ref }} - path: clerk-expo-quickstart - uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 with: - node-version: 20 + node-version: 24.15.0 cache: pnpm - - name: Install monorepo deps + - name: Install monorepo dependencies run: pnpm install --frozen-lockfile - - name: Build @clerk/expo - run: pnpm turbo build --filter=@clerk/expo... - - - name: Install quickstart deps - working-directory: clerk-expo-quickstart/NativeComponentQuickstart - run: pnpm install - - - name: Resolve Clerk instance keys - id: keys - env: - INTEGRATION_STAGING_INSTANCE_KEYS: ${{ secrets.INTEGRATION_STAGING_INSTANCE_KEYS }} - run: node scripts/resolve-instance-keys.mjs INTEGRATION_STAGING_INSTANCE_KEYS "$EXPO_INSTANCE_NAME" - - - name: Write quickstart .env - working-directory: clerk-expo-quickstart/NativeComponentQuickstart + - name: Build and pack @clerk/expo run: | - echo "EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=${{ steps.keys.outputs.pk }}" > .env + pnpm --filter @clerk/expo... build + mkdir -p "$SDK_PACK_DIR" + pnpm --filter @clerk/expo pack --pack-destination "$SDK_PACK_DIR" - - name: Provision test user via BAPI - id: user + - name: Install fixture dependencies + working-directory: ${{ env.FIXTURE_DIR }} env: - CLERK_SECRET_KEY: ${{ steps.keys.outputs.sk }} + EXPO_SDK: ${{ inputs.expo_sdk }} run: | - email="ci-${GITHUB_RUN_ID}-${RANDOM}+clerk_test@clerkcookie.com" - password="ClerkCI!$(openssl rand -hex 8)Aa1" - response=$(curl -fsS -X POST https://api.clerk.com/v1/users \ - -H "Authorization: Bearer $CLERK_SECRET_KEY" \ - -H "Content-Type: application/json" \ - -d "{\"email_address\":[\"$email\"],\"password\":\"$password\"}") - user_id=$(echo "$response" | jq -er '.id') - echo "::add-mask::$password" - echo "email=$email" >> "$GITHUB_OUTPUT" - echo "password=$password" >> "$GITHUB_OUTPUT" - echo "user_id=$user_id" >> "$GITHUB_OUTPUT" - - - name: Cache SPM - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 - with: - path: ~/Library/Developer/Xcode/DerivedData - key: spm-${{ hashFiles('packages/expo/package.json') }} + cp "package.sdk-$EXPO_SDK.json" package.json + pnpm install --no-frozen-lockfile + SDK_TARBALL="$(ls "$SDK_PACK_DIR"/clerk-expo-*.tgz)" + pnpm add "$SDK_TARBALL" -w + pnpm expo install expo-auth-session expo-constants expo-crypto expo-dev-client expo-secure-store expo-web-browser + + - name: Write fixture .env + working-directory: ${{ env.FIXTURE_DIR }} + run: echo "EXPO_PUBLIC_CLERK_PUBLISHABLE_KEY=$FIXTURE_PUBLISHABLE_KEY" > .env - name: Install Maestro run: | curl -Ls "https://get.maestro.mobile.dev" | bash echo "$HOME/.maestro/bin" >> "$GITHUB_PATH" + "$HOME/.maestro/bin/maestro" --version - - name: Build and run iOS e2e - env: - CLERK_TEST_EMAIL: ${{ steps.user.outputs.email }} - CLERK_TEST_PASSWORD: ${{ steps.user.outputs.password }} - EXCLUDE_TAGS: ${{ inputs.exclude_tags }} + - name: Build and run iOS smoke test + working-directory: ${{ env.FIXTURE_DIR }} run: | - cd clerk-expo-quickstart/NativeComponentQuickstart - npx expo prebuild --clean - npx expo run:ios --configuration Release --no-bundler - cd ../../integration-mobile - # Maestro doesn't auto-recurse into subdirectories; pass each flow explicitly. - find flows -type f -name "*.yaml" ! -path "*/common/*" -print0 | \ - xargs -0 maestro test --exclude-tags "$EXCLUDE_TAGS,androidOnly" + pnpm expo prebuild --clean --platform ios + pnpm expo run:ios --configuration Release --no-bundler + maestro test --test-output-dir artifacts/maestro .maestro/smoke.yaml - name: Upload Maestro artifacts on failure if: failure() uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: - name: maestro-ios - path: ~/.maestro/tests - - - name: Cleanup test user - if: always() && steps.user.outputs.user_id != '' - env: - CLERK_SECRET_KEY: ${{ steps.keys.outputs.sk }} - USER_ID: ${{ steps.user.outputs.user_id }} - run: | - curl -fsS -X DELETE "https://api.clerk.com/v1/users/$USER_ID" \ - -H "Authorization: Bearer $CLERK_SECRET_KEY" || true + name: maestro-ios-sdk-${{ inputs.expo_sdk }} + path: ${{ env.FIXTURE_DIR }}/artifacts/maestro diff --git a/integration/templates/expo-native/.maestro/smoke.yaml b/integration/templates/expo-native/.maestro/smoke.yaml new file mode 100644 index 00000000000..940e58b8ce7 --- /dev/null +++ b/integration/templates/expo-native/.maestro/smoke.yaml @@ -0,0 +1,7 @@ +appId: com.clerk.exponativebuildfixture +--- +- launchApp +- assertVisible: 'Clerk Expo Native Fixture' +- assertVisible: 'Open native AuthView' +- tapOn: 'Open native AuthView' +- assertVisible: 'Native AuthView mounted' diff --git a/integration/templates/expo-native/App.tsx b/integration/templates/expo-native/App.tsx index 4d549077e3e..9ba50a6b329 100644 --- a/integration/templates/expo-native/App.tsx +++ b/integration/templates/expo-native/App.tsx @@ -35,7 +35,10 @@ function NativeBuildFixture() { presentationStyle='pageSheet' onRequestClose={() => setIsAuthOpen(false)} > - setIsAuthOpen(false)} /> + + Native AuthView mounted + setIsAuthOpen(false)} /> + ); @@ -70,4 +73,7 @@ const styles = StyleSheet.create({ fontSize: 20, fontWeight: '600', }, + modalContent: { + flex: 1, + }, });