Skip to content

Commit 7472683

Browse files
Add Bitrise E2E pipeline skeleton
Assisted-By: devx/396ca0c4-44ad-415d-8d80-7200df4e42a4
1 parent 285bb9c commit 7472683

8 files changed

Lines changed: 379 additions & 2 deletions

File tree

dev.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ up:
99
- swiftlint
1010
- swiftformat
1111
- sccache
12+
- bitrise
1213
- ruby
1314
- xcode:
1415
version: "26.2"

e2e/BITRISE.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# Bitrise E2E Pipeline Setup
2+
3+
This document tracks the manual setup required for the Bitrise app that will run Checkout Kit E2E pipelines.
4+
5+
Parent issue: https://github.com/shop/issues-checkout-kit/issues/1096
6+
Epic: https://github.com/shop/issues-checkout-kit/issues/1084
7+
8+
## Bitrise app
9+
10+
Use the allocated Bitrise app and point it at the Checkout Kit repository:
11+
12+
- Bitrise app: https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76
13+
- Repository: `Shopify/checkout-kit`
14+
15+
The app is currently empty and can be reconfigured for this pipeline.
16+
17+
Useful Bitrise app URLs:
18+
19+
| Area | URL |
20+
|---|---|
21+
| App overview | https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76 |
22+
| Workflow/config editor | https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/workflow |
23+
| Secrets/env vars | https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/secrets |
24+
| Code signing | https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/codesigning |
25+
| Build triggers | https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/triggers |
26+
| Start build | https://app.bitrise.io/app/f51f9054-053e-40f1-81e9-ae727567ae76/build/start |
27+
28+
If a direct URL does not resolve in the current Bitrise UI, open the app overview and navigate to the matching area from the sidebar.
29+
30+
## Pipeline
31+
32+
The initial repo-owned pipeline is `e2e` in `e2e/bitrise.yml`.
33+
34+
Configure the Bitrise app to read the YAML from the repository path:
35+
36+
```text
37+
e2e/bitrise.yml
38+
```
39+
40+
Phase 2 only validates the graph shape and intermediate artifact wiring. BrowserStack execution is added in a later phase.
41+
42+
Validate locally with:
43+
44+
```bash
45+
bitrise validate -c e2e/bitrise.yml
46+
```
47+
48+
## Required app environment variables
49+
50+
The non-secret E2E defaults are defined in `e2e/bitrise.yml` under `app.envs`. Do not edit these in the Bitrise Workflow Editor; change them in this repository and submit them through the Graphite stack.
51+
52+
| Variable | Initial value | Purpose |
53+
|---|---|---|
54+
| `E2E_RUN_COUNT` | `2` | Number of expanded matrix rows to run in parallel. Keep this aligned with `ruby e2e/scripts/e2e_matrix count`. |
55+
| `E2E_STRICT` | `false` | Soft/hard failure switch for BrowserStack Maestro runs. |
56+
| `E2E_BROWSERSTACK_API_RETRIES` | `1` | Retries for transient BrowserStack API responses. |
57+
| `E2E_BROWSERSTACK_TIMEOUT_SECONDS` | `1800` | BrowserStack build timeout. |
58+
| `E2E_BROWSERSTACK_POLL_SECONDS` | `30` | BrowserStack status polling interval. |
59+
| `E2E_IOS_EXPORT_METHOD` | `development` | Export method for the React Native iOS IPA. |
60+
| `RBENV_VERSION` | `system` | Forces Bitrise to use the stack Ruby instead of the repository `.ruby-version` when that exact Ruby is not installed. |
61+
62+
Secrets still need to be configured in Bitrise.io.
63+
64+
## Future secrets
65+
66+
Do not add BrowserStack credentials until the BrowserStack integration phase.
67+
68+
Future secret names:
69+
70+
| Secret | Purpose |
71+
|---|---|
72+
| `BROWSERSTACK_USERNAME` | BrowserStack API username |
73+
| `BROWSERSTACK_ACCESS_KEY` | BrowserStack API access key |
74+
75+
## PR trigger
76+
77+
Configure the Bitrise app to run the `e2e` pipeline for pull requests once the skeleton is ready to validate in Bitrise.
78+
79+
## Code signing
80+
81+
React Native iOS IPA generation is added in a later phase and will require Bitrise iOS code signing setup for the sample app.
82+
83+
## Caching
84+
85+
The pipeline uses Bitrise cache steps for key-based pnpm/CocoaPods/Gradle cache paths.
86+
87+
Do not add `activate-build-cache-for-xcode` or `activate-build-cache-for-gradle`; the Bitrise Build Cache add-on is disabled for Shopify Bitrise apps.
88+
89+
Bitrise stacks can also have `rbenv` installed without the repository `.ruby-version`. The pipeline sets `RBENV_VERSION=system` at the app env level so Ruby helpers use the Ruby already available on the Bitrise stack instead of failing when `3.4.4` is not preinstalled.

e2e/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,12 @@ Expand a single run row by index:
3939
ruby e2e/scripts/e2e_matrix expand --index 0
4040
```
4141

42+
Count expanded run rows:
43+
44+
```bash
45+
ruby e2e/scripts/e2e_matrix count
46+
```
47+
4248
## Run locally
4349

4450
Install Maestro locally, launch the target sample app, then run the shared smoke flow with the same environment contract used by CI.

e2e/bitrise.yml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
format_version: "23"
2+
default_step_lib_source: https://github.com/bitrise-io/bitrise-steplib.git
3+
project_type: other
4+
5+
meta:
6+
bitrise.io:
7+
stack: osx-xcode-26.0.x-edge
8+
9+
app:
10+
envs:
11+
- E2E_RUN_COUNT: "2"
12+
- E2E_STRICT: "false"
13+
- E2E_BROWSERSTACK_API_RETRIES: "1"
14+
- E2E_BROWSERSTACK_TIMEOUT_SECONDS: "1800"
15+
- E2E_BROWSERSTACK_POLL_SECONDS: "30"
16+
- E2E_IOS_EXPORT_METHOD: development
17+
- RBENV_VERSION: system
18+
19+
pipelines:
20+
e2e:
21+
workflows:
22+
e2e-package-suite: {}
23+
e2e-build-react-native-ios: {}
24+
e2e-build-react-native-android: {}
25+
e2e-run-browserstack:
26+
depends_on:
27+
- e2e-package-suite
28+
- e2e-build-react-native-ios
29+
- e2e-build-react-native-android
30+
parallel: $E2E_RUN_COUNT
31+
e2e-report:
32+
depends_on:
33+
- e2e-run-browserstack
34+
should_always_run: workflow
35+
36+
workflows:
37+
e2e-package-suite:
38+
steps:
39+
- git-clone@8: {}
40+
- script@1:
41+
title: Validate E2E matrix and create suite placeholder
42+
inputs:
43+
- content: |-
44+
set -euo pipefail
45+
ruby e2e/scripts/e2e_matrix validate
46+
ruby e2e/scripts/e2e_matrix expand > "$BITRISE_DEPLOY_DIR/e2e-matrix.json"
47+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
48+
echo "Phase 2 placeholder for BrowserStack Maestro suite zip" > "$BITRISE_DEPLOY_DIR/e2e/maestro-suite.zip"
49+
envman add --key E2E_MAESTRO_SUITE_ZIP --value "$BITRISE_DEPLOY_DIR/e2e/maestro-suite.zip"
50+
- deploy-to-bitrise-io@2:
51+
inputs:
52+
- pipeline_intermediate_files: |-
53+
$E2E_MAESTRO_SUITE_ZIP:E2E_MAESTRO_SUITE_ZIP
54+
$BITRISE_DEPLOY_DIR/e2e-matrix.json:E2E_MATRIX_JSON
55+
56+
e2e-build-react-native-ios:
57+
steps:
58+
- git-clone@8: {}
59+
- restore-cache@1:
60+
inputs:
61+
- key: |-
62+
rn-ios-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
63+
- script@1:
64+
title: Create React Native iOS artifact placeholder
65+
inputs:
66+
- content: |-
67+
set -euo pipefail
68+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
69+
echo "Phase 2 placeholder for React Native iOS IPA" > "$BITRISE_DEPLOY_DIR/e2e/react-native-ios.ipa"
70+
envman add --key E2E_REACT_NATIVE_IOS_APP_PATH --value "$BITRISE_DEPLOY_DIR/e2e/react-native-ios.ipa"
71+
- deploy-to-bitrise-io@2:
72+
inputs:
73+
- pipeline_intermediate_files: |-
74+
$E2E_REACT_NATIVE_IOS_APP_PATH:E2E_REACT_NATIVE_IOS_APP_PATH
75+
- save-cache@1:
76+
inputs:
77+
- key: |-
78+
rn-ios-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
79+
- paths: |-
80+
platforms/react-native/node_modules
81+
platforms/react-native/sample/ios/Pods
82+
83+
e2e-build-react-native-android:
84+
steps:
85+
- git-clone@8: {}
86+
- restore-cache@1:
87+
inputs:
88+
- key: |-
89+
rn-android-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/android/**/*.gradle*" }}
90+
- script@1:
91+
title: Create React Native Android artifact placeholder
92+
inputs:
93+
- content: |-
94+
set -euo pipefail
95+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
96+
echo "Phase 2 placeholder for React Native Android APK" > "$BITRISE_DEPLOY_DIR/e2e/react-native-android.apk"
97+
envman add --key E2E_REACT_NATIVE_ANDROID_APP_PATH --value "$BITRISE_DEPLOY_DIR/e2e/react-native-android.apk"
98+
- deploy-to-bitrise-io@2:
99+
inputs:
100+
- pipeline_intermediate_files: |-
101+
$E2E_REACT_NATIVE_ANDROID_APP_PATH:E2E_REACT_NATIVE_ANDROID_APP_PATH
102+
- save-cache@1:
103+
inputs:
104+
- key: |-
105+
rn-android-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/android/**/*.gradle*" }}
106+
- paths: |-
107+
platforms/react-native/node_modules
108+
~/.gradle/caches
109+
~/.gradle/wrapper
110+
111+
e2e-run-browserstack:
112+
steps:
113+
- git-clone@8: {}
114+
- pull-intermediate-files@1:
115+
inputs:
116+
- artifact_sources: |-
117+
e2e-package-suite
118+
e2e-build-react-native-*
119+
- script@1:
120+
title: Resolve E2E matrix row placeholder
121+
inputs:
122+
- content: |-
123+
set -euo pipefail
124+
run_index="${BITRISE_IO_PARALLEL_INDEX:-0}"
125+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e/results"
126+
ruby e2e/scripts/e2e_matrix expand --index "$run_index" > "$BITRISE_DEPLOY_DIR/e2e/results/run-${run_index}.json"
127+
- deploy-to-bitrise-io@2:
128+
inputs:
129+
- pipeline_intermediate_files: |-
130+
$BITRISE_DEPLOY_DIR/e2e/results:E2E_BROWSERSTACK_RESULTS_DIR
131+
132+
e2e-report:
133+
steps:
134+
- git-clone@8: {}
135+
- pull-intermediate-files@1:
136+
inputs:
137+
- artifact_sources: |-
138+
e2e-run-browserstack
139+
- script@1:
140+
title: Placeholder E2E report
141+
inputs:
142+
- content: |-
143+
set -euo pipefail
144+
echo "Phase 2 placeholder for aggregate E2E reporting"

e2e/lib/e2e_matrix.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ def run_at(index)
2929
runs.fetch(index)
3030
end
3131

32+
def count
33+
expand.length
34+
end
35+
3236
def validation_errors
3337
errors = []
3438
errors << "version must be 1" unless @config.fetch("version", nil) == 1

e2e/scripts/e2e_matrix

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@ options = {
1010
}
1111

1212
parser = OptionParser.new do |opts|
13-
opts.banner = "Usage: e2e/scripts/e2e_matrix validate|expand [options]"
13+
opts.banner = "Usage: e2e/scripts/e2e_matrix validate|expand|count [options]"
1414
opts.on("--config PATH") { |path| options[:config] = path }
1515
opts.on("--index INDEX", Integer) { |index| options[:index] = index }
1616
end
1717

1818
command = ARGV.shift
1919
parser.parse!(ARGV)
2020

21-
unless ["validate", "expand"].include?(command)
21+
unless ["validate", "expand", "count"].include?(command)
2222
warn parser
2323
exit 1
2424
end
@@ -48,4 +48,12 @@ when "expand"
4848
end
4949

5050
puts JSON.pretty_generate(output)
51+
when "count"
52+
errors = matrix.validation_errors
53+
unless errors.empty?
54+
warn errors.join("\n")
55+
exit 1
56+
end
57+
58+
puts matrix.count
5159
end

0 commit comments

Comments
 (0)