1- name : Test Kotlin Multiplatform foundation
1+ name : Test Kotlin Multiplatform pilot
22
33on :
44 workflow_dispatch :
77 - ' .github/workflows/test-kmp.yml'
88 - ' .github/actions/setup-gradle/**'
99 - ' .github/actions/setup-xcode/**'
10+ - ' .github/actions/setup-node/**'
11+ - ' .github/actions/yarn-install/**'
12+ - ' Gemfile'
13+ - ' Gemfile.lock'
14+ - ' build.gradle.kts'
15+ - ' gradle.properties'
16+ - ' gradle/wrapper/**'
17+ - ' settings.gradle.kts'
18+ - ' yarn.lock'
19+ - ' packages/rn-tester/Podfile'
20+ - ' packages/rn-tester/RCTTest/**'
21+ - ' packages/rn-tester/RNTesterPods.xcodeproj/**'
22+ - ' packages/rn-tester/RNTester/RNTester.xctestplan'
1023 - ' packages/react-native/ReactShared/**'
24+ - ' packages/react-native/ReactAndroid/build.gradle.kts'
25+ - ' packages/react-native/ReactAndroid/gradle.properties'
26+ - ' packages/react-native/gradle/libs.versions.toml'
27+ - ' packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ColorStop.kt'
28+ - ' packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/style/ColorStopTest.kt'
29+ - ' packages/react-native/React/Fabric/Utils/RCTGradientUtils.*'
30+ - ' packages/react-native/React/Fabric/RCTConversions.h'
31+ - ' packages/react-native/Libraries/NativeAnimation/RCTAnimationUtils.*'
32+ - ' packages/react-native/ReactCommon/react/renderer/graphics/**'
33+ - ' packages/react-native/ReactCommon/react/utils/FloatComparison.h'
34+ - ' packages/react-native/ReactCommon/react/utils/ManagedObjectWrapper.*'
35+ - ' packages/react-native/React/React-RCTFabric.podspec'
36+ - ' packages/react-native/scripts/react_native_pods.rb'
37+ - ' packages/react-native/scripts/cocoapods/kmp.rb'
38+ - ' packages/react-native/Package.swift'
39+ - ' packages/react-native/package.json'
40+ - ' packages/react-native/settings.gradle.kts'
1141 push :
1242 branches :
1343 - main
1646 - ' .github/workflows/test-kmp.yml'
1747 - ' .github/actions/setup-gradle/**'
1848 - ' .github/actions/setup-xcode/**'
49+ - ' .github/actions/setup-node/**'
50+ - ' .github/actions/yarn-install/**'
51+ - ' Gemfile'
52+ - ' Gemfile.lock'
53+ - ' build.gradle.kts'
54+ - ' gradle.properties'
55+ - ' gradle/wrapper/**'
56+ - ' settings.gradle.kts'
57+ - ' yarn.lock'
58+ - ' packages/rn-tester/Podfile'
59+ - ' packages/rn-tester/RCTTest/**'
60+ - ' packages/rn-tester/RNTesterPods.xcodeproj/**'
61+ - ' packages/rn-tester/RNTester/RNTester.xctestplan'
1962 - ' packages/react-native/ReactShared/**'
63+ - ' packages/react-native/ReactAndroid/build.gradle.kts'
64+ - ' packages/react-native/ReactAndroid/gradle.properties'
65+ - ' packages/react-native/gradle/libs.versions.toml'
66+ - ' packages/react-native/ReactAndroid/src/main/java/com/facebook/react/uimanager/style/ColorStop.kt'
67+ - ' packages/react-native/ReactAndroid/src/test/java/com/facebook/react/uimanager/style/ColorStopTest.kt'
68+ - ' packages/react-native/React/Fabric/Utils/RCTGradientUtils.*'
69+ - ' packages/react-native/React/Fabric/RCTConversions.h'
70+ - ' packages/react-native/Libraries/NativeAnimation/RCTAnimationUtils.*'
71+ - ' packages/react-native/ReactCommon/react/renderer/graphics/**'
72+ - ' packages/react-native/ReactCommon/react/utils/FloatComparison.h'
73+ - ' packages/react-native/ReactCommon/react/utils/ManagedObjectWrapper.*'
74+ - ' packages/react-native/React/React-RCTFabric.podspec'
75+ - ' packages/react-native/scripts/react_native_pods.rb'
76+ - ' packages/react-native/scripts/cocoapods/kmp.rb'
77+ - ' packages/react-native/Package.swift'
78+ - ' packages/react-native/package.json'
79+ - ' packages/react-native/settings.gradle.kts'
2080
2181permissions :
2282 contents : read
@@ -26,6 +86,227 @@ concurrency:
2686 cancel-in-progress : true
2787
2888jobs :
89+ test-shared :
90+ runs-on : macos-26
91+ timeout-minutes : 45
92+ steps :
93+ - name : Checkout
94+ uses : actions/checkout@v6
95+ - name : Set up JDK 17
96+ uses : actions/setup-java@v5
97+ with :
98+ java-version : ' 17'
99+ distribution : ' zulu'
100+ - name : Set up Xcode for Kotlin Native
101+ uses : ./.github/actions/setup-xcode
102+ with :
103+ xcode-version : ' 26.4.1'
104+ - name : Set up Gradle
105+ uses : ./.github/actions/setup-gradle
106+ - name : Set up Ruby and CocoaPods
107+ uses : ruby/setup-ruby@v1
108+ with :
109+ ruby-version : ' 3.2.0'
110+ bundler-cache : true
111+ - name : Check CocoaPods linking configurations
112+ run : bundle exec ruby packages/react-native/ReactShared/scripts/test-cocoapods-linking.rb
113+ - name : Cache Kotlin Native toolchain
114+ uses : actions/cache@v5
115+ with :
116+ path : ~/.konan
117+ key : kmp-native-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('packages/react-native/ReactShared/*.gradle.kts', 'packages/react-native/ReactShared/gradle.properties', 'packages/react-native/ReactShared/gradle/wrapper/gradle-wrapper.properties') }}
118+ - name : Test shared code on JVM and iOS
119+ id : shared
120+ working-directory : packages/react-native/ReactShared
121+ run : >-
122+ ./gradlew
123+ jvmTest iosSimulatorArm64Test
124+ linkDebugFrameworkIosArm64 linkReleaseFrameworkIosArm64
125+ linkDebugFrameworkIosSimulatorArm64 linkReleaseFrameworkIosSimulatorArm64
126+ linkDebugFrameworkIosX64 linkReleaseFrameworkIosX64
127+ --stacktrace --console=plain
128+ - name : Compare the Apple adapter with native gradients
129+ if : ${{ !cancelled() && steps.shared.outcome == 'success' }}
130+ working-directory : packages/react-native/ReactShared
131+ run : ./scripts/test-apple-gradient.sh
132+ - name : Compare optimized Apple gradients
133+ if : ${{ !cancelled() && steps.shared.outcome == 'success' }}
134+ working-directory : packages/react-native/ReactShared
135+ env :
136+ RCT_KMP_BUILD_TYPE : Release
137+ run : ./scripts/test-apple-gradient.sh
138+ - name : Test packaged XCFramework consumption
139+ if : ${{ !cancelled() && steps.shared.outcome == 'success' }}
140+ working-directory : packages/react-native/ReactShared
141+ run : ./scripts/test-apple-distribution.sh
142+ - name : Test independent Kotlin runtime coexistence
143+ if : ${{ !cancelled() && steps.shared.outcome == 'success' }}
144+ working-directory : packages/react-native/ReactShared
145+ run : python3 scripts/test-kotlin-coexistence.py
146+ - name : Measure native gradient costs
147+ if : ${{ !cancelled() && steps.shared.outcome == 'success' }}
148+ working-directory : packages/react-native/ReactShared
149+ run : python3 scripts/benchmark-apple-gradient.py
150+ - name : Measure clean and incremental shared builds
151+ if : ${{ !cancelled() && steps.shared.outcome == 'success' }}
152+ working-directory : packages/react-native/ReactShared
153+ run : python3 scripts/benchmark-kmp-build.py
154+ - name : Upload test reports
155+ if : always()
156+ uses : actions/upload-artifact@v6
157+ with :
158+ name : kotlin-multiplatform-test-results
159+ path : |
160+ packages/react-native/ReactShared/build/reports/tests
161+ packages/react-native/ReactShared/build/test-results
162+ packages/react-native/ReactShared/build/apple-distribution/**/*.json
163+ packages/react-native/ReactShared/build/apple-distribution/**/*.log
164+ packages/react-native/ReactShared/build/apple-distribution/**/consumer.xcresult
165+ packages/react-native/ReactShared/build/kotlin-coexistence/**/*.json
166+ packages/react-native/ReactShared/build/kotlin-coexistence/**/*.log
167+ packages/react-native/ReactShared/build/apple-gradient-benchmark/**/*.json
168+ packages/react-native/ReactShared/build/apple-gradient-benchmark/**/*.log
169+ packages/react-native/ReactShared/build/kmp-build-benchmark/**/*.json
170+ packages/react-native/ReactShared/build/kmp-build-benchmark/**/*.log
171+ if-no-files-found : warn
172+
173+ test-android-consumers :
174+ name : Android Maven and npm source consumers
175+ runs-on : 8-core-ubuntu
176+ timeout-minutes : 90
177+ steps :
178+ - name : Checkout
179+ uses : actions/checkout@v6
180+ - name : Set up Node
181+ uses : ./.github/actions/setup-node
182+ - name : Install JavaScript dependencies
183+ uses : ./.github/actions/yarn-install
184+ - name : Set up Python
185+ uses : actions/setup-python@v5
186+ with :
187+ python-version : ' 3.12'
188+ - name : Set up JDK 17
189+ uses : actions/setup-java@v5
190+ with :
191+ java-version : ' 17'
192+ distribution : ' zulu'
193+ - name : Set up Gradle
194+ uses : ./.github/actions/setup-gradle
195+ - name : Install Android build SDK
196+ id : android-sdk
197+ run : |
198+ python3 - <<'PY'
199+ import os, pathlib, re, shutil, subprocess, tomllib
200+ versions = tomllib.loads(pathlib.Path('packages/react-native/gradle/libs.versions.toml').read_text())['versions']
201+ sdkmanager = shutil.which('sdkmanager') or str(pathlib.Path(os.environ['ANDROID_HOME']) / 'cmdline-tools/latest/bin/sdkmanager')
202+ packages = subprocess.check_output([sdkmanager, '--list'], text=True)
203+ base = 'platforms;android-' + versions['compileSdk']
204+ # Recent SDKs use a minor version in their package ID (for example android-37.0).
205+ platform = next((name for name in [base + '.0', base] if re.search(r'^\s*' + re.escape(name) + r'\s*\|', packages, re.M)), None)
206+ if platform is None:
207+ raise SystemExit('No Android SDK package matches compileSdk ' + versions['compileSdk'])
208+ subprocess.run([sdkmanager, platform, 'build-tools;' + versions['buildTools']], check=True)
209+ with open(os.environ['GITHUB_OUTPUT'], 'a') as output:
210+ output.write('ndk=' + versions['ndkVersion'] + '\n')
211+ PY
212+ - name : Enable emulator hardware acceleration
213+ run : |
214+ echo 'KERNEL=="kvm", GROUP="kvm", MODE="0666", OPTIONS+="static_node=kvm"' | sudo tee /etc/udev/rules.d/99-kvm4all.rules
215+ sudo udevadm control --reload-rules
216+ sudo udevadm trigger --name-match=kvm
217+ - name : Build and run packaged Android consumers
218+ uses : reactivecircus/android-emulator-runner@v2
219+ with :
220+ api-level : 35
221+ target : google_apis
222+ arch : x86_64
223+ ndk : ${{ steps.android-sdk.outputs.ndk }}
224+ cmake : 3.30.5
225+ cores : 4
226+ disable-animations : true
227+ script : python3 packages/react-native/ReactShared/scripts/test-android-consumers.py --output-dir "$RUNNER_TEMP/kmp-android-consumers" --abi x86_64 --device emulator-5554
228+ - name : Upload consumer reports
229+ if : always()
230+ uses : actions/upload-artifact@v6
231+ with :
232+ name : kmp-android-consumers
233+ path : |
234+ ${{ runner.temp }}/kmp-android-consumers/*.log
235+ ${{ runner.temp }}/kmp-android-consumers/*.json
236+ if-no-files-found : warn
237+
238+ test-apple-app :
239+ name : RNTester KMP ${{ matrix.platform }} (${{ matrix.linkage }})
240+ runs-on : macos-26
241+ timeout-minutes : 90
242+ strategy :
243+ fail-fast : false
244+ matrix :
245+ include :
246+ - platform : simulator
247+ linkage : libraries
248+ - platform : simulator
249+ linkage : static
250+ - platform : simulator
251+ linkage : dynamic
252+ - platform : device
253+ linkage : libraries
254+ - platform : catalyst
255+ linkage : libraries
256+ env :
257+ RCT_KMP_APP_OUTPUT_DIR : ${{ github.workspace }}/packages/react-native/ReactShared/build/apple-app-results
258+ steps :
259+ - name : Checkout
260+ uses : actions/checkout@v6
261+ - name : Set up Node
262+ uses : ./.github/actions/setup-node
263+ - name : Install JavaScript dependencies
264+ uses : ./.github/actions/yarn-install
265+ - name : Select the Hermes compiler package
266+ run : node scripts/releases/use-hermes-prebuilt.js
267+ - name : Install the selected Hermes compiler
268+ uses : ./.github/actions/yarn-install
269+ - name : Set up JDK 17
270+ uses : actions/setup-java@v5
271+ with :
272+ java-version : ' 17'
273+ distribution : ' zulu'
274+ - name : Set up Xcode for Kotlin Native
275+ uses : ./.github/actions/setup-xcode
276+ with :
277+ xcode-version : ' 26.4.1'
278+ - name : Set up Gradle
279+ uses : ./.github/actions/setup-gradle
280+ - name : Set up Ruby and CocoaPods
281+ uses : ruby/setup-ruby@v1
282+ with :
283+ ruby-version : ' 3.2.0'
284+ bundler-cache : true
285+ - name : Cache Kotlin Native toolchain
286+ uses : actions/cache@v5
287+ with :
288+ path : ~/.konan
289+ key : kmp-native-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('packages/react-native/ReactShared/*.gradle.kts', 'packages/react-native/ReactShared/gradle.properties', 'packages/react-native/ReactShared/gradle/wrapper/gradle-wrapper.properties') }}
290+ - name : Build and validate the KMP source application
291+ run : |
292+ if [[ '${{ matrix.linkage }}' != libraries ]]; then
293+ export USE_FRAMEWORKS='${{ matrix.linkage }}'
294+ fi
295+ ./packages/react-native/ReactShared/scripts/test-apple-app.sh '${{ matrix.platform }}'
296+ - name : Upload application test reports
297+ if : always()
298+ uses : actions/upload-artifact@v6
299+ with :
300+ name : kmp-app-${{ matrix.platform }}-${{ matrix.linkage }}
301+ path : |
302+ ${{ env.RCT_KMP_APP_OUTPUT_DIR }}/*.log
303+ ${{ env.RCT_KMP_APP_OUTPUT_DIR }}/*.json
304+ ${{ env.RCT_KMP_APP_OUTPUT_DIR }}/*.txt
305+ ${{ env.RCT_KMP_APP_OUTPUT_DIR }}/*.xcresult
306+ ${{ env.RCT_KMP_APP_OUTPUT_DIR }}/Podfile*
307+ ${{ env.RCT_KMP_APP_OUTPUT_DIR }}/project.pbxproj
308+ if-no-files-found : warn
309+
29310 smoke :
30311 runs-on : macos-26
31312 timeout-minutes : 45
0 commit comments