diff --git a/.circleci/config.yml b/.circleci/config.yml index 040fd4ef666..cf9d1a55e30 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,13 +1,2080 @@ version: 2.1 -# this allows you to use CircleCI's dynamic configuration feature -setup: true +# ------------------------- +# ORBS +# ------------------------- orbs: - continuation: circleci/continuation@1.0.0 + win: circleci/windows@2.4.0 + android: circleci/android@2.3.0 +# ------------------------- +# REFERENCES +# ------------------------- +references: + defaults: &defaults + working_directory: ~/react-native + environment: + - GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1 + # The public github tokens are publicly visible by design + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_analysisbot_token_a "312d354b5c36f082cfe9" + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_analysisbot_token_b "07973d757026bdd9f196" + # Homebrew currently breaks while updating: + # https://discuss.circleci.com/t/brew-install-fails-while-updating/32992 + - HOMEBREW_NO_AUTO_UPDATE: 1 + android-defaults: &android-defaults + working_directory: ~/react-native + docker: + - image: reactnativecommunity/react-native-android:v11.0 + environment: + - TERM: "dumb" + - GRADLE_OPTS: '-Dorg.gradle.daemon=false' + # By default we only build ARM64 to save time/resources. For release/nightlies, we override this value to build all archs. + - ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a" + # Repeated here, as the environment key in this executor will overwrite the one in defaults + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_analysisbot_token_a + - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_analysisbot_token_b + + hermes_workspace_root: &hermes_workspace_root + /tmp/hermes + hermes_tarball_artifacts_dir: &hermes_tarball_artifacts_dir + /tmp/hermes/hermes-runtime-darwin + hermes_osxbin_artifacts_dir: &hermes_osxbin_artifacts_dir + /tmp/hermes/osx-bin + attach_hermes_workspace: &attach_hermes_workspace + attach_workspace: + at: *hermes_workspace_root + xcodebuild_derived_data_path: &xcodebuild_derived_data_path + ~/Library/Developer/Xcode/DerivedData/ + + main_or_stable_only: &main_or_stable_only + filters: + branches: + only: + - main + - /0\.[0-9]+[\.[0-9]+]?-stable/ + + + # ------------------------- + # Dependency Anchors + # ------------------------- + dependency_versions: + xcode_version: &xcode_version "14.3.0" + nodelts_image: &nodelts_image "cimg/node:20.2.0" + nodeprevlts_image: &nodeprevlts_image "cimg/node:18.12.1" + nodelts_browser_image: &nodelts_browser_image "cimg/node:20.2.0-browsers" + + # ------------------------- + # Cache Key Anchors + # ------------------------- + # Anchors for the cache keys + + cache_keys: + checkout_cache_key: &checkout_cache_key v1-checkout + gems_cache_key: &gems_cache_key v1-gems-{{ checksum "Gemfile.lock" }} + gradle_cache_key: &gradle_cache_key v3-gradle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "packages/react-native/ReactAndroid/gradle.properties" }} + yarn_cache_key: &yarn_cache_key v6-yarn-cache-{{ .Environment.CIRCLE_JOB }} + rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ checksum "/tmp/required_ruby" }} + hermes_workspace_cache_key: &hermes_workspace_cache_key v5-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }} + hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }} + hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }} + hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + # Hermes iOS + hermesc_apple_cache_key: &hermesc_apple_cache_key v2-hermesc-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_apple_slices_cache_key: &hermes_apple_slices_cache_key v2-hermes-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }} + hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_macosx_bin_release_cache_key: &hermes_macosx_bin_release_cache_key v1-hermes-release-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_macosx_bin_debug_cache_key: &hermes_macosx_bin_debug_cache_key v1-hermes-debug-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_dsym_debug_cache_key: &hermes_dsym_debug_cache_key v1-hermes-debug-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + hermes_dsym_release_cache_key: &hermes_dsym_release_cache_key v1-hermes-release-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} + # Cocoapods - RNTester + pods_cache_key: &pods_cache_key v10-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} + cocoapods_cache_key: &cocoapods_cache_key v7-cocoapods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock" }}-{{ checksum "packages/rn-tester/Podfile" }} + rntester_podfile_lock_cache_key: &rntester_podfile_lock_cache_key v5-podfilelock-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/week_year" }} + + # Cocoapods - Template + template_cocoapods_cache_key: &template_cocoapods_cache_key v1-cocoapods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile.lock" }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }} + template_podfile_lock_cache_key: &template_podfile_lock_cache_key v1-podfilelock-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }}-{{ checksum "/tmp/week_year" }} + + # Windows + windows_yarn_cache_key: &windows_yarn_cache_key v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }} + windows_choco_cache_key: &windows_choco_cache_key v1-win-choco-cache-{{ .Environment.CIRCLE_JOB }} + + + cache_paths: + hermes_workspace_macos_cache_paths: &hermes_workspace_macos_cache_paths + - ~/react-native/packages/react-native/sdks/hermes/build_macosx + - ~/react-native/packages/react-native/sdks/hermes/destroot + hermes_tarball_cache_paths: &hermes_tarball_cache_paths + - *hermes_tarball_artifacts_dir + + # ------------------------- + # Filters + # ------------------------- + # CircleCI filters are OR-ed, with all branches triggering by default and tags excluded by default + # CircleCI env-vars are only set with the branch OR tag that triggered the job, not both. + + # In this case, CIRCLE_BRANCH is unset, but CIRCLE_TAG is set. + only_release_tags: &only_release_tags + # Both of the following conditions must be included! + # Ignore any commit on any branch by default. + branches: + ignore: /.*/ + # Only act on version tags. + tags: + only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ + +# ------------------------- +# EXECUTORS +# ------------------------- +executors: + nodelts: + <<: *defaults + docker: + - image: *nodelts_image + resource_class: "large" + nodeprevlts: + <<: *defaults + docker: + - image: *nodeprevlts_image + resource_class: "large" + # Executor with Node & Java used to inspect and lint + node-browsers-small: + <<: *defaults + docker: + - image: *nodelts_browser_image + resource_class: "small" + reactnativeandroid-xlarge: + <<: *android-defaults + resource_class: "xlarge" + reactnativeandroid-large: + <<: *android-defaults + resource_class: "large" + reactnativeios: + <<: *defaults + macos: + xcode: *xcode_version + resource_class: macos.x86.medium.gen2 + environment: + - BUILD_FROM_SOURCE: true + +# ------------------------- +# COMMANDS +# ------------------------- +commands: + # Checkout with cache, on machines that are using Docker the cache is ignored + checkout_code_with_cache: + parameters: + checkout_base_cache_key: + default: *checkout_cache_key + type: string + steps: + - restore_cache: + key: << parameters.checkout_base_cache_key >>-{{ arch }}-{{ .Branch }}-{{ .Revision }} + - checkout + - save_cache: + key: << parameters.checkout_base_cache_key >>-{{ arch }}-{{ .Branch }}-{{ .Revision }} + paths: + - ".git" + + setup_ruby: + parameters: + ruby_version: + default: "2.6.10" + type: string + steps: + - restore_cache: + key: *gems_cache_key + - run: + name: Set Required Ruby + command: echo << parameters.ruby_version >> > /tmp/required_ruby + - restore_cache: + key: *rbenv_cache_key + - run: + name: Bundle Install + command: | + # Check if rbenv is installed. CircleCI is migrating to rbenv so we may not need to always install it. + + if [[ -z "$(command -v rbenv)" ]]; then + brew install rbenv ruby-build + # Load and init rbenv + (rbenv init 2> /dev/null) || true + echo '' >> ~/.bash_profile + echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile + source ~/.bash_profile + else + echo "rbenv found; Skipping installation" + fi + + brew reinstall libyaml + gem install psych -- --with-libyaml-dir=$(brew --prefix libyaml) + export RUBY_CONFIGURE_OPTS=--with-libyaml-dir=$(brew --prefix libyaml) + + # Install the right version of ruby + if [[ -z "$(rbenv versions | grep << parameters.ruby_version >>)" ]]; then + # ensure that `ruby-build` can see all the available versions of Ruby + # some PRs received machines in a weird state, this should make the pipelines + # more robust. + brew update && brew upgrade ruby-build + rbenv install << parameters.ruby_version >> + fi + + # Set ruby dependencies + rbenv global << parameters.ruby_version >> + gem install bundler + bundle check || bundle install --path vendor/bundle --clean + - save_cache: + key: *rbenv_cache_key + paths: + - ~/.rbenv + - save_cache: + key: *gems_cache_key + paths: + - vendor/bundle + + run_yarn: + parameters: + yarn_base_cache_key: + default: *yarn_cache_key + type: string + + steps: + - restore_cache: + keys: + - << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }} + - << parameters.yarn_base_cache_key >>-{{ arch }} + - << parameters.yarn_base_cache_key >> + - run: + name: "Yarn: Install Dependencies" + 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 + - save_cache: + paths: + - ~/.cache/yarn + key: << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }} + + build_packages: + steps: + - run: + name: Build packages + command: yarn build + + brew_install: + parameters: + package: + description: Homebrew package to install + type: string + steps: + - run: + name: "Brew: Install << parameters.package >>" + command: brew install << parameters.package >> + + with_rntester_pods_cache_span: + parameters: + steps: + type: steps + steps: + - run: + name: Setup CocoaPods cache + # Copy packages/rn-tester/Podfile.lock since it can be changed by pod install + command: cp packages/rn-tester/Podfile.lock packages/rn-tester/Podfile.lock.bak + - restore_cache: + keys: + # The committed lockfile is generated using static libraries and USE_HERMES=1 so it could load an outdated cache if a change + # only affects the frameworks or hermes config. To help prevent this also cache based on the content of Podfile. + - *pods_cache_key + - steps: << parameters.steps >> + - save_cache: + paths: + - packages/rn-tester/Pods + key: *pods_cache_key + + with_gradle_cache: + parameters: + steps: + type: steps + steps: + - restore_cache: + keys: + - *gradle_cache_key + - v3-gradle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}- + - v3-gradle-{{ .Environment.CIRCLE_JOB }}- + - v3-gradle- + - steps: << parameters.steps >> + - save_cache: + paths: + - ~/.gradle/caches + - ~/.gradle/wrapper + - packages/react-native/ReactAndroid/build/downloads + - packages/react-native/ReactAndroid/build/third-party-ndk + key: *gradle_cache_key + + run_e2e: + parameters: + platform: + description: Target platform + type: enum + enum: ["android", "ios", "js"] + default: "js" + retries: + description: How many times the job should try to run these tests + type: integer + default: 3 + steps: + - run: + name: "Run Tests: << parameters.platform >> End-to-End Tests" + command: node ./scripts/run-ci-e2e-tests.js --<< parameters.platform >> --retries << parameters.retries >> + + report_bundle_size: + parameters: + platform: + description: Target platform + type: enum + enum: ["android", "ios"] + steps: + - run: + name: Report size of RNTester.app (analysis-bot) + command: GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" scripts/circleci/report-bundle-size.sh << parameters.platform >> || true + + get_react_native_version: + steps: + - run: + name: Get React Native version + command: | + VERSION=$(cat packages/react-native/package.json | jq -r '.version') + # Save the react native version we are building in a file so we can use that file as part of the cache key. + echo "$VERSION" > /tmp/react-native-version + echo "React Native Version is $(cat /tmp/react-native-version)" + HERMES_VERSION="$(cat /tmp/hermes/hermesversion)" + echo "Hermes commit is $HERMES_VERSION" + + get_react_native_version_windows: + steps: + - run: + name: Get React Native version on Windows + command: | + $VERSION=cat packages/react-native/package.json | jq -r '.version' + # Save the react native version we are building in a file so we can use that file as part of the cache key. + echo "$VERSION" > /tmp/react-native-version + echo "React Native Version is $(cat /tmp/react-native-version)" + $HERMES_VERSION=cat C:\Users\circleci\project\tmp\hermes\hermesversion + echo "Hermes commit is $HERMES_VERSION" + + with_hermes_tarball_cache_span: + parameters: + steps: + type: steps + set_tarball_path: + type: boolean + default: False + flavor: + default: "Debug" + description: The Hermes build type. Must be one of "Debug", "Release". + type: enum + enum: ["Debug", "Release"] + hermes_tarball_artifacts_dir: + type: string + default: *hermes_tarball_artifacts_dir + steps: + - get_react_native_version + - when: + condition: + equal: [ << parameters.flavor >>, "Debug"] + steps: + - restore_cache: + keys: + - *hermes_tarball_debug_cache_key + - when: + condition: + equal: [ << parameters.flavor >>, "Release"] + steps: + - restore_cache: + keys: + - *hermes_tarball_release_cache_key + - when: + condition: << parameters.set_tarball_path >> + steps: + - run: + name: Set HERMES_ENGINE_TARBALL_PATH envvar if Hermes tarball is present + command: | + HERMES_TARBALL_ARTIFACTS_DIR=<< parameters.hermes_tarball_artifacts_dir >> + if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then + echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR). Build Hermes from source." + exit 0 + fi + + if [ ! -d ~/react-native ]; then + echo "No React Native checkout found. Run `checkout` first." + exit 0 + fi + + TARBALL_FILENAME=$(node ~/react-native/packages/react-native/scripts/hermes/get-tarball-name.js --buildType "<< parameters.flavor >>") + TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME + + echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR" + echo "$TARBALL_PATH" + + if [ ! -f $TARBALL_PATH ]; then + echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source." + exit 0 + fi + + echo "Found Hermes tarball at $TARBALL_PATH" + echo "export HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $BASH_ENV + - run: + name: Print Hermes version + command: | + HERMES_TARBALL_ARTIFACTS_DIR=<< parameters.hermes_tarball_artifacts_dir >> + TARBALL_FILENAME=$(node ~/react-native/packages/react-native/scripts/hermes/get-tarball-name.js --buildType "<< parameters.flavor >>") + TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME + if [[ -e $TARBALL_PATH ]]; then + tar -xf $TARBALL_PATH + echo 'print(HermesInternal?.getRuntimeProperties?.()["OSS Release Version"])' > test.js + ./destroot/bin/hermes test.js + rm test.js + rm -rf destroot + else + echo 'No Hermes tarball found.' + fi + - steps: << parameters.steps >> + - when: + condition: + equal: [ << parameters.flavor >>, "Debug"] + steps: + - save_cache: + key: *hermes_tarball_debug_cache_key + paths: *hermes_tarball_cache_paths + - when: + condition: + equal: [ << parameters.flavor >>, "Release"] + steps: + - save_cache: + key: *hermes_tarball_release_cache_key + paths: *hermes_tarball_cache_paths + + store_hermes_apple_artifacts: + description: Stores the tarball and the osx binaries + parameters: + flavor: + default: "Debug" + description: The Hermes build type. Must be one of "Debug", "Release". + type: enum + enum: ["Debug", "Release"] + steps: + - when: + condition: + equal: [ << parameters.flavor >>, "Debug"] + steps: + - store_artifacts_if_needed: + path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-debug.tar.gz + - when: + condition: + equal: [ << parameters.flavor >>, "Release"] + steps: + - store_artifacts_if_needed: + path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-release.tar.gz + - store_artifacts_if_needed: + path: /tmp/hermes/osx-bin/<< parameters.flavor >>/hermesc + - store_artifacts: + path: /tmp/hermes/dSYM/<< parameters.flavor >>/hermes.framework.dSYM + + stop_job_if_apple_artifacts_are_there: + description: Stops the current job if there are already the required artifacts + parameters: + flavor: + default: "All" + description: The flavor of artifacts to check. Must be one of "Debug", "Release" or "All" + type: enum + enum: ["Debug", "Release", "All"] + steps: + - when: + condition: + equal: [ << parameters.flavor >>, "All"] + steps: + - run: + name: "Export files to be checked" + command: | + echo "/tmp/hermes/Release_tarball_present" > /tmp/hermes_files + echo "/tmp/hermes/Debug_tarball_present" >> /tmp/hermes_files + echo "/tmp/hermes/Release_osx_bin" >> /tmp/hermes_files + echo "/tmp/hermes/Debug_osx_bin" >> /tmp/hermes_files + echo "/tmp/hermes/Release_dSYM" >> /tmp/hermes_files + echo "/tmp/hermes/Debug_dSYM" >> /tmp/hermes_files + - when: + condition: + not: + equal: [ << parameters.flavor >>, "All"] + steps: + - run: + name: "Export files to be checked" + command: | + echo "/tmp/hermes/<< parameters.flavor >>_tarball_present" > /tmp/hermes_files + echo "/tmp/hermes/<< parameters.flavor >>_osx_bin" >> /tmp/hermes_files + echo "/tmp/hermes/<< parameters.flavor >>_dSYM" >> /tmp/hermes_files + - run: + name: Stop if files are present + command: | + files=($(cat /tmp/hermes_files)) + # Initialize a flag indicating all files exist + + all_files_exist=true + + for file in "${files[@]}"; do + if [[ ! -f "$file" ]]; then + all_files_exist=false + echo "$file does not exist." + else + echo "$file exist." + fi + done + + if [[ "$all_files_exist" == true ]]; then + echo "Tarball, osx-bin and dSYM are present. Halting this job" + circleci-agent step halt + fi + + check_if_tarball_is_present: + description: "Checks if the tarball of a specific Flavor is present and adds a marker file" + parameters: + flavor: + default: "Debug" + description: The flavor of artifacts to check. Must be one of "Debug" or "Release" + type: enum + enum: ["Debug", "Release"] + steps: + - run: + name: Check if << parameters.flavor >> tarball is there + command: | + FLAVOR=debug + if [[ << parameters.flavor >> == "Release" ]]; then + FLAVOR=release + fi + + if [[ -f "/tmp/hermes/hermes-runtime-darwin/hermes-ios-$FLAVOR.tar.gz" ]]; then + echo "[HERMES TARBALL] Found the << parameters.flavor >> tarball" + touch /tmp/hermes/<< parameters.flavor >>_tarball_present + fi + + check_if_osx_bin_is_present: + description: "Checks if the osx bin of a specific Flavor is present and adds a marker file" + parameters: + flavor: + default: "Debug" + description: The flavor of artifacts to check. Must be one of "Debug" or "Release" + type: enum + enum: ["Debug", "Release"] + steps: + - run: + name: Check if macosx binary is there + command: | + if [[ -d /tmp/hermes/osx-bin/<< parameters.flavor >> ]]; then + echo "[HERMES MACOSX BIN] Found the osx bin << parameters.flavor >>" + touch /tmp/hermes/<< parameters.flavor >>_osx_bin + fi + + check_if_dsym_are_present: + description: "Checks if the dSYM a specific Flavor are present and adds a marker file" + parameters: + flavor: + default: "Debug" + description: The flavor of artifacts to check. Must be one of "Debug" or "Release" + type: enum + enum: ["Debug", "Release"] + steps: + - run: + name: Check if dSYM are there + command: | + if [[ -d /tmp/hermes/dSYM/<< parameters.flavor >> ]]; then + echo "[HERMES dSYM] Found the dSYM << parameters.flavor >>" + touch /tmp/hermes/<< parameters.flavor >>_dSYM + fi + + setup_hermes_workspace: + description: "Setup Hermes Workspace" + steps: + - run: + name: Set up workspace + command: | + mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes + cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/. + cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/. + + with_xcodebuild_cache: + description: "Add caching to iOS jobs to speed up builds" + parameters: + steps: + type: steps + podfile_lock_path: + type: string + default: packages/rn-tester/Podfile.lock + pods_build_folder: + type: string + default: packages/rn-tester/Pods + podfile_lock_cache_key: + type: string + default: *rntester_podfile_lock_cache_key + cocoapods_cache_key: + type: string + default: *cocoapods_cache_key + steps: + - run: + name: Prepare Xcodebuild cache + command: | + WEEK=$(date +"%U") + YEAR=$(date +"%Y") + echo "$WEEK-$YEAR" > /tmp/week_year + - restore_cache: + key: << parameters.podfile_lock_cache_key >> + - restore_cache: + key: << parameters.cocoapods_cache_key >> + - steps: << parameters.steps >> + - save_cache: + key: << parameters.podfile_lock_cache_key >> + paths: + - << parameters.podfile_lock_path >> + - save_cache: + key: << parameters.cocoapods_cache_key >> + paths: + - << parameters.pods_build_folder >> + + store_artifacts_if_needed: + description: "This step stores the artifacts only if we are on main or on a stable branch" + parameters: + path: + type: string + destination: + type: string + default: << parameters.path >> + when: + type: enum + enum: ['always', 'on_fail', 'on_success'] + default: 'always' + steps: + - when: + condition: + or: + - equal: [ main, << pipeline.git.branch >> ] + - matches: + pattern: /0\.[0-9]+[\.[0-9]+]?-stable/ + value: << pipeline.git.branch >> + steps: + - store_artifacts: + when: << parameters.when >> + path: << parameters.path >> + destination: << parameters.destination >> + + +# ------------------------- +# JOBS +# ------------------------- +jobs: + # ------------------------- + # JOBS: Analyze PR + # ------------------------- + # 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. + analyze_pr: + executor: node-browsers-small + steps: + - checkout + - run_yarn + - run: + name: Run linters against modified files (analysis-bot) + command: GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" yarn lint-ci + + # ------------------------- + # JOBS: Analyze Code + # ------------------------- + analyze_code: + executor: node-browsers-small + steps: + - checkout + - run_yarn + + - run: + name: Lint code + command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml + when: always + + - run: + name: Lint Java + command: scripts/circleci/exec_swallow_error.sh yarn lint-java --check + when: always + + - run: + name: Set server.max_workers=1 in .flowconfig + command: | + sed -i '/\[options\]/a server.max_workers=1' .flowconfig + sed -i '/\[options\]/a server.max_workers=1' .flowconfig.android + when: always + + - run: + name: Check for errors in code using Flow (iOS) + command: yarn flow-check-ios + when: always + + - run: + name: Check for errors in code using Flow (Android) + command: yarn flow-check-android + when: always + + - run: + name: Run TypeScript tests + command: yarn test-typescript + when: always + + - run: + name: Sanity checks + command: | + ./scripts/circleci/check_license.sh + ./scripts/circleci/validate_yarn_lockfile.sh + when: always + + - run: + name: Check formatting + command: yarn run format-check + when: always + + - store_test_results: + path: ./reports/junit + + # ------------------------- + # JOBS: Test JavaScript + # ------------------------- + test_js: + parameters: + executor: + type: executor + default: nodelts + run_disabled_tests: + type: boolean + default: false + executor: << parameters.executor >> + steps: + - checkout + - run_yarn + - run: + name: Install rsync + command: sudo apt update && sudo apt install rsync + + # ------------------------- + # Run JavaScript tests + - run: + name: "Run Tests: JavaScript Tests" + command: node ./scripts/run-ci-javascript-tests.js --maxWorkers 2 + - run_e2e: + platform: js + + # Optionally, run disabled tests + - when: + condition: << parameters.run_disabled_tests >> + steps: + - run: echo "Failing tests may be moved here temporarily." + # ------------------------- + + - store_test_results: + path: ./reports/junit + + # ------------------------- + # JOBS: iOS Unit Tests + # ------------------------- + test_ios: + executor: reactnativeios + parameters: + run_unit_tests: + description: Specifies whether unit tests should run. + type: boolean + default: false + jsengine: + default: "Hermes" + description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". + type: enum + enum: ["Hermes", "JSC"] + ruby_version: + default: "2.6.10" + description: The version of ruby that must be used + type: string + environment: + - REPORTS_DIR: "./reports/junit" + steps: + - checkout_code_with_cache + - setup_ruby: + ruby_version: << parameters.ruby_version >> + - brew_install: + package: xcbeautify + - run: + name: Run Ruby Tests + command: | + cd packages/react-native/scripts + sh run_ruby_tests.sh + - run_yarn + - *attach_hermes_workspace + - run: | + cd packages/rn-tester + bundle check || bundle install + - run: + name: Boot iPhone Simulator + command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true + + - run: + name: Configure Environment Variables + command: | + echo 'export PATH=/usr/local/opt/node@18/bin:$PATH' >> $BASH_ENV + source $BASH_ENV + + - run: + name: "Brew: Tap wix/brew" + command: brew tap wix/brew + - brew_install: + package: applesimutils watchman + + - run: + name: Configure Watchman + command: echo "{}" > .watchmanconfig + + - run: + name: Setup the CocoaPods environment + command: | + bundle exec pod setup + + - with_hermes_tarball_cache_span: + set_tarball_path: True + steps: + - with_rntester_pods_cache_span: + steps: + - run: + name: Generate RNTesterPods Workspace + command: | + if [[ << parameters.jsengine >> == "JSC" ]]; then + export USE_HERMES=0 + fi + + cd packages/rn-tester + bundle install + bundle exec pod install --verbose + + # ------------------------- + # Runs iOS unit tests + - when: + condition: << parameters.run_unit_tests >> + steps: + - run: + name: "Run Tests: iOS Unit and Integration Tests" + command: node ./scripts/circleci/run_with_retry.js 3 yarn test-ios + - run: + name: Zip Derived data folder + when: always + command: | + echo "zipping tests results" + cd /Users/distiller/Library/Developer/Xcode + XCRESULT_PATH=$(find . -name '*.xcresult') + tar -zcvf xcresults.tar.gz $XCRESULT_PATH + - store_artifacts_if_needed: + path: /Users/distiller/Library/Developer/Xcode/xcresults.tar.gz + # ------------------------- + # Collect Results + - report_bundle_size: + platform: ios + - store_test_results: + path: ./reports/junit + + # ------------------------- + # JOBS: iOS E2E Tests + # ------------------------- + test_e2e_ios: + executor: reactnativeios + parameters: + ruby_version: + default: "2.7.7" + description: The version of ruby that must be used + type: string + steps: + - checkout_code_with_cache + - run_yarn + - attach_workspace: + at: . + - run: + name: Install appium + command: npm install appium@2.0.0 -g + - run: + name: Install appium drivers + command: | + appium driver install uiautomator2 + appium driver install xcuitest + - run: + name: Start Appium server + command: appium --base-path /wd/hub + background: true + - run: + name: Start Metro + command: | + cd packages/rn-tester + yarn start + background: true + - brew_install: + package: cmake + - setup_ruby: + ruby_version: << parameters.ruby_version >> + - run: + name: Boot iOS Simulator + command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true + - with_xcodebuild_cache: + steps: + - run: + name: Install Bundler + command: | + cd packages/rn-tester + bundle check || bundle install + bundle exec pod setup + RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --verbose + - run: + name: Build app + command: | + xcodebuild build \ + -workspace packages/rn-tester/RNTesterPods.xcworkspace \ + -configuration Debug \ + -scheme RNTester \ + -sdk iphonesimulator \ + -derivedDataPath /tmp/e2e/ + - run: + name: Move app to correct directory + command: mv /tmp/e2e/Build/Products/Debug-iphonesimulator/RNTester.app packages/rn-tester-e2e/apps/rn-tester.app + - run: + name: Check Appium server status + command: scripts/circleci/check_appium_server_status.sh + - run: + name: Run E2E tests + command: | + cd packages/rn-tester-e2e + yarn test-e2e ios + + # ------------------------- + # JOBS: Android E2E Tests + # ------------------------- + test_e2e_android: + executor: + name: android/android-machine + tag: 2023.07.1 + steps: + - checkout_code_with_cache + - run_yarn + - android/create-avd: + avd-name: e2e_emulator + system-image: system-images;android-34;google_apis;x86_64 + install: true + - android/start-emulator: + avd-name: e2e_emulator + no-window: true + restore-gradle-cache-prefix: v1a + post-emulator-launch-assemble-command: "" + - run: + name: Install appium + command: npm install appium@2.0.0 -g + - run: + name: Install appium drivers + command: | + appium driver install uiautomator2 + appium driver install xcuitest + - run: + name: Start Appium server + command: appium --base-path /wd/hub + background: true + - run: + name: Start Metro + command: | + cd packages/rn-tester + yarn start + background: true + - attach_workspace: + at: . + - with_gradle_cache: + steps: + - run: + name: Build app + command: | + ./gradlew :packages:rn-tester:android:app:assembleHermesDebug -PreactNativeArchitectures=x86_64 + - run: + name: Move app to correct directory + command: mv packages/rn-tester/android/app/build/outputs/apk/hermes/debug/app-hermes-x86_64-debug.apk packages/rn-tester-e2e/apps/rn-tester.apk + - run: + name: Check Appium server status + command: | + if ! nc -z 127.0.0.1 4723; then + echo Could not find Appium server + exit 1 + fi + - run: + name: Run E2E tests + command: | + cd packages/rn-tester-e2e + yarn test-e2e android + + # ------------------------- + # JOBS: Build Android + # ------------------------- + build_android: + executor: reactnativeandroid-xlarge + parameters: + release_type: + description: The type of release to build. Must be one of "nightly", "release", "dry-run". + type: enum + enum: ["nightly", "release", "dry-run"] + default: "dry-run" + steps: + - checkout + - run_yarn + - run: + name: Set React Native Version + command: node ./scripts/set-rn-version.js --build-type << parameters.release_type >> + + - with_gradle_cache: + steps: + - run: + name: Build and publish all the Android Artifacts to /tmp/maven-local + command: | + if [[ << parameters.release_type >> == "dry-run" ]]; then + export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a" + else + export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64" + fi + ./gradlew publishAllToMavenTempLocal + + - persist_to_workspace: + root: /root/react-native/ + paths: + - build/ + - .gradle/ + - packages/rn-tester/android/app/.cxx/ + - packages/rn-tester/android/app/build/ + - packages/react-native/sdks/download/ + - packages/react-native/sdks/hermes/ + - packages/react-native/ReactAndroid/.cxx/ + - packages/react-native/ReactAndroid/build/ + - packages/react-native/ReactAndroid/hermes-engine/.cxx/ + - packages/react-native/ReactAndroid/hermes-engine/build/ + - packages/react-native/ReactAndroid/flipper-integration/build/ + - packages/react-native/ReactAndroid/src/main/jni/prebuilt/ + - packages/react-native-gradle-plugin/.gradle/ + - packages/react-native-gradle-plugin/build/ + - packages/react-native-codegen/lib/ + + # ------------------------- + # JOBS: Test Android + # ------------------------- + test_android: + executor: reactnativeandroid-xlarge + steps: + - checkout + - run_yarn + - run: + name: Set React Native Version to "dry-run" + # test_android executes only for dry-run builds. We need to bump the version for caching + # reasons otherwise we won't reuse the artifacts from the build_android job. + command: node ./scripts/set-rn-version.js --build-type "dry-run" + - attach_workspace: + at: . + + - with_gradle_cache: + steps: + - run: + name: Build & Test React Native using Gradle + command: ./gradlew build -PenableWarningsAsErrors=true + + - report_bundle_size: + platform: android + + - store_test_results: + path: ~/react-native/packages/react-native-gradle-plugin/build/test-results + + - store_test_results: + path: ~/react-native/packages/react-native/ReactAndroid/build/test-results + + - store_artifacts: + path: ~/react-native/packages/rn-tester/android/app/build/outputs/apk/ + destination: rntester-apk + + # ------------------------- + # JOBS: Test Android Template + # ------------------------- + test_android_template: + executor: reactnativeandroid-large + parameters: + flavor: + default: "Debug" + description: The Android build type. Must be one of "Debug", "Release". + type: enum + enum: ["Debug", "Release"] + architecture: + default: "OldArch" + description: Which React Native architecture to use. Must be one of "NewArch", "OldArch". + type: enum + enum: [ "NewArch", "OldArch" ] + jsengine: + default: "Hermes" + description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". + type: enum + enum: ["Hermes", "JSC"] + environment: + - PROJECT_NAME: "AndroidTemplateProject" + steps: + - checkout_code_with_cache + - run_yarn + - attach_workspace: + at: . + - run: + name: Create Android template project + command: | + REPO_ROOT=$(pwd) + node ./scripts/update-template-package.js "{\"react-native\":\"file:$REPO_ROOT/build/$(cat build/react-native-package-version)\"}" + node ./scripts/template/initialize.js --reactNativeRootPath $REPO_ROOT --templateName $PROJECT_NAME --templateConfigPath "$REPO_ROOT/packages/react-native" --directory "/tmp/$PROJECT_NAME" + - with_gradle_cache: + steps: + - run: + name: Build the template application for << parameters.flavor >> with Architecture set to << parameters.architecture >>, and using the << parameters.jsengine>> JS engine. + command: | + cd /tmp/$PROJECT_NAME/android/ + if [[ << parameters.architecture >> == "NewArch" ]]; then + export ORG_GRADLE_PROJECT_newArchEnabled=true + else + export ORG_GRADLE_PROJECT_newArchEnabled=false + fi + if [[ << parameters.jsengine >> == "Hermes" ]]; then + export ORG_GRADLE_PROJECT_hermesEnabled=true + else + export ORG_GRADLE_PROJECT_hermesEnabled=false + fi + ./gradlew assemble<< parameters.flavor >> -Preact.internal.mavenLocalRepo=/root/react-native/maven-local + + - store_artifacts: + path: /tmp/AndroidTemplateProject/android/app/build/outputs/apk/ + destination: template-apk + + # ------------------------- + # JOBS: Test iOS Template + # ------------------------- + test_ios_template: + executor: reactnativeios + parameters: + flavor: + default: "Debug" + description: The Xcode build type. Must be one of "Debug", "Release". + type: enum + enum: ["Debug", "Release"] + architecture: + default: "OldArch" + description: Which React Native architecture to use. Must be one of "NewArch", "OldArch". + type: enum + enum: ["NewArch", "OldArch"] + jsengine: + default: "Hermes" + description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". + type: enum + enum: ["Hermes", "JSC"] + flipper: + default: "WithFlipper" + description: Whether Flipper is enabled. Must be one of "WithFlipper", "WithoutFlipper". + type: enum + enum: ["WithFlipper", "WithoutFlipper"] + use_frameworks: + default: "StaticLibraries" + description: Which kind of option we want to use for `use_frameworks!` + type: enum + enum: ["StaticLibraries", "DynamicFrameworks"] + ruby_version: + default: "2.6.10" + description: The version of ruby that must be used + type: string + podfile_lock_path: + type: string + default: "/tmp/iOSTemplateProject/ios/Podfile.lock" + pods_build_folder: + type: string + default: "/tmp/iOSTemplateProject/ios/Pods" + podfile_lock_cache_key: + type: string + default: *template_podfile_lock_cache_key + cocoapods_cache_key: + type: string + default: *template_cocoapods_cache_key + environment: + - PROJECT_NAME: "iOSTemplateProject" + - HERMES_WS_DIR: *hermes_workspace_root + steps: + - checkout_code_with_cache + - run_yarn + - attach_workspace: + at: . + - *attach_hermes_workspace + - setup_ruby: + ruby_version: << parameters.ruby_version >> + - when: + condition: + equal: ["Hermes", << parameters.jsengine >>] + steps: + - run: + name: Set HERMES_ENGINE_TARBALL_PATH + command: | + BUILD_TYPE="<< parameters.flavor >>" + TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE") + echo "export HERMES_ENGINE_TARBALL_PATH=$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME" >> $BASH_ENV + - run: + name: Create iOS template project + command: | + REPO_ROOT=$(pwd) + PACKAGE=$(cat build/react-native-package-version) + PATH_TO_PACKAGE="$REPO_ROOT/build/$PACKAGE" + node ./scripts/update-template-package.js "{\"react-native\":\"file:$PATH_TO_PACKAGE\"}" + node ./scripts/template/initialize.js --reactNativeRootPath $REPO_ROOT --templateName $PROJECT_NAME --templateConfigPath "$REPO_ROOT/packages/react-native" --directory "/tmp/$PROJECT_NAME" + - with_xcodebuild_cache: + podfile_lock_path: << parameters.podfile_lock_path >> + pods_build_folder: << parameters.pods_build_folder >> + cocoapods_cache_key: << parameters.cocoapods_cache_key >> + podfile_lock_cache_key: << parameters.podfile_lock_cache_key >> + steps: + - run: + name: Install iOS dependencies - Configuration << parameters.flavor >>; New Architecture << parameters.architecture >>; JS Engine << parameters.jsengine>>; Flipper << parameters.flipper >> + command: | + cd /tmp/$PROJECT_NAME/ios + + if [[ << parameters.architecture >> == "NewArch" ]]; then + export RCT_NEW_ARCH_ENABLED=1 + fi + + if [[ << parameters.jsengine >> == "JSC" ]]; then + export USE_HERMES=0 + fi + + if [[ << parameters.flipper >> == "WithoutFlipper" ]]; then + export NO_FLIPPER=1 + fi + + if [[ << parameters.use_frameworks >> == "DynamicFrameworks" ]]; then + export USE_FRAMEWORKS=dynamic + fi + + cd .. + bundle install + bundle exec pod install --project-directory=ios + - run: + name: Build template project + command: | + xcodebuild build \ + -configuration << parameters.flavor >> \ + -workspace /tmp/$PROJECT_NAME/ios/$PROJECT_NAME.xcworkspace \ + -scheme $PROJECT_NAME \ + -sdk iphonesimulator + + # ------------------------- + # JOBS: Test iOS RNTester + # ------------------------- + test_ios_rntester: + executor: reactnativeios + parameters: + jsengine: + default: "Hermes" + description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". + type: enum + enum: ["Hermes", "JSC"] + architecture: + default: "OldArch" + description: Which React Native architecture to use. Must be one of "OldArch", "NewArch". + type: enum + enum: ["NewArch", "OldArch"] + use_frameworks: + default: "StaticLibraries" + description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "DynamicFrameworks" + type: enum + enum: ["StaticLibraries", "DynamicFrameworks"] + ruby_version: + default: "2.6.10" + description: The version of ruby that must be used + type: string + steps: + - checkout_code_with_cache + - run_yarn + - *attach_hermes_workspace + + # The macOS machine can run out of storage if Hermes is enabled and built from source. + # Since this job does not use the iOS Simulator, deleting it provides a quick way to + # free up space. + - run: + name: Delete iOS Simulators + background: true + command: sudo rm -rf /Library/Developer/CoreSimulator/Profiles/Runtimes/ + - setup_ruby: + ruby_version: << parameters.ruby_version >> + - with_hermes_tarball_cache_span: + set_tarball_path: True + steps: + - with_xcodebuild_cache: + steps: + - run: + name: Install CocoaPods dependencies - Architecture << parameters.architecture >> + command: | + if [[ << parameters.architecture >> == "NewArch" ]]; then + export RCT_NEW_ARCH_ENABLED=1 + fi + + if [[ << parameters.jsengine >> == "JSC" ]]; then + export USE_HERMES=0 + fi + + if [[ << parameters.use_frameworks >> == "DynamicFrameworks" ]]; then + export NO_FLIPPER=1 + export USE_FRAMEWORKS=dynamic + fi + + cd packages/rn-tester + + bundle install + bundle exec pod install + - run: + name: Build RNTester + command: | + xcodebuild build \ + -workspace packages/rn-tester/RNTesterPods.xcworkspace \ + -scheme RNTester \ + -sdk iphonesimulator + + # ------------------------- + # JOBS: Windows + # ------------------------- + test_windows: + executor: + name: win/default + environment: + - CHOCO_CACHE_DIR: "C:\\ChocoCache" + steps: + - checkout_code_with_cache + + - restore_cache: + keys: + - *windows_choco_cache_key + + - run: + name: Choco cache + # Cache our dependencies which can be flakey to download + command: | + if (!Test-Path $env:CHOCO_CACHE_DIR) { + mkdir $env:CHOCO_CACHE_DIR + } + choco config set --name cacheLocation --value $env:CHOCO_CACHE_DIR + + - run: + name: Disable NVM + # Use choco to manage node versions due to https://github.com/npm/cli/issues/4234 + command: nvm off + + - run: + name: Install Node JS + # Note: Version set separately for non-Windows builds, see above. + command: choco install nodejs-lts + + # Setup Dependencies + - run: + name: Enable Yarn with corepack + command: corepack enable + + # it looks like that, last week, envinfo released version 7.9.0 which does not works + # with Windows. I have opened an issue here: https://github.com/tabrindle/envinfo/issues/238 + # TODO: T156811874 - Revert this to npx envinfo@latest when the issue is addressed + - run: + name: Display Environment info + command: | + npm install -g envinfo + envinfo -v + envinfo + + - restore_cache: + keys: + - *windows_yarn_cache_key + - run: + name: "Yarn: Install Dependencies" + command: yarn install --frozen-lockfile --non-interactive + + - save_cache: + key: *windows_yarn_cache_key + paths: + - C:\Users\circleci\AppData\Local\Yarn + + - save_cache: + key: *windows_choco_cache_key + paths: + - $env:CHOCO_CACHE_DIR + + # ------------------------- + # Run Tests + - run: + name: "Flow: Check Android" + command: yarn flow-check-android + - run: + name: "Flow: Check iOS" + command: yarn flow-check-ios + - run: + name: "Run Tests: JavaScript Tests" + command: yarn test + + # ------------------------- + # JOBS: Build Hermes + # ------------------------- + prepare_hermes_workspace: + docker: + - image: debian:bullseye + environment: + - HERMES_WS_DIR: *hermes_workspace_root + - HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion" + - BUILD_FROM_SOURCE: true + steps: + - run: + name: Install dependencies + command: | + apt update + + apt install -y wget git curl jq + curl -sL https://deb.nodesource.com/setup_18.x | bash - + apt install -y nodejs + npm install --global yarn + - checkout + - run: + name: Set up Hermes workspace and caching + command: | + mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" + + if [ -f "$HERMES_VERSION_FILE" ]; then + echo "Hermes Version file found! Using this version for the build:" + cat $HERMES_VERSION_FILE > /tmp/hermes/hermesversion + else + echo "Hermes Version file not found!!!" + echo "Using the last commit from main for the build:" + HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') + echo $HERMES_TAG_SHA > /tmp/hermes/hermesversion + fi + cat /tmp/hermes/hermesversion + - get_react_native_version + - restore_cache: + key: *hermes_workspace_cache_key + - run_yarn + - run: + name: Download Hermes tarball + command: | + node packages/react-native/scripts/hermes/prepare-hermes-for-build $CIRCLE_PULL_REQUEST + cp packages/react-native/sdks/download/* $HERMES_WS_DIR/download/. + cp -r packages/react-native/sdks/hermes/* $HERMES_WS_DIR/hermes/. + + cat /tmp/hermes/hermesversion + - save_cache: + key: *hermes_workspace_cache_key + paths: + - /tmp/hermes/download/ + - /tmp/hermes/hermes/ + # Check if we already built the tarball + # if yes, we can skip the building and we can skip some jobs building + - restore_cache: + keys: + - *hermes_tarball_release_cache_key + - check_if_tarball_is_present: + flavor: Release + - restore_cache: + keys: + - *hermes_tarball_debug_cache_key + - check_if_tarball_is_present: + flavor: Debug + - restore_cache: + keys: + - *hermes_macosx_bin_release_cache_key + - check_if_osx_bin_is_present: + flavor: Release + - restore_cache: + keys: + - *hermes_macosx_bin_debug_cache_key + - check_if_osx_bin_is_present: + flavor: Debug + - restore_cache: + keys: + - *hermes_dsym_debug_cache_key + - check_if_dsym_are_present: + flavor: Debug + - restore_cache: + keys: + - *hermes_dsym_release_cache_key + - check_if_dsym_are_present: + flavor: Release + - persist_to_workspace: + root: *hermes_workspace_root + paths: + - download + - hermes + - hermes-runtime-darwin + - osx-bin + - dSYM + - hermesversion + - Release_tarball_present + - Debug_tarball_present + - Release_osx_bin + - Debug_osx_bin + - Release_dSYM + - Debug_dSYM + - persist_to_workspace: + root: /tmp + paths: + - react-native-version + + build_hermesc_linux: + docker: + - image: debian:bullseye + resource_class: "large" + steps: + - checkout_code_with_cache + - run: + name: Install dependencies + command: | + apt update + apt install -y git openssh-client cmake build-essential \ + libreadline-dev libicu-dev jq zip python3 + - *attach_hermes_workspace + - get_react_native_version + - restore_cache: + key: *hermes_linux_cache_key + - run: + name: Set up workspace + command: | + mkdir -p /tmp/hermes/linux64-bin + - run: + name: Build HermesC for Linux + command: | + if [ -f /tmp/hermes/linux64-bin/hermesc ]; then + echo 'Skipping; Clean "/tmp/hermes/linux64-bin" to rebuild.' + else + cd /tmp/hermes + cmake -S hermes -B build -DHERMES_STATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \ + -DCMAKE_EXE_LINKER_FLAGS="-Wl,--whole-archive -lpthread -Wl,--no-whole-archive" + cmake --build build --target check-hermes -j 4 + cp /tmp/hermes/build/bin/hermesc /tmp/hermes/linux64-bin/. + fi + - save_cache: + key: *hermes_linux_cache_key + paths: + - /tmp/hermes/linux64-bin/ + - /tmp/hermes/hermes/destroot/ + - store_artifacts_if_needed: + path: /tmp/hermes/linux64-bin/ + - persist_to_workspace: + root: /tmp/hermes/ + paths: + - linux64-bin + + build_hermesc_apple: + executor: reactnativeios + environment: + - HERMES_WS_DIR: *hermes_workspace_root + - HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir + steps: + - *attach_hermes_workspace + - stop_job_if_apple_artifacts_are_there: + flavor: "All" + - checkout_code_with_cache + - get_react_native_version + - setup_hermes_workspace + - restore_cache: + key: *hermesc_apple_cache_key + - brew_install: + package: cmake + - run: + name: "Build HermesC Apple" + command: | + cd ./packages/react-native/sdks/hermes || exit 1 + . ./utils/build-apple-framework.sh + build_host_hermesc_if_needed + - save_cache: + key: *hermesc_apple_cache_key + paths: + - ./packages/react-native/sdks/hermes/build_host_hermesc + - persist_to_workspace: + root: ./packages/react-native/sdks/hermes/ + paths: + - build_host_hermesc + + build_apple_slices_hermes: + parameters: + slice_base_cache_key: + default: *hermes_apple_slices_cache_key + type: string + flavor: + default: "Debug" + description: The Hermes build type. Must be one of "Debug", "Release". + type: enum + enum: ["Debug", "Release"] + slice: + default: "iphoneos" + description: The Hermes Slice that this job has to build + type: enum + enum: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] + executor: reactnativeios + environment: + - HERMES_WS_DIR: *hermes_workspace_root + - HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir + - HERMES_OSXBIN_ARTIFACTS_DIR: *hermes_osxbin_artifacts_dir + steps: + - *attach_hermes_workspace + - stop_job_if_apple_artifacts_are_there: + flavor: << parameters.flavor >> + - checkout_code_with_cache + - get_react_native_version + - setup_hermes_workspace + - restore_cache: + key: *hermesc_apple_cache_key + - brew_install: + package: cmake + - restore_cache: + key: << parameters.slice_base_cache_key >>-<< parameters.slice >>-<< parameters.flavor >> + - run: + name: Build the Hermes << parameters.slice >> frameworks + command: | + cd ./packages/react-native/sdks/hermes || exit 1 + SLICE=<< parameters.slice >> + FLAVOR=<< parameters.flavor >> + FINAL_PATH=build_"$SLICE"_"$FLAVOR" + echo "Final path for this slice is: $FINAL_PATH" + + if [[ -d "$FINAL_PATH" ]]; then + echo "[HERMES] Skipping! Found the requested slice at $FINAL_PATH". + exit 0 + fi + + if [[ "$SLICE" == "macosx" ]]; then + echo "[HERMES] Building Hermes for MacOS" + BUILD_TYPE="<< parameters.flavor >>" ./utils/build-mac-framework.sh + else + echo "[HERMES] Building Hermes for iOS: $SLICE" + BUILD_TYPE="<< parameters.flavor >>" ./utils/build-ios-framework.sh "$SLICE" + fi + + echo "Moving from build_$SLICE to $FINAL_PATH" + mv build_"$SLICE" "$FINAL_PATH" + - save_cache: + key: << parameters.slice_base_cache_key >>-<< parameters.slice >>-<< parameters.flavor >> + paths: + - ./packages/react-native/sdks/hermes/build_<< parameters.slice >>_<< parameters.flavor >> + + build_hermes_macos: + parameters: + slice_base_cache_key: + default: *hermes_apple_slices_cache_key + type: string + flavor: + default: "Debug" + description: The Hermes build type. Must be one of "Debug", "Release". + type: enum + enum: ["Debug", "Release"] + executor: reactnativeios + environment: + - HERMES_WS_DIR: *hermes_workspace_root + - HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir + steps: + - *attach_hermes_workspace + # Try to store the artifacts if they are already in the workspace + - store_hermes_apple_artifacts: + flavor: << parameters.flavor >> + - stop_job_if_apple_artifacts_are_there: + flavor: << parameters.flavor >> + - checkout_code_with_cache + - run_yarn + - get_react_native_version + - brew_install: + package: cmake + - setup_hermes_workspace + - restore_cache: + key: << parameters.slice_base_cache_key >>-macosx-<< parameters.flavor >> + - restore_cache: + key: << parameters.slice_base_cache_key >>-iphoneos-<< parameters.flavor >> + - restore_cache: + key: << parameters.slice_base_cache_key >>-iphonesimulator-<< parameters.flavor >> + - restore_cache: + key: << parameters.slice_base_cache_key >>-catalyst-<< parameters.flavor >> + - run: + name: "Move back build folders" + command: | + cd ./packages/react-native/sdks/hermes || exit 1 + mv build_macosx_<< parameters.flavor >> build_macosx + mv build_iphoneos_<< parameters.flavor >> build_iphoneos + mv build_iphonesimulator_<< parameters.flavor >> build_iphonesimulator + mv build_catalyst_<< parameters.flavor >> build_catalyst + - run: + name: "Prepare destroot folder" + command: | + cd ./packages/react-native/sdks/hermes || exit 1 + . ./utils/build-apple-framework.sh + prepare_dest_root_for_ci + - run: + name: "Create fat framework for iOS" + command: | + cd ./packages/react-native/sdks/hermes || exit 1 + echo "[HERMES] Creating the universal framework" + ./utils/build-ios-framework.sh build_framework + - run: + name: Package the Hermes Apple frameworks + command: | + BUILD_TYPE="<< parameters.flavor >>" + echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" + + TARBALL_OUTPUT_DIR=$(mktemp -d /tmp/hermes-tarball-output-XXXXXXXX) + + TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE") + + echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" + + TARBALL_OUTPUT_PATH=$(node ./packages/react-native/scripts/hermes/create-tarball.js \ + --inputDir ./packages/react-native/sdks/hermes \ + --buildType "$BUILD_TYPE" \ + --outputDir $TARBALL_OUTPUT_DIR) + + echo "Hermes tarball saved to $TARBALL_OUTPUT_PATH" + + mkdir -p $HERMES_TARBALL_ARTIFACTS_DIR + cp $TARBALL_OUTPUT_PATH $HERMES_TARBALL_ARTIFACTS_DIR/. + + mkdir -p /tmp/hermes/osx-bin/<< parameters.flavor >> + cp ./packages/react-native/sdks/hermes/build_macosx/bin/* /tmp/hermes/osx-bin/<< parameters.flavor >> + - run: + name: Create dSYM archive + command: | + FLAVOR=<< parameters.flavor >> + WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR" + + mkdir -p "$WORKING_DIR/macosx" + mkdir -p "$WORKING_DIR/catalyst" + mkdir -p "$WORKING_DIR/iphoneos" + mkdir -p "$WORKING_DIR/iphonesimulator" + + cd ./packages/react-native/sdks/hermes || exit 1 + + DSYM_FILE_PATH=API/hermes/hermes.framework.dSYM + cp -r build_macosx/$DSYM_FILE_PATH "$WORKING_DIR/macosx/" + cp -r build_catalyst/$DSYM_FILE_PATH "$WORKING_DIR/catalyst/" + cp -r build_iphoneos/$DSYM_FILE_PATH "$WORKING_DIR/iphoneos/" + cp -r build_iphonesimulator/$DSYM_FILE_PATH "$WORKING_DIR/iphonesimulator/" + + DEST_DIR="/tmp/hermes/dSYM/$FLAVOR" + tar -C "$WORKING_DIR" -czvf "hermes.framework.dSYM" . + + mkdir -p "$DEST_DIR" + mv "hermes.framework.dSYM" "$DEST_DIR" + + - when: + condition: + equal: [ << parameters.flavor >>, "Debug"] + steps: + - save_cache: + key: *hermes_tarball_debug_cache_key + paths: *hermes_tarball_cache_paths + - save_cache: + key: *hermes_macosx_bin_debug_cache_key + paths: /tmp/hermes/osx-bin/Debug + - save_cache: + key: *hermes_dsym_debug_cache_key + paths: /tmp/hermes/dSYM/Debug + - when: + condition: + equal: [ << parameters.flavor >>, "Release"] + steps: + - save_cache: + key: *hermes_tarball_release_cache_key + paths: *hermes_tarball_cache_paths + - save_cache: + key: *hermes_macosx_bin_release_cache_key + paths: /tmp/hermes/osx-bin/Release + - save_cache: + key: *hermes_dsym_release_cache_key + paths: /tmp/hermes/dSYM/Release + - store_hermes_apple_artifacts: + flavor: << parameters.flavor >> + - persist_to_workspace: + root: /tmp/hermes/ + paths: + - hermes-runtime-darwin + - osx-bin + - dSYM + + build_hermesc_windows: + executor: + name: win/default + shell: powershell.exe + environment: + - HERMES_WS_DIR: 'C:\tmp\hermes' + - ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip" + - MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin' + - CMAKE_DIR: 'C:\Program Files\CMake\bin' + steps: + - checkout_code_with_cache + - *attach_hermes_workspace + - get_react_native_version_windows + - restore_cache: + key: *hermes_windows_cache_key + - run: + name: Set up workspace + command: | + New-Item -ItemType Directory $Env:HERMES_WS_DIR + New-Item -ItemType Directory $Env:HERMES_WS_DIR\icu + New-Item -ItemType Directory $Env:HERMES_WS_DIR\deps + New-Item -ItemType Directory $Env:HERMES_WS_DIR\win64-bin + New-Item -ItemType SymbolicLink -Target tmp\hermes\hermes -Path $Env:HERMES_WS_DIR -Name hermes + - run: + name: Build HermesC for Windows + command: | + if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) { + choco install --no-progress cmake --version 3.14.7 + if (-not $?) { throw "Failed to install CMake" } + + cd $Env:HERMES_WS_DIR\icu + # If Invoke-WebRequest shows a progress bar, it will fail with + # Win32 internal error "Access is denied" 0x5 occurred [...] + $progressPreference = 'silentlyContinue' + Invoke-WebRequest -Uri "$Env:ICU_URL" -OutFile "icu.zip" + Expand-Archive -Path "icu.zip" -DestinationPath "." + + cd $Env:HERMES_WS_DIR + Copy-Item -Path "icu\bin64\icu*.dll" -Destination "deps" + # Include MSVC++ 2015 redistributables + Copy-Item -Path "c:\windows\system32\msvcp140.dll" -Destination "deps" + Copy-Item -Path "c:\windows\system32\vcruntime140.dll" -Destination "deps" + Copy-Item -Path "c:\windows\system32\vcruntime140_1.dll" -Destination "deps" + + $Env:PATH += ";$Env:CMAKE_DIR;$Env:MSBUILD_DIR" + $Env:ICU_ROOT = "$Env:HERMES_WS_DIR\icu" + + cmake -S hermes -B build_release -G 'Visual Studio 16 2019' -Ax64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DHERMES_ENABLE_WIN10_ICU_FALLBACK=OFF + if (-not $?) { throw "Failed to configure Hermes" } + cd build_release + cmake --build . --target hermesc --config Release + if (-not $?) { throw "Failed to build Hermes" } + + cd $Env:HERMES_WS_DIR + Copy-Item -Path "build_release\bin\Release\hermesc.exe" -Destination "win64-bin" + # Include Windows runtime dependencies + Copy-Item -Path "deps\*" -Destination "win64-bin" + } + else { + Write-Host "Skipping; Clean c:\tmp\hermes\win64-bin to rebuild." + } + - save_cache: + key: *hermes_windows_cache_key + paths: + - C:\tmp\hermes\win64-bin\ + - C:\tmp\hermes\hermes\icu\ + - C:\tmp\hermes\hermes\deps\ + - C:\tmp\hermes\hermes\build_release\ + - store_artifacts_if_needed: + path: C:\tmp\hermes\win64-bin\ + - persist_to_workspace: + root: C:\tmp\hermes\ + paths: + - win64-bin + + # ------------------------- + # JOBS: Releases + # ------------------------- + prepare_package_for_release: + parameters: + version: + type: string + latest: + type: boolean + default: false + dryrun: + type: boolean + default: false + executor: reactnativeios + steps: + - checkout_code_with_cache + - run_yarn + - add_ssh_keys: + fingerprints: + - "1f:c7:61:c4:e2:ff:77:e3:cc:ca:a7:34:c2:79:e3:3c" + - brew_install: + package: cmake + - run: + name: "Set new react-native version and commit changes" + command: | + VERSION=<< parameters.version >> + + if [[ -z "$VERSION" ]]; then + VERSION=$(grep '"version"' package.json | cut -d '"' -f 4 | head -1) + echo "Using the version from the package.json: $VERSION" + fi + + node ./scripts/prepare-package-for-release.js -v "$VERSION" -l << parameters.latest >> --dry-run << parameters.dryrun >> + + build_npm_package: + parameters: + release_type: + description: The type of release to build. Must be one of "nightly", "release", "dry-run". + type: enum + enum: ["nightly", "release", "dry-run"] + default: "dry-run" + executor: reactnativeandroid-xlarge + environment: + - HERMES_WS_DIR: *hermes_workspace_root + steps: + - run: + name: Add github.com to SSH known hosts + command: | + mkdir -p ~/.ssh + echo '|1|If6MU203eXTaaWL678YEfWkVMrw=|kqLeIAyTy8pzpj8x8Ae4Fr8Mtlc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts + - checkout + - *attach_hermes_workspace + - run: + name: Copy Hermes binaries + command: | + mkdir -p ./packages/react-native/sdks/hermesc ./packages/react-native/sdks/hermesc/osx-bin ./packages/react-native/sdks/hermesc/win64-bin ./packages/react-native/sdks/hermesc/linux64-bin + + # When build_hermes_macos runs as a matrix, it outputs + if [[ -d $HERMES_WS_DIR/osx-bin/Release ]]; then + cp -r $HERMES_WS_DIR/osx-bin/Release/* ./packages/react-native/sdks/hermesc/osx-bin/. + elif [[ -d $HERMES_WS_DIR/osx-bin/Debug ]]; then + cp -r $HERMES_WS_DIR/osx-bin/Debug/* ./packages/react-native/sdks/hermesc/osx-bin/. + else + ls $HERMES_WS_DIR/osx-bin || echo "hermesc macOS artifacts directory missing." + echo "Could not locate macOS hermesc binary."; exit 1; + fi + + cp -r $HERMES_WS_DIR/win64-bin/* ./packages/react-native/sdks/hermesc/win64-bin/. + cp -r $HERMES_WS_DIR/linux64-bin/* ./packages/react-native/sdks/hermesc/linux64-bin/. + mkdir -p ./packages/react-native/ReactAndroid/external-artifacts/artifacts/ + cp $HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-debug.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-debug.tar.gz + cp $HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-release.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-release.tar.gz + cp $HERMES_WS_DIR/dSYM/Debug/hermes.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-debug.tar.gz + cp $HERMES_WS_DIR/dSYM/Release/hermes.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-release.tar.gz + - run_yarn + - build_packages + - attach_workspace: + at: . + + # START: Stables and nightlies + # This conditional step sets up the necessary credentials for publishing react-native to npm. + - when: + condition: + or: + - equal: [ "release", << parameters.release_type >> ] + - equal: [ "nightly", << parameters.release_type >> ] + steps: + - run: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc + # END: Stables and nightlies + + - with_gradle_cache: + steps: + - run: + name: Publish NPM + command: | + # We can't have a separate step because each command is executed in a separate shell + # so variables exported in a command are not visible in another. + if [[ << parameters.release_type >> == "dry-run" ]]; then + export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a" + else + export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64" + fi + node ./scripts/publish-npm.js --<< parameters.release_type >> + + - run: + name: Zip Maven Artifacts from /tmp/maven-local + command: zip -r /tmp/maven-local.zip /tmp/maven-local + - store_artifacts: + path: /tmp/maven-local.zip + - store_artifacts: + path: /root/.npm/_logs + - persist_to_workspace: + root: /tmp + paths: + - maven-local + + # START: Dry-run + # Provide a react-native package for this commit as a Circle CI release artifact. + - when: + condition: + equal: [ "dry-run", << parameters.release_type >> ] + steps: + - run: + name: Build release package as a job artifact + command: | + mkdir -p build + + FILENAME=$(cd packages/react-native; npm pack | tail -1) + mv packages/react-native/$FILENAME build/ + + echo $FILENAME > build/react-native-package-version + - store_artifacts: + path: ~/react-native/build/ + destination: build + - persist_to_workspace: + root: . + paths: + - build/* + # END: Dry-run + + # START: Stable releases + - when: + condition: + equal: [ "release", << parameters.release_type >> ] + steps: + - run: + name: Update rn-diff-purge to generate upgrade-support diff + command: | + curl -X POST https://api.github.com/repos/react-native-community/rn-diff-purge/dispatches \ + -H "Accept: application/vnd.github.v3+json" \ + -H "Authorization: Bearer $REACT_NATIVE_BOT_GITHUB_TOKEN" \ + -d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"${CIRCLE_TAG:1}\" }}" + # END: Stable releases + + poll_maven: + docker: + - image: cimg/node:current + resource_class: small + steps: + - checkout_code_with_cache + - run_yarn + - run: + name: Poll Maven for Artifacts + command: | + node scripts/circleci/poll-maven.js + + + # ------------------------- + # JOBS: Nightly + # ------------------------- + nightly_job: + machine: + image: ubuntu-2004:202010-01 + steps: + - run: + name: Nightly + command: | + echo "Nightly build run" + + find_and_publish_bumped_packages: + executor: nodelts + steps: + - checkout + - run_yarn + - build_packages + - run: + name: Set NPM auth token + command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc + - run: + name: Find and publish all bumped packages + command: node ./scripts/monorepo/find-and-publish-all-bumped-packages.js + + +# ------------------------- +# PIPELINE PARAMETERS +# ------------------------- parameters: - # Real pipelines parameters run_release_workflow: default: false type: boolean @@ -24,74 +2091,329 @@ parameters: default: false type: boolean -jobs: - choose_ci_jobs: - docker: - - image: debian:bullseye - resource_class: small - steps: - - run: - name: Install Yarn - command: | - apt update - apt install -y wget git curl jq - curl -sL https://deb.nodesource.com/setup_18.x | bash - - apt install -y nodejs - npm install --global yarn - - checkout - - run: - name: Yarn Install - command: yarn install - - when: - condition: - or: - - equal: [ main, << pipeline.git.branch >> ] - - matches: - pattern: /0\.[0-9]+[\.[0-9]+]?-stable/ - value: << pipeline.git.branch >> - steps: - - run: - name: "[Main or Stable] Create input fo config to test everything" - command: | - mkdir -p /tmp/circleci/ - echo '{ "run_all": true }' > /tmp/circleci/pipeline_config.json - - when: - condition: - not: - or: - - equal: [ main, << pipeline.git.branch >> ] - - matches: - pattern: /0\.[0-9]+[\.[0-9]+]?-stable/ - value: << pipeline.git.branch >> - steps: - - run: - name: "[PR Branch] Filter jobs" - command: | - if [[ -z "$CIRCLE_PULL_REQUEST" ]]; then - echo "Not in a PR. Can't filter properly outside a PR. Please open a PR so that we can run the proper CI tests." - echo "Skipping!" - mkdir -p /tmp/circleci/ - echo '{}' > /tmp/circleci/pipeline_config.json - else - PR_NUMBER="${CIRCLE_PULL_REQUEST##*/}" - node ./scripts/circleci/pipeline_selection.js filter-jobs \ - -t $REACT_NATIVE_BOT_GITHUB_TOKEN \ - -n $PR_NUMBER \ - -u $CIRCLE_USERNAME - fi - - run: - name: Create config - description: Generates a configuration on the fly, depending on the files that have been modified - command: | - node ./scripts/circleci/pipeline_selection.js create-configs - - store_artifacts: - path: .circleci/generated_config.yml - destination: generated_config.yml - - continuation/continue: - configuration_path: .circleci/generated_config.yml +# ------------------------- +# WORKFLOWS +# +# When creating a new workflow, make sure to include condition: +# +# when: +# and: +# - equal: [ false, << pipeline.parameters.run_release_workflow >> ] +# - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] +# +# It's setup this way so we can trigger a release via a POST +# See limitations: https://support.circleci.com/hc/en-us/articles/360050351292-How-to-trigger-a-workflow-via-CircleCI-API-v2 +# ------------------------- -# our single workflow, that triggers the setup job defined above workflows: - always-run: + version: 2 + + tests: + when: + and: + - equal: [ false, << pipeline.parameters.run_release_workflow >> ] + - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] jobs: - - choose_ci_jobs + - prepare_package_for_release: + name: prepare_package_for_release + version: '' + latest : false + dryrun: true + - prepare_hermes_workspace + - build_android: + release_type: "dry-run" + - build_hermesc_linux: + requires: + - prepare_hermes_workspace + - build_hermesc_apple: + requires: + - prepare_hermes_workspace + - build_apple_slices_hermes: + requires: + - build_hermesc_apple + matrix: + parameters: + flavor: ["Debug", "Release"] + slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] + - build_hermes_macos: + requires: + - build_apple_slices_hermes + matrix: + parameters: + flavor: ["Debug", "Release"] + - build_hermesc_windows: + requires: + - prepare_hermes_workspace + - build_npm_package: + # Build a release package on every untagged commit, but do not publish to npm. + release_type: "dry-run" + requires: + - build_android + - build_hermesc_linux + - build_hermes_macos + - build_hermesc_windows + - test_js: + run_disabled_tests: false + - test_android: + requires: + - build_android + - test_e2e_ios: + ruby_version: "2.7.7" + - test_e2e_android + - test_android_template: + requires: + - build_npm_package + matrix: + parameters: + architecture: ["NewArch", "OldArch"] + jsengine: ["Hermes", "JSC"] + flavor: ["Debug", "Release"] + - test_ios_template: + requires: + - build_npm_package + name: "Test Template with Ruby 3.2.0" + ruby_version: "3.2.0" + architecture: "NewArch" + flavor: "Debug" + - test_ios_template: + requires: + - build_npm_package + matrix: + parameters: + architecture: ["NewArch", "OldArch"] + flavor: ["Debug", "Release"] + jsengine: ["Hermes", "JSC"] + flipper: ["WithFlipper", "WithoutFlipper"] + use_frameworks: ["StaticLibraries", "DynamicFrameworks"] + exclude: + - architecture: "NewArch" + flavor: "Release" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - architecture: "NewArch" + flavor: "Release" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "NewArch" + flavor: "Release" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - architecture: "NewArch" + flavor: "Release" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "OldArch" + flavor: "Release" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - architecture: "OldArch" + flavor: "Release" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "OldArch" + flavor: "Release" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - architecture: "OldArch" + flavor: "Release" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "NewArch" + flavor: "Debug" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "NewArch" + flavor: "Debug" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "OldArch" + flavor: "Debug" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "OldArch" + flavor: "Debug" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "DynamicFrameworks" + - architecture: "NewArch" + flavor: "Debug" + jsengine: "Hermes" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - architecture: "NewArch" + flavor: "Debug" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - architecture: "OldArch" + flavor: "Debug" + jsengine: "JSC" + flipper: "WithFlipper" + use_frameworks: "StaticLibraries" + - test_ios_rntester: + requires: + - build_hermes_macos + name: "Test RNTester with Ruby 3.2.0" + ruby_version: "3.2.0" + architecture: "NewArch" + - test_ios_rntester: + requires: + - build_hermes_macos + matrix: + parameters: + architecture: ["NewArch", "OldArch"] + jsengine: ["Hermes", "JSC"] + use_frameworks: ["StaticLibraries", "DynamicFrameworks"] + exclude: + # Tested by test_ios-Hermes + - architecture: "OldArch" + jsengine: "Hermes" + use_frameworks: "StaticLibraries" + # Tested by test_ios-JSC + - architecture: "OldArch" + jsengine: "JSC" + use_frameworks: "StaticLibraries" + - test_ios: + name: "Test iOS with Ruby 3.2.0" + run_unit_tests: true + requires: + - build_hermes_macos + ruby_version: "3.2.0" + - test_ios: + run_unit_tests: true + requires: + - build_hermes_macos + matrix: + parameters: + jsengine: ["Hermes", "JSC"] + - test_js: + name: test_js_prev_lts + executor: nodeprevlts + - test_windows + + # This workflow should only be triggered by release script + package_release: + when: << pipeline.parameters.run_release_workflow >> + jobs: + # This job will push a tag that will trigger the publish_release workflow + - prepare_package_for_release: + name: prepare_package_for_release + version: << pipeline.parameters.release_version >> + latest : << pipeline.parameters.release_latest >> + + # This job will run only when a tag is published due to all the jobs being filtered. + publish_release: + jobs: + - prepare_hermes_workspace: + filters: *only_release_tags + - build_android: + filters: *only_release_tags + name: build_android_for_release + release_type: "release" + - build_hermesc_linux: + filters: *only_release_tags + requires: + - prepare_hermes_workspace + - build_hermesc_apple: + filters: *only_release_tags + requires: + - prepare_hermes_workspace + - build_apple_slices_hermes: + requires: + - build_hermesc_apple + matrix: + parameters: + flavor: ["Debug", "Release"] + slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] + - build_hermesc_windows: + filters: *only_release_tags + requires: + - prepare_hermes_workspace + - build_hermes_macos: + requires: + - build_apple_slices_hermes + matrix: + parameters: + flavor: ["Debug", "Release"] + # This job will trigger when a version tag is pushed (by package_release) + - build_npm_package: + name: build_and_publish_npm_package + release_type: "release" + filters: *only_release_tags + requires: + - build_android_for_release + - build_hermesc_linux + - build_hermes_macos + - build_hermesc_windows + - poll_maven: + requires: + - build_and_publish_npm_package + + analysis: + when: + and: + - equal: [ false, << pipeline.parameters.run_release_workflow >> ] + - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] + jobs: + # Run lints on every commit + - analyze_code + + # Run code checks on PRs + - analyze_pr + + nightly: + when: << pipeline.parameters.run_nightly_workflow >> + jobs: + - nightly_job + - prepare_hermes_workspace + - build_android: + release_type: "nightly" + - build_hermesc_linux: + requires: + - prepare_hermes_workspace + - build_hermesc_apple: + requires: + - prepare_hermes_workspace + - build_apple_slices_hermes: + requires: + - build_hermesc_apple + matrix: + parameters: + flavor: ["Debug", "Release"] + slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] + - build_hermesc_windows: + requires: + - prepare_hermes_workspace + - build_hermes_macos: + requires: + - build_apple_slices_hermes + matrix: + parameters: + flavor: ["Debug", "Release"] + - build_npm_package: + release_type: "nightly" + requires: + - build_android + - build_hermesc_linux + - build_hermes_macos + - build_hermesc_windows + + publish_bumped_packages: + when: + and: + - equal: [ false, << pipeline.parameters.run_release_workflow >> ] + - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] + jobs: + - find_and_publish_bumped_packages: + <<: *main_or_stable_only diff --git a/.circleci/configurations/commands.yml b/.circleci/configurations/commands.yml deleted file mode 100644 index a2af76dbb37..00000000000 --- a/.circleci/configurations/commands.yml +++ /dev/null @@ -1,508 +0,0 @@ -# ------------------------- -# COMMANDS -# ------------------------- -commands: - # Checkout with cache, on machines that are using Docker the cache is ignored - checkout_code_with_cache: - parameters: - checkout_base_cache_key: - default: *checkout_cache_key - type: string - steps: - - restore_cache: - key: << parameters.checkout_base_cache_key >>-{{ arch }}-{{ .Branch }}-{{ .Revision }} - - checkout - - save_cache: - key: << parameters.checkout_base_cache_key >>-{{ arch }}-{{ .Branch }}-{{ .Revision }} - paths: - - ".git" - - setup_ruby: - parameters: - ruby_version: - default: "2.6.10" - type: string - steps: - - restore_cache: - key: *gems_cache_key - - run: - name: Set Required Ruby - command: echo << parameters.ruby_version >> > /tmp/required_ruby - - restore_cache: - key: *rbenv_cache_key - - run: - name: Bundle Install - command: | - # Check if rbenv is installed. CircleCI is migrating to rbenv so we may not need to always install it. - - if [[ -z "$(command -v rbenv)" ]]; then - brew install rbenv ruby-build - # Load and init rbenv - (rbenv init 2> /dev/null) || true - echo '' >> ~/.bash_profile - echo 'eval "$(rbenv init - bash)"' >> ~/.bash_profile - source ~/.bash_profile - else - echo "rbenv found; Skipping installation" - fi - - brew reinstall libyaml - gem install psych -- --with-libyaml-dir=$(brew --prefix libyaml) - export RUBY_CONFIGURE_OPTS=--with-libyaml-dir=$(brew --prefix libyaml) - - # Install the right version of ruby - if [[ -z "$(rbenv versions | grep << parameters.ruby_version >>)" ]]; then - # ensure that `ruby-build` can see all the available versions of Ruby - # some PRs received machines in a weird state, this should make the pipelines - # more robust. - brew update && brew upgrade ruby-build - rbenv install << parameters.ruby_version >> - fi - - # Set ruby dependencies - rbenv global << parameters.ruby_version >> - gem install bundler - bundle check || bundle install --path vendor/bundle --clean - - save_cache: - key: *rbenv_cache_key - paths: - - ~/.rbenv - - save_cache: - key: *gems_cache_key - paths: - - vendor/bundle - - run_yarn: - parameters: - yarn_base_cache_key: - default: *yarn_cache_key - type: string - - steps: - - restore_cache: - keys: - - << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }} - - << parameters.yarn_base_cache_key >>-{{ arch }} - - << parameters.yarn_base_cache_key >> - - run: - name: "Yarn: Install Dependencies" - 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 - - save_cache: - paths: - - ~/.cache/yarn - key: << parameters.yarn_base_cache_key >>-{{ arch }}-{{ checksum "yarn.lock" }} - - build_packages: - steps: - - run: - name: Build packages - command: yarn build - - brew_install: - parameters: - package: - description: Homebrew package to install - type: string - steps: - - run: - name: "Brew: Install << parameters.package >>" - command: brew install << parameters.package >> - - with_rntester_pods_cache_span: - parameters: - steps: - type: steps - steps: - - run: - name: Setup CocoaPods cache - # Copy packages/rn-tester/Podfile.lock since it can be changed by pod install - command: cp packages/rn-tester/Podfile.lock packages/rn-tester/Podfile.lock.bak - - restore_cache: - keys: - # The committed lockfile is generated using static libraries and USE_HERMES=1 so it could load an outdated cache if a change - # only affects the frameworks or hermes config. To help prevent this also cache based on the content of Podfile. - - *pods_cache_key - - steps: << parameters.steps >> - - save_cache: - paths: - - packages/rn-tester/Pods - key: *pods_cache_key - - with_gradle_cache: - parameters: - steps: - type: steps - steps: - - restore_cache: - keys: - - *gradle_cache_key - - v3-gradle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}- - - v3-gradle-{{ .Environment.CIRCLE_JOB }}- - - v3-gradle- - - steps: << parameters.steps >> - - save_cache: - paths: - - ~/.gradle/caches - - ~/.gradle/wrapper - - packages/react-native/ReactAndroid/build/downloads - - packages/react-native/ReactAndroid/build/third-party-ndk - key: *gradle_cache_key - - run_e2e: - parameters: - platform: - description: Target platform - type: enum - enum: ["android", "ios", "js"] - default: "js" - retries: - description: How many times the job should try to run these tests - type: integer - default: 3 - steps: - - run: - name: "Run Tests: << parameters.platform >> End-to-End Tests" - command: node ./scripts/run-ci-e2e-tests.js --<< parameters.platform >> --retries << parameters.retries >> - - report_bundle_size: - parameters: - platform: - description: Target platform - type: enum - enum: ["android", "ios"] - steps: - - run: - name: Report size of RNTester.app (analysis-bot) - command: GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" scripts/circleci/report-bundle-size.sh << parameters.platform >> || true - - get_react_native_version: - steps: - - run: - name: Get React Native version - command: | - VERSION=$(cat packages/react-native/package.json | jq -r '.version') - # Save the react native version we are building in a file so we can use that file as part of the cache key. - echo "$VERSION" > /tmp/react-native-version - echo "React Native Version is $(cat /tmp/react-native-version)" - HERMES_VERSION="$(cat /tmp/hermes/hermesversion)" - echo "Hermes commit is $HERMES_VERSION" - - get_react_native_version_windows: - steps: - - run: - name: Get React Native version on Windows - command: | - $VERSION=cat packages/react-native/package.json | jq -r '.version' - # Save the react native version we are building in a file so we can use that file as part of the cache key. - echo "$VERSION" > /tmp/react-native-version - echo "React Native Version is $(cat /tmp/react-native-version)" - $HERMES_VERSION=cat C:\Users\circleci\project\tmp\hermes\hermesversion - echo "Hermes commit is $HERMES_VERSION" - - with_hermes_tarball_cache_span: - parameters: - steps: - type: steps - set_tarball_path: - type: boolean - default: False - flavor: - default: "Debug" - description: The Hermes build type. Must be one of "Debug", "Release". - type: enum - enum: ["Debug", "Release"] - hermes_tarball_artifacts_dir: - type: string - default: *hermes_tarball_artifacts_dir - steps: - - get_react_native_version - - when: - condition: - equal: [ << parameters.flavor >>, "Debug"] - steps: - - restore_cache: - keys: - - *hermes_tarball_debug_cache_key - - when: - condition: - equal: [ << parameters.flavor >>, "Release"] - steps: - - restore_cache: - keys: - - *hermes_tarball_release_cache_key - - when: - condition: << parameters.set_tarball_path >> - steps: - - run: - name: Set HERMES_ENGINE_TARBALL_PATH envvar if Hermes tarball is present - command: | - HERMES_TARBALL_ARTIFACTS_DIR=<< parameters.hermes_tarball_artifacts_dir >> - if [ ! -d $HERMES_TARBALL_ARTIFACTS_DIR ]; then - echo "Hermes tarball artifacts dir not present ($HERMES_TARBALL_ARTIFACTS_DIR). Build Hermes from source." - exit 0 - fi - - if [ ! -d ~/react-native ]; then - echo "No React Native checkout found. Run `checkout` first." - exit 0 - fi - - TARBALL_FILENAME=$(node ~/react-native/packages/react-native/scripts/hermes/get-tarball-name.js --buildType "<< parameters.flavor >>") - TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME - - echo "Looking for $TARBALL_FILENAME in $HERMES_TARBALL_ARTIFACTS_DIR" - echo "$TARBALL_PATH" - - if [ ! -f $TARBALL_PATH ]; then - echo "Hermes tarball not present ($TARBALL_PATH). Build Hermes from source." - exit 0 - fi - - echo "Found Hermes tarball at $TARBALL_PATH" - echo "export HERMES_ENGINE_TARBALL_PATH=$TARBALL_PATH" >> $BASH_ENV - - run: - name: Print Hermes version - command: | - HERMES_TARBALL_ARTIFACTS_DIR=<< parameters.hermes_tarball_artifacts_dir >> - TARBALL_FILENAME=$(node ~/react-native/packages/react-native/scripts/hermes/get-tarball-name.js --buildType "<< parameters.flavor >>") - TARBALL_PATH=$HERMES_TARBALL_ARTIFACTS_DIR/$TARBALL_FILENAME - if [[ -e $TARBALL_PATH ]]; then - tar -xf $TARBALL_PATH - echo 'print(HermesInternal?.getRuntimeProperties?.()["OSS Release Version"])' > test.js - ./destroot/bin/hermes test.js - rm test.js - rm -rf destroot - else - echo 'No Hermes tarball found.' - fi - - steps: << parameters.steps >> - - when: - condition: - equal: [ << parameters.flavor >>, "Debug"] - steps: - - save_cache: - key: *hermes_tarball_debug_cache_key - paths: *hermes_tarball_cache_paths - - when: - condition: - equal: [ << parameters.flavor >>, "Release"] - steps: - - save_cache: - key: *hermes_tarball_release_cache_key - paths: *hermes_tarball_cache_paths - - store_hermes_apple_artifacts: - description: Stores the tarball and the osx binaries - parameters: - flavor: - default: "Debug" - description: The Hermes build type. Must be one of "Debug", "Release". - type: enum - enum: ["Debug", "Release"] - steps: - - when: - condition: - equal: [ << parameters.flavor >>, "Debug"] - steps: - - store_artifacts_if_needed: - path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-debug.tar.gz - - when: - condition: - equal: [ << parameters.flavor >>, "Release"] - steps: - - store_artifacts_if_needed: - path: /tmp/hermes/hermes-runtime-darwin/hermes-ios-release.tar.gz - - store_artifacts_if_needed: - path: /tmp/hermes/osx-bin/<< parameters.flavor >>/hermesc - - store_artifacts: - path: /tmp/hermes/dSYM/<< parameters.flavor >>/hermes.framework.dSYM - - stop_job_if_apple_artifacts_are_there: - description: Stops the current job if there are already the required artifacts - parameters: - flavor: - default: "All" - description: The flavor of artifacts to check. Must be one of "Debug", "Release" or "All" - type: enum - enum: ["Debug", "Release", "All"] - steps: - - when: - condition: - equal: [ << parameters.flavor >>, "All"] - steps: - - run: - name: "Export files to be checked" - command: | - echo "/tmp/hermes/Release_tarball_present" > /tmp/hermes_files - echo "/tmp/hermes/Debug_tarball_present" >> /tmp/hermes_files - echo "/tmp/hermes/Release_osx_bin" >> /tmp/hermes_files - echo "/tmp/hermes/Debug_osx_bin" >> /tmp/hermes_files - echo "/tmp/hermes/Release_dSYM" >> /tmp/hermes_files - echo "/tmp/hermes/Debug_dSYM" >> /tmp/hermes_files - - when: - condition: - not: - equal: [ << parameters.flavor >>, "All"] - steps: - - run: - name: "Export files to be checked" - command: | - echo "/tmp/hermes/<< parameters.flavor >>_tarball_present" > /tmp/hermes_files - echo "/tmp/hermes/<< parameters.flavor >>_osx_bin" >> /tmp/hermes_files - echo "/tmp/hermes/<< parameters.flavor >>_dSYM" >> /tmp/hermes_files - - run: - name: Stop if files are present - command: | - files=($(cat /tmp/hermes_files)) - # Initialize a flag indicating all files exist - - all_files_exist=true - - for file in "${files[@]}"; do - if [[ ! -f "$file" ]]; then - all_files_exist=false - echo "$file does not exist." - else - echo "$file exist." - fi - done - - if [[ "$all_files_exist" == true ]]; then - echo "Tarball, osx-bin and dSYM are present. Halting this job" - circleci-agent step halt - fi - - check_if_tarball_is_present: - description: "Checks if the tarball of a specific Flavor is present and adds a marker file" - parameters: - flavor: - default: "Debug" - description: The flavor of artifacts to check. Must be one of "Debug" or "Release" - type: enum - enum: ["Debug", "Release"] - steps: - - run: - name: Check if << parameters.flavor >> tarball is there - command: | - FLAVOR=debug - if [[ << parameters.flavor >> == "Release" ]]; then - FLAVOR=release - fi - - if [[ -f "/tmp/hermes/hermes-runtime-darwin/hermes-ios-$FLAVOR.tar.gz" ]]; then - echo "[HERMES TARBALL] Found the << parameters.flavor >> tarball" - touch /tmp/hermes/<< parameters.flavor >>_tarball_present - fi - - check_if_osx_bin_is_present: - description: "Checks if the osx bin of a specific Flavor is present and adds a marker file" - parameters: - flavor: - default: "Debug" - description: The flavor of artifacts to check. Must be one of "Debug" or "Release" - type: enum - enum: ["Debug", "Release"] - steps: - - run: - name: Check if macosx binary is there - command: | - if [[ -d /tmp/hermes/osx-bin/<< parameters.flavor >> ]]; then - echo "[HERMES MACOSX BIN] Found the osx bin << parameters.flavor >>" - touch /tmp/hermes/<< parameters.flavor >>_osx_bin - fi - - check_if_dsym_are_present: - description: "Checks if the dSYM a specific Flavor are present and adds a marker file" - parameters: - flavor: - default: "Debug" - description: The flavor of artifacts to check. Must be one of "Debug" or "Release" - type: enum - enum: ["Debug", "Release"] - steps: - - run: - name: Check if dSYM are there - command: | - if [[ -d /tmp/hermes/dSYM/<< parameters.flavor >> ]]; then - echo "[HERMES dSYM] Found the dSYM << parameters.flavor >>" - touch /tmp/hermes/<< parameters.flavor >>_dSYM - fi - - setup_hermes_workspace: - description: "Setup Hermes Workspace" - steps: - - run: - name: Set up workspace - command: | - mkdir -p $HERMES_OSXBIN_ARTIFACTS_DIR ./packages/react-native/sdks/hermes - cp -r $HERMES_WS_DIR/hermes/* ./packages/react-native/sdks/hermes/. - cp -r ./packages/react-native/sdks/hermes-engine/utils ./packages/react-native/sdks/hermes/. - - with_xcodebuild_cache: - description: "Add caching to iOS jobs to speed up builds" - parameters: - steps: - type: steps - podfile_lock_path: - type: string - default: packages/rn-tester/Podfile.lock - pods_build_folder: - type: string - default: packages/rn-tester/Pods - podfile_lock_cache_key: - type: string - default: *rntester_podfile_lock_cache_key - cocoapods_cache_key: - type: string - default: *cocoapods_cache_key - steps: - - run: - name: Prepare Xcodebuild cache - command: | - WEEK=$(date +"%U") - YEAR=$(date +"%Y") - echo "$WEEK-$YEAR" > /tmp/week_year - - restore_cache: - key: << parameters.podfile_lock_cache_key >> - - restore_cache: - key: << parameters.cocoapods_cache_key >> - - steps: << parameters.steps >> - - save_cache: - key: << parameters.podfile_lock_cache_key >> - paths: - - << parameters.podfile_lock_path >> - - save_cache: - key: << parameters.cocoapods_cache_key >> - paths: - - << parameters.pods_build_folder >> - - store_artifacts_if_needed: - description: "This step stores the artifacts only if we are on main or on a stable branch" - parameters: - path: - type: string - destination: - type: string - default: << parameters.path >> - when: - type: enum - enum: ['always', 'on_fail', 'on_success'] - default: 'always' - steps: - - when: - condition: - or: - - equal: [ main, << pipeline.git.branch >> ] - - matches: - pattern: /0\.[0-9]+[\.[0-9]+]?-stable/ - value: << pipeline.git.branch >> - steps: - - store_artifacts: - when: << parameters.when >> - path: << parameters.path >> - destination: << parameters.destination >> diff --git a/.circleci/configurations/executors.yml b/.circleci/configurations/executors.yml deleted file mode 100644 index 7adf41062ca..00000000000 --- a/.circleci/configurations/executors.yml +++ /dev/null @@ -1,33 +0,0 @@ -# ------------------------- -# EXECUTORS -# ------------------------- -executors: - nodelts: - <<: *defaults - docker: - - image: *nodelts_image - resource_class: "large" - nodeprevlts: - <<: *defaults - docker: - - image: *nodeprevlts_image - resource_class: "large" - # Executor with Node & Java used to inspect and lint - node-browsers-small: - <<: *defaults - docker: - - image: *nodelts_browser_image - resource_class: "small" - reactnativeandroid-xlarge: - <<: *android-defaults - resource_class: "xlarge" - reactnativeandroid-large: - <<: *android-defaults - resource_class: "large" - reactnativeios: - <<: *defaults - macos: - xcode: *xcode_version - resource_class: macos.x86.medium.gen2 - environment: - - BUILD_FROM_SOURCE: true diff --git a/.circleci/configurations/jobs.yml b/.circleci/configurations/jobs.yml deleted file mode 100644 index 546f2dd4de2..00000000000 --- a/.circleci/configurations/jobs.yml +++ /dev/null @@ -1,1399 +0,0 @@ -# ------------------------- -# JOBS -# ------------------------- -jobs: - # ------------------------- - # JOBS: Analyze PR - # ------------------------- - # 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. - analyze_pr: - executor: node-browsers-small - steps: - - checkout - - run_yarn - - run: - name: Run linters against modified files (analysis-bot) - command: GITHUB_TOKEN="$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A""$PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B" yarn lint-ci - - # ------------------------- - # JOBS: Analyze Code - # ------------------------- - analyze_code: - executor: node-browsers-small - steps: - - checkout - - run_yarn - - - run: - name: Lint code - command: scripts/circleci/exec_swallow_error.sh yarn lint --format junit -o ./reports/junit/eslint/results.xml - when: always - - - run: - name: Lint Java - command: scripts/circleci/exec_swallow_error.sh yarn lint-java --check - when: always - - - run: - name: Set server.max_workers=1 in .flowconfig - command: | - sed -i '/\[options\]/a server.max_workers=1' .flowconfig - sed -i '/\[options\]/a server.max_workers=1' .flowconfig.android - when: always - - - run: - name: Check for errors in code using Flow (iOS) - command: yarn flow-check-ios - when: always - - - run: - name: Check for errors in code using Flow (Android) - command: yarn flow-check-android - when: always - - - run: - name: Run TypeScript tests - command: yarn test-typescript - when: always - - - run: - name: Sanity checks - command: | - ./scripts/circleci/check_license.sh - ./scripts/circleci/validate_yarn_lockfile.sh - when: always - - - run: - name: Check formatting - command: yarn run format-check - when: always - - - store_test_results: - path: ./reports/junit - - # ------------------------- - # JOBS: Test JavaScript - # ------------------------- - test_js: - parameters: - executor: - type: executor - default: nodelts - run_disabled_tests: - type: boolean - default: false - executor: << parameters.executor >> - steps: - - checkout - - run_yarn - - run: - name: Install rsync - command: sudo apt update && sudo apt install rsync - - # ------------------------- - # Run JavaScript tests - - run: - name: "Run Tests: JavaScript Tests" - command: node ./scripts/run-ci-javascript-tests.js --maxWorkers 2 - - run_e2e: - platform: js - - # Optionally, run disabled tests - - when: - condition: << parameters.run_disabled_tests >> - steps: - - run: echo "Failing tests may be moved here temporarily." - # ------------------------- - - - store_test_results: - path: ./reports/junit - - # ------------------------- - # JOBS: iOS Unit Tests - # ------------------------- - test_ios: - executor: reactnativeios - parameters: - run_unit_tests: - description: Specifies whether unit tests should run. - type: boolean - default: false - jsengine: - default: "Hermes" - description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". - type: enum - enum: ["Hermes", "JSC"] - ruby_version: - default: "2.6.10" - description: The version of ruby that must be used - type: string - environment: - - REPORTS_DIR: "./reports/junit" - steps: - - checkout_code_with_cache - - setup_ruby: - ruby_version: << parameters.ruby_version >> - - brew_install: - package: xcbeautify - - run: - name: Run Ruby Tests - command: | - cd packages/react-native/scripts - sh run_ruby_tests.sh - - run_yarn - - *attach_hermes_workspace - - run: | - cd packages/rn-tester - bundle check || bundle install - - run: - name: Boot iPhone Simulator - command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true - - - run: - name: Configure Environment Variables - command: | - echo 'export PATH=/usr/local/opt/node@18/bin:$PATH' >> $BASH_ENV - source $BASH_ENV - - - run: - name: "Brew: Tap wix/brew" - command: brew tap wix/brew - - brew_install: - package: applesimutils watchman - - - run: - name: Configure Watchman - command: echo "{}" > .watchmanconfig - - - run: - name: Setup the CocoaPods environment - command: | - bundle exec pod setup - - - with_hermes_tarball_cache_span: - set_tarball_path: True - steps: - - with_rntester_pods_cache_span: - steps: - - run: - name: Generate RNTesterPods Workspace - command: | - if [[ << parameters.jsengine >> == "JSC" ]]; then - export USE_HERMES=0 - fi - - cd packages/rn-tester - bundle install - bundle exec pod install --verbose - - # ------------------------- - # Runs iOS unit tests - - when: - condition: << parameters.run_unit_tests >> - steps: - - run: - name: "Run Tests: iOS Unit and Integration Tests" - command: node ./scripts/circleci/run_with_retry.js 3 yarn test-ios - - run: - name: Zip Derived data folder - when: always - command: | - echo "zipping tests results" - cd /Users/distiller/Library/Developer/Xcode - XCRESULT_PATH=$(find . -name '*.xcresult') - tar -zcvf xcresults.tar.gz $XCRESULT_PATH - - store_artifacts_if_needed: - path: /Users/distiller/Library/Developer/Xcode/xcresults.tar.gz - # ------------------------- - # Collect Results - - report_bundle_size: - platform: ios - - store_test_results: - path: ./reports/junit - - # ------------------------- - # JOBS: iOS E2E Tests - # ------------------------- - test_e2e_ios: - executor: reactnativeios - parameters: - ruby_version: - default: "2.7.7" - description: The version of ruby that must be used - type: string - steps: - - checkout_code_with_cache - - run_yarn - - attach_workspace: - at: . - - run: - name: Install appium - command: npm install appium@2.0.0 -g - - run: - name: Install appium drivers - command: | - appium driver install uiautomator2 - appium driver install xcuitest - - run: - name: Start Appium server - command: appium --base-path /wd/hub - background: true - - run: - name: Start Metro - command: | - cd packages/rn-tester - yarn start - background: true - - brew_install: - package: cmake - - setup_ruby: - ruby_version: << parameters.ruby_version >> - - run: - name: Boot iOS Simulator - command: source scripts/.tests.env && xcrun simctl boot "$IOS_DEVICE" || true - - with_xcodebuild_cache: - steps: - - run: - name: Install Bundler - command: | - cd packages/rn-tester - bundle check || bundle install - bundle exec pod setup - RCT_NEW_ARCH_ENABLED=1 bundle exec pod install --verbose - - run: - name: Build app - command: | - xcodebuild build \ - -workspace packages/rn-tester/RNTesterPods.xcworkspace \ - -configuration Debug \ - -scheme RNTester \ - -sdk iphonesimulator \ - -derivedDataPath /tmp/e2e/ - - run: - name: Move app to correct directory - command: mv /tmp/e2e/Build/Products/Debug-iphonesimulator/RNTester.app packages/rn-tester-e2e/apps/rn-tester.app - - run: - name: Check Appium server status - command: scripts/circleci/check_appium_server_status.sh - - run: - name: Run E2E tests - command: | - cd packages/rn-tester-e2e - yarn test-e2e ios - - # ------------------------- - # JOBS: Android E2E Tests - # ------------------------- - test_e2e_android: - executor: - name: android/android-machine - tag: 2023.07.1 - steps: - - checkout_code_with_cache - - run_yarn - - android/create-avd: - avd-name: e2e_emulator - system-image: system-images;android-34;google_apis;x86_64 - install: true - - android/start-emulator: - avd-name: e2e_emulator - no-window: true - restore-gradle-cache-prefix: v1a - post-emulator-launch-assemble-command: "" - - run: - name: Install appium - command: npm install appium@2.0.0 -g - - run: - name: Install appium drivers - command: | - appium driver install uiautomator2 - appium driver install xcuitest - - run: - name: Start Appium server - command: appium --base-path /wd/hub - background: true - - run: - name: Start Metro - command: | - cd packages/rn-tester - yarn start - background: true - - attach_workspace: - at: . - - with_gradle_cache: - steps: - - run: - name: Build app - command: | - ./gradlew :packages:rn-tester:android:app:assembleHermesDebug -PreactNativeArchitectures=x86_64 - - run: - name: Move app to correct directory - command: mv packages/rn-tester/android/app/build/outputs/apk/hermes/debug/app-hermes-x86_64-debug.apk packages/rn-tester-e2e/apps/rn-tester.apk - - run: - name: Check Appium server status - command: | - if ! nc -z 127.0.0.1 4723; then - echo Could not find Appium server - exit 1 - fi - - run: - name: Run E2E tests - command: | - cd packages/rn-tester-e2e - yarn test-e2e android - - # ------------------------- - # JOBS: Build Android - # ------------------------- - build_android: - executor: reactnativeandroid-xlarge - parameters: - release_type: - description: The type of release to build. Must be one of "nightly", "release", "dry-run". - type: enum - enum: ["nightly", "release", "dry-run"] - default: "dry-run" - steps: - - checkout - - run_yarn - - run: - name: Set React Native Version - command: node ./scripts/set-rn-version.js --build-type << parameters.release_type >> - - - with_gradle_cache: - steps: - - run: - name: Build and publish all the Android Artifacts to /tmp/maven-local - command: | - if [[ << parameters.release_type >> == "dry-run" ]]; then - export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a" - else - export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64" - fi - ./gradlew publishAllToMavenTempLocal - - - persist_to_workspace: - root: /root/react-native/ - paths: - - build/ - - .gradle/ - - packages/rn-tester/android/app/.cxx/ - - packages/rn-tester/android/app/build/ - - packages/react-native/sdks/download/ - - packages/react-native/sdks/hermes/ - - packages/react-native/ReactAndroid/.cxx/ - - packages/react-native/ReactAndroid/build/ - - packages/react-native/ReactAndroid/hermes-engine/.cxx/ - - packages/react-native/ReactAndroid/hermes-engine/build/ - - packages/react-native/ReactAndroid/flipper-integration/build/ - - packages/react-native/ReactAndroid/src/main/jni/prebuilt/ - - packages/react-native-gradle-plugin/.gradle/ - - packages/react-native-gradle-plugin/build/ - - packages/react-native-codegen/lib/ - - # ------------------------- - # JOBS: Test Android - # ------------------------- - test_android: - executor: reactnativeandroid-xlarge - steps: - - checkout - - run_yarn - - run: - name: Set React Native Version to "dry-run" - # test_android executes only for dry-run builds. We need to bump the version for caching - # reasons otherwise we won't reuse the artifacts from the build_android job. - command: node ./scripts/set-rn-version.js --build-type "dry-run" - - attach_workspace: - at: . - - - with_gradle_cache: - steps: - - run: - name: Build & Test React Native using Gradle - command: ./gradlew build -PenableWarningsAsErrors=true - - - report_bundle_size: - platform: android - - - store_test_results: - path: ~/react-native/packages/react-native-gradle-plugin/build/test-results - - - store_test_results: - path: ~/react-native/packages/react-native/ReactAndroid/build/test-results - - - store_artifacts: - path: ~/react-native/packages/rn-tester/android/app/build/outputs/apk/ - destination: rntester-apk - - # ------------------------- - # JOBS: Test Android Template - # ------------------------- - test_android_template: - executor: reactnativeandroid-large - parameters: - flavor: - default: "Debug" - description: The Android build type. Must be one of "Debug", "Release". - type: enum - enum: ["Debug", "Release"] - architecture: - default: "OldArch" - description: Which React Native architecture to use. Must be one of "NewArch", "OldArch". - type: enum - enum: [ "NewArch", "OldArch" ] - jsengine: - default: "Hermes" - description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". - type: enum - enum: ["Hermes", "JSC"] - environment: - - PROJECT_NAME: "AndroidTemplateProject" - steps: - - checkout_code_with_cache - - run_yarn - - attach_workspace: - at: . - - run: - name: Create Android template project - command: | - REPO_ROOT=$(pwd) - node ./scripts/update-template-package.js "{\"react-native\":\"file:$REPO_ROOT/build/$(cat build/react-native-package-version)\"}" - node ./scripts/template/initialize.js --reactNativeRootPath $REPO_ROOT --templateName $PROJECT_NAME --templateConfigPath "$REPO_ROOT/packages/react-native" --directory "/tmp/$PROJECT_NAME" - - with_gradle_cache: - steps: - - run: - name: Build the template application for << parameters.flavor >> with Architecture set to << parameters.architecture >>, and using the << parameters.jsengine>> JS engine. - command: | - cd /tmp/$PROJECT_NAME/android/ - if [[ << parameters.architecture >> == "NewArch" ]]; then - export ORG_GRADLE_PROJECT_newArchEnabled=true - else - export ORG_GRADLE_PROJECT_newArchEnabled=false - fi - if [[ << parameters.jsengine >> == "Hermes" ]]; then - export ORG_GRADLE_PROJECT_hermesEnabled=true - else - export ORG_GRADLE_PROJECT_hermesEnabled=false - fi - ./gradlew assemble<< parameters.flavor >> -Preact.internal.mavenLocalRepo=/root/react-native/maven-local - - - store_artifacts: - path: /tmp/AndroidTemplateProject/android/app/build/outputs/apk/ - destination: template-apk - - # ------------------------- - # JOBS: Test iOS Template - # ------------------------- - test_ios_template: - executor: reactnativeios - parameters: - flavor: - default: "Debug" - description: The Xcode build type. Must be one of "Debug", "Release". - type: enum - enum: ["Debug", "Release"] - architecture: - default: "OldArch" - description: Which React Native architecture to use. Must be one of "NewArch", "OldArch". - type: enum - enum: ["NewArch", "OldArch"] - jsengine: - default: "Hermes" - description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". - type: enum - enum: ["Hermes", "JSC"] - flipper: - default: "WithFlipper" - description: Whether Flipper is enabled. Must be one of "WithFlipper", "WithoutFlipper". - type: enum - enum: ["WithFlipper", "WithoutFlipper"] - use_frameworks: - default: "StaticLibraries" - description: Which kind of option we want to use for `use_frameworks!` - type: enum - enum: ["StaticLibraries", "DynamicFrameworks"] - ruby_version: - default: "2.6.10" - description: The version of ruby that must be used - type: string - podfile_lock_path: - type: string - default: "/tmp/iOSTemplateProject/ios/Podfile.lock" - pods_build_folder: - type: string - default: "/tmp/iOSTemplateProject/ios/Pods" - podfile_lock_cache_key: - type: string - default: *template_podfile_lock_cache_key - cocoapods_cache_key: - type: string - default: *template_cocoapods_cache_key - environment: - - PROJECT_NAME: "iOSTemplateProject" - - HERMES_WS_DIR: *hermes_workspace_root - steps: - - checkout_code_with_cache - - run_yarn - - attach_workspace: - at: . - - *attach_hermes_workspace - - setup_ruby: - ruby_version: << parameters.ruby_version >> - - when: - condition: - equal: ["Hermes", << parameters.jsengine >>] - steps: - - run: - name: Set HERMES_ENGINE_TARBALL_PATH - command: | - BUILD_TYPE="<< parameters.flavor >>" - TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE") - echo "export HERMES_ENGINE_TARBALL_PATH=$HERMES_WS_DIR/hermes-runtime-darwin/$TARBALL_FILENAME" >> $BASH_ENV - - run: - name: Create iOS template project - command: | - REPO_ROOT=$(pwd) - PACKAGE=$(cat build/react-native-package-version) - PATH_TO_PACKAGE="$REPO_ROOT/build/$PACKAGE" - node ./scripts/update-template-package.js "{\"react-native\":\"file:$PATH_TO_PACKAGE\"}" - node ./scripts/template/initialize.js --reactNativeRootPath $REPO_ROOT --templateName $PROJECT_NAME --templateConfigPath "$REPO_ROOT/packages/react-native" --directory "/tmp/$PROJECT_NAME" - - with_xcodebuild_cache: - podfile_lock_path: << parameters.podfile_lock_path >> - pods_build_folder: << parameters.pods_build_folder >> - cocoapods_cache_key: << parameters.cocoapods_cache_key >> - podfile_lock_cache_key: << parameters.podfile_lock_cache_key >> - steps: - - run: - name: Install iOS dependencies - Configuration << parameters.flavor >>; New Architecture << parameters.architecture >>; JS Engine << parameters.jsengine>>; Flipper << parameters.flipper >> - command: | - cd /tmp/$PROJECT_NAME/ios - - if [[ << parameters.architecture >> == "NewArch" ]]; then - export RCT_NEW_ARCH_ENABLED=1 - fi - - if [[ << parameters.jsengine >> == "JSC" ]]; then - export USE_HERMES=0 - fi - - if [[ << parameters.flipper >> == "WithoutFlipper" ]]; then - export NO_FLIPPER=1 - fi - - if [[ << parameters.use_frameworks >> == "DynamicFrameworks" ]]; then - export USE_FRAMEWORKS=dynamic - fi - - cd .. - bundle install - bundle exec pod install --project-directory=ios - - run: - name: Build template project - command: | - xcodebuild build \ - -configuration << parameters.flavor >> \ - -workspace /tmp/$PROJECT_NAME/ios/$PROJECT_NAME.xcworkspace \ - -scheme $PROJECT_NAME \ - -sdk iphonesimulator - - # ------------------------- - # JOBS: Test iOS RNTester - # ------------------------- - test_ios_rntester: - executor: reactnativeios - parameters: - jsengine: - default: "Hermes" - description: Which JavaScript engine to use. Must be one of "Hermes", "JSC". - type: enum - enum: ["Hermes", "JSC"] - architecture: - default: "OldArch" - description: Which React Native architecture to use. Must be one of "OldArch", "NewArch". - type: enum - enum: ["NewArch", "OldArch"] - use_frameworks: - default: "StaticLibraries" - description: The dependency building and linking strategy to use. Must be one of "StaticLibraries", "DynamicFrameworks" - type: enum - enum: ["StaticLibraries", "DynamicFrameworks"] - ruby_version: - default: "2.6.10" - description: The version of ruby that must be used - type: string - steps: - - checkout_code_with_cache - - run_yarn - - *attach_hermes_workspace - - # The macOS machine can run out of storage if Hermes is enabled and built from source. - # Since this job does not use the iOS Simulator, deleting it provides a quick way to - # free up space. - - run: - name: Delete iOS Simulators - background: true - command: sudo rm -rf /Library/Developer/CoreSimulator/Profiles/Runtimes/ - - setup_ruby: - ruby_version: << parameters.ruby_version >> - - with_hermes_tarball_cache_span: - set_tarball_path: True - steps: - - with_xcodebuild_cache: - steps: - - run: - name: Install CocoaPods dependencies - Architecture << parameters.architecture >> - command: | - if [[ << parameters.architecture >> == "NewArch" ]]; then - export RCT_NEW_ARCH_ENABLED=1 - fi - - if [[ << parameters.jsengine >> == "JSC" ]]; then - export USE_HERMES=0 - fi - - if [[ << parameters.use_frameworks >> == "DynamicFrameworks" ]]; then - export NO_FLIPPER=1 - export USE_FRAMEWORKS=dynamic - fi - - cd packages/rn-tester - - bundle install - bundle exec pod install - - run: - name: Build RNTester - command: | - xcodebuild build \ - -workspace packages/rn-tester/RNTesterPods.xcworkspace \ - -scheme RNTester \ - -sdk iphonesimulator - - # ------------------------- - # JOBS: Windows - # ------------------------- - test_windows: - executor: - name: win/default - environment: - - CHOCO_CACHE_DIR: "C:\\ChocoCache" - steps: - - checkout_code_with_cache - - - restore_cache: - keys: - - *windows_choco_cache_key - - - run: - name: Choco cache - # Cache our dependencies which can be flakey to download - command: | - if (!Test-Path $env:CHOCO_CACHE_DIR) { - mkdir $env:CHOCO_CACHE_DIR - } - choco config set --name cacheLocation --value $env:CHOCO_CACHE_DIR - - - run: - name: Disable NVM - # Use choco to manage node versions due to https://github.com/npm/cli/issues/4234 - command: nvm off - - - run: - name: Install Node JS - # Note: Version set separately for non-Windows builds, see above. - command: choco install nodejs-lts - - # Setup Dependencies - - run: - name: Enable Yarn with corepack - command: corepack enable - - # it looks like that, last week, envinfo released version 7.9.0 which does not works - # with Windows. I have opened an issue here: https://github.com/tabrindle/envinfo/issues/238 - # TODO: T156811874 - Revert this to npx envinfo@latest when the issue is addressed - - run: - name: Display Environment info - command: | - npm install -g envinfo - envinfo -v - envinfo - - - restore_cache: - keys: - - *windows_yarn_cache_key - - run: - name: "Yarn: Install Dependencies" - command: yarn install --frozen-lockfile --non-interactive - - - save_cache: - key: *windows_yarn_cache_key - paths: - - C:\Users\circleci\AppData\Local\Yarn - - - save_cache: - key: *windows_choco_cache_key - paths: - - $env:CHOCO_CACHE_DIR - - # ------------------------- - # Run Tests - - run: - name: "Flow: Check Android" - command: yarn flow-check-android - - run: - name: "Flow: Check iOS" - command: yarn flow-check-ios - - run: - name: "Run Tests: JavaScript Tests" - command: yarn test - - # ------------------------- - # JOBS: Build Hermes - # ------------------------- - prepare_hermes_workspace: - docker: - - image: debian:bullseye - environment: - - HERMES_WS_DIR: *hermes_workspace_root - - HERMES_VERSION_FILE: "packages/react-native/sdks/.hermesversion" - - BUILD_FROM_SOURCE: true - steps: - - run: - name: Install dependencies - command: | - apt update - - apt install -y wget git curl jq - curl -sL https://deb.nodesource.com/setup_18.x | bash - - apt install -y nodejs - npm install --global yarn - - checkout - - run: - name: Set up Hermes workspace and caching - command: | - mkdir -p "/tmp/hermes" "/tmp/hermes/download" "/tmp/hermes/hermes" - - if [ -f "$HERMES_VERSION_FILE" ]; then - echo "Hermes Version file found! Using this version for the build:" - cat $HERMES_VERSION_FILE > /tmp/hermes/hermesversion - else - echo "Hermes Version file not found!!!" - echo "Using the last commit from main for the build:" - HERMES_TAG_SHA=$(git ls-remote https://github.com/facebook/hermes main | cut -f 1 | tr -d '[:space:]') - echo $HERMES_TAG_SHA > /tmp/hermes/hermesversion - fi - cat /tmp/hermes/hermesversion - - get_react_native_version - - restore_cache: - key: *hermes_workspace_cache_key - - run_yarn - - run: - name: Download Hermes tarball - command: | - node packages/react-native/scripts/hermes/prepare-hermes-for-build $CIRCLE_PULL_REQUEST - cp packages/react-native/sdks/download/* $HERMES_WS_DIR/download/. - cp -r packages/react-native/sdks/hermes/* $HERMES_WS_DIR/hermes/. - - cat /tmp/hermes/hermesversion - - save_cache: - key: *hermes_workspace_cache_key - paths: - - /tmp/hermes/download/ - - /tmp/hermes/hermes/ - # Check if we already built the tarball - # if yes, we can skip the building and we can skip some jobs building - - restore_cache: - keys: - - *hermes_tarball_release_cache_key - - check_if_tarball_is_present: - flavor: Release - - restore_cache: - keys: - - *hermes_tarball_debug_cache_key - - check_if_tarball_is_present: - flavor: Debug - - restore_cache: - keys: - - *hermes_macosx_bin_release_cache_key - - check_if_osx_bin_is_present: - flavor: Release - - restore_cache: - keys: - - *hermes_macosx_bin_debug_cache_key - - check_if_osx_bin_is_present: - flavor: Debug - - restore_cache: - keys: - - *hermes_dsym_debug_cache_key - - check_if_dsym_are_present: - flavor: Debug - - restore_cache: - keys: - - *hermes_dsym_release_cache_key - - check_if_dsym_are_present: - flavor: Release - - persist_to_workspace: - root: *hermes_workspace_root - paths: - - download - - hermes - - hermes-runtime-darwin - - osx-bin - - dSYM - - hermesversion - - Release_tarball_present - - Debug_tarball_present - - Release_osx_bin - - Debug_osx_bin - - Release_dSYM - - Debug_dSYM - - persist_to_workspace: - root: /tmp - paths: - - react-native-version - - build_hermesc_linux: - docker: - - image: debian:bullseye - resource_class: "large" - steps: - - checkout_code_with_cache - - run: - name: Install dependencies - command: | - apt update - apt install -y git openssh-client cmake build-essential \ - libreadline-dev libicu-dev jq zip python3 - - *attach_hermes_workspace - - get_react_native_version - - restore_cache: - key: *hermes_linux_cache_key - - run: - name: Set up workspace - command: | - mkdir -p /tmp/hermes/linux64-bin - - run: - name: Build HermesC for Linux - command: | - if [ -f /tmp/hermes/linux64-bin/hermesc ]; then - echo 'Skipping; Clean "/tmp/hermes/linux64-bin" to rebuild.' - else - cd /tmp/hermes - cmake -S hermes -B build -DHERMES_STATIC_LINK=ON -DCMAKE_BUILD_TYPE=Release \ - -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DCMAKE_CXX_FLAGS=-s -DCMAKE_C_FLAGS=-s \ - -DCMAKE_EXE_LINKER_FLAGS="-Wl,--whole-archive -lpthread -Wl,--no-whole-archive" - cmake --build build --target check-hermes -j 4 - cp /tmp/hermes/build/bin/hermesc /tmp/hermes/linux64-bin/. - fi - - save_cache: - key: *hermes_linux_cache_key - paths: - - /tmp/hermes/linux64-bin/ - - /tmp/hermes/hermes/destroot/ - - store_artifacts_if_needed: - path: /tmp/hermes/linux64-bin/ - - persist_to_workspace: - root: /tmp/hermes/ - paths: - - linux64-bin - - build_hermesc_apple: - executor: reactnativeios - environment: - - HERMES_WS_DIR: *hermes_workspace_root - - HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir - steps: - - *attach_hermes_workspace - - stop_job_if_apple_artifacts_are_there: - flavor: "All" - - checkout_code_with_cache - - get_react_native_version - - setup_hermes_workspace - - restore_cache: - key: *hermesc_apple_cache_key - - brew_install: - package: cmake - - run: - name: "Build HermesC Apple" - command: | - cd ./packages/react-native/sdks/hermes || exit 1 - . ./utils/build-apple-framework.sh - build_host_hermesc_if_needed - - save_cache: - key: *hermesc_apple_cache_key - paths: - - ./packages/react-native/sdks/hermes/build_host_hermesc - - persist_to_workspace: - root: ./packages/react-native/sdks/hermes/ - paths: - - build_host_hermesc - - build_apple_slices_hermes: - parameters: - slice_base_cache_key: - default: *hermes_apple_slices_cache_key - type: string - flavor: - default: "Debug" - description: The Hermes build type. Must be one of "Debug", "Release". - type: enum - enum: ["Debug", "Release"] - slice: - default: "iphoneos" - description: The Hermes Slice that this job has to build - type: enum - enum: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - executor: reactnativeios - environment: - - HERMES_WS_DIR: *hermes_workspace_root - - HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir - - HERMES_OSXBIN_ARTIFACTS_DIR: *hermes_osxbin_artifacts_dir - steps: - - *attach_hermes_workspace - - stop_job_if_apple_artifacts_are_there: - flavor: << parameters.flavor >> - - checkout_code_with_cache - - get_react_native_version - - setup_hermes_workspace - - restore_cache: - key: *hermesc_apple_cache_key - - brew_install: - package: cmake - - restore_cache: - key: << parameters.slice_base_cache_key >>-<< parameters.slice >>-<< parameters.flavor >> - - run: - name: Build the Hermes << parameters.slice >> frameworks - command: | - cd ./packages/react-native/sdks/hermes || exit 1 - SLICE=<< parameters.slice >> - FLAVOR=<< parameters.flavor >> - FINAL_PATH=build_"$SLICE"_"$FLAVOR" - echo "Final path for this slice is: $FINAL_PATH" - - if [[ -d "$FINAL_PATH" ]]; then - echo "[HERMES] Skipping! Found the requested slice at $FINAL_PATH". - exit 0 - fi - - if [[ "$SLICE" == "macosx" ]]; then - echo "[HERMES] Building Hermes for MacOS" - BUILD_TYPE="<< parameters.flavor >>" ./utils/build-mac-framework.sh - else - echo "[HERMES] Building Hermes for iOS: $SLICE" - BUILD_TYPE="<< parameters.flavor >>" ./utils/build-ios-framework.sh "$SLICE" - fi - - echo "Moving from build_$SLICE to $FINAL_PATH" - mv build_"$SLICE" "$FINAL_PATH" - - save_cache: - key: << parameters.slice_base_cache_key >>-<< parameters.slice >>-<< parameters.flavor >> - paths: - - ./packages/react-native/sdks/hermes/build_<< parameters.slice >>_<< parameters.flavor >> - - build_hermes_macos: - parameters: - slice_base_cache_key: - default: *hermes_apple_slices_cache_key - type: string - flavor: - default: "Debug" - description: The Hermes build type. Must be one of "Debug", "Release". - type: enum - enum: ["Debug", "Release"] - executor: reactnativeios - environment: - - HERMES_WS_DIR: *hermes_workspace_root - - HERMES_TARBALL_ARTIFACTS_DIR: *hermes_tarball_artifacts_dir - steps: - - *attach_hermes_workspace - # Try to store the artifacts if they are already in the workspace - - store_hermes_apple_artifacts: - flavor: << parameters.flavor >> - - stop_job_if_apple_artifacts_are_there: - flavor: << parameters.flavor >> - - checkout_code_with_cache - - run_yarn - - get_react_native_version - - brew_install: - package: cmake - - setup_hermes_workspace - - restore_cache: - key: << parameters.slice_base_cache_key >>-macosx-<< parameters.flavor >> - - restore_cache: - key: << parameters.slice_base_cache_key >>-iphoneos-<< parameters.flavor >> - - restore_cache: - key: << parameters.slice_base_cache_key >>-iphonesimulator-<< parameters.flavor >> - - restore_cache: - key: << parameters.slice_base_cache_key >>-catalyst-<< parameters.flavor >> - - run: - name: "Move back build folders" - command: | - cd ./packages/react-native/sdks/hermes || exit 1 - mv build_macosx_<< parameters.flavor >> build_macosx - mv build_iphoneos_<< parameters.flavor >> build_iphoneos - mv build_iphonesimulator_<< parameters.flavor >> build_iphonesimulator - mv build_catalyst_<< parameters.flavor >> build_catalyst - - run: - name: "Prepare destroot folder" - command: | - cd ./packages/react-native/sdks/hermes || exit 1 - . ./utils/build-apple-framework.sh - prepare_dest_root_for_ci - - run: - name: "Create fat framework for iOS" - command: | - cd ./packages/react-native/sdks/hermes || exit 1 - echo "[HERMES] Creating the universal framework" - ./utils/build-ios-framework.sh build_framework - - run: - name: Package the Hermes Apple frameworks - command: | - BUILD_TYPE="<< parameters.flavor >>" - echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" - - TARBALL_OUTPUT_DIR=$(mktemp -d /tmp/hermes-tarball-output-XXXXXXXX) - - TARBALL_FILENAME=$(node ./packages/react-native/scripts/hermes/get-tarball-name.js --buildType "$BUILD_TYPE") - - echo "Packaging Hermes Apple frameworks for $BUILD_TYPE build type" - - TARBALL_OUTPUT_PATH=$(node ./packages/react-native/scripts/hermes/create-tarball.js \ - --inputDir ./packages/react-native/sdks/hermes \ - --buildType "$BUILD_TYPE" \ - --outputDir $TARBALL_OUTPUT_DIR) - - echo "Hermes tarball saved to $TARBALL_OUTPUT_PATH" - - mkdir -p $HERMES_TARBALL_ARTIFACTS_DIR - cp $TARBALL_OUTPUT_PATH $HERMES_TARBALL_ARTIFACTS_DIR/. - - mkdir -p /tmp/hermes/osx-bin/<< parameters.flavor >> - cp ./packages/react-native/sdks/hermes/build_macosx/bin/* /tmp/hermes/osx-bin/<< parameters.flavor >> - - run: - name: Create dSYM archive - command: | - FLAVOR=<< parameters.flavor >> - WORKING_DIR="/tmp/hermes_tmp/dSYM/$FLAVOR" - - mkdir -p "$WORKING_DIR/macosx" - mkdir -p "$WORKING_DIR/catalyst" - mkdir -p "$WORKING_DIR/iphoneos" - mkdir -p "$WORKING_DIR/iphonesimulator" - - cd ./packages/react-native/sdks/hermes || exit 1 - - DSYM_FILE_PATH=API/hermes/hermes.framework.dSYM - cp -r build_macosx/$DSYM_FILE_PATH "$WORKING_DIR/macosx/" - cp -r build_catalyst/$DSYM_FILE_PATH "$WORKING_DIR/catalyst/" - cp -r build_iphoneos/$DSYM_FILE_PATH "$WORKING_DIR/iphoneos/" - cp -r build_iphonesimulator/$DSYM_FILE_PATH "$WORKING_DIR/iphonesimulator/" - - DEST_DIR="/tmp/hermes/dSYM/$FLAVOR" - tar -C "$WORKING_DIR" -czvf "hermes.framework.dSYM" . - - mkdir -p "$DEST_DIR" - mv "hermes.framework.dSYM" "$DEST_DIR" - - - when: - condition: - equal: [ << parameters.flavor >>, "Debug"] - steps: - - save_cache: - key: *hermes_tarball_debug_cache_key - paths: *hermes_tarball_cache_paths - - save_cache: - key: *hermes_macosx_bin_debug_cache_key - paths: /tmp/hermes/osx-bin/Debug - - save_cache: - key: *hermes_dsym_debug_cache_key - paths: /tmp/hermes/dSYM/Debug - - when: - condition: - equal: [ << parameters.flavor >>, "Release"] - steps: - - save_cache: - key: *hermes_tarball_release_cache_key - paths: *hermes_tarball_cache_paths - - save_cache: - key: *hermes_macosx_bin_release_cache_key - paths: /tmp/hermes/osx-bin/Release - - save_cache: - key: *hermes_dsym_release_cache_key - paths: /tmp/hermes/dSYM/Release - - store_hermes_apple_artifacts: - flavor: << parameters.flavor >> - - persist_to_workspace: - root: /tmp/hermes/ - paths: - - hermes-runtime-darwin - - osx-bin - - dSYM - - build_hermesc_windows: - executor: - name: win/default - shell: powershell.exe - environment: - - HERMES_WS_DIR: 'C:\tmp\hermes' - - ICU_URL: "https://github.com/unicode-org/icu/releases/download/release-64-2/icu4c-64_2-Win64-MSVC2017.zip" - - MSBUILD_DIR: 'C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\MSBuild\Current\Bin' - - CMAKE_DIR: 'C:\Program Files\CMake\bin' - steps: - - checkout_code_with_cache - - *attach_hermes_workspace - - get_react_native_version_windows - - restore_cache: - key: *hermes_windows_cache_key - - run: - name: Set up workspace - command: | - New-Item -ItemType Directory $Env:HERMES_WS_DIR - New-Item -ItemType Directory $Env:HERMES_WS_DIR\icu - New-Item -ItemType Directory $Env:HERMES_WS_DIR\deps - New-Item -ItemType Directory $Env:HERMES_WS_DIR\win64-bin - New-Item -ItemType SymbolicLink -Target tmp\hermes\hermes -Path $Env:HERMES_WS_DIR -Name hermes - - run: - name: Build HermesC for Windows - command: | - if (-not(Test-Path -Path $Env:HERMES_WS_DIR\win64-bin\hermesc.exe)) { - choco install --no-progress cmake --version 3.14.7 - if (-not $?) { throw "Failed to install CMake" } - - cd $Env:HERMES_WS_DIR\icu - # If Invoke-WebRequest shows a progress bar, it will fail with - # Win32 internal error "Access is denied" 0x5 occurred [...] - $progressPreference = 'silentlyContinue' - Invoke-WebRequest -Uri "$Env:ICU_URL" -OutFile "icu.zip" - Expand-Archive -Path "icu.zip" -DestinationPath "." - - cd $Env:HERMES_WS_DIR - Copy-Item -Path "icu\bin64\icu*.dll" -Destination "deps" - # Include MSVC++ 2015 redistributables - Copy-Item -Path "c:\windows\system32\msvcp140.dll" -Destination "deps" - Copy-Item -Path "c:\windows\system32\vcruntime140.dll" -Destination "deps" - Copy-Item -Path "c:\windows\system32\vcruntime140_1.dll" -Destination "deps" - - $Env:PATH += ";$Env:CMAKE_DIR;$Env:MSBUILD_DIR" - $Env:ICU_ROOT = "$Env:HERMES_WS_DIR\icu" - - cmake -S hermes -B build_release -G 'Visual Studio 16 2019' -Ax64 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=True -DHERMES_ENABLE_WIN10_ICU_FALLBACK=OFF - if (-not $?) { throw "Failed to configure Hermes" } - cd build_release - cmake --build . --target hermesc --config Release - if (-not $?) { throw "Failed to build Hermes" } - - cd $Env:HERMES_WS_DIR - Copy-Item -Path "build_release\bin\Release\hermesc.exe" -Destination "win64-bin" - # Include Windows runtime dependencies - Copy-Item -Path "deps\*" -Destination "win64-bin" - } - else { - Write-Host "Skipping; Clean c:\tmp\hermes\win64-bin to rebuild." - } - - save_cache: - key: *hermes_windows_cache_key - paths: - - C:\tmp\hermes\win64-bin\ - - C:\tmp\hermes\hermes\icu\ - - C:\tmp\hermes\hermes\deps\ - - C:\tmp\hermes\hermes\build_release\ - - store_artifacts_if_needed: - path: C:\tmp\hermes\win64-bin\ - - persist_to_workspace: - root: C:\tmp\hermes\ - paths: - - win64-bin - - # ------------------------- - # JOBS: Releases - # ------------------------- - prepare_package_for_release: - parameters: - version: - type: string - latest: - type: boolean - default: false - dryrun: - type: boolean - default: false - executor: reactnativeios - steps: - - checkout_code_with_cache - - run_yarn - - add_ssh_keys: - fingerprints: - - "1f:c7:61:c4:e2:ff:77:e3:cc:ca:a7:34:c2:79:e3:3c" - - brew_install: - package: cmake - - run: - name: "Set new react-native version and commit changes" - command: | - VERSION=<< parameters.version >> - - if [[ -z "$VERSION" ]]; then - VERSION=$(grep '"version"' package.json | cut -d '"' -f 4 | head -1) - echo "Using the version from the package.json: $VERSION" - fi - - node ./scripts/prepare-package-for-release.js -v "$VERSION" -l << parameters.latest >> --dry-run << parameters.dryrun >> - - build_npm_package: - parameters: - release_type: - description: The type of release to build. Must be one of "nightly", "release", "dry-run". - type: enum - enum: ["nightly", "release", "dry-run"] - default: "dry-run" - executor: reactnativeandroid-xlarge - environment: - - HERMES_WS_DIR: *hermes_workspace_root - steps: - - run: - name: Add github.com to SSH known hosts - command: | - mkdir -p ~/.ssh - echo '|1|If6MU203eXTaaWL678YEfWkVMrw=|kqLeIAyTy8pzpj8x8Ae4Fr8Mtlc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts - - checkout - - *attach_hermes_workspace - - run: - name: Copy Hermes binaries - command: | - mkdir -p ./packages/react-native/sdks/hermesc ./packages/react-native/sdks/hermesc/osx-bin ./packages/react-native/sdks/hermesc/win64-bin ./packages/react-native/sdks/hermesc/linux64-bin - - # When build_hermes_macos runs as a matrix, it outputs - if [[ -d $HERMES_WS_DIR/osx-bin/Release ]]; then - cp -r $HERMES_WS_DIR/osx-bin/Release/* ./packages/react-native/sdks/hermesc/osx-bin/. - elif [[ -d $HERMES_WS_DIR/osx-bin/Debug ]]; then - cp -r $HERMES_WS_DIR/osx-bin/Debug/* ./packages/react-native/sdks/hermesc/osx-bin/. - else - ls $HERMES_WS_DIR/osx-bin || echo "hermesc macOS artifacts directory missing." - echo "Could not locate macOS hermesc binary."; exit 1; - fi - - cp -r $HERMES_WS_DIR/win64-bin/* ./packages/react-native/sdks/hermesc/win64-bin/. - cp -r $HERMES_WS_DIR/linux64-bin/* ./packages/react-native/sdks/hermesc/linux64-bin/. - mkdir -p ./packages/react-native/ReactAndroid/external-artifacts/artifacts/ - cp $HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-debug.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-debug.tar.gz - cp $HERMES_WS_DIR/hermes-runtime-darwin/hermes-ios-release.tar.gz ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-ios-release.tar.gz - cp $HERMES_WS_DIR/dSYM/Debug/hermes.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-debug.tar.gz - cp $HERMES_WS_DIR/dSYM/Release/hermes.framework.dSYM ./packages/react-native/ReactAndroid/external-artifacts/artifacts/hermes-framework-dSYM-release.tar.gz - - run_yarn - - build_packages - - attach_workspace: - at: . - - # START: Stables and nightlies - # This conditional step sets up the necessary credentials for publishing react-native to npm. - - when: - condition: - or: - - equal: [ "release", << parameters.release_type >> ] - - equal: [ "nightly", << parameters.release_type >> ] - steps: - - run: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc - # END: Stables and nightlies - - - with_gradle_cache: - steps: - - run: - name: Publish NPM - command: | - # We can't have a separate step because each command is executed in a separate shell - # so variables exported in a command are not visible in another. - if [[ << parameters.release_type >> == "dry-run" ]]; then - export ORG_GRADLE_PROJECT_reactNativeArchitectures="arm64-v8a" - else - export ORG_GRADLE_PROJECT_reactNativeArchitectures="armeabi-v7a,arm64-v8a,x86,x86_64" - fi - node ./scripts/publish-npm.js --<< parameters.release_type >> - - - run: - name: Zip Maven Artifacts from /tmp/maven-local - command: zip -r /tmp/maven-local.zip /tmp/maven-local - - store_artifacts: - path: /tmp/maven-local.zip - - store_artifacts: - path: /root/.npm/_logs - - persist_to_workspace: - root: /tmp - paths: - - maven-local - - # START: Dry-run - # Provide a react-native package for this commit as a Circle CI release artifact. - - when: - condition: - equal: [ "dry-run", << parameters.release_type >> ] - steps: - - run: - name: Build release package as a job artifact - command: | - mkdir -p build - - FILENAME=$(cd packages/react-native; npm pack | tail -1) - mv packages/react-native/$FILENAME build/ - - echo $FILENAME > build/react-native-package-version - - store_artifacts: - path: ~/react-native/build/ - destination: build - - persist_to_workspace: - root: . - paths: - - build/* - # END: Dry-run - - # START: Stable releases - - when: - condition: - equal: [ "release", << parameters.release_type >> ] - steps: - - run: - name: Update rn-diff-purge to generate upgrade-support diff - command: | - curl -X POST https://api.github.com/repos/react-native-community/rn-diff-purge/dispatches \ - -H "Accept: application/vnd.github.v3+json" \ - -H "Authorization: Bearer $REACT_NATIVE_BOT_GITHUB_TOKEN" \ - -d "{\"event_type\": \"publish\", \"client_payload\": { \"version\": \"${CIRCLE_TAG:1}\" }}" - # END: Stable releases - - poll_maven: - docker: - - image: cimg/node:current - resource_class: small - steps: - - checkout_code_with_cache - - run_yarn - - run: - name: Poll Maven for Artifacts - command: | - node scripts/circleci/poll-maven.js - - - # ------------------------- - # JOBS: Nightly - # ------------------------- - nightly_job: - machine: - image: ubuntu-2004:202010-01 - steps: - - run: - name: Nightly - command: | - echo "Nightly build run" - - find_and_publish_bumped_packages: - executor: nodelts - steps: - - checkout - - run_yarn - - build_packages - - run: - name: Set NPM auth token - command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc - - run: - name: Find and publish all bumped packages - command: node ./scripts/monorepo/find-and-publish-all-bumped-packages.js diff --git a/.circleci/configurations/test_workflows/testAll.yml b/.circleci/configurations/test_workflows/testAll.yml deleted file mode 100644 index acdc2e2b43d..00000000000 --- a/.circleci/configurations/test_workflows/testAll.yml +++ /dev/null @@ -1,185 +0,0 @@ - tests: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - prepare_package_for_release: - name: prepare_package_for_release - version: '' - latest : false - dryrun: true - - prepare_hermes_workspace - - build_android: - release_type: "dry-run" - - build_hermesc_linux: - requires: - - prepare_hermes_workspace - - build_hermesc_apple: - requires: - - prepare_hermes_workspace - - build_apple_slices_hermes: - requires: - - build_hermesc_apple - matrix: - parameters: - flavor: ["Debug", "Release"] - slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - - build_hermes_macos: - requires: - - build_apple_slices_hermes - matrix: - parameters: - flavor: ["Debug", "Release"] - - build_hermesc_windows: - requires: - - prepare_hermes_workspace - - build_npm_package: - # Build a release package on every untagged commit, but do not publish to npm. - release_type: "dry-run" - requires: - - build_android - - build_hermesc_linux - - build_hermes_macos - - build_hermesc_windows - - test_android: - requires: - - build_android - - test_android_template: - requires: - - build_npm_package - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - jsengine: ["Hermes", "JSC"] - flavor: ["Debug", "Release"] - - test_ios_template: - requires: - - build_npm_package - name: "Test Template with Ruby 3.2.0" - ruby_version: "3.2.0" - architecture: "NewArch" - flavor: "Debug" - - test_ios_template: - requires: - - build_npm_package - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - flavor: ["Debug", "Release"] - jsengine: ["Hermes", "JSC"] - flipper: ["WithFlipper", "WithoutFlipper"] - use_frameworks: ["StaticLibraries", "DynamicFrameworks"] - exclude: - - architecture: "NewArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "NewArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "NewArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "OldArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "OldArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "OldArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - test_ios_rntester: - requires: - - build_hermes_macos - name: "Test RNTester with Ruby 3.2.0" - ruby_version: "3.2.0" - architecture: "NewArch" - - test_ios_rntester: - requires: - - build_hermes_macos - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - jsengine: ["Hermes", "JSC"] - use_frameworks: ["StaticLibraries", "DynamicFrameworks"] - exclude: - # Tested by test_ios-Hermes - - architecture: "OldArch" - jsengine: "Hermes" - use_frameworks: "StaticLibraries" - # Tested by test_ios-JSC - - architecture: "OldArch" - jsengine: "JSC" - use_frameworks: "StaticLibraries" - - test_ios: - name: "Test iOS with Ruby 3.2.0" - run_unit_tests: true - requires: - - build_hermes_macos - ruby_version: "3.2.0" - - test_ios: - run_unit_tests: true - requires: - - build_hermes_macos - matrix: - parameters: - jsengine: ["Hermes", "JSC"] - - test_windows diff --git a/.circleci/configurations/test_workflows/testAndroid.yml b/.circleci/configurations/test_workflows/testAndroid.yml deleted file mode 100644 index b21ed9775fc..00000000000 --- a/.circleci/configurations/test_workflows/testAndroid.yml +++ /dev/null @@ -1,57 +0,0 @@ - tests_android: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - prepare_package_for_release: - name: prepare_package_for_release - version: '' - latest : false - dryrun: true - - prepare_hermes_workspace - - build_android: - release_type: "dry-run" - - build_hermesc_linux: - requires: - - prepare_hermes_workspace - - build_hermesc_apple: - requires: - - prepare_hermes_workspace - - build_apple_slices_hermes: - requires: - - build_hermesc_apple - matrix: - parameters: - flavor: ["Debug", "Release"] - slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - - build_hermes_macos: - requires: - - build_apple_slices_hermes - matrix: - parameters: - flavor: ["Debug", "Release"] - - build_hermesc_windows: - requires: - - prepare_hermes_workspace - - build_npm_package: - # Build a release package on every untagged commit, but do not publish to npm. - release_type: "dry-run" - requires: - - build_android - - build_hermesc_linux - - build_hermes_macos - - build_hermesc_windows - - test_android: - requires: - - build_android - - test_e2e_android - - test_android_template: - requires: - - build_npm_package - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - jsengine: ["Hermes", "JSC"] - flavor: ["Debug", "Release"] - - test_windows diff --git a/.circleci/configurations/test_workflows/testE2E.yml b/.circleci/configurations/test_workflows/testE2E.yml deleted file mode 100644 index 998abf796ff..00000000000 --- a/.circleci/configurations/test_workflows/testE2E.yml +++ /dev/null @@ -1,9 +0,0 @@ - tests_e2e: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - test_e2e_ios: - ruby_version: "2.7.7" - - test_e2e_android diff --git a/.circleci/configurations/test_workflows/testIOS.yml b/.circleci/configurations/test_workflows/testIOS.yml deleted file mode 100644 index f93aeefa817..00000000000 --- a/.circleci/configurations/test_workflows/testIOS.yml +++ /dev/null @@ -1,175 +0,0 @@ - test_ios: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - prepare_package_for_release: - name: prepare_package_for_release - version: '' - latest : false - dryrun: true - - prepare_hermes_workspace - - build_android: - release_type: "dry-run" - - build_hermesc_linux: - requires: - - prepare_hermes_workspace - - build_hermesc_apple: - requires: - - prepare_hermes_workspace - - build_apple_slices_hermes: - requires: - - build_hermesc_apple - matrix: - parameters: - flavor: ["Debug", "Release"] - slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - - build_hermes_macos: - requires: - - build_apple_slices_hermes - matrix: - parameters: - flavor: ["Debug", "Release"] - - build_hermesc_windows: - requires: - - prepare_hermes_workspace - - build_npm_package: - # Build a release package on every untagged commit, but do not publish to npm. - release_type: "dry-run" - requires: - - build_android - - build_hermesc_linux - - build_hermes_macos - - build_hermesc_windows - - test_e2e_ios: - ruby_version: "2.7.7" - - test_ios_template: - requires: - - build_npm_package - name: "Test Template with Ruby 3.2.0" - ruby_version: "3.2.0" - architecture: "NewArch" - flavor: "Debug" - - test_ios_template: - requires: - - build_npm_package - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - flavor: ["Debug", "Release"] - jsengine: ["Hermes", "JSC"] - flipper: ["WithFlipper", "WithoutFlipper"] - use_frameworks: ["StaticLibraries", "DynamicFrameworks"] - exclude: - - architecture: "NewArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "NewArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "NewArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "OldArch" - flavor: "Release" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "OldArch" - flavor: "Release" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "OldArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "DynamicFrameworks" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "Hermes" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "NewArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - architecture: "OldArch" - flavor: "Debug" - jsengine: "JSC" - flipper: "WithFlipper" - use_frameworks: "StaticLibraries" - - test_ios_rntester: - requires: - - build_hermes_macos - name: "Test RNTester with Ruby 3.2.0" - ruby_version: "3.2.0" - architecture: "NewArch" - - test_ios_rntester: - requires: - - build_hermes_macos - matrix: - parameters: - architecture: ["NewArch", "OldArch"] - jsengine: ["Hermes", "JSC"] - use_frameworks: ["StaticLibraries", "DynamicFrameworks"] - exclude: - # Tested by test_ios-Hermes - - architecture: "OldArch" - jsengine: "Hermes" - use_frameworks: "StaticLibraries" - # Tested by test_ios-JSC - - architecture: "OldArch" - jsengine: "JSC" - use_frameworks: "StaticLibraries" - - test_ios: - name: "Test iOS with Ruby 3.2.0" - run_unit_tests: true - requires: - - build_hermes_macos - ruby_version: "3.2.0" - - test_ios: - run_unit_tests: true - requires: - - build_hermes_macos - matrix: - parameters: - jsengine: ["Hermes", "JSC"] diff --git a/.circleci/configurations/test_workflows/testJS.yml b/.circleci/configurations/test_workflows/testJS.yml deleted file mode 100644 index 6c5ea93e1c7..00000000000 --- a/.circleci/configurations/test_workflows/testJS.yml +++ /dev/null @@ -1,11 +0,0 @@ - tests_js: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - test_js: - run_disabled_tests: false - - test_js: - name: test_js_prev_lts - executor: nodeprevlts diff --git a/.circleci/configurations/top_level.yml b/.circleci/configurations/top_level.yml deleted file mode 100644 index d2b64fba13e..00000000000 --- a/.circleci/configurations/top_level.yml +++ /dev/null @@ -1,147 +0,0 @@ -version: 2.1 - -# ------------------------- -# ORBS -# ------------------------- - -orbs: - win: circleci/windows@2.4.0 - android: circleci/android@2.3.0 - -# ------------------------- -# REFERENCES -# ------------------------- -references: - defaults: &defaults - working_directory: ~/react-native - environment: - - GIT_COMMIT_DESC: git log --format=oneline -n 1 $CIRCLE_SHA1 - # The public github tokens are publicly visible by design - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: &github_analysisbot_token_a "312d354b5c36f082cfe9" - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: &github_analysisbot_token_b "07973d757026bdd9f196" - # Homebrew currently breaks while updating: - # https://discuss.circleci.com/t/brew-install-fails-while-updating/32992 - - HOMEBREW_NO_AUTO_UPDATE: 1 - android-defaults: &android-defaults - working_directory: ~/react-native - docker: - - image: reactnativecommunity/react-native-android:v11.0 - environment: - - TERM: "dumb" - - GRADLE_OPTS: '-Dorg.gradle.daemon=false' - # By default we only build ARM64 to save time/resources. For release/nightlies, we override this value to build all archs. - - ORG_GRADLE_PROJECT_reactNativeArchitectures: "arm64-v8a" - # Repeated here, as the environment key in this executor will overwrite the one in defaults - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_A: *github_analysisbot_token_a - - PUBLIC_ANALYSISBOT_GITHUB_TOKEN_B: *github_analysisbot_token_b - - hermes_workspace_root: &hermes_workspace_root - /tmp/hermes - hermes_tarball_artifacts_dir: &hermes_tarball_artifacts_dir - /tmp/hermes/hermes-runtime-darwin - hermes_osxbin_artifacts_dir: &hermes_osxbin_artifacts_dir - /tmp/hermes/osx-bin - attach_hermes_workspace: &attach_hermes_workspace - attach_workspace: - at: *hermes_workspace_root - xcodebuild_derived_data_path: &xcodebuild_derived_data_path - ~/Library/Developer/Xcode/DerivedData/ - - main_or_stable_only: &main_or_stable_only - filters: - branches: - only: - - main - - /0\.[0-9]+[\.[0-9]+]?-stable/ - - - # ------------------------- - # Dependency Anchors - # ------------------------- - dependency_versions: - xcode_version: &xcode_version "14.3.0" - nodelts_image: &nodelts_image "cimg/node:20.2.0" - nodeprevlts_image: &nodeprevlts_image "cimg/node:18.12.1" - nodelts_browser_image: &nodelts_browser_image "cimg/node:20.2.0-browsers" - - # ------------------------- - # Cache Key Anchors - # ------------------------- - # Anchors for the cache keys - - cache_keys: - checkout_cache_key: &checkout_cache_key v1-checkout - gems_cache_key: &gems_cache_key v1-gems-{{ checksum "Gemfile.lock" }} - gradle_cache_key: &gradle_cache_key v3-gradle-{{ .Environment.CIRCLE_JOB }}-{{ checksum "gradle/wrapper/gradle-wrapper.properties" }}-{{ checksum "packages/react-native/ReactAndroid/gradle.properties" }} - yarn_cache_key: &yarn_cache_key v6-yarn-cache-{{ .Environment.CIRCLE_JOB }} - rbenv_cache_key: &rbenv_cache_key v1-rbenv-{{ checksum "/tmp/required_ruby" }} - hermes_workspace_cache_key: &hermes_workspace_cache_key v5-hermes-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/hermes/hermesversion" }} - hermes_workspace_debug_cache_key: &hermes_workspace_debug_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }} - hermes_workspace_release_cache_key: &hermes_workspace_release_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }} - hermes_linux_cache_key: &hermes_linux_cache_key v1-hermes-{{ .Environment.CIRCLE_JOB }}-linux-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_windows_cache_key: &hermes_windows_cache_key v2-hermes-{{ .Environment.CIRCLE_JOB }}-windows-{{ checksum "/Users/circleci/project/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - # Hermes iOS - hermesc_apple_cache_key: &hermesc_apple_cache_key v2-hermesc-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_apple_slices_cache_key: &hermes_apple_slices_cache_key v2-hermes-apple-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }}-{{ checksum "packages/react-native/sdks/hermes-engine/utils/build-apple-framework.sh" }} - hermes_tarball_debug_cache_key: &hermes_tarball_debug_cache_key v4-hermes-tarball-debug-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_tarball_release_cache_key: &hermes_tarball_release_cache_key v3-hermes-tarball-release-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_macosx_bin_release_cache_key: &hermes_macosx_bin_release_cache_key v1-hermes-release-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_macosx_bin_debug_cache_key: &hermes_macosx_bin_debug_cache_key v1-hermes-debug-macosx-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_dsym_debug_cache_key: &hermes_dsym_debug_cache_key v1-hermes-debug-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - hermes_dsym_release_cache_key: &hermes_dsym_release_cache_key v1-hermes-release-dsym-{{ checksum "/tmp/hermes/hermesversion" }}-{{ checksum "/tmp/react-native-version" }} - # Cocoapods - RNTester - pods_cache_key: &pods_cache_key v10-pods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock.bak" }}-{{ checksum "packages/rn-tester/Podfile" }} - cocoapods_cache_key: &cocoapods_cache_key v7-cocoapods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile.lock" }}-{{ checksum "packages/rn-tester/Podfile" }} - rntester_podfile_lock_cache_key: &rntester_podfile_lock_cache_key v5-podfilelock-{{ .Environment.CIRCLE_JOB }}-{{ checksum "packages/rn-tester/Podfile" }}-{{ checksum "/tmp/week_year" }} - - # Cocoapods - Template - template_cocoapods_cache_key: &template_cocoapods_cache_key v1-cocoapods-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile.lock" }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }} - template_podfile_lock_cache_key: &template_podfile_lock_cache_key v1-podfilelock-{{ .Environment.CIRCLE_JOB }}-{{ checksum "/tmp/iOSTemplateProject/ios/Podfile" }}-{{ checksum "/tmp/week_year" }} - - # Windows - windows_yarn_cache_key: &windows_yarn_cache_key v1-win-yarn-cache-{{ arch }}-{{ checksum "yarn.lock" }} - windows_choco_cache_key: &windows_choco_cache_key v1-win-choco-cache-{{ .Environment.CIRCLE_JOB }} - - - cache_paths: - hermes_workspace_macos_cache_paths: &hermes_workspace_macos_cache_paths - - ~/react-native/packages/react-native/sdks/hermes/build_macosx - - ~/react-native/packages/react-native/sdks/hermes/destroot - hermes_tarball_cache_paths: &hermes_tarball_cache_paths - - *hermes_tarball_artifacts_dir - - # ------------------------- - # Filters - # ------------------------- - # CircleCI filters are OR-ed, with all branches triggering by default and tags excluded by default - # CircleCI env-vars are only set with the branch OR tag that triggered the job, not both. - - # In this case, CIRCLE_BRANCH is unset, but CIRCLE_TAG is set. - only_release_tags: &only_release_tags - # Both of the following conditions must be included! - # Ignore any commit on any branch by default. - branches: - ignore: /.*/ - # Only act on version tags. - tags: - only: /v[0-9]+(\.[0-9]+)*(\-rc(\.[0-9]+)?)?/ - -# ------------------------- -# PIPELINE PARAMETERS -# ------------------------- -parameters: - run_release_workflow: - default: false - type: boolean - - release_latest: - default: false - type: boolean - - release_version: - default: "9999" - type: string - - run_nightly_workflow: - default: false - type: boolean diff --git a/.circleci/configurations/workflows.yml b/.circleci/configurations/workflows.yml deleted file mode 100644 index 4b346cb78fa..00000000000 --- a/.circleci/configurations/workflows.yml +++ /dev/null @@ -1,132 +0,0 @@ -# ------------------------- -# WORKFLOWS -# -# When creating a new workflow, make sure to include condition: -# -# when: -# and: -# - equal: [ false, << pipeline.parameters.run_release_workflow >> ] -# - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] -# -# It's setup this way so we can trigger a release via a POST -# See limitations: https://support.circleci.com/hc/en-us/articles/360050351292-How-to-trigger-a-workflow-via-CircleCI-API-v2 -# ------------------------- - -workflows: - version: 2 - - # This workflow should only be triggered by release script - package_release: - when: << pipeline.parameters.run_release_workflow >> - jobs: - # This job will push a tag that will trigger the publish_release workflow - - prepare_package_for_release: - name: prepare_package_for_release - version: << pipeline.parameters.release_version >> - latest : << pipeline.parameters.release_latest >> - - # This job will run only when a tag is published due to all the jobs being filtered. - publish_release: - jobs: - - prepare_hermes_workspace: - filters: *only_release_tags - - build_android: - filters: *only_release_tags - name: build_android_for_release - release_type: "release" - - build_hermesc_linux: - filters: *only_release_tags - requires: - - prepare_hermes_workspace - - build_hermesc_apple: - filters: *only_release_tags - requires: - - prepare_hermes_workspace - - build_apple_slices_hermes: - requires: - - build_hermesc_apple - matrix: - parameters: - flavor: ["Debug", "Release"] - slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - - build_hermesc_windows: - filters: *only_release_tags - requires: - - prepare_hermes_workspace - - build_hermes_macos: - requires: - - build_apple_slices_hermes - matrix: - parameters: - flavor: ["Debug", "Release"] - # This job will trigger when a version tag is pushed (by package_release) - - build_npm_package: - name: build_and_publish_npm_package - release_type: "release" - filters: *only_release_tags - requires: - - build_android_for_release - - build_hermesc_linux - - build_hermes_macos - - build_hermesc_windows - - poll_maven: - requires: - - build_and_publish_npm_package - - analysis: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - # Run lints on every commit - - analyze_code - - # Run code checks on PRs - - analyze_pr - - nightly: - when: << pipeline.parameters.run_nightly_workflow >> - jobs: - - nightly_job - - prepare_hermes_workspace - - build_android: - release_type: "nightly" - - build_hermesc_linux: - requires: - - prepare_hermes_workspace - - build_hermesc_apple: - requires: - - prepare_hermes_workspace - - build_apple_slices_hermes: - requires: - - build_hermesc_apple - matrix: - parameters: - flavor: ["Debug", "Release"] - slice: ["macosx", "iphoneos", "iphonesimulator", "catalyst"] - - build_hermesc_windows: - requires: - - prepare_hermes_workspace - - build_hermes_macos: - requires: - - build_apple_slices_hermes - matrix: - parameters: - flavor: ["Debug", "Release"] - - build_npm_package: - release_type: "nightly" - requires: - - build_android - - build_hermesc_linux - - build_hermes_macos - - build_hermesc_windows - - publish_bumped_packages: - when: - and: - - equal: [ false, << pipeline.parameters.run_release_workflow >> ] - - equal: [ false, << pipeline.parameters.run_nightly_workflow >> ] - jobs: - - find_and_publish_bumped_packages: - <<: *main_or_stable_only diff --git a/.gitignore b/.gitignore index 05a5f92aa7b..ce1c26d86ac 100644 --- a/.gitignore +++ b/.gitignore @@ -151,6 +151,3 @@ package-lock.json # E2E files /packages/rn-tester-e2e/apps/*.apk /packages/rn-tester-e2e/apps/*.app - -# CircleCI -.circleci/generated_config.yml diff --git a/scripts/circleci/pipeline_selection.js b/scripts/circleci/pipeline_selection.js deleted file mode 100644 index 7ce5796c88a..00000000000 --- a/scripts/circleci/pipeline_selection.js +++ /dev/null @@ -1,292 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - * - * @format - */ - -/** - * This script is meant to be used only in CircleCI to compute which tests we should execute - * based on the files modified by the commit. - */ - -const fs = require('fs'); -const yargs = require('yargs'); -const fetch = require('node-fetch'); - -/** - * Check whether the filename is a JS/TS file and not in the script folder - */ -function isJSChange(name) { - const isJS = - name.endsWith('.js') || - name.endsWith('.jsx') || - name.endsWith('.ts') || - name.endsWith('.tsx'); - const notAScript = name.indexOf('scripts/') < 0; - return isJS && notAScript; -} - -function isIOS(name) { - return ( - name.indexOf('React/') > -1 || - name.endsWith('.rb') || - name.endsWith('.podspec') - ); -} - -/** - * This maps some high level pipelines to some conditions. - * If those conditions are true, we are going to run the associated pipeline in CI. - * So, for example, is the commit the CI is analyzing only contains changes in the React/ folder or changes to ruby files - * the RUN_IOS flag will be turned on and we will run only the CI suite for iOS tests. - * - * This mapping is not final and we can update it with more pipelines or we can update the filter condition in the future. - */ -const mapping = [ - { - name: 'RUN_IOS', - filterFN: name => isIOS(name), - }, - { - name: 'RUN_ANDROID', - filterFN: name => name.indexOf('ReactAndroid/') > -1, - }, - { - name: 'RUN_E2E', - filterFN: name => name.indexOf('rn-tester-e2e/') > -1, - }, - { - name: 'RUN_JS', - filterFN: name => isJSChange(name), - }, - { - name: 'SKIP', - filterFN: name => name.endsWith('.md'), - }, -]; - -// ===== // -// Yargs // -// ===== // - -const createConfigsOption = { - input_path: { - alias: 'i', - describe: 'The path to the folder where the Config parts are located', - default: '.circleci/configurations', - }, - output_path: { - alias: 'o', - describe: 'The path where the `generated_config.yml` will be created', - default: '.circleci', - }, - config_file: { - alias: 'c', - describe: 'The configuration file with the parameter to set', - default: '/tmp/circleci/pipeline_config.json', - }, -}; - -const filterJobsOptions = { - github_token: { - alias: 't', - describe: 'The token to perform query to github', - demandOption: true, - }, - pr_number: { - alias: 'n', - describe: 'The PR number', - demandOption: true, - }, - username: { - alias: 'u', - describe: 'The username of the person creating the PR', - demandOption: true, - }, - output_path: { - alias: 'o', - ddescribe: 'The output path for the configurations', - default: '/tmp/circleci', - }, -}; - -yargs - .command( - 'create-configs', - 'Creates the circleci config from its files', - createConfigsOption, - argv => createConfigs(argv.input_path, argv.output_path, argv.config_file), - ) - .command( - 'filter-jobs', - 'Filters the jobs based on the list of chaged files in the PR', - filterJobsOptions, - argv => - filterJobs( - argv.github_token, - argv.pr_number, - argv.username, - argv.output_path, - ).then(() => console.info('Filtering done!')), - ) - .demandCommand() - .strict() - .help().argv; - -// ============== // -// GITHUB UTILS // -// ============== // - -function _githubHeaders(githubToken, username) { - return { - Authorization: `token ${githubToken}`, - Accept: 'application/vnd.github.v3+json', - 'User-Agent': `${username}`, - }; -} - -function _queryOptions(githubToken, username) { - return { - method: 'GET', - headers: _githubHeaders(githubToken, username), - }; -} - -async function _performRequest(url, options) { - const response = await fetch(url, options); - if (!response.ok) { - throw new Error( - `Request failed with status ${response.status}\n${response.statusText}`, - ); - } - return await response.json(); -} - -async function _getNumberOfFiles(githubToken, prNumber, username) { - const url = `https://api.github.com/repos/facebook/react-native/pulls/${prNumber}`; - const options = _queryOptions(githubToken, username); - const body = await _performRequest(url, options); - - return body.changed_files; -} - -async function _getFilesFromPR(githubToken, prNumber, username, numberOfFiles) { - const url = `https://api.github.com/repos/facebook/react-native/pulls/${prNumber}/files?page=`; - const options = _queryOptions(githubToken, username); - const numberOfPages = numberOfFiles / 30 + 1; - let allFiles = []; - for (let page = 1; page <= numberOfPages; page++) { - const body = await _performRequest(`${url}${page}`, options); - files = body.map(f => f.filename); - allFiles = allFiles.concat(files); - } - - return allFiles; -} - -async function _computeAndSavePipelineParameters(pipelineType, outputPath) { - fs.mkdirSync(outputPath, {recursive: true}); - const filePath = `${outputPath}/pipeline_config.json`; - - if (pipelineType === 'SKIP') { - fs.writeFileSync(filePath, JSON.stringify({}, null, 2)); - return; - } - - if (pipelineType === 'ALL') { - fs.writeFileSync(filePath, JSON.stringify({run_all: true}, null, 2)); - return; - } - - const params = { - run_all: false, - run_ios: pipelineType === 'RUN_IOS', - run_android: pipelineType === 'RUN_ANDROID', - run_js: pipelineType === 'RUN_JS', - run_e2e: pipelineType === 'RUN_E2E' || pipelineType === 'RUN_JS', - }; - - const stringifiedParams = JSON.stringify(params, null, 2); - fs.writeFileSync(filePath, stringifiedParams); - console.info(`Generated params:\n${stringifiedParams}`); -} - -// ============== // -// COMMANDS // -// ============== // - -function createConfigs(inputPath, outputPath, configFile) { - // Order is important! - const baseConfigFiles = [ - 'top_level.yml', - 'executors.yml', - 'commands.yml', - 'jobs.yml', - 'workflows.yml', - ]; - - const baseFolder = 'test_workflows'; - const testConfigs = { - run_ios: ['testIOS.yml'], - run_android: ['testAndroid.yml'], - run_e2e: ['testE2E.yml'], - run_all: ['testE2E.yml', 'testJS.yml', 'testAll.yml'], - run_js: ['testJS.yml'], - }; - - if (!fs.existsSync(configFile)) { - throw new Error(`Config file: ${configFile} does not exists`); - } - - const jsonParams = JSON.parse(fs.readFileSync(configFile)); - let configurationPartsFiles = baseConfigFiles; - - for (const [key, shouldTest] of Object.entries(jsonParams)) { - if (shouldTest) { - const mappedFiles = testConfigs[key].map(f => `${baseFolder}/${f}`); - configurationPartsFiles = configurationPartsFiles.concat(mappedFiles); - } - } - console.log(configurationPartsFiles); - let configParts = []; - configurationPartsFiles.forEach(yamlPart => { - const fileContent = fs.readFileSync(`${inputPath}/${yamlPart}`); - configParts.push(fileContent); - }); - console.info(`writing to: ${outputPath}/generated_config.yml`); - fs.writeFileSync( - `${outputPath}/generated_config.yml`, - configParts.join('\n'), - ); -} - -async function filterJobs(githubToken, prNumber, username, outputPath) { - const numberOfFiles = await _getNumberOfFiles( - githubToken, - prNumber, - username, - ); - const fileList = await _getFilesFromPR( - githubToken, - prNumber, - username, - numberOfFiles, - ); - - if (fileList.length === 0) { - await _computeAndSavePipelineParameters('SKIP', outputPath); - return; - } - - for (const filter of mapping) { - const found = fileList.every(filter.filterFN); - if (found) { - await _computeAndSavePipelineParameters(filter.name, outputPath); - return; - } - } - await _computeAndSavePipelineParameters('ALL', outputPath); -}