Skip to content

Commit 670a50e

Browse files
Add Bitrise E2E pipeline skeleton
Assisted-By: devx/6c1e3ad5-96c8-4972-b087-da7ff7b195c3
1 parent 285bb9c commit 670a50e

12 files changed

Lines changed: 1090 additions & 2 deletions

File tree

.agents/skills/using-bitrise-ci/SKILL.md

Lines changed: 481 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Building Pipelines
2+
3+
Pipelines allow creating complex processes from workflows with dependencies, parallel or sequential execution, sharding and sharing files. Documentation is available [here](https://docs.bitrise.io/en/bitrise-ci/workflows-and-pipelines/build-pipelines/configuring-a-bitrise-pipeline.html).
4+
5+
## Execution order
6+
7+
**Parallel execution**: Workflows that don't depend on each other can run concurrently
8+
```yaml
9+
pipelines:
10+
tests:
11+
workflows:
12+
test_ios:
13+
depends_on: [setup]
14+
test_android:
15+
depends_on: [setup]
16+
# test_ios and test_android run in parallel after setup completes
17+
```
18+
19+
**Sequential execution**: Chain dependencies for ordered execution
20+
```yaml
21+
pipelines:
22+
ci:
23+
workflows:
24+
build:
25+
depends_on: [setup]
26+
test:
27+
depends_on: [build]
28+
deploy:
29+
depends_on: [test]
30+
# Executes: setup → build → test → deploy
31+
```
32+
33+
## Passing Data Between Workflows
34+
35+
Workflows do not have access to the data of other workflows, as they are running in separate virtual machines. To share artifacts or other data across workflow boundaries in pipelines, use the following pattern:
36+
37+
```yaml
38+
workflows:
39+
build_app:
40+
steps:
41+
- xcode-archive@5: {}
42+
- deploy-to-bitrise-io@2:
43+
inputs:
44+
- deploy_path: $BITRISE_IPA_PATH
45+
46+
test_integration:
47+
depends_on: [build_app]
48+
steps:
49+
- pull-intermediate-files@1: {}
50+
- script@1:
51+
inputs:
52+
- content: |
53+
# Access artifacts from previous workflow
54+
echo "Using artifacts from $BITRISE_PULL_ARTIFACTS_DIR"
55+
```
56+
57+
Artifacts uploaded via `deploy-to-bitrise-io` in one workflow can be pulled by dependent workflows using `pull-intermediate-files`. Environment variables set in pipeline stages are accessible to all workflows in that pipeline.
58+
59+
## Test Sharding
60+
61+
Split test execution across parallel workflows for faster results:
62+
63+
```yaml
64+
workflows:
65+
test-without-building:
66+
depends_on: [build-for-testing]
67+
parallel: 5
68+
```
69+
Each copy receives two new Environment Variables:
70+
- `$BITRISE_IO_PARALLEL_INDEX`: a zero based index for each copy of the Workflow.
71+
- `$BITRISE_IO_PARALLEL_TOTAL`: the total number of copies.
72+
73+
XCode test and Gradle runner also support automatic shard calculation, see [this page](https://docs.bitrise.io/en/bitrise-ci/testing/test-sharding.html) for details.
74+
75+
## Stages (legacy)
76+
77+
Older, existing configuration might be using [stages](https://docs.bitrise.io/en/bitrise-ci/workflows-and-pipelines/build-pipelines/pipelines-with-stages.html). Example:
78+
79+
```yaml
80+
pipelines:
81+
pipeline-successful:
82+
stages:
83+
- stage-successful-1: {}
84+
- stage-successful-2: {}
85+
- stage-successful-3: {}
86+
stages:
87+
stage-successful-1:
88+
workflows:
89+
- test-1: {}
90+
stage-successful-2:
91+
workflows:
92+
- build-1: {}
93+
- build-2: {}
94+
stage-successful-3:
95+
workflows:
96+
- deploy-1: {}
97+
- deploy-2: {}
98+
workflows:
99+
test-1: {}
100+
build-1: {}
101+
build-2: {}
102+
deploy-1: {}
103+
deploy-2: {}
104+
```
105+
106+
Workflows in a stage run in parallel. Stages run sequentially, after all workflows in the previous stage have completed.

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: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
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+
| `E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS` | `300` | Per-command timeout for package-suite matrix and suite commands. |
61+
| `E2E_RUBY_INSTALL_TIMEOUT_SECONDS` | `1800` | Timeout for installing the exact repository Ruby version from `.ruby-version`. |
62+
63+
Secrets still need to be configured in Bitrise.io.
64+
65+
## Future secrets
66+
67+
Do not add BrowserStack credentials until the BrowserStack integration phase.
68+
69+
Future secret names:
70+
71+
| Secret | Purpose |
72+
|---|---|
73+
| `BROWSERSTACK_USERNAME` | BrowserStack API username |
74+
| `BROWSERSTACK_ACCESS_KEY` | BrowserStack API access key |
75+
76+
## PR trigger
77+
78+
Configure the Bitrise app to run the `e2e` pipeline for pull requests once the skeleton is ready to validate in Bitrise.
79+
80+
## Code signing
81+
82+
React Native iOS IPA generation is added in a later phase and will require Bitrise iOS code signing setup for the sample app.
83+
84+
## Caching
85+
86+
The pipeline uses Bitrise cache steps for key-based pnpm/CocoaPods/Gradle cache paths.
87+
88+
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.
89+
90+
Bitrise stacks can also have `rbenv` installed without the repository `.ruby-version`. The pipeline sources `e2e/scripts/bitrise_ci_helpers` and installs the exact Ruby version from `.ruby-version` with `rbenv install -s` before Ruby helpers run.

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: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
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+
- E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS: "300"
18+
- E2E_RUBY_INSTALL_TIMEOUT_SECONDS: "1800"
19+
20+
pipelines:
21+
e2e:
22+
workflows:
23+
e2e-package-suite: {}
24+
e2e-build-react-native-ios: {}
25+
e2e-build-react-native-android: {}
26+
e2e-run-browserstack:
27+
depends_on:
28+
- e2e-package-suite
29+
- e2e-build-react-native-ios
30+
- e2e-build-react-native-android
31+
parallel: $E2E_RUN_COUNT
32+
e2e-report:
33+
depends_on:
34+
- e2e-run-browserstack
35+
should_always_run: workflow
36+
37+
workflows:
38+
e2e-package-suite:
39+
steps:
40+
- git-clone@8: {}
41+
- script@1:
42+
title: Validate E2E matrix and create suite placeholder
43+
inputs:
44+
- content: |-
45+
set -euo pipefail
46+
source e2e/scripts/bitrise_ci_helpers
47+
e2e_prepare_ruby
48+
e2e_run_with_timeout "${E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS:-300}" ruby e2e/scripts/e2e_matrix validate
49+
e2e_log "Expanding E2E matrix"
50+
e2e_run_with_timeout "${E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS:-300}" ruby e2e/scripts/e2e_matrix expand > "$BITRISE_DEPLOY_DIR/e2e-matrix.json"
51+
e2e_log "Creating Maestro suite placeholder"
52+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
53+
echo "Phase 2 placeholder for BrowserStack Maestro suite zip" > "$BITRISE_DEPLOY_DIR/e2e/maestro-suite.zip"
54+
e2e_log "Publishing Maestro suite path"
55+
envman add --key E2E_MAESTRO_SUITE_ZIP --value "$BITRISE_DEPLOY_DIR/e2e/maestro-suite.zip"
56+
- deploy-to-bitrise-io@2:
57+
inputs:
58+
- pipeline_intermediate_files: |-
59+
$E2E_MAESTRO_SUITE_ZIP:E2E_MAESTRO_SUITE_ZIP
60+
$BITRISE_DEPLOY_DIR/e2e-matrix.json:E2E_MATRIX_JSON
61+
62+
e2e-build-react-native-ios:
63+
steps:
64+
- git-clone@8: {}
65+
- restore-cache@1:
66+
inputs:
67+
- key: |-
68+
rn-ios-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
69+
- script@1:
70+
title: Create React Native iOS artifact placeholder
71+
inputs:
72+
- content: |-
73+
set -euo pipefail
74+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
75+
echo "Phase 2 placeholder for React Native iOS IPA" > "$BITRISE_DEPLOY_DIR/e2e/react-native-ios.ipa"
76+
envman add --key E2E_REACT_NATIVE_IOS_APP_PATH --value "$BITRISE_DEPLOY_DIR/e2e/react-native-ios.ipa"
77+
- deploy-to-bitrise-io@2:
78+
inputs:
79+
- pipeline_intermediate_files: |-
80+
$E2E_REACT_NATIVE_IOS_APP_PATH:E2E_REACT_NATIVE_IOS_APP_PATH
81+
- save-cache@1:
82+
inputs:
83+
- key: |-
84+
rn-ios-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/ios/Podfile.lock" }}
85+
- paths: |-
86+
platforms/react-native/node_modules
87+
platforms/react-native/sample/ios/Pods
88+
89+
e2e-build-react-native-android:
90+
steps:
91+
- git-clone@8: {}
92+
- restore-cache@1:
93+
inputs:
94+
- key: |-
95+
rn-android-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/android/**/*.gradle*" }}
96+
- script@1:
97+
title: Create React Native Android artifact placeholder
98+
inputs:
99+
- content: |-
100+
set -euo pipefail
101+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e"
102+
echo "Phase 2 placeholder for React Native Android APK" > "$BITRISE_DEPLOY_DIR/e2e/react-native-android.apk"
103+
envman add --key E2E_REACT_NATIVE_ANDROID_APP_PATH --value "$BITRISE_DEPLOY_DIR/e2e/react-native-android.apk"
104+
- deploy-to-bitrise-io@2:
105+
inputs:
106+
- pipeline_intermediate_files: |-
107+
$E2E_REACT_NATIVE_ANDROID_APP_PATH:E2E_REACT_NATIVE_ANDROID_APP_PATH
108+
- save-cache@1:
109+
inputs:
110+
- key: |-
111+
rn-android-{{ checksum "platforms/react-native/pnpm-lock.yaml" }}-{{ checksum "platforms/react-native/sample/android/**/*.gradle*" }}
112+
- paths: |-
113+
platforms/react-native/node_modules
114+
~/.gradle/caches
115+
~/.gradle/wrapper
116+
117+
e2e-run-browserstack:
118+
steps:
119+
- git-clone@8: {}
120+
- pull-intermediate-files@1:
121+
inputs:
122+
- artifact_sources: |-
123+
e2e-package-suite
124+
e2e-build-react-native-*
125+
- script@1:
126+
title: Resolve E2E matrix row placeholder
127+
inputs:
128+
- content: |-
129+
set -euo pipefail
130+
source e2e/scripts/bitrise_ci_helpers
131+
e2e_prepare_ruby
132+
run_index="${BITRISE_IO_PARALLEL_INDEX:-0}"
133+
mkdir -p "$BITRISE_DEPLOY_DIR/e2e/results"
134+
e2e_log "Resolving E2E matrix row ${run_index}"
135+
e2e_run_with_timeout "${E2E_PACKAGE_COMMAND_TIMEOUT_SECONDS:-300}" ruby e2e/scripts/e2e_matrix expand --index "$run_index" > "$BITRISE_DEPLOY_DIR/e2e/results/run-${run_index}.json"
136+
- deploy-to-bitrise-io@2:
137+
inputs:
138+
- pipeline_intermediate_files: |-
139+
$BITRISE_DEPLOY_DIR/e2e/results:E2E_BROWSERSTACK_RESULTS_DIR
140+
141+
e2e-report:
142+
steps:
143+
- git-clone@8: {}
144+
- pull-intermediate-files@1:
145+
inputs:
146+
- artifact_sources: |-
147+
e2e-run-browserstack
148+
- script@1:
149+
title: Placeholder E2E report
150+
inputs:
151+
- content: |-
152+
set -euo pipefail
153+
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

0 commit comments

Comments
 (0)