From d955474deadb927a3ba130c610cb1befcf4972fd Mon Sep 17 00:00:00 2001 From: Mike Hardy Date: Sun, 5 Sep 2021 12:34:55 -0500 Subject: [PATCH] test(e2e): split e2e into ios/android, use all yarn scripts for build/test --- .../{tests_e2e.yml => tests_e2e_android.yml} | 199 ++++-------------- .github/workflows/tests_e2e_ios.yml | 190 +++++++++++++++++ example/.detoxrc.json | 2 +- package.json | 2 +- 4 files changed, 234 insertions(+), 159 deletions(-) rename .github/workflows/{tests_e2e.yml => tests_e2e_android.yml} (54%) create mode 100644 .github/workflows/tests_e2e_ios.yml diff --git a/.github/workflows/tests_e2e.yml b/.github/workflows/tests_e2e_android.yml similarity index 54% rename from .github/workflows/tests_e2e.yml rename to .github/workflows/tests_e2e_android.yml index 6c750e31..068db996 100644 --- a/.github/workflows/tests_e2e.yml +++ b/.github/workflows/tests_e2e_android.yml @@ -1,4 +1,4 @@ -name: Testing E2E +name: Testing E2E Android on: pull_request: @@ -20,9 +20,6 @@ on: - '**/*.md' jobs: - # ------------------ - # Android - # ------------------ android: name: Android runs-on: macos-latest @@ -40,26 +37,32 @@ jobs: with: fetch-depth: 50 + # Set up tool versions - uses: actions/setup-node@v2 with: node-version: '14' - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" + - name: Configure JDK 1.11 + uses: actions/setup-java@v2 + with: + distribution: 'adopt' + java-version: '11' # ubuntu-latest is about to default to 11, force it everywhere + + # Set path variables needed for caches + - name: Set workflow variables + id: workflow-variables + run: | + echo "::set-output name=metro-cache::$HOME/.metro" + echo "::set-output name=yarn-cache-dir::$(yarn cache dir)" + echo "::set-output name=tempdir::$TMPDIR" - uses: actions/cache@v2 name: Yarn Cache id: yarn-cache with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }}-v1 - - - uses: actions/cache@v2 - name: Gradle Cache - with: - path: ~/.gradle/caches - key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}-v1 + path: ${{ steps.workflow-variables.outputs.yarn-cache-dir }} + key: ${{ runner.os }}-yarn-v1-${{ hashFiles('**/package.json') }} + restore-keys: ${{ runner.os }}-yarn-v1 - name: Yarn Install uses: nick-invision/retry@v2 @@ -69,16 +72,22 @@ jobs: max_attempts: 3 command: DETOX_DISABLE_POSTINSTALL=1 yarn --no-audit --prefer-offline - - name: Configure JDK 1.11 - uses: actions/setup-java@v1 + - name: Cache Firestore Emulator + uses: actions/cache@v2 with: - java-version: '11' # ubuntu-latest is about to default to 11, force it everywhere + path: ~/.cache/firebase/emulators + key: firebase-emulators-v1-${{ github.run_id }} + restore-keys: firebase-emulators-v1 - - name: Verify JDK11 - # Default JDK varies depending on different runner flavors, make sure we are on 11 - # Run a check that exits with error unless it is 11 version to future-proof against unexpected upgrades - run: java -fullversion 2>&1 | grep '11.0' - shell: bash + - name: Start Firestore Emulator + run: yarn tests:emulator:start-ci + + - uses: actions/cache@v2 + name: Gradle Cache + with: + path: ~/.gradle/caches + key: ${{ runner.os }}-gradle-v1-${{ hashFiles('**/*.gradle*') }} + restore-keys: ${{ runner.os }}-gradle-v1 - name: Build Android App uses: nick-invision/retry@v2 @@ -86,7 +95,14 @@ jobs: timeout_minutes: 15 retry_wait_seconds: 60 max_attempts: 3 - command: cd example/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug -Dorg.gradle.daemon=false + command: yarn tests:android:build + + - name: Metro Bundler Cache + uses: actions/cache@v2 + with: + path: ${{ steps.workflow-variables.outputs.metro-cache }} + key: ${{ runner.os }}-metro-v1-${{ github.run_id }} + restore-keys: ${{ runner.os }}-metro-v1 - name: Pre-fetch Javascript bundle # Prebuild the bundle so that's fast when the app starts. @@ -168,7 +184,7 @@ jobs: $ANDROID_HOME/platform-tools/adb shell settings put global animator_duration_scale 0.0 nohup sh -c "until false; do $ANDROID_HOME/platform-tools/adb shell input tap 100 800; sleep 0.2; done" & nohup sh -c "$ANDROID_HOME/platform-tools/adb logcat '*:D' > adb-log.txt" & - yarn tests:android:test-cover --cleanup + yarn tests:android:test shell: bash - name: Submit Coverage @@ -178,7 +194,7 @@ jobs: timeout_minutes: 10 retry_wait_seconds: 60 max_attempts: 3 - command: yarn codecov + command: ./node_modules/.bin/codecov - name: Compress Emulator Log if: always() @@ -191,134 +207,3 @@ jobs: with: name: adb_logs path: adb-log.txt.gz - - # ------------------ - # iOS - # ------------------ - ios: - name: iOS - runs-on: macos-latest - # TODO matrix across APIs, at least 10 and 13 (lowest to highest) - timeout-minutes: 60 - env: - CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - steps: - - uses: styfle/cancel-workflow-action@0.9.1 - with: - all_but_latest: true - - - uses: actions/checkout@v2 - with: - fetch-depth: 50 - - - uses: actions/setup-node@v2 - with: - node-version: 14 - - - uses: maxim-lobanov/setup-xcode@v1 - with: - xcode-version: latest-stable - - - name: Get Xcode version - id: xcode-version - run: echo "::set-output name=xcode-version::$(xcodebuild -version|tail -1|cut -f3 -d' ')" - - - name: Get yarn cache directory path - id: yarn-cache-dir-path - run: echo "::set-output name=dir::$(yarn cache dir)" - - - uses: actions/cache@v2 - name: Yarn Cache - id: yarn-cache - with: - path: ${{ steps.yarn-cache-dir-path.outputs.dir }} - key: ${{ runner.os }}-yarn-${{ hashFiles('**/package.json') }}-v1 - - - uses: actions/cache@v2 - name: Cache Pods - with: - path: tests/ios/Pods - key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}-v1 - - - uses: actions/cache@v2 - name: Detox Framework Cache - with: - path: ~/Library/Detox/ios - key: ${{ runner.os }}-detox-framework-cache-${{ steps.xcode-version.outputs.xcode-version }} - - - name: Update Ruby build tools - uses: nick-invision/retry@v2 - with: - timeout_minutes: 10 - retry_wait_seconds: 60 - max_attempts: 3 - command: gem update cocoapods xcodeproj - - - name: Yarn Install - uses: nick-invision/retry@v2 - with: - timeout_minutes: 10 - retry_wait_seconds: 60 - max_attempts: 3 - command: yarn --no-audit --prefer-offline - - - name: Build iOS App - run: | - export SKIP_BUNDLING=1 - export RCT_NO_LAUNCH_PACKAGER=1 - cd tests - set -o pipefail - yarn detox build --configuration ios.sim.debug - shell: bash - - - name: Install applesimutils - uses: nick-invision/retry@v2 - with: - timeout_minutes: 10 - retry_wait_seconds: 60 - max_attempts: 3 - command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils && applesimutils --list - - - name: Pre-fetch Javascript bundle - run: | - nohup yarn tests:packager & - printf 'Waiting for packager to come online' - until curl --output /dev/null --silent --head --fail http://localhost:8081/status; do - printf '.' - sleep 2 - done - echo "Packager is online! Preparing bundle..." - curl --output /dev/null --silent --head --fail "http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=true" - echo "...javascript bundle ready" - - - name: Create Simulator Log - # With a little delay so the detox test below has time to spawn it, missing the first part of boot is fine - # If you boot the simulator separately from detox, some other race fails and detox testee never sends ready to proxy - continue-on-error: true - run: nohup sh -c "sleep 30 && xcrun simctl spawn booted log stream --level debug --style compact > simulator.log 2>&1 &" - - - name: Detox Test - timeout-minutes: 40 - run: | - cd tests - yarn nyc ./node_modules/.bin/detox test --loglevel trace --debug-synchronization 200 --configuration ios.sim.debug --cleanup - - - name: Compress Simulator Log - if: always() - run: gzip -9 simulator.log - - - name: Upload Simulator Log - uses: actions/upload-artifact@v2 - if: always() - with: - name: simulator_logs - path: simulator.log.gz - - - name: Submit Coverage - # This can fail on timeouts etc, wrap with retry - uses: nick-invision/retry@v2 - with: - timeout_minutes: 10 - retry_wait_seconds: 60 - max_attempts: 3 - command: yarn codecov diff --git a/.github/workflows/tests_e2e_ios.yml b/.github/workflows/tests_e2e_ios.yml new file mode 100644 index 00000000..92de1af0 --- /dev/null +++ b/.github/workflows/tests_e2e_ios.yml @@ -0,0 +1,190 @@ +name: Testing E2E iOS + +on: + pull_request: + branches: + - '**' + paths-ignore: + - 'docs/**' + - 'website/**' + - '.spellcheck.dict.txt' + - '**/*.md' + + push: + branches: + - main + paths-ignore: + - 'docs/**' + - 'website/**' + - '.spellcheck.dict.txt' + - '**/*.md' + +jobs: + ios: + name: iOS + runs-on: macos-latest + # TODO matrix across APIs, at least 10 and 13 (lowest to highest) + timeout-minutes: 60 + env: + CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} + steps: + - uses: styfle/cancel-workflow-action@0.9.1 + with: + all_but_latest: true + + # Set up tool versions + - uses: actions/setup-node@v2 + with: + node-version: 14 + + - uses: maxim-lobanov/setup-xcode@v1 + with: + xcode-version: latest-stable + + - uses: actions/checkout@v2 + with: + fetch-depth: 50 + + # Set path variables needed for caches + - name: Set workflow variables + id: workflow-variables + run: | + echo "::set-output name=metro-cache::$HOME/.metro" + echo "::set-output name=xcode-version::$(xcodebuild -version|tail -1|cut -f3 -d' ')" + echo "::set-output name=yarn-cache-dir::$(yarn cache dir)" + + - uses: actions/cache@v2 + name: Yarn Cache + id: yarn-cache + with: + path: ${{ steps.workflow-variables.outputs.yarn-cache-dir }} + key: ${{ runner.os }}-yarn-v1-${{ hashFiles('**/package.json') }} + restore-keys: ${{ runner.os }}-yarn-v1 + + - uses: actions/cache@v2 + name: Detox Framework Cache + id: detox-cache + with: + path: ~/Library/Detox/ios + key: ${{ runner.os }}-detox-framework-cache-${{ steps.workflow-variables.outputs.xcode-version }} + + # Detox is compiled during yarn install, using Xcode, set up cache first + - uses: hendrikmuhs/ccache-action@v1 + name: Xcode Compile Cache + with: + key: ${{ runner.os }}-v2 # makes a unique key w/related restore key internally + max-size: 400M + + - name: Yarn Install + uses: nick-invision/retry@v2 + with: + timeout_minutes: 10 + retry_wait_seconds: 60 + max_attempts: 3 + command: yarn --no-audit --prefer-offline + + - name: Update Ruby build tools + uses: nick-invision/retry@v2 + with: + timeout_minutes: 2 + retry_wait_seconds: 60 + max_attempts: 3 + command: gem update cocoapods xcodeproj + + - uses: actions/cache@v2 + name: Cache Pods + id: pods-cache + with: + path: tests/ios/Pods + key: ${{ runner.os }}-pods-v2-${{ hashFiles('**/Podfile.lock') }} + restore-keys: ${{ runner.os }}-pods-v2 + + - name: Pod Install + uses: nick-invision/retry@v2 + with: + timeout_minutes: 10 + retry_wait_seconds: 30 + max_attempts: 3 + command: yarn tests:ios:pod:install + + - name: Cache Firestore Emulator + uses: actions/cache@v2 + with: + path: ~/.cache/firebase/emulators + key: firebase-emulators-v1-${{ github.run_id }} + restore-keys: firebase-emulators-v1 + + - name: Start Firestore Emulator + run: yarn tests:emulator:start-ci + + - name: Build iOS App + run: | + export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH" + export CCACHE_SLOPPINESS=clang_index_store,file_stat_matches,include_file_ctime,include_file_mtime,ivfsoverlay,pch_defines,modules,system_headers,time_macros + export CCACHE_FILECLONE=true + export CCACHE_DEPEND=true + export CCACHE_INODECACHE=true + ccache -s + export SKIP_BUNDLING=1 + export RCT_NO_LAUNCH_PACKAGER=1 + set -o pipefail + yarn tests:ios:build + ccache -s + shell: bash + + - name: Install applesimutils + uses: nick-invision/retry@v2 + with: + timeout_minutes: 5 + retry_wait_seconds: 60 + max_attempts: 3 + command: HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew && HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils && applesimutils --list + + - name: Metro Bundler Cache + uses: actions/cache@v2 + with: + path: ${{ steps.workflow-variables.outputs.metro-cache }} + key: ${{ runner.os }}-metro-v1-${{ github.run_id }} + restore-keys: ${{ runner.os }}-metro-v1 + + - name: Pre-fetch Javascript bundle + run: | + nohup yarn tests:packager:jet-ci & + printf 'Waiting for packager to come online' + until curl --output /dev/null --silent --head --fail http://localhost:8081/status; do + printf '.' + sleep 2 + done + echo "Packager is online! Preparing bundle..." + curl --output /dev/null --silent --head --fail "http://localhost:8081/index.bundle?platform=ios&dev=true&minify=false&inlineSourceMap=true" + echo "...javascript bundle ready" + + - name: Create Simulator Log + # With a little delay so the detox test below has time to spawn it, missing the first part of boot is fine + # If you boot the simulator separately from detox, some other race fails and detox testee never sends ready to proxy + continue-on-error: true + run: nohup sh -c "sleep 30 && xcrun simctl spawn booted log stream --level debug --style compact > simulator.log 2>&1 &" + + - name: Detox Test + timeout-minutes: 10 + run: yarn tests:ios:test + + - name: Compress Simulator Log + if: always() + run: gzip -9 simulator.log + + - name: Upload Simulator Log + uses: actions/upload-artifact@v2 + if: always() + with: + name: simulator_log + path: simulator.log.gz + + - name: Submit Coverage + # This can fail on timeouts etc, wrap with retry + uses: nick-invision/retry@v2 + with: + timeout_minutes: 10 + retry_wait_seconds: 60 + max_attempts: 3 + command: ./node_modules/.bin/codecov diff --git a/example/.detoxrc.json b/example/.detoxrc.json index 58eeae3f..6aa9fa98 100644 --- a/example/.detoxrc.json +++ b/example/.detoxrc.json @@ -25,7 +25,7 @@ "android.debug": { "type": "android.apk", "binaryPath": "android/app/build/outputs/apk/debug/app-debug.apk", - "build": "cd android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug && cd .." + "build": "cd android && ./gradlew assembleDebug assembleAndroidTest lintDebug -DtestBuildType=debug && cd .." }, "android.release": { "type": "android.apk", diff --git a/package.json b/package.json index 9191131f..fdd46013 100644 --- a/package.json +++ b/package.json @@ -68,7 +68,7 @@ "tests:ios:test-reuse": "cd example && yarn detox test --configuration ios.sim.debug --reuse --loglevel warn", "tests:ios:test-cover": "cd example && ./node_modules/.bin/nyc yarn detox test --configuration ios.sim.debug", "tests:ios:test-cover-reuse": "cd example && node_modules/.bin/nyc yarn detox test --configuration ios.sim.debug --reuse --loglevel warn", - "tests:ios:pod:install": "cd example && cd ios && rm -rf ReactNativeFirebaseDemo.xcworkspace && rm -f Podfile.lock && pod install --repo-update && cd .." + "tests:ios:pod:install": "cd example && cd ios && rm -rf example.xcworkspace && rm -f Podfile.lock && pod install --repo-update && cd .." }, "devDependencies": { "@babel/core": "^7.15.5",