Skip to content

Commit aa7c075

Browse files
feat: add harness tests for turbo module
1 parent 9f36982 commit aa7c075

25 files changed

+2480
-122
lines changed

.github/CI_DOCUMENTATION.md

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
# GitHub Actions CI/CD Documentation
2+
3+
This document describes the Continuous Integration setup for the mendix-native project.
4+
5+
## Overview
6+
7+
The CI pipeline runs on every pull request and includes:
8+
9+
1. **Linting** - Code quality checks
10+
2. **Building** - iOS and Android example app builds
11+
3. **Testing** - Automated harness tests on both platforms
12+
13+
## Tooling Versions
14+
15+
All workflows use standardized tooling versions to ensure consistency:
16+
17+
### Core Tools
18+
19+
| Tool | Version | Defined In |
20+
| ---------------- | -------- | ----------------------------- |
21+
| **Node.js** | `24` | `.nvmrc` |
22+
| **Yarn** | `4.12.0` | `package.json#packageManager` |
23+
| **React Native** | `0.78.2` | `package.json` |
24+
| **React** | `19.0.0` | `package.json` |
25+
| **TypeScript** | `5.9.2` | `package.json` |
26+
27+
### Android Tooling
28+
29+
| Tool | Version | Defined In |
30+
| ----------------------- | ------------------------ | ------------------------------ |
31+
| **Java** | `17` (Zulu distribution) | All Android workflows |
32+
| **Gradle** | `8.12` | `gradle-wrapper.properties` |
33+
| **Android Build Tools** | `35.0.0` | `example/android/build.gradle` |
34+
| **NDK** | `27.3.13750724` | `example/android/build.gradle` |
35+
| **Kotlin** | `2.0.21` | `example/android/build.gradle` |
36+
| **compileSdkVersion** | `35` | `example/android/build.gradle` |
37+
| **targetSdkVersion** | `35` | `example/android/build.gradle` |
38+
| **minSdkVersion** | `24` | `example/android/build.gradle` |
39+
40+
### iOS Tooling
41+
42+
| Tool | Version | Defined In |
43+
| ------------- | ----------------------------------- | -------------------------------- |
44+
| **Xcode** | `26.2` | All iOS workflows |
45+
| **iOS SDK** | `26.2` | Xcode 26.2 includes iOS 26.2 SDK |
46+
| **Ruby** | `3.2` | `ios.yml` |
47+
| **CocoaPods** | `>= 1.13` (excludes 1.15.0, 1.15.1) | `example/Gemfile` |
48+
49+
> **Note for Local Development:** GitHub Actions `macos-latest` runners use Xcode 26.2 as the default.
50+
> Your local machine may have a different Xcode version. The workflows are configured to match GitHub Actions'
51+
> environment. Local development can use any compatible Xcode version, but ensure simulator devices specified
52+
> in `rn-harness.config.mjs` are available on your system.
53+
54+
### Test Configuration
55+
56+
| Tool | Version | Defined In |
57+
| ------------------------ | --------------------- | ----------------------- |
58+
| **React Native Harness** | `1.0.0-alpha.21` | `package.json` |
59+
| **Android Emulator** | Pixel_API_34 (API 34) | `rn-harness.config.mjs` |
60+
| **iOS Simulator** | iPhone 17 (iOS 26.2) | `rn-harness.config.mjs` |
61+
62+
### GitHub Actions
63+
64+
All actions are pinned to specific commit SHAs for security and reproducibility:
65+
66+
| Action | Version | SHA |
67+
| ---------------------------------------- | -------- | ------------------------------------------ |
68+
| `actions/checkout` | v4.2.2 | `93cb6efe18208431cddfb8368fd83d5badbf9bfd` |
69+
| `actions/setup-node` | v4.2.2 | `49933ea5288caeca8642d1e84afbd3f7d6820020` |
70+
| `actions/setup-java` | v4.7.1 | `f2beeb24e141e01a676f977032f5a29d81c9e27e` |
71+
| `actions/cache` | v4.2.0 | `0057852bfaa89a56745cba8c7296529d2fc39830` |
72+
| `ruby/setup-ruby` | v1.204.0 | `d697be2f83c6234b20877c3b5eac7a7f342f0d0c` |
73+
| `android-actions/setup-android` | v3.2.1 | `9fc6c4e9069bf8d3d10b2204b1fb8f6ef7065407` |
74+
| `reactivecircus/android-emulator-runner` | v2.33.0 | `b530d96654c385303d652368551fb075bc2f0b6b` |
75+
76+
> **Note on iOS Simulator:** We use a custom shell script (`.github/scripts/launch-ios-simulator.sh`) instead of `futureware-tech/simulator-action` for better reliability and faster boot times. The action was sometimes unstable and could hang for hours without response.
77+
78+
### Version Consistency Rules
79+
80+
**IMPORTANT**: When updating versions, maintain consistency:
81+
82+
1. **iOS Simulator Device**: Must match between:
83+
84+
- `rn-harness.config.mjs` (test configuration)
85+
- `ios.yml` (xcodebuild destination)
86+
- `example/package.json` (ios:simulator:build script)
87+
- Must be available in the specified Xcode version
88+
89+
2. **Xcode Version**: Must match in:
90+
91+
- `ios.yml` (xcode-select command and DEVELOPER_DIR env var)
92+
- iOS simulator version in harness config must be compatible
93+
94+
3. **Android Emulator Device**: Must match between:
95+
96+
- `rn-harness.config.mjs` (test configuration)
97+
- `android.yml` (AVD_NAME environment variable)
98+
99+
4. **NDK Version**: Must match between:
100+
101+
- `example/android/build.gradle` (ndkVersion)
102+
- `android.yml` (sdkmanager install command and cache path)
103+
104+
5. **Java Version**: Must be specified in:
105+
106+
- `android.yml` (Setup Java step)
107+
108+
6. **Ruby Version**: Must satisfy:
109+
110+
- `ios.yml` specification (3.2)
111+
- `example/Gemfile` requirement (>= 2.6.10)
112+
- `ios.yml` working-directory must point to `example` (where Gemfile lives)
113+
114+
7. **React Native Harness**: Must match between:
115+
- `example/package.json`
116+
- All harness platform packages (`@react-native-harness/*`)
117+
118+
## Workflows
119+
120+
#### 1. Lint (`.github/workflows/lint.yml`)
121+
122+
- Runs ESLint and TypeScript checks
123+
124+
#### 2. Android Build & Test (`.github/workflows/android.yml`)
125+
126+
**Single integrated job that:**
127+
128+
- Builds the Android example app (debug APK)
129+
- Sets up Android emulator
130+
- Runs harness tests
131+
- Runs on: `ubuntu-latest`
132+
- Uses: Java 17, Android SDK, NDK 27.3.13750724
133+
134+
#### 3. iOS Build & Test (`.github/workflows/ios.yml`)
135+
136+
**Single integrated job that:**
137+
138+
- Builds the iOS example app for simulator
139+
- Sets up iOS simulator
140+
- Runs harness tests
141+
- Runs on: `macos-latest`
142+
- Uses: Xcode 26.2, Ruby 3.2, CocoaPods
143+
144+
## Test Configuration
145+
146+
The harness tests are configured in `example/rn-harness.config.mjs`:
147+
148+
```javascript
149+
runners: [
150+
androidPlatform({
151+
name: 'android',
152+
device: androidEmulator('Pixel_API_34'),
153+
bundleId: 'mendixnative.example',
154+
}),
155+
applePlatform({
156+
name: 'ios',
157+
device: appleSimulator('iPhone 17', '26.2'),
158+
bundleId: 'mendixnative.example',
159+
}),
160+
];
161+
```
162+
163+
The workflows handle device setup automatically:
164+
165+
- **Android**: Uses `reactivecircus/android-emulator-runner` to launch the emulator
166+
- **iOS**: Uses a custom script (`.github/scripts/launch-ios-simulator.sh`) that launches the simulator with specific OS version pinning
167+
168+
## Running Tests Locally
169+
170+
### iOS
171+
172+
Make sure `iPhone 17 (iOS 26.2)` simulator is up and running. You can use the launch script:
173+
174+
```bash
175+
# Launch simulator automatically
176+
./.github/scripts/launch-ios-simulator.sh "iPhone 17" "26.2"
177+
178+
# Then run tests
179+
corepack enable
180+
yarn install
181+
yarn prepare
182+
cd example
183+
yarn pod
184+
yarn harness:ios:with:build
185+
```
186+
187+
### Android
188+
189+
Make sure emulator with name `Pixel_API_34` is up and running
190+
191+
```bash
192+
corepack enable
193+
yarn install
194+
yarn prepare
195+
cd example
196+
yarn harness:android:with:build
197+
```
198+
199+
## Troubleshooting
200+
201+
### Device/Emulator Issues
202+
203+
**Android emulator fails to boot or tests time out:**
204+
205+
- Check AVD cache - clear `avd-*` entries if corrupted
206+
- Verify KVM is enabled (workflows handle this automatically)
207+
- Check emulator logs in workflow output
208+
- Ensure AVD_NAME matches harness config (`Pixel_API_34`)
209+
210+
**iOS simulator not found or fails to boot:**
211+
212+
- Verify simulator model exists in Xcode version (`iPhone 17`)
213+
- Check iOS version compatibility (`26.2`)
214+
- Review simulator launch script logs for errors
215+
- Ensure device name matches harness config exactly
216+
- Check if `jq` is installed (script requires it for JSON parsing)
217+
- Simulator script automatically handles stuck processes and timeouts
218+
219+
## References
220+
221+
- [React Native Harness Documentation](https://www.react-native-harness.dev/)
222+
- [React Native Harness CI/CD Guide](https://www.react-native-harness.dev/docs/guides/ci-cd)
223+
- [Android Emulator Runner Action](https://github.com/ReactiveCircus/android-emulator-runner)

.github/actions/setup-node-yarn/action.yml

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,41 @@ runs:
88
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020
99
with:
1010
node-version-file: '.nvmrc'
11-
cache: yarn
1211

1312
- name: Enable corepack
1413
shell: bash
1514
run: corepack enable
1615

16+
- name: Get yarn cache directory path
17+
id: yarn-cache-dir-path
18+
shell: bash
19+
run: echo "dir=$(yarn config get cacheFolder)" >> $GITHUB_OUTPUT
20+
21+
- name: Cache Yarn dependencies
22+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
23+
with:
24+
path: |
25+
${{ steps.yarn-cache-dir-path.outputs.dir }}
26+
.yarn/cache
27+
.yarn/install-state.gz
28+
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
29+
restore-keys: |
30+
${{ runner.os }}-yarn-
31+
1732
- name: Install dependencies
1833
shell: bash
1934
run: yarn install --immutable
2035

21-
- name: Prepare package
36+
- name: Cache built library
37+
id: cache-lib
38+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830
39+
with:
40+
path: lib
41+
key: ${{ runner.os }}-lib-${{ hashFiles('src/**/*.{ts,tsx,js,jsx}', 'package.json', 'tsconfig.json') }}
42+
restore-keys: |
43+
${{ runner.os }}-lib-
44+
45+
- name: Build library (bob build)
46+
if: steps.cache-lib.outputs.cache-hit != 'true'
2247
shell: bash
2348
run: yarn prepare

0 commit comments

Comments
 (0)