aliases: # Cache Management - &restore-yarn-cache keys: - v1-yarn-cache-{{ arch }}-{{ checksum "package.json" }} - v1-yarn-cache-{{ arch }} - &save-yarn-cache paths: - ~/.cache/yarn key: v1-yarn-cache-{{ arch }}-{{ checksum "package.json" }} - &restore-node-modules keys: - v2-node-modules-{{ arch }}-{{ checksum "package.json" }} - &save-node-modules paths: - node_modules key: v2-node-modules-{{ arch }}-{{ checksum "package.json" }} - &restore-cache-analysis keys: - v1-analysis-dependencies-{{ arch }}-{{ checksum "package.json" }}{{ checksum "bots/package.json" }} - &save-cache-analysis paths: - bots/node_modules - node_modules key: v1-analysis-dependencies-{{ arch }}-{{ checksum "package.json" }}{{ checksum "bots/package.json" }} - &restore-cache-android-packages keys: - v1-android-sdkmanager-packages-api-27-alpha-{{ checksum "scripts/.tests.env" }} - &save-cache-android-packages paths: - /opt/android/sdk key: v1-android-sdkmanager-packages-api-27-alpha-{{ checksum "scripts/.tests.env" }} - &restore-cache-gradle keys: - v1-gradle-{{ .Branch }}-{{ checksum "build.gradle" }}-{{ checksum "ReactAndroid/build.gradle" }} # Fallback in case checksum fails - v1-gradle-{{ .Branch }}-{{ checksum "build.gradle" }}- - v1-gradle-{{ .Branch }}- # Fallback in case this is a first-time run on a fork - v1-gradle-master- - &save-cache-gradle paths: - ~/.gradle key: v1-gradle-{{ .Branch }}-{{ checksum "build.gradle" }}-{{ checksum "ReactAndroid/build.gradle" }} - &restore-cache-ndk keys: - v3-android-ndk-r17b-{{ checksum "scripts/android-setup.sh" }} - &save-cache-ndk paths: - /opt/ndk key: v3-android-ndk-r17b-{{ checksum "scripts/android-setup.sh" }} - &restore-cache-downloads-buck keys: - v3-buck-v2018.07.23.01-{{ checksum "scripts/circleci/buck_fetch.sh" }}} - v3-buck-v2018.07.23.01- - &save-cache-downloads-buck paths: - ~/buck - ~/okbuck key: v3-buck-v2018.07.23.01-{{ checksum "scripts/circleci/buck_fetch.sh" }} - &restore-cache-watchman keys: - v1-watchman-{{ arch }}-v4.9.0 - &save-cache-watchman paths: - ~/watchman key: v1-watchman-{{ arch }}-v4.9.0 - &restore-cache-downloads-gradle keys: - v1-gradle-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }} - v1-gradle- - &save-cache-downloads-gradle paths: - ~/.gradle - ReactAndroid/build/downloads - ReactAndroid/build/third-party-ndk key: v1-gradle-{{ checksum "ReactAndroid/build.gradle" }}-{{ checksum "scripts/circleci/gradle_download_deps.sh" }} # Branch Filtering - &filter-only-master-stable branches: only: - /.*-stable/ - master - &filter-only-stable branches: only: - /.*-stable/ - &filter-ignore-gh-pages branches: ignore: gh-pages - &filter-ignore-master-stable branches: ignore: - master - /.*-stable/ - gh-pages # Dependency Management - &install-ndk name: Install Android NDK command: source scripts/android-setup.sh && getAndroidNDK - &yarn name: Run Yarn command: | # Skip yarn install on metro bump commits as the package is not yet # available on npm if [[ $(echo "$GIT_COMMIT_DESC" | grep -c "Bump metro@") -eq 0 ]]; then yarn install --non-interactive --cache-folder ~/.cache/yarn fi - &install-yarn name: Install Yarn command: | curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | sudo apt-key add - echo "deb https://dl.yarnpkg.com/debian/ stable main" | sudo tee /etc/apt/sources.list.d/yarn.list sudo apt-get update && sudo apt-get install yarn - &install-buck name: Install BUCK command: | if [[ ! -e ~/buck ]]; then git clone https://github.com/facebook/buck.git ~/buck --branch v2018.07.23.01 --depth=1 fi cd ~/buck && ant buck --version # Install related tooling if [[ ! -e ~/okbuck ]]; then git clone https://github.com/uber/okbuck.git ~/okbuck --depth=1 fi mkdir -p ~/react-native/tooling/junit cp -R ~/okbuck/tooling/junit/* ~/react-native/tooling/junit/. - &create-ndk-directory name: Create Android NDK Directory command: | if [[ ! -e /opt/ndk ]]; then sudo mkdir /opt/ndk fi sudo chown ${USER:=$(/usr/bin/id -run)}:$USER /opt/ndk # CircleCI does not support interpolating env variables in the environment # https://circleci.com/docs/2.0/env-vars/#interpolating-environment-variables-to-set-other-environment-variables - &configure-android-path name: Configure Environment Variables command: | echo 'export PATH=${ANDROID_NDK}:~/buck/bin:$PATH' >> $BASH_ENV source $BASH_ENV - &install-android-packages name: Install Android SDK Packages command: source scripts/android-setup.sh && getAndroidPackages - &install-android-build-dependencies name: Install Android Build Dependencies command: ./scripts/circleci/apt-get-android-deps.sh - &validate-android-sdk name: Validate Android SDK Install command: ./scripts/validate-android-sdk.sh - &validate-android-test-env name: Validate Android Test Environment command: ./scripts/validate-android-test-env.sh # Test Definitions - &run-js-tests name: JavaScript Test Suite command: yarn test-ci # eslint sometimes runs into trouble generating the reports - &run-lint-checks name: Lint code command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ~/react-native/reports/junit/eslint/results.xml - &run-flow-checks name: Check for errors in code using Flow command: yarn flow check - &run-sanity-checks name: Sanity checks command: | ./scripts/circleci/check_license.sh ./scripts/circleci/check_cache.sh when: always - &download-dependencies-gradle name: Download Dependencies Using Gradle command: ./scripts/circleci/gradle_download_deps.sh - &download-dependencies-buck name: Download Dependencies Using Buck command: ./scripts/circleci/buck_fetch.sh - &build-android-app name: Build Android App command: | buck build ReactAndroid/src/main/java/com/facebook/react buck build ReactAndroid/src/main/java/com/facebook/react/shell - &create-avd name: Create Android Virtual Device command: source scripts/android-setup.sh && createAVD - &launch-avd name: Launch Android Virtual Device in Background command: source scripts/android-setup.sh && launchAVD background: true - &wait-for-avd name: Wait for Android Virtual Device command: source scripts/android-setup.sh && waitForAVD - &build-js-bundle name: Build JavaScript Bundle command: node local-cli/cli.js bundle --max-workers 2 --platform android --dev true --entry-file ReactAndroid/src/androidTest/js/TestBundle.js --bundle-output ReactAndroid/src/androidTest/assets/AndroidTestBundle.js - &compile-native-libs name: Compile Native Libs for Unit and Integration Tests command: ./gradlew :ReactAndroid:packageReactNdkLibsForBuck -Pjobs=$BUILD_THREADS -Pcom.android.build.threadPoolSize=1 no_output_timeout: 6m - &run-android-unit-tests name: Run Unit Tests command: buck test ReactAndroid/src/test/... --config build.threads=$BUILD_THREADS --xml ~/react-native/reports/buck/all-results-raw.xml - &run-android-instrumentation-tests name: Run Instrumentation Tests command: | if [[ ! -e ReactAndroid/src/androidTest/assets/AndroidTestBundle.js ]]; then echo "JavaScript bundle missing, cannot run instrumentation tests. Verify build-js-bundle step completed successfully."; exit 1; fi source scripts/android-setup.sh && NO_BUCKD=1 retry3 timeout 300 buck install ReactAndroid/src/androidTest/buck-runner:instrumentation-tests --config build.threads=$BUILD_THREADS - &build-android-rntester-app name: Build Android RNTester App command: ./gradlew RNTester:android:app:assembleRelease -Pjobs=$BUILD_THREADS - &collect-android-test-results name: Collect Test Results command: | find . -type f -regex ".*/build/test-results/debug/.*xml" -exec cp {} ~/react-native/reports/build/ \; find . -type f -regex ".*/outputs/androidTest-results/connected/.*xml" -exec cp {} ~/react-native/reports/outputs/ \; find . -type f -regex ".*/buck-out/gen/ReactAndroid/src/test/.*/.*xml" -exec cp {} ~/react-native/reports/buck/ \; ./tooling/junit/buck_to_junit.sh ~/react-native/reports/buck/all-results-raw.xml ~/react-native/reports/junit/all-results-junit.xml when: always - &setup-artifacts name: Initial Setup command: | mkdir -p ~/react-native/reports/buck/ mkdir -p ~/react-native/reports/build/ mkdir -p ~/react-native/reports/junit/ mkdir -p ~/react-native/reports/outputs/ - &brew-install-watchman name: Install Watchman command: | brew install watchman touch .watchmanconfig - &boot-simulator-iphone name: Boot iPhone Simulator command: xcrun simctl boot "iPhone 5s" || true - &boot-simulator-appletv name: Boot Apple TV Simulator command: xcrun simctl boot "Apple TV" || true - &run-objc-ios-tests name: iOS Test Suite command: ./scripts/objc-test-ios.sh test - &run-objc-tvos-tests name: tvOS Test Suite command: ./scripts/objc-test-tvos.sh test - &display-broken-tests-warning name: Running broken tests (Ignore any failures past this point) command: | echo 'The following steps are known to be failing on master.' echo 'They will no-op for most users.' echo 'PRs that bring these back to green are appreciated.' - &run-podspec-tests name: Test CocoaPods (Disabled) command: ./scripts/circleci/exec_author_check.sh ./scripts/process-podspecs.sh - &run-e2e-tests name: End-to-End Test Suite (Disabled) command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --ios --tvos --js --retries 3; - &run-objc-ios-e2e-tests name: iOS End-to-End Test Suite (Disabled) command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --ios --retries 3; - &run-objc-tvos-e2e-tests name: tvOS End-to-End Test Suite (Disabled) command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --tvos --js --retries 3; - &run-android-e2e-tests name: Android End-to-End Test Suite (Disabled) command: ./scripts/circleci/exec_author_check.sh node ./scripts/run-ci-e2e-tests.js --android --retries 3; - &run-js-e2e-tests name: JavaScript End-to-End Test Suite command: node ./scripts/run-ci-e2e-tests.js --js --retries 3; defaults: &defaults working_directory: ~/react-native environment: - GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1 js_defaults: &js_defaults <<: *defaults docker: - image: circleci/node:8 environment: - PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" android_defaults: &android_defaults <<: *defaults docker: - image: circleci/android:api-27-node8-alpha resource_class: "large" environment: - TERM: "dumb" - ADB_INSTALL_TIMEOUT: 10 - _JAVA_OPTIONS: "-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap" - GRADLE_OPTS: '-Dorg.gradle.daemon=false -Dorg.gradle.jvmargs="-XX:+HeapDumpOnOutOfMemoryError"' - ANDROID_NDK: '/opt/ndk/android-ndk-r17b' - BUILD_THREADS: 2 macos_defaults: &macos_defaults <<: *defaults macos: xcode: "9.4.0" version: 2 jobs: # Set up a Node environment for downstream jobs checkout_code: <<: *js_defaults steps: - checkout - run: *setup-artifacts - restore-cache: *restore-yarn-cache - run: *yarn - save-cache: *save-yarn-cache # Basic checks against the checkout, cache... - run: *run-sanity-checks - persist_to_workspace: root: . paths: . # Runs JavaScript lint and flow checks. # Currently will fail a PR if lint/flow raises issues. analyze: <<: *js_defaults steps: - attach_workspace: at: ~/react-native - run: *run-lint-checks - run: *run-flow-checks - store_test_results: path: ~/react-native/reports/junit - store_artifacts: path: ~/react-native/yarn.lock # Runs JavaScript tests on Node 8 test_javascript: <<: *js_defaults steps: - attach_workspace: at: ~/react-native - run: *run-js-tests - store_test_results: path: ~/react-native/reports/junit # Run JavaScript tests on Node 10 test_node10: <<: *defaults docker: - image: circleci/node:10 environment: - PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" steps: - checkout - run: *setup-artifacts - run: *yarn - run: *run-js-tests - store_test_results: path: ~/react-native/reports/junit # Runs unit tests on iOS and Apple TV devices test_objc: <<: *macos_defaults steps: - attach_workspace: at: ~/react-native - run: *boot-simulator-iphone - run: *boot-simulator-appletv - run: *brew-install-watchman - run: *run-objc-ios-tests - run: *run-objc-tvos-tests # TODO: Fix these failing tests. - run: *display-broken-tests-warning - run: *run-podspec-tests - run: *run-objc-ios-e2e-tests - run: *run-objc-tvos-e2e-tests - store_test_results: path: ~/react-native/reports/junit # Runs end to end tests (Detox) test_detox_end_to_end: <<: *macos_defaults steps: - attach_workspace: at: ~/react-native - run: xcrun simctl boot "iPhone 5s" || true - run: name: Configure Environment Variables command: | echo 'export PATH=/usr/local/opt/node@8/bin:$PATH' >> $BASH_ENV source $BASH_ENV - run: name: Install Node 8 command: | brew install node@8 brew link node@8 brew tap wix/brew brew install applesimutils node -v - run: *yarn - run: name: Build iOS app for simulator command: yarn run build-ios-e2e - run: name: Run Detox Tests command: yarn run test-ios-e2e # Set up an Android environment for downstream jobs test_android: <<: *android_defaults steps: - attach_workspace: at: ~/react-native # Configure Android SDK and related dependencies - run: *configure-android-path # Android build deps install from the network faster than cache - run: *install-android-build-dependencies - restore-cache: *restore-cache-android-packages - run: *install-android-packages - save-cache: *save-cache-android-packages # Validate Android SDK installation and packages - run: *validate-android-sdk # Starting emulator in advance as it takes some time to boot. - run: *create-avd - run: *launch-avd # Keep configuring Android dependencies while AVD boots up # Install Android NDK - run: *create-ndk-directory - restore-cache: *restore-cache-ndk - run: *install-ndk - save-cache: *save-cache-ndk # Install Buck - restore-cache: *restore-cache-downloads-buck - run: *install-buck - save-cache: *save-cache-downloads-buck # Validate Android test environment (including Buck) - run: *validate-android-test-env # Download dependencies using Buck - run: *download-dependencies-buck # Download dependencies using Gradle - restore-cache: *restore-cache-downloads-gradle - run: *download-dependencies-gradle - save-cache: *save-cache-downloads-gradle # Build and compile - run: *build-android-app - run: *compile-native-libs # Build JavaScript Bundle for instrumentation tests - run: *build-js-bundle # Wait for AVD to finish booting before running tests - run: *wait-for-avd # Test Suite - run: *run-android-unit-tests - run: *run-android-instrumentation-tests - run: *build-android-rntester-app # Run Android end-to-end tests # TODO: Fix these failing tests. - run: *display-broken-tests-warning - run: *run-android-e2e-tests # Collect Results - run: *collect-android-test-results - store_test_results: path: ~/react-native/reports/junit # Analyze pull request and raise any lint/flow issues. # Issues will be posted to the PR itself via GitHub bots. # This workflow should only fail if the bots fail to run. # The public github tokens are publicly visible by design analyze_pr: <<: *defaults docker: - image: circleci/node:10 environment: - PATH: "/opt/yarn/yarn-v1.5.1/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" - PUBLIC_PULLBOT_GITHUB_TOKEN_A: "a6edf8e8d40ce4e8b11a" - PUBLIC_PULLBOT_GITHUB_TOKEN_B: "150e1341f4dd9c944d2a" - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: "78a72af35445ca3f8180" - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: "b1a98e0bbd56ff1ccba1" steps: - checkout - run: *setup-artifacts - restore-cache: *restore-yarn-cache - run: *yarn - run: name: Analyze Code command: | if [ -n "$CIRCLE_PR_NUMBER" ]; then echo -e "\\x1B[36mInstalling additional dependencies\\x1B[0m"; yarn add @octokit/rest@15.10.0 echo -e "\\x1B[36mAnalyzing code\\x1B[0m"; GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" ./scripts/circleci/analyze_code.sh else echo "Skipping code analysis." fi when: always - restore-cache: *restore-cache-analysis - run: name: Analyze Pull Request command: | if [ -n "$CIRCLE_PR_NUMBER" ]; then cd bots yarn install --non-interactive --cache-folder ~/.cache/yarn DANGER_GITHUB_API_TOKEN="$PUBLIC_PULLBOT_GITHUB_TOKEN_A""$PUBLIC_PULLBOT_GITHUB_TOKEN_B" yarn danger else echo "Skipping pull request analysis." fi when: always - save-cache: *save-cache-analysis # Publishes new version onto npm # Only works on stable branches when a properly tagged commit is pushed publish_npm_package: <<: *android_defaults steps: - checkout - restore-cache: *restore-yarn-cache - run: *yarn # Configure Android SDK and related dependencies - run: *configure-android-path - run: *install-android-build-dependencies - restore-cache: *restore-cache-android-packages - run: *install-android-packages # Install Android NDK - run: *create-ndk-directory - restore-cache: *restore-cache-ndk - run: *install-ndk # Fetch dependencies using Buck - restore-cache: *restore-cache-downloads-buck - run: *install-buck - run: *download-dependencies-buck # Fetch dependencies using Gradle - restore-cache: *restore-cache-downloads-gradle - run: *download-dependencies-gradle - restore-cache: *restore-yarn-cache - run: *yarn - run: name: Authenticate with npm command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc - run: name: Authenticate git user command: | git config --global user.email "react-native-bot@users.noreply.github.com" git config --global user.name "npm Deployment Script" echo "machine github.com login react-native-bot password $GITHUB_TOKEN" > ~/.netrc - run: name: Publish React Native Package command: node ./scripts/publish-npm.js # Workflows enables us to run multiple jobs in parallel workflows: version: 2 tests: jobs: # Checkout repo and run Yarn - checkout_code: filters: *filter-ignore-gh-pages # Run lint, flow, and other checks - analyze: filters: *filter-ignore-gh-pages requires: - checkout_code # Test JavaScript - test_javascript: filters: *filter-ignore-gh-pages requires: - checkout_code # Test JavaScript and Node 10 compatibility - test_node10: filters: *filter-ignore-gh-pages # Test Android - test_android: filters: *filter-ignore-gh-pages requires: - checkout_code # Test iOS & tvOS - test_objc: filters: *filter-ignore-gh-pages requires: - checkout_code - test_detox_end_to_end: filters: *filter-ignore-gh-pages requires: - checkout_code # Only runs on vX.X.X tags if all tests are green - publish_npm_package: filters: tags: only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ requires: - analyze - test_detox_end_to_end - test_javascript - test_objc - test_android # Run code checks - analyze_pr: filters: *filter-ignore-master-stable