Skip to content

Commit ffb6424

Browse files
Build React Native iOS E2E IPA artifact
Assisted-By: devx/6c1e3ad5-96c8-4972-b087-da7ff7b195c3
1 parent 17f737e commit ffb6424

3 files changed

Lines changed: 125 additions & 6 deletions

File tree

e2e/BITRISE.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ The non-secret E2E defaults are defined in `e2e/bitrise.yml` under `app.envs`. D
6060
| `E2E_BROWSERSTACK_POLL_SECONDS` | `30` | BrowserStack status polling interval. |
6161
| `E2E_IOS_EXPORT_METHOD` | `development` | Export method for the React Native iOS IPA. |
6262
| `E2E_ANDROID_COMMAND_TIMEOUT_SECONDS` | `1800` | Per-command timeout for React Native Android artifact commands. |
63+
| `E2E_IOS_COMMAND_TIMEOUT_SECONDS` | `1800` | Per-command timeout for React Native iOS dependency, CocoaPods, archive, and export commands. |
6364
| `E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS` | `300` | Per-command timeout for package-suite matrix and suite commands. |
6465
| `E2E_RUBY_INSTALL_TIMEOUT_SECONDS` | `1800` | Timeout for installing the exact repository Ruby version from `.ruby-version`. |
6566

@@ -87,7 +88,11 @@ Configure the Bitrise app to run the `e2e` pipeline for pull requests once the s
8788

8889
## Code signing
8990

90-
React Native iOS IPA generation is added in a later phase and will require Bitrise iOS code signing setup for the sample app.
91+
React Native iOS IPA generation uses Bitrise's certificate and profile installer before running `xcodebuild archive` and `xcodebuild -exportArchive`.
92+
93+
The React Native iOS artifact workflow overrides the default Linux stack and runs on `osx-xcode-26.0.x-edge` with `g2.mac.4large`, because it requires Xcode and iOS signing. Its cache keys are prefixed with `rn-ios-macos-` so macOS caches cannot restore Linux-built dependencies.
94+
95+
Upload the required signing certificate and provisioning profile for the React Native sample app to the Bitrise app before running the iOS artifact workflow.
9196

9297
## Caching
9398

e2e/bitrise.yml

Lines changed: 65 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ app:
1616
- E2E_BROWSERSTACK_POLL_SECONDS: "30"
1717
- E2E_IOS_EXPORT_METHOD: development
1818
- E2E_ANDROID_COMMAND_TIMEOUT_SECONDS: "1800"
19+
- E2E_IOS_COMMAND_TIMEOUT_SECONDS: "1800"
1920
- E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS: "300"
2021
- E2E_RUBY_INSTALL_TIMEOUT_SECONDS: "1800"
2122

@@ -62,28 +63,87 @@ workflows:
6263
$BITRISE_DEPLOY_DIR/e2e-matrix.json:E2E_MATRIX_JSON
6364
6465
e2e-build-react-native-ios:
66+
meta:
67+
bitrise.io:
68+
stack: osx-xcode-26.0.x-edge
69+
machine_type_id: g2.mac.4large
6570
steps:
6671
- git-clone@8: {}
72+
- certificate-and-profile-installer@1: {}
6773
- restore-cache@1:
6874
inputs:
6975
- key: |-
70-
rn-ios-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
76+
rn-ios-macos-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
7177
- script@1:
72-
title: Create React Native iOS artifact placeholder
78+
title: Build React Native iOS IPA artifact
7379
inputs:
7480
- content: |-
7581
set -euo pipefail
82+
source e2e/scripts/bitrise_ci_helpers
83+
e2e_prepare_ruby
84+
e2e_log "Enabling Corepack"
85+
corepack enable
86+
e2e_log "Checking storefront configuration secrets"
87+
: "${STOREFRONT_DOMAIN:?STOREFRONT_DOMAIN is required. Check https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/workflow_editor#!/secrets and enable Expose for pull requests.}"
88+
: "${STOREFRONT_ACCESS_TOKEN:?STOREFRONT_ACCESS_TOKEN is required. Check https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/workflow_editor#!/secrets and enable Expose for pull requests.}"
89+
e2e_log "Configuring storefront environment"
90+
./scripts/setup_storefront_env --skip-optional-prompts
91+
e2e_log "Installing React Native dependencies"
92+
cd platforms/react-native
93+
e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" pnpm install --frozen-lockfile
94+
cd sample
95+
e2e_log "Installing iOS Ruby dependencies"
96+
e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" bundle install
97+
cd ios
98+
e2e_log "Installing CocoaPods dependencies"
99+
e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" bundle exec pod install --deployment --repo-update
76100
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
77-
echo "Phase 2 placeholder for React Native iOS IPA" > "$BITRISE_DEPLOY_DIR/e2e/react-native-ios.ipa"
78-
envman add --key E2E_REACT_NATIVE_IOS_APP_PATH --value "$BITRISE_DEPLOY_DIR/e2e/react-native-ios.ipa"
101+
archive_path="$BITRISE_DEPLOY_DIR/e2e/CheckoutKitReactNativeDemo.xcarchive"
102+
export_path="$BITRISE_DEPLOY_DIR/e2e/react-native-ios-export"
103+
export_options="$BITRISE_DEPLOY_DIR/e2e/ExportOptions.plist"
104+
export_method="${E2E_IOS_EXPORT_METHOD:-development}"
105+
cat > "$export_options" <<PLIST
106+
<?xml version="1.0" encoding="UTF-8"?>
107+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
108+
<plist version="1.0">
109+
<dict>
110+
<key>method</key>
111+
<string>$export_method</string>
112+
<key>signingStyle</key>
113+
<string>automatic</string>
114+
<key>stripSwiftSymbols</key>
115+
<true/>
116+
<key>compileBitcode</key>
117+
<false/>
118+
</dict>
119+
</plist>
120+
PLIST
121+
e2e_log "Archiving React Native iOS app"
122+
e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" xcodebuild archive \
123+
-workspace CheckoutKitReactNativeDemo.xcworkspace \
124+
-scheme CheckoutKitReactNativeDemo \
125+
-configuration Release \
126+
-sdk iphoneos \
127+
-destination generic/platform=iOS \
128+
-archivePath "$archive_path" \
129+
-skipPackagePluginValidation
130+
e2e_log "Exporting React Native iOS IPA"
131+
e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" xcodebuild -exportArchive \
132+
-archivePath "$archive_path" \
133+
-exportPath "$export_path" \
134+
-exportOptionsPlist "$export_options"
135+
ios_ipa="$(find "$export_path" -name "*.ipa" -print -quit)"
136+
test -f "$ios_ipa"
137+
e2e_log "Publishing iOS IPA path"
138+
envman add --key E2E_REACT_NATIVE_IOS_APP_PATH --value "$ios_ipa"
79139
- deploy-to-bitrise-io@2:
80140
inputs:
81141
- pipeline_intermediate_files: |-
82142
$E2E_REACT_NATIVE_IOS_APP_PATH:E2E_REACT_NATIVE_IOS_APP_PATH
83143
- save-cache@1:
84144
inputs:
85145
- key: |-
86-
rn-ios-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
146+
rn-ios-macos-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
87147
- paths: |-
88148
platforms/react-native/node_modules
89149
platforms/react-native/sample/ios/Pods

e2e/test/bitrise_pipeline_test.rb

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,60 @@ def test_react_native_android_workflow_does_not_use_local_native_sdk_overrides
161161
refute_includes script, "--local"
162162
end
163163

164+
def test_react_native_ios_workflow_uses_macos_xcode_resources
165+
workflow = load_bitrise_config.fetch("workflows").fetch("e2e-build-react-native-ios")
166+
meta = workflow.fetch("meta").fetch("bitrise.io")
167+
168+
assert_equal "osx-xcode-26.0.x-edge", meta.fetch("stack")
169+
assert_equal "g2.mac.4large", meta.fetch("machine_type_id")
170+
end
171+
172+
def test_react_native_ios_workflow_builds_real_ipa_artifact
173+
config = load_bitrise_config
174+
script = workflow_script("e2e-build-react-native-ios")
175+
176+
assert_equal "1800", app_env_values.fetch("E2E_IOS_COMMAND_TIMEOUT_SECONDS")
177+
assert_workflow_has_step(config, "e2e-build-react-native-ios", "certificate-and-profile-installer")
178+
assert_includes script, "source e2e/scripts/bitrise_ci_helpers"
179+
assert_includes script, "e2e_prepare_ruby"
180+
assert_includes script, 'e2e_log "Checking storefront configuration secrets"'
181+
assert_includes script, 'STOREFRONT_DOMAIN is required'
182+
assert_includes script, 'STOREFRONT_ACCESS_TOKEN is required'
183+
assert_includes script, 'workflow_editor#!/secrets'
184+
assert_includes script, 'Expose for pull requests'
185+
assert_includes script, 'e2e_log "Configuring storefront environment"'
186+
assert_includes script, 'e2e_log "Installing React Native dependencies"'
187+
assert_includes script, 'e2e_log "Installing iOS Ruby dependencies"'
188+
assert_includes script, 'e2e_log "Installing CocoaPods dependencies"'
189+
assert_includes script, 'e2e_log "Archiving React Native iOS app"'
190+
assert_includes script, 'e2e_log "Exporting React Native iOS IPA"'
191+
assert_includes script, 'e2e_log "Publishing iOS IPA path"'
192+
assert_includes script, "corepack enable"
193+
assert_includes script, "cd platforms/react-native"
194+
assert_command_order script, "cd platforms/react-native", "pnpm install --frozen-lockfile"
195+
assert_includes script, "pnpm install --frozen-lockfile"
196+
assert_includes script, "./scripts/setup_storefront_env --skip-optional-prompts"
197+
assert_includes script, 'e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" pnpm install --frozen-lockfile'
198+
assert_includes script, 'e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" bundle install'
199+
assert_includes script, 'e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" bundle exec pod install --deployment --repo-update'
200+
assert_includes script, 'e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" xcodebuild archive'
201+
assert_includes script, 'e2e_run_with_timeout "${E2E_IOS_COMMAND_TIMEOUT_SECONDS:-1800}" xcodebuild -exportArchive'
202+
assert_includes script, "bundle exec pod install --deployment --repo-update"
203+
assert_includes script, "xcodebuild archive"
204+
assert_includes script, "-sdk iphoneos"
205+
assert_includes script, "generic/platform=iOS"
206+
assert_includes script, "xcodebuild -exportArchive"
207+
assert_includes script, "E2E_REACT_NATIVE_IOS_APP_PATH"
208+
refute_includes script, "Phase 2 placeholder for React Native iOS IPA"
209+
end
210+
211+
def test_react_native_ios_workflow_does_not_use_local_native_sdk_overrides
212+
script = workflow_script("e2e-build-react-native-ios")
213+
214+
refute_includes script, "USE_LOCAL_SDK"
215+
refute_includes script, "--local"
216+
end
217+
164218
def test_bitrise_setup_docs_exist
165219
assert File.exist?("e2e/BITRISE.md")
166220
end

0 commit comments

Comments
 (0)