Skip to content

Commit

Permalink
[js/react_native] Create ONNX Runtime React Native pipeline (#10474)
Browse files Browse the repository at this point in the history
* Pipeline for ONNX Runtime react native

* Fix a test failure

* test with custom built binaries

* add onnxruntime-common package back

* don't bob build when bootstrap

* revise Android test

* rename example to e2e

* remove onnxruntime packages from package.json

* remove release-it package

* upgrade gradle version to the same as CI

* add a pipeline for react native

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* android and ios mobile build for react native e2e

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* use android aar package template

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* use android aar package template

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* publish ios test results

* add e2e tests and publish a npm package

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* remove aar from npm package

* wait for view displayed

* change a waiting logic

* increase wait time for app launching

* give more time to launch an app

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* disable metro server on testing

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* test ios simulator launching

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* fix iOS e2e test

* use a publishing version of npm packages

* make pretty

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* make only one onnxruntime-common package after packaging

* make a powershell script of packaging universal

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Add a warning for file changes during a test

* clean up

* fix lint errors

* fix js npm packaging

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* Update mac-react-native-ci-pipeline.yml for Azure Pipelines

* resolve comments

* fix a typo
  • Loading branch information
hanbitmyths authored Feb 10, 2022
1 parent 6f3ade5 commit dd33ce0
Show file tree
Hide file tree
Showing 81 changed files with 2,089 additions and 312 deletions.
2 changes: 1 addition & 1 deletion js/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ module.exports = {
'@typescript-eslint/naming-convention': 'off'
}
}, {
files: ['react_native/example/src/**/*.ts', 'react_native/example/src/**/*.tsx'], rules: {
files: ['react_native/e2e/src/**/*.ts', 'react_native/e2e/src/**/*.tsx'], rules: {
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-unnecessary-type-assertion': 'off',
'unicorn/filename-case': 'off',
Expand Down
47 changes: 32 additions & 15 deletions js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -363,12 +363,10 @@ By default, ONNX Runtime React Native leverages ONNX Runtime Mobile package with
4. Copy `<BUILD_DIRECTORY>/aar_out/MinSizeRel/com/microsoft/onnxruntime/onnxruntime-mobile/<version>/onnxruntime-mobile-<version>.aar` into `<ORT_ROOT>/js/react_native/android/libs` directory.
5. Modify `Onnxruntime_mobileVersion` property in `<ORT_ROOT>/js/react_native/android/build.properties` to consume a locally built package or a newly published package from Maven.
6. To verify, open Android Emulator and run this command from `<ORT_ROOT>/js/react_native/android`
5. To verify, open Android Emulator and run this command from `<ORT_ROOT>/js/react_native/android`
```sh
adb shell am instrument -w ai.onnxruntime.react_native.test/androidx.test.runner.AndroidJUnitRunner
./gradlew connectedDebugAndroidTest
```
3. Build iOS ONNX Runtime package
Expand All @@ -393,38 +391,57 @@ By default, ONNX Runtime React Native leverages ONNX Runtime Mobile package with
```sh
pod install
xcodebuild test -workspace OnnxruntimeModule.xcworkspace -scheme OnnxruntimeModuleTest -destination 'platform=iOS Simulator,name=iPhone 11,OS=15.0'
xcodebuild test -workspace OnnxruntimeModule.xcworkspace -scheme OnnxruntimeModuleTest -destination 'platform=iOS Simulator,OS=latest,name=iPhone 13'
```
4. Test an example for Android and iOS. In Windows, open Android Emulator first.
4. Test Android and iOS apps. In Windows, open Android Emulator first.
`debug.keystore` must be generated ahead for Android example.
```sh
keytool -genkey -v -keystore <ORT_ROOT>/js/react_native/example/android/app/debug.keystore -alias androiddebugkey -storepass android -keypass android -keyalg RSA -keysize 2048 -validity 999999 -dname "CN=Android Debug,O=Android,C=US"
keytool -genkey -v -keystore <ORT_ROOT>/js/react_native/e2e/android/debug.keystore -alias androiddebugkey -storepass android -keypass android -keyalg RSA -keysize 2048 -validity 999999 -dname "CN=Android Debug,O=Android,C=US"
```

From `<ORT_ROOT>/js/react_native,

```sh
yarn bootstrap
yarn example ios
yarn example android
```

When testing with a custom built ONNX Runtime Android package, copy `<BUILD_DIRECTORY>/aar_out/MinSizeRel/com/microsoft/onnxruntime/onnxruntime-mobile/<version>/onnxruntime-mobile-<version>.aar` into `<ORT_ROOT>/js/react_native/e2e/node_modules/onnxruntime-react-native/android/libs` directory. Using a custom built ONNX Runtime iOS package, copy `onnxruntime-mobile-c.zip` into `<ORT_ROOT>/js/react_native/local_pods` directory if it's not already done.

From `<ORT_ROOT>/js/react_native/e2e/android`, run e2e Android tests as follows,

```sh
./gradlew :app:connectedDebugAndroidTest
```

From `<ORT_ROOT>/js/react_native/e2e/ios`, run e2e iOS tests as follows,

```sh
xcrun xcodebuild test -workspace OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -destination 'platform=iOS Simulator,OS=latest,name=iPhone 13'
```

***`yarn bootstrap` changes `packages.json` and `yarn.lock` files. Once testing is done, restore changes to avoid unwanted commit.***

5. Run Android and iOS apps.

```sh
yarn e2e android
yarn e2e ios
```

### NPM Packaging

1. Update a version using `npm verison <version>` from `<ORT_ROOT>/js/react_native` folder. If it's for a dev, use `npm version <version>-dev.<subversion>`

2. Modify Onnxruntime_mobileVersion property in `<ORT_ROOT>/js/react_native/android/build.properties` to update ONNX Runtime Android package version.

3. Run `yarn prepack` to change `onnxruntime-common` to point to a published npm package
2. Run `yarn prepack-rel` to change `onnxruntime-common` to point to a published npm package

4. Run `npm pack` and verify NPM package contents
3. Run `npm pack` and verify NPM package contents

5. Run `npm publish <tgz> --dry-run` to see how it's going to be published
4. Run `npm publish <tgz> --dry-run` to see how it's going to be published

6. Run `npm publish <tgz>` to publish to npmjs. If it's for a dev, add flag `--tag dev`.
5. Run `npm publish <tgz>` to publish to npmjs. If it's for a dev, add flag `--tag dev`.

### Distribution

Expand Down
2 changes: 1 addition & 1 deletion js/react_native/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ android.iml
# Cocoapods
#
ios/Pods/
example/ios/Pods/
e2e/ios/Pods/

# node.js
#
Expand Down
4 changes: 1 addition & 3 deletions js/react_native/android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ repositories {
}

dependencies {
def onnxruntimeMobileVersion = project.properties['Onnxruntime_mobileVersion']

// noinspection GradleDynamicVersion
api "com.facebook.react:react-native:+"
api "org.mockito:mockito-core:2.28.2"
Expand All @@ -134,5 +132,5 @@ dependencies {

androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline-extended:2.28.1"

implementation "com.microsoft.onnxruntime:onnxruntime-mobile:$onnxruntimeMobileVersion@aar"
implementation "com.microsoft.onnxruntime:onnxruntime-mobile:latest.integration@aar"
}
1 change: 0 additions & 1 deletion js/react_native/android/gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ android.useAndroidX=true
OnnxruntimeModule_buildToolsVersion=29.0.2
OnnxruntimeModule_compileSdkVersion=29
OnnxruntimeModule_targetSdkVersion=29
Onnxruntime_mobileVersion=1.8.2
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#Tue Jan 26 16:57:19 PST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ esac

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar


# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
Expand Down Expand Up @@ -129,6 +130,7 @@ fi
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

JAVACMD=`cygpath --unix "$JAVACMD"`

# We build the pattern for arguments to be converted via cygpath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem http://www.apache.org/licenses/LICENSE-2.0
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
Expand Down Expand Up @@ -84,6 +84,7 @@ set CMD_LINE_ARGS=%*

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar


@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,8 @@ android {
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
splits {
abi {
Expand All @@ -144,16 +146,13 @@ android {
}
signingConfigs {
debug {
storeFile file('debug.keystore')
storePassword 'android'
storeFile rootProject.file('debug.keystore')
keyAlias 'androiddebugkey'
keyPassword 'android'
storePassword 'android'
}
}
buildTypes {
debug {
signingConfig signingConfigs.debug
}
release {
// Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android.
Expand Down Expand Up @@ -183,7 +182,6 @@ dependencies {
//noinspection GradleDynamicVersion
implementation "com.facebook.react:react-native:+" // From node_modules


implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0"
debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
exclude group:'com.facebook.fbjni'
Expand All @@ -204,7 +202,11 @@ dependencies {
implementation jscFlavor
}

implementation project(':onnxruntimereactnative')
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
androidTestImplementation 'androidx.test:runner:1.4.0'
androidTestImplementation 'androidx.test:rules:1.4.0'

implementation project(':onnxruntime-react-native')
}

// Run this once to be able to run the application with BUCK
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package com.example.reactnativeonnxruntimemodule;

import android.view.View;
import android.widget.TextView;

import androidx.test.espresso.NoMatchingViewException;
import androidx.test.espresso.UiController;
import androidx.test.espresso.ViewAction;
import androidx.test.espresso.ViewInteraction;
import androidx.test.filters.LargeTest;
import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;

import org.hamcrest.Matcher;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;

import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withContentDescription;
import static org.hamcrest.Matchers.allOf;

@RunWith(AndroidJUnit4.class)
@LargeTest
public class OnnxruntimeModuleExampleUITests {
@Rule
public ActivityTestRule<MainActivity> activityTestRule = new ActivityTestRule<>(MainActivity.class);

@Test
public void testExample() {
// Wait for a view displayed
int waitTime = 0;
final int sleepTime = 1000;
do {
try {
ViewInteraction view = onView(allOf(withContentDescription("output"), isDisplayed()));
if (getText(view) != null) {
break;
}
} catch (NoMatchingViewException ne) {
try {
Thread.sleep(sleepTime);
} catch (InterruptedException ie) {
}
waitTime += sleepTime;
}
} while (waitTime < 180000);

ViewInteraction view = onView(allOf(withContentDescription("output"), isDisplayed()));
Assert.assertEquals(getText(view), "Result: 3");
}

private String getText(ViewInteraction matcher) {
final String[] text = {null};

matcher.perform(new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return isAssignableFrom(TextView.class);
}

@Override
public String getDescription() {
return "get a text from a TextView";
}

@Override
public void perform(UiController uiController, View view) {
TextView textView = (TextView)view;
text[0] = textView.getText().toString();
}
});

return text[0];
}
}
Loading

0 comments on commit dd33ce0

Please sign in to comment.