onnxruntime/tools/ci_build/github/azure-pipelines/templates/react-native-ci.yml
Scott McKay ae211999dd
Attempt to make the usage of the Android emulator in CIs more robust (#17903)
### Description
<!-- Describe your changes. -->
Android emulator usage updates:
- Change approach to detecting boot has completed
- use `-delay-adb` and a simple command (`ls`) with `wait-for-device` as
the first step
    - this ensures enough startup has occurred for adb to be responsive
- use secondary loop on the python side to check for sys.boot_completed
to be set
- doing the check on the python side provides more feedback and seems to
work well
- make the 'stop' logic more precise by using psutil
- add internal timeout of 20 mins for emulator startup
  - waiting for the CI jobs overall timeout is way too long
- value is hardcoded for now (most CIs startup in under 10 mins) but
could be made configurable if needed

CI updates:
- add template for using the Android emulator
  - update CIs to use template
- reorder React Native CI
- minimize the time the Android emulator or iOS simulator is running by
moving some build steps around
  - don't run both at the same time
- unnecessary and potentially adds significant memory pressure to the
machine
- fix QNN Android emulator CI as much as possible
- now everything works apart from running onnx_test_runner with the QNN
EP

### Motivation and Context
<!-- - Why is this change required? What problem does it solve?
- If it fixes an open issue, please link to the issue here. -->
Fix inconsistent detection of the emulator boot completing.

---------

Co-authored-by: Edward Chen <18449977+edgchen1@users.noreply.github.com>
2023-10-15 08:42:36 +10:00

394 lines
15 KiB
YAML

parameters:
- name: NpmPackagingMode
displayName: 'NPM packages publish configuration'
type: string
default: 'dev'
- name: BuildConfig
displayName: 'Build config'
type: string
values:
- 'Release'
- 'MinSizeRel'
- 'Debug'
- 'RelWithDebugInfo'
default: 'Release'
- name: PoolName
displayName: 'Pool name'
type: string
- name: PackageName
displayName: 'Package name'
type: string
default: 'NPM_packages'
- name: BuildAndroidAARStageDependsOn
displayName: 'Stage the Build Android AAR stage depends on'
type: string
default: ''
stages:
- stage: Build_Android_AAR
displayName: Build Android AAR
dependsOn: '${{parameters.BuildAndroidAARStageDependsOn}}'
jobs:
- template: android-java-api-aar.yml
parameters:
buildConfig: '${{parameters.BuildConfig}}'
# Mobile build:
# buildSettings: '$(Build.SourcesDirectory)/tools/ci_build/github/js/react_native_e2e_mobile_aar_build_settings.json'
# includedOpsConfig: '$(Build.SourcesDirectory)/tools/ci_build/github/android/mobile_package.required_operators.config'
# artifactName: 'onnxruntime-android-mobile-aar'
# packageName: 'onnxruntime-mobile'
buildSettings: '$(Build.SourcesDirectory)/tools/ci_build/github/js/react_native_e2e_full_aar_build_settings.json'
artifactName: 'onnxruntime-android-full-aar'
job_name_suffix: 'For_React_Native'
pool_name: '${{parameters.PoolName}}'
packageName: 'onnxruntime-android'
- stage: ReactNative_CI
displayName: React Native CI
dependsOn:
- Build_Android_AAR
jobs:
- job: ReactNative_CI
pool:
# We need macOS-12 to run the Android emulator for now.
# https://github.com/actions/runner-images/issues/7671
vmImage: 'macOS-12'
variables:
runCodesignValidationInjection: false
TODAY: $[format('{0:dd}{0:MM}{0:yyyy}', pipeline.startTime)]
PROTO_CACHE_DIR: '$(Pipeline.Workspace)/ccache_proto'
ORT_CACHE_DIR: '$(Pipeline.Workspace)/ccache_ort'
timeoutInMinutes: 180
steps:
- task: mspremier.PostBuildCleanup.PostBuildCleanup-task.PostBuildCleanup@3
displayName: Clean Agent Directories
condition: always()
- task: UsePythonVersion@0
displayName: Use python 3.9
inputs:
versionSpec: "3.9"
addToPath: true
architecture: "x64"
- task: JavaToolInstaller@0
displayName: Use jdk 11
inputs:
versionSpec: '11'
jdkArchitectureOption: 'x64'
jdkSourceOption: 'PreInstalled'
- task: NodeTool@0
inputs:
versionSpec: '18.x'
- script:
brew install coreutils ninja npm yarn
displayName: Install coreutils, ninja, npm, and yarn
- script:
yarn global add detox-cli
displayName: Install detox cli tools
- script:
brew tap wix/brew
displayName: brew tap wix/brew
- script:
brew install applesimutils
displayName: Install applesimutils tools required by detox ios
- script: |
python -m pip install -q flatbuffers
displayName: Install python modules
- template: mac-build-step-with-cache.yml
parameters:
WithCache: true
Today: $(TODAY)
AdditionalKey: ' protobuf | "$(Agent.OS)" | $(Build.SourcesDirectory)/cmake/deps.txt, $(Build.SourcesDirectory)/tools/ci_build/github/linux/docker/inference/x64/python/cpu/scripts/install_protobuf.sh'
CacheDir: $(PROTO_CACHE_DIR)
ChangeEveryCommit: false
BuildStep:
- script: |
set -e -x
$(Build.SourcesDirectory)/tools/ci_build/github/linux/docker/inference/x64/python/cpu/scripts/install_protobuf.sh -d $(Build.SourcesDirectory)/cmake/deps.txt -p $(Build.BinariesDirectory)/installed
displayName: Build protobuf
env:
CCACHE_DIR: $(PROTO_CACHE_DIR)
- template: mac-build-step-with-cache.yml
parameters:
WithCache: true
Today: $(TODAY)
AdditionalKey: react_${{parameters.BuildConfig}}
CacheDir: $(ORT_CACHE_DIR)
BuildStep:
- script: |
set -e -x
python $(Build.SourcesDirectory)/tools/ci_build/github/apple/build_and_assemble_ios_pods.py \
--build-dir "$(Build.BinariesDirectory)/ios_framework_full" \
--staging-dir "$(Build.BinariesDirectory)/staging" \
--variant Full \
--build-settings-file $(Build.SourcesDirectory)/tools/ci_build/github/js/react_native_e2e_full_ios_framework_build_settings.json \
-b="--path_to_protoc_exe" -b "$(Build.BinariesDirectory)/installed/bin/protoc"
# Mobile build:
# python $(Build.SourcesDirectory)/tools/ci_build/github/apple/build_and_assemble_ios_pods.py \
# --build_dir $(Build.BinariesDirectory)/ios_framework_mobile \
# --staging-dir "$(Build.BinariesDirectory)/staging" \
# --include_ops_by_config $(Build.SourcesDirectory)/tools/ci_build/github/android/mobile_package.required_operators.config \
# --variant Mobile \
# --build-settings-file $(Build.SourcesDirectory)/tools/ci_build/github/js/react_native_e2e_mobile_ios_framework_build_settings.json \
# -b="--path_to_protoc_exe" -b "$(Build.BinariesDirectory)/installed/bin/protoc"
displayName: Build iOS package and assemble pods
env:
CC: clang
CXX: clang++
CCACHE_CPP2: 1
CCACHE_DEPEND: 1
CCACHE_SLOPPINESS: modules
CCACHE_DIR: $(ORT_CACHE_DIR)
- task: DownloadPipelineArtifact@2
inputs:
buildType: 'current'
# Mobile build:
# artifactName: 'onnxruntime-android-mobile-aar'
# targetPath: '$(Build.BinariesDirectory)/android-mobile-aar'
artifactName: 'onnxruntime-android-full-aar'
targetPath: '$(Build.BinariesDirectory)/android-full-aar'
displayName: Download Android AAR artifacts
- task: CopyFiles@2
inputs:
# Mobile build:
# sourceFolder: $(Build.BinariesDirectory)/android-mobile-aar
# contents: onnxruntime-mobile-*.aar
sourceFolder: $(Build.BinariesDirectory)/android-full-aar
contents: onnxruntime-android-*.aar
targetFolder: $(Build.SourcesDirectory)/js/react_native/android/libs
displayName: Copy Android package to React Native directory
- script: |
npm ci
workingDirectory: '$(Build.SourcesDirectory)/js'
displayName: npm ci js
- script: |
npm ci
workingDirectory: '$(Build.SourcesDirectory)/js/common'
displayName: npm ci js/common
- script: |
yarn
workingDirectory: '$(Build.SourcesDirectory)/js/react_native'
displayName: yarn js/react_native
- task: PowerShell@2
inputs:
filePath: '$(Build.SourcesDirectory)/tools/ci_build/github/js/pack-npm-packages.ps1'
arguments: '"-dev.$(Get-Date -Format yyyyMMdd)-$(git rev-parse --short HEAD)" $(Build.SourcesDirectory) react_native'
workingDirectory: '$(Build.SourcesDirectory)'
errorActionPreference: stop
env:
ORT_JS_PACK_MODE: e2e
displayName: Pack NPM packages
- script: |
mv $(Build.SourcesDirectory)/js/common/onnxruntime-common*.tgz onnxruntime-common.tgz
yarn add --no-lockfile file:./onnxruntime-common.tgz
mv $(Build.SourcesDirectory)/js/react_native/onnxruntime-react-native*.tgz onnxruntime-react-native.tgz
yarn add --no-lockfile file:./onnxruntime-react-native.tgz
yarn
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e'
displayName: Bootstrap Android and iOS e2e tests
- script: |
# Mobile build:
# ORT_MOBILE_C_LOCAL_POD_PATH=$(Build.BinariesDirectory)/staging/onnxruntime-mobile-c \
ORT_C_LOCAL_POD_PATH=$(Build.BinariesDirectory)/staging/onnxruntime-c \
pod install
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/ios'
displayName: Pod install for onnxruntime react native ios bridge library
- script: |
# Mobile build:
# ORT_MOBILE_C_LOCAL_POD_PATH=$(Build.BinariesDirectory)/staging/onnxruntime-mobile-c \
ORT_C_LOCAL_POD_PATH=$(Build.BinariesDirectory)/staging/onnxruntime-c \
pod install
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/ios'
displayName: Pod install for onnxruntime react native ios e2e tests
- script: |
yarn add --dev jest-junit
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e'
displayName: install jest junit reporter js/react_native/e2e
- script: |
keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -storepass android \
-keypass android -keyalg RSA -keysize 2048 -validity 999999 -dname "CN=Android Debug,O=Android,C=US"
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/android'
displayName: Generate a debug keystore
- task: CopyFiles@2
inputs:
# Mobile build:
# sourceFolder: $(Build.BinariesDirectory)/android-mobile-aar
# contents: onnxruntime-mobile-*.aar
sourceFolder: $(Build.BinariesDirectory)/android-full-aar
contents: onnxruntime-*.aar
targetFolder: $(Build.SourcesDirectory)/js/react_native/e2e/android/app/libs
displayName: Copy Android package to Android e2e test directory
- script: |
detox build --configuration android.emu.release
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e'
displayName: Build React Native Detox Android e2e Tests
- script: |
detox build --configuration ios.sim.release
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e'
displayName: Build React Native Detox iOS e2e Tests
#
# Unit tests and E2E tests with Android emulator
#
- template: use-android-emulator.yml
parameters:
create: true
start: true
- template: android-dump-logs-from-steps.yml
parameters:
steps:
- task: Gradle@3
inputs:
gradleWrapperFile: '$(Build.SourcesDirectory)/js/react_native/android/gradlew'
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/android'
options: '--stacktrace'
tasks: 'connectedDebugAndroidTest'
publishJUnitResults: true
testResultsFiles: '**/TEST-*.xml'
testRunTitle: 'React Native Android Instrumented Test results'
javaHomeOption: 'path'
jdkDirectory: '$(JAVA_HOME_11_X64)'
sonarQubeRunAnalysis: false
spotBugsAnalysis: false
displayName: Run React Native Android Instrumented Tests
- script: |
JEST_JUNIT_OUTPUT_FILE=$(Build.SourcesDirectory)/js/react_native/e2e/android-test-results.xml \
detox test --record-logs all --configuration android.emu.release
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e'
displayName: Run React Native Detox Android e2e Tests
- template: use-android-emulator.yml
parameters:
stop: true
- task: PublishTestResults@2
inputs:
testResultsFiles: '$(Build.SourcesDirectory)/js/react_native/e2e/android-test-results.xml'
failTaskOnFailedTests: true
testRunTitle: 'React Native Detox Android e2e Test Results'
condition: succeededOrFailed()
displayName: Publish React Native Detox Android e2e Test Results
#
# Unit tests and E2E tests with iOS simulator
#
- script: |
xcrun simctl create iPhoneRNTest com.apple.CoreSimulator.SimDeviceType.iPhone-13
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/ios'
displayName: Start iOS Simulator
- task: Xcode@5
inputs:
actions: 'test'
configuration: 'Debug'
sdk: 'iphonesimulator'
xcWorkspacePath: '$(Build.SourcesDirectory)/js/react_native/ios/OnnxruntimeModule.xcworkspace'
scheme: 'OnnxruntimeModuleTest'
packageApp: false
destinationPlatformOption: 'iOS'
destinationSimulators: 'iPhone 13,OS=latest'
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/ios'
xcprettyArgs: '--output build/reports/test-results.xml'
publishJUnitResults: true
testRunTitle: 'React Native iOS Instrumented Test Results'
displayName: Run React Native iOS Instrumented Tests
- task: PublishTestResults@2
inputs:
testResultsFiles: '$(Build.SourcesDirectory)/js/react_native/ios/build/reports/test-results.xml'
failTaskOnFailedTests: true
testRunTitle: 'React Native iOS Instrumented Test results'
condition: succeededOrFailed()
displayName: Publish React Native iOS Instrumented Test Results
- script: |
JEST_JUNIT_OUTPUT_FILE=$(Build.SourcesDirectory)/js/react_native/e2e/ios-test-results.xml \
detox test --record-logs all --configuration ios.sim.release
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e'
displayName: Run React Native Detox iOS e2e Tests
- script: |
xcrun simctl delete iPhoneRNTest
workingDirectory: '$(Build.SourcesDirectory)/js/react_native/e2e/ios'
displayName: Stop iOS Simulator
condition: always()
- task: PublishTestResults@2
inputs:
testResultsFiles: '$(Build.SourcesDirectory)/js/react_native/e2e/ios-test-results.xml'
failTaskOnFailedTests: true
testRunTitle: 'React Native Detox iOS e2e Test Results'
condition: succeededOrFailed()
displayName: Publish React Native Detox iOS e2e Test Results
- task: PublishPipelineArtifact@1
inputs:
artifact: e2e_test_logs
targetPath: '$(Build.SourcesDirectory)/js/react_native/e2e/artifacts'
condition: succeededOrFailed()
displayName: Publish React Native Detox E2E test logs
- script: |
git restore .
workingDirectory: '$(Build.SourcesDirectory)/js'
displayName: Restore git changes
- task: PowerShell@2
inputs:
filePath: '$(Build.SourcesDirectory)/tools/ci_build/github/js/pack-npm-packages.ps1'
arguments: '"${{parameters.NpmPackagingMode}}" $(Build.SourcesDirectory) react_native'
workingDirectory: '$(Build.SourcesDirectory)'
errorActionPreference: stop
displayName: Pack NPM packages
- task: CopyFiles@2
inputs:
sourceFolder: $(Build.SourcesDirectory)/js/common
contents: onnxruntime-common*.tgz
targetFolder: $(Build.ArtifactStagingDirectory)
displayName: 'Create Artifacts onnxruntime-common'
- task: CopyFiles@2
inputs:
sourceFolder: $(Build.SourcesDirectory)/js/react_native
contents: onnxruntime-react-native*.tgz
targetFolder: $(Build.ArtifactStagingDirectory)
displayName: Create Artifacts onnxruntime-react-native
- task: PublishPipelineArtifact@0
inputs:
artifactName: '${{parameters.PackageName}}'
targetPath: '$(Build.ArtifactStagingDirectory)'
displayName: Publish Pipeline Artifact
- template: component-governance-component-detection-steps.yml
parameters :
condition : 'succeeded'
- template: explicitly-defined-final-tasks.yml