This document describes the Continuous Integration setup for the mendix-native project.
The CI pipeline runs on every pull request and includes:
- Linting - Code quality checks
- Building - iOS and Android example app builds
- Testing - Automated harness tests on both platforms
All workflows use standardized tooling versions to ensure consistency:
| Tool | Version | Defined In |
|---|---|---|
| Node.js | 24 |
.nvmrc |
| Yarn | 4.12.0 |
package.json#packageManager |
| React Native | 0.83.4 |
package.json |
| React | 19.2.14 |
package.json |
| TypeScript | 5.9.3 |
package.json |
| Tool | Version | Defined In |
|---|---|---|
| Java | 21 (Zulu distribution) |
All Android workflows |
| Gradle | 8.12 |
gradle-wrapper.properties |
| Android Build Tools | 35.0.0 |
example/android/build.gradle |
| NDK | 27.3.13750724 |
example/android/build.gradle |
| Kotlin | 2.0.21 |
example/android/build.gradle |
| compileSdkVersion | 35 |
example/android/build.gradle |
| targetSdkVersion | 35 |
example/android/build.gradle |
| minSdkVersion | 24 |
example/android/build.gradle |
| Tool | Version | Defined In |
|---|---|---|
| Xcode | 26.2 |
All iOS workflows |
| iOS SDK | 26.2 |
Xcode 26.2 includes iOS 26.2 SDK |
| Ruby | 3.2 |
ios.yml |
| CocoaPods | >= 1.13 (excludes 1.15.0, 1.15.1) |
example/Gemfile |
Note for Local Development: GitHub Actions
macos-latestrunners use Xcode 26.2 as the default.
Your local machine may have a different Xcode version. The workflows are configured to match GitHub Actions'
environment. Local development can use any compatible Xcode version, but ensure simulator devices specified
inrn-harness.config.mjsare available on your system.
| Tool | Version | Defined In |
|---|---|---|
| React Native Harness | 1.0.0-alpha.21 |
package.json |
| Android Emulator | Pixel_API_35 (API 35) | rn-harness.config.mjs |
| iOS Simulator | iPhone 17 (iOS 26.2) | rn-harness.config.mjs |
All actions are pinned to specific commit SHAs for security and reproducibility:
| Action | Version | SHA |
|---|---|---|
actions/checkout |
v4.2.2 | 93cb6efe18208431cddfb8368fd83d5badbf9bfd |
actions/setup-node |
v4.2.2 | 49933ea5288caeca8642d1e84afbd3f7d6820020 |
actions/setup-java |
v4.7.1 | f2beeb24e141e01a676f977032f5a29d81c9e27e |
actions/cache |
v4.2.0 | 0057852bfaa89a56745cba8c7296529d2fc39830 |
ruby/setup-ruby |
v1.204.0 | d697be2f83c6234b20877c3b5eac7a7f342f0d0c |
android-actions/setup-android |
v3.2.1 | 9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407 |
reactivecircus/android-emulator-runner |
v2.33.0 | b530d96654c385303d652368551fb075bc2f0b6b |
Note on iOS Simulator: We use a custom shell script (
.github/scripts/launch-ios-simulator.sh) instead offutureware-tech/simulator-actionfor better reliability and faster boot times. The action was sometimes unstable and could hang for hours without response.
IMPORTANT: When updating versions, maintain consistency:
-
iOS Simulator Device: Must match between:
rn-harness.config.mjs(test configuration)ios.yml(xcodebuild destination)example/package.json(ios:simulator:build script)- Must be available in the specified Xcode version
-
Xcode Version: Must match in:
ios.yml(xcode-select command and DEVELOPER_DIR env var)- iOS simulator version in harness config must be compatible
-
Android Emulator Device: Must match between:
rn-harness.config.mjs(test configuration)android.yml(AVD_NAME environment variable)
-
NDK Version: Must match between:
example/android/build.gradle(ndkVersion)android.yml(sdkmanager install command and cache path)
-
Java Version: Must be specified in:
android.yml(Setup Java step)
-
Ruby Version: Must satisfy:
ios.ymlspecification (3.2)example/Gemfilerequirement (>= 2.6.10)ios.ymlworking-directory must point toexample(where Gemfile lives)
-
React Native Harness: Must match between:
example/package.json- All harness platform packages (
@react-native-harness/*)
- Runs ESLint and TypeScript checks
Single integrated job that:
- Builds the Android example app (debug APK)
- Sets up Android emulator
- Runs harness tests
- Runs on:
ubuntu-latest - Uses: Java 21, Android SDK, NDK 27.3.13750724
Single integrated job that:
- Builds the iOS example app for simulator
- Sets up iOS simulator
- Runs harness tests
- Runs on:
macos-latest - Uses: Xcode 26.2, Ruby 3.2, CocoaPods
The harness tests are configured in example/rn-harness.config.mjs:
runners: [
androidPlatform({
name: 'android',
device: androidEmulator('Pixel_API_35'),
bundleId: 'mendixnative.example',
}),
applePlatform({
name: 'ios',
device: appleSimulator('iPhone 17', '26.2'),
bundleId: 'mendixnative.example',
}),
];The workflows handle device setup automatically:
- Android: Uses
reactivecircus/android-emulator-runnerto launch the emulator - iOS: Uses a custom script (
.github/scripts/launch-ios-simulator.sh) that launches the simulator with specific OS version pinning
Make sure iPhone 17 (iOS 26.2) simulator is up and running. You can use the launch script:
# Launch simulator automatically
./.github/scripts/launch-ios-simulator.sh "iPhone 17" "26.2"
# Then run tests
corepack enable
yarn install
yarn prepare
cd example
yarn pod
yarn harness:ios:with:buildMake sure emulator with name Pixel_API_35 is up and running
corepack enable
yarn install
yarn prepare
cd example
yarn harness:android:with:buildAndroid emulator fails to boot or tests time out:
- Check AVD cache - clear
avd-*entries if corrupted - Verify KVM is enabled (workflows handle this automatically)
- Check emulator logs in workflow output
- Ensure AVD_NAME matches harness config (
Pixel_API_35)
iOS simulator not found or fails to boot:
- Verify simulator model exists in Xcode version (
iPhone 17) - Check iOS version compatibility (
26.2) - Review simulator launch script logs for errors
- Ensure device name matches harness config exactly
- Check if
jqis installed (script requires it for JSON parsing) - Simulator script automatically handles stuck processes and timeouts