diff --git a/.github/workflows/devbox-update.yml b/.github/workflows/devbox-update.yml new file mode 100644 index 000000000..002190e76 --- /dev/null +++ b/.github/workflows/devbox-update.yml @@ -0,0 +1,31 @@ +name: Devbox Update + +on: + # Weekly schedule - Monday 10am UTC + schedule: + - cron: '0 10 * * 1' + + # Manual trigger + workflow_dispatch: + +concurrency: + group: devbox-update-${{ github.ref }} + cancel-in-progress: true + +jobs: + update: + name: Update Devbox Dependencies + runs-on: ubuntu-latest + permissions: + contents: write + pull-requests: write + steps: + - uses: actions/checkout@v4 + + - name: Install devbox + uses: jetify-com/devbox-install-action@v0.14.0 + + - name: Update devbox packages + uses: xiaolutech/devbox-update-action@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/e2e-mobile-tests.yml b/.github/workflows/e2e-mobile-tests.yml new file mode 100644 index 000000000..ff4c390ad --- /dev/null +++ b/.github/workflows/e2e-mobile-tests.yml @@ -0,0 +1,156 @@ +name: E2E Mobile Tests + +on: + # Weekly schedule - Monday 9am UTC + schedule: + - cron: '0 9 * * 1' + + # TODO: Remove before merging - for testing only + push: + branches: + - feat/mobile-devtools-e2e-integration + + # Manual trigger + workflow_dispatch: + inputs: + test_matrix: + description: 'Test matrix to run' + required: false + type: choice + options: + - all + - android + - ios + - compat + - latest + default: 'all' + + # Callable by other workflows (e.g., release) + workflow_call: + +concurrency: + group: e2e-mobile-${{ github.ref }} + cancel-in-progress: true + +jobs: + e2e-android-compat: + name: E2E Android (RN 0.72) + runs-on: ubuntu-latest + timeout-minutes: 30 + if: | + inputs.test_matrix == 'all' || + inputs.test_matrix == 'android' || + inputs.test_matrix == 'compat' || + github.event_name != 'workflow_dispatch' + steps: + - uses: actions/checkout@v4 + + - name: Install devbox + uses: jetify-com/devbox-install-action@v0.14.0 + with: + project-path: examples/E2E-compat + + - name: Run Android E2E Tests + working-directory: examples/E2E-compat + run: devbox run --pure test:e2e:android + env: + DETOX_AVD: medium_phone_API33_x86_64 + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-android-compat-results + path: examples/E2E-compat/reports/ + if-no-files-found: ignore + + e2e-ios-compat: + name: E2E iOS (RN 0.72) + runs-on: macos-latest + timeout-minutes: 30 + if: | + inputs.test_matrix == 'all' || + inputs.test_matrix == 'ios' || + inputs.test_matrix == 'compat' || + github.event_name != 'workflow_dispatch' + steps: + - uses: actions/checkout@v4 + + - name: Install devbox + uses: jetify-com/devbox-install-action@v0.14.0 + with: + project-path: examples/E2E-compat + + - name: Run iOS E2E Tests + working-directory: examples/E2E-compat + run: devbox run --pure test:e2e:ios + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-ios-compat-results + path: examples/E2E-compat/reports/ + if-no-files-found: ignore + + e2e-android-latest: + name: E2E Android (RN 0.84) + runs-on: ubuntu-latest + timeout-minutes: 30 + continue-on-error: true # TODO: Remove when RN 0.84 support is complete + if: | + inputs.test_matrix == 'all' || + inputs.test_matrix == 'android' || + inputs.test_matrix == 'latest' || + github.event_name != 'workflow_dispatch' + steps: + - uses: actions/checkout@v4 + + - name: Install devbox + uses: jetify-com/devbox-install-action@v0.14.0 + with: + project-path: examples/E2E-latest + + - name: Run Android E2E Tests + working-directory: examples/E2E-latest + run: devbox run --pure test:e2e:android + env: + DETOX_AVD: medium_phone_API35_x86_64 + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-android-latest-results + path: examples/E2E-latest/reports/ + if-no-files-found: ignore + + e2e-ios-latest: + name: E2E iOS (RN 0.84) + runs-on: macos-latest + timeout-minutes: 30 + continue-on-error: true # TODO: Remove when RN 0.84 support is complete + if: | + inputs.test_matrix == 'all' || + inputs.test_matrix == 'ios' || + inputs.test_matrix == 'latest' || + github.event_name != 'workflow_dispatch' + steps: + - uses: actions/checkout@v4 + + - name: Install devbox + uses: jetify-com/devbox-install-action@v0.14.0 + with: + project-path: examples/E2E-latest + + - name: Run iOS E2E Tests + working-directory: examples/E2E-latest + run: devbox run --pure test:e2e:ios + + - name: Upload test results + if: always() + uses: actions/upload-artifact@v4 + with: + name: e2e-ios-latest-results + path: examples/E2E-latest/reports/ + if-no-files-found: ignore diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4dc77483f..d39a94de0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -37,6 +37,12 @@ jobs: - name: Test run: devbox run test + e2e-tests: + name: E2E Mobile Tests + needs: [ci] + if: inputs.type == 'beta' || inputs.type == 'production' + uses: ./.github/workflows/e2e-mobile-tests.yml + release-dryrun: name: Release (dry-run) if: inputs.type == 'dry-run' @@ -64,7 +70,7 @@ jobs: release-beta: name: Release (beta) if: inputs.type == 'beta' - needs: [ci] + needs: [ci, e2e-tests] runs-on: ubuntu-latest environment: Publish-Beta permissions: @@ -91,7 +97,7 @@ jobs: release-production: name: Release (production) if: inputs.type == 'production' - needs: [ci] + needs: [ci, e2e-tests] runs-on: ubuntu-latest environment: Publish permissions: diff --git a/examples/E2E-compat/README.md b/examples/E2E-compat/README.md index 8bd066df0..0bbc4be87 100644 --- a/examples/E2E-compat/README.md +++ b/examples/E2E-compat/README.md @@ -1,8 +1,56 @@ This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). -# Getting Started +# E2E Test App - React Native 0.72 (Compat) -> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. +This example app tests SDK compatibility with React Native 0.72.9 + React 18.3.1. + +## Developer Setup (Devbox) + +### Prerequisites + +```bash +# Install devbox +curl -fsSL https://get.jetify.com/devbox | bash +``` + +### Quick Start + +```bash +cd examples/E2E-compat + +# Enter devbox shell (downloads SDKs on first run) +devbox shell + +# Install dependencies +devbox run install + +# Start Android emulator +devbox run start:emu + +# Run E2E tests +devbox run test:e2e:android +``` + +### Available Commands + +- `devbox run install` - Install Node dependencies +- `devbox run install:pods` - Install iOS CocoaPods +- `devbox run build:android` - Build Android app +- `devbox run build:ios` - Build iOS app +- `devbox run test:e2e:android` - Run Android E2E tests +- `devbox run test:e2e:ios` - Run iOS E2E tests +- `devbox run start:emu` - Start Android emulator +- `devbox run start:sim` - Start iOS simulator +- `devbox run stop:emu` - Stop Android emulator +- `devbox run stop:sim` - Stop iOS simulator + +See [mobile-devtools](https://github.com/segment-integrations/mobile-devtools) for more details. + +--- + +# Getting Started (Manual Setup) + +> **Note**: The devbox setup above is recommended. For manual setup, follow the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. ## Step 1: Start the Metro Server diff --git a/examples/E2E-compat/android/build.gradle b/examples/E2E-compat/android/build.gradle index c83bf5b8a..bcdfc2d9f 100644 --- a/examples/E2E-compat/android/build.gradle +++ b/examples/E2E-compat/android/build.gradle @@ -2,16 +2,18 @@ buildscript { ext { - // Default to the build-tools pinned in devbox; allow override via ANDROID_BUILD_TOOLS_VERSION. - // Keep in sync with nix/flake.nix when ANDROID_BUILD_TOOLS_VERSION is unset. - buildToolsVersion = System.getenv("ANDROID_BUILD_TOOLS_VERSION") ?: "30.0.3" + def compileSdkEnv = System.getenv("ANDROID_COMPILE_SDK") ?: System.getenv("ANDROID_MAX_API") ?: "33" + def targetSdkEnv = System.getenv("ANDROID_TARGET_SDK") ?: System.getenv("ANDROID_MAX_API") ?: "33" + buildToolsVersion = System.getenv("ANDROID_BUILD_TOOLS_VERSION") ?: "35.0.0" minSdkVersion = 21 - compileSdkVersion = 33 - targetSdkVersion = 33 + compileSdkVersion = compileSdkEnv.toInteger() + targetSdkVersion = targetSdkEnv.toInteger() kotlinVersion="1.7.20" - // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. - ndkVersion = "23.1.7779620" + def ndkVersionEnv = System.getenv("ANDROID_NDK_VERSION") + if (ndkVersionEnv) { + ndkVersion = ndkVersionEnv + } } repositories { google() diff --git a/examples/E2E-compat/devbox.json b/examples/E2E-compat/devbox.json new file mode 100644 index 000000000..374b7dd34 --- /dev/null +++ b/examples/E2E-compat/devbox.json @@ -0,0 +1,54 @@ +{ + "include": [ + "github:segment-integrations/mobile-devtools?dir=plugins/react-native" + ], + "packages": [ + "nodejs@20", + "yarn-berry@latest", + "watchman@latest", + "jdk17@latest", + "gradle@latest" + ], + "env": { + "IOS_APP_SCHEME": "AnalyticsReactNativeE2E", + "IOS_APP_BUNDLE_ID": "com.analyticsreactnativeexample", + "ANDROID_APP_ID": "com.analyticsreactnativeexample", + "ANDROID_APP_APK": "android/app/build/outputs/apk/release/app-release.apk", + "ANDROID_MAX_API": "35", + "ANDROID_SDK_REQUIRED": "0" + }, + "shell": { + "scripts": { + "install": ["yarn install"], + "install:pods": ["(cd ios && pod install)"], + "build:android": [ + "yarn install", + "(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)" + ], + "build:ios": [ + "yarn install", + "(cd ios && pod install)", + "ios.sh xcodebuild -workspace ios/AnalyticsReactNativeE2E.xcworkspace -scheme AnalyticsReactNativeE2E -configuration Release -sdk iphonesimulator -derivedDataPath ios/build" + ], + "test:e2e:android": [ + "yarn install", + "(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)", + "yarn detox test --configuration android.emu.release" + ], + "test:e2e:ios": [ + "yarn install", + "(cd ios && pod install)", + "ios.sh xcodebuild -workspace ios/AnalyticsReactNativeE2E.xcworkspace -scheme AnalyticsReactNativeE2E -configuration Release -sdk iphonesimulator -derivedDataPath ios/build", + "yarn detox test --configuration ios.sim.release" + ], + "start:metro": ["metro.sh start ${1:-default}"], + "stop:metro": ["metro.sh stop ${1:-default}"], + "start:sim": ["ios.sh simulator start ${1:-${IOS_DEFAULT_DEVICE:-max}}"], + "stop:sim": ["ios.sh simulator stop"], + "start:emu": [ + "android.sh emulator start ${1:-${ANDROID_DEFAULT_DEVICE:-max}}" + ], + "stop:emu": ["android.sh emulator stop"] + } + } +} diff --git a/examples/E2E-latest/README.md b/examples/E2E-latest/README.md index 8bd066df0..6c16ffbfe 100644 --- a/examples/E2E-latest/README.md +++ b/examples/E2E-latest/README.md @@ -1,8 +1,56 @@ This is a new [**React Native**](https://reactnative.dev) project, bootstrapped using [`@react-native-community/cli`](https://github.com/react-native-community/cli). -# Getting Started +# E2E Test App - React Native 0.84 (Latest) -> **Note**: Make sure you have completed the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. +This example app tests SDK compatibility with React Native 0.84.1 + React 19.2.3. + +## Developer Setup (Devbox) + +### Prerequisites + +```bash +# Install devbox +curl -fsSL https://get.jetify.com/devbox | bash +``` + +### Quick Start + +```bash +cd examples/E2E-latest + +# Enter devbox shell (downloads SDKs on first run) +devbox shell + +# Install dependencies +devbox run install + +# Start Android emulator +devbox run start:emu + +# Run E2E tests +devbox run test:e2e:android +``` + +### Available Commands + +- `devbox run install` - Install Node dependencies +- `devbox run install:pods` - Install iOS CocoaPods +- `devbox run build:android` - Build Android app +- `devbox run build:ios` - Build iOS app +- `devbox run test:e2e:android` - Run Android E2E tests +- `devbox run test:e2e:ios` - Run iOS E2E tests +- `devbox run start:emu` - Start Android emulator +- `devbox run start:sim` - Start iOS simulator +- `devbox run stop:emu` - Stop Android emulator +- `devbox run stop:sim` - Stop iOS simulator + +See [mobile-devtools](https://github.com/segment-integrations/mobile-devtools) for more details. + +--- + +# Getting Started (Manual Setup) + +> **Note**: The devbox setup above is recommended. For manual setup, follow the [React Native - Environment Setup](https://reactnative.dev/docs/environment-setup) instructions till "Creating a new application" step, before proceeding. ## Step 1: Start the Metro Server diff --git a/examples/E2E-latest/android/build.gradle b/examples/E2E-latest/android/build.gradle index c83bf5b8a..ae7670564 100644 --- a/examples/E2E-latest/android/build.gradle +++ b/examples/E2E-latest/android/build.gradle @@ -2,16 +2,18 @@ buildscript { ext { - // Default to the build-tools pinned in devbox; allow override via ANDROID_BUILD_TOOLS_VERSION. - // Keep in sync with nix/flake.nix when ANDROID_BUILD_TOOLS_VERSION is unset. - buildToolsVersion = System.getenv("ANDROID_BUILD_TOOLS_VERSION") ?: "30.0.3" + def compileSdkEnv = System.getenv("ANDROID_COMPILE_SDK") ?: System.getenv("ANDROID_MAX_API") ?: "35" + def targetSdkEnv = System.getenv("ANDROID_TARGET_SDK") ?: System.getenv("ANDROID_MAX_API") ?: "35" + buildToolsVersion = System.getenv("ANDROID_BUILD_TOOLS_VERSION") ?: "35.0.0" minSdkVersion = 21 - compileSdkVersion = 33 - targetSdkVersion = 33 + compileSdkVersion = compileSdkEnv.toInteger() + targetSdkVersion = targetSdkEnv.toInteger() kotlinVersion="1.7.20" - // We use NDK 23 which has both M1 support and is the side-by-side NDK version from AGP. - ndkVersion = "23.1.7779620" + def ndkVersionEnv = System.getenv("ANDROID_NDK_VERSION") + if (ndkVersionEnv) { + ndkVersion = ndkVersionEnv + } } repositories { google() diff --git a/examples/E2E-latest/devbox.json b/examples/E2E-latest/devbox.json new file mode 100644 index 000000000..374b7dd34 --- /dev/null +++ b/examples/E2E-latest/devbox.json @@ -0,0 +1,54 @@ +{ + "include": [ + "github:segment-integrations/mobile-devtools?dir=plugins/react-native" + ], + "packages": [ + "nodejs@20", + "yarn-berry@latest", + "watchman@latest", + "jdk17@latest", + "gradle@latest" + ], + "env": { + "IOS_APP_SCHEME": "AnalyticsReactNativeE2E", + "IOS_APP_BUNDLE_ID": "com.analyticsreactnativeexample", + "ANDROID_APP_ID": "com.analyticsreactnativeexample", + "ANDROID_APP_APK": "android/app/build/outputs/apk/release/app-release.apk", + "ANDROID_MAX_API": "35", + "ANDROID_SDK_REQUIRED": "0" + }, + "shell": { + "scripts": { + "install": ["yarn install"], + "install:pods": ["(cd ios && pod install)"], + "build:android": [ + "yarn install", + "(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)" + ], + "build:ios": [ + "yarn install", + "(cd ios && pod install)", + "ios.sh xcodebuild -workspace ios/AnalyticsReactNativeE2E.xcworkspace -scheme AnalyticsReactNativeE2E -configuration Release -sdk iphonesimulator -derivedDataPath ios/build" + ], + "test:e2e:android": [ + "yarn install", + "(cd android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release)", + "yarn detox test --configuration android.emu.release" + ], + "test:e2e:ios": [ + "yarn install", + "(cd ios && pod install)", + "ios.sh xcodebuild -workspace ios/AnalyticsReactNativeE2E.xcworkspace -scheme AnalyticsReactNativeE2E -configuration Release -sdk iphonesimulator -derivedDataPath ios/build", + "yarn detox test --configuration ios.sim.release" + ], + "start:metro": ["metro.sh start ${1:-default}"], + "stop:metro": ["metro.sh stop ${1:-default}"], + "start:sim": ["ios.sh simulator start ${1:-${IOS_DEFAULT_DEVICE:-max}}"], + "stop:sim": ["ios.sh simulator stop"], + "start:emu": [ + "android.sh emulator start ${1:-${ANDROID_DEFAULT_DEVICE:-max}}" + ], + "stop:emu": ["android.sh emulator stop"] + } + } +}