Skip to content

Commit d1159c3

Browse files
committed
ci(ios): Parallelize snapshot workflow across simulator matrix
Split the Sentry snapshots workflow into three stages: a single build-for-testing job that archives the test products, a matrix job that runs the snapshot tests on each simulator in parallel, and a final aggregation job that downloads every per-sim artifact and uploads them to Sentry in one fastlane invocation. Rename the workflows to "Sentry Snapshots Upload" so the renamed naming is consistent between the sequential and Swift Snapshot Testing variants.
1 parent c4233ee commit d1159c3

2 files changed

Lines changed: 129 additions & 42 deletions

File tree

.github/workflows/ios_sentry_upload_snapshots.yml

Lines changed: 128 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Sentry iOS Upload (Snapshots)
1+
name: Sentry Snapshots Upload
22

33
on:
44
push:
@@ -15,9 +15,12 @@ defaults:
1515
env:
1616
DERIVED_DATA_PATH: ${{ github.workspace }}/DerivedData-snapshot-upload
1717
SNAPSHOT_UPLOAD_BASE_DIR: ${{ github.workspace }}/ios/snapshot-images
18+
BUILD_PRODUCTS_ARCHIVE: ${{ github.workspace }}/snapshot-build-products.tar.gz
1819

1920
jobs:
20-
upload_sentry_snapshots:
21+
# Build the snapshot test bundle once on a single runner, then share the
22+
# products with downstream simulator jobs via an artifact.
23+
build_for_testing:
2124
runs-on: macos-26
2225

2326
env:
@@ -41,6 +44,9 @@ jobs:
4144
- name: Setup gems
4245
run: exec ../.github/scripts/ios/setup.sh
4346

47+
- name: Prepare DerivedData directory
48+
run: mkdir -p "${DERIVED_DATA_PATH}"
49+
4450
- name: Cache Swift Package Manager
4551
uses: actions/cache@v4
4652
with:
@@ -50,20 +56,7 @@ jobs:
5056
key: ${{ runner.os }}-spm-${{ hashFiles('**/Package.resolved') }}
5157
restore-keys: ${{ runner.os }}-spm-
5258

53-
- name: Prepare snapshot directories
54-
run: |
55-
mkdir -p "${SNAPSHOT_UPLOAD_BASE_DIR}/iphone-17-pro-max"
56-
mkdir -p "${SNAPSHOT_UPLOAD_BASE_DIR}/iphone-17e"
57-
mkdir -p "${SNAPSHOT_UPLOAD_BASE_DIR}/ipad-air-11-inch-m4"
58-
mkdir -p "${DERIVED_DATA_PATH}"
59-
60-
- name: Boot simulators
61-
run: |
62-
xcrun simctl boot "iPhone 17 Pro Max" || true
63-
xcrun simctl boot "iPhone 17e" || true
64-
xcrun simctl boot "iPad Air 11-inch (M4)" || true
65-
66-
- name: Build snapshot tests
59+
- name: Build snapshot tests for distribution
6760
run: |
6861
set -o pipefail && xcodebuild build-for-testing \
6962
-scheme HackerNews \
@@ -82,6 +75,77 @@ jobs:
8275
FUSE_BUILD_SCRIPT_PHASES=YES \
8376
| xcpretty
8477
78+
- name: Archive test products
79+
run: tar -C "${DERIVED_DATA_PATH}/Build" -czf "${BUILD_PRODUCTS_ARCHIVE}" Products
80+
81+
- name: Upload build products artifact
82+
uses: actions/upload-artifact@v7
83+
with:
84+
name: snapshot-build-products
85+
path: ${{ env.BUILD_PRODUCTS_ARCHIVE }}
86+
if-no-files-found: error
87+
88+
# One simulator per runner. Each job extracts the shared build products,
89+
# runs the snapshot tests, and uploads its PNGs as a per-sim artifact so
90+
# the final job can aggregate them.
91+
generate_snapshots:
92+
runs-on: macos-26
93+
needs: build_for_testing
94+
95+
strategy:
96+
fail-fast: false
97+
matrix:
98+
include:
99+
- simulator_name: iPhone 17 Pro Max
100+
slug: iphone-17-pro-max
101+
- simulator_name: iPhone 17e
102+
slug: iphone-17e
103+
- simulator_name: iPad Air 11-inch (M4)
104+
slug: ipad-air-11-inch-m4
105+
106+
env:
107+
XCODE_RUNNING_FOR_PREVIEWS: 1
108+
109+
steps:
110+
- name: Checkout
111+
uses: actions/checkout@v6
112+
with:
113+
fetch-depth: 0
114+
115+
- name: Select Xcode 26.4
116+
run: sudo xcode-select -s /Applications/Xcode_26.4.app
117+
118+
- name: Set up Ruby env
119+
uses: ruby/setup-ruby@v1
120+
with:
121+
ruby-version: 3.3.10
122+
bundler-cache: true
123+
124+
- name: Setup gems
125+
run: exec ../.github/scripts/ios/setup.sh
126+
127+
- name: Download build products artifact
128+
uses: actions/download-artifact@v5
129+
with:
130+
name: snapshot-build-products
131+
path: ${{ github.workspace }}
132+
133+
- name: Extract test products
134+
# Restore the build products back under the same DerivedData path used
135+
# during build-for-testing. The generated .xctestrun file references
136+
# those product locations directly, so test-without-building does not
137+
# need an extra -derivedDataPath flag as long as we recreate the same
138+
# layout on each runner.
139+
run: |
140+
mkdir -p "${DERIVED_DATA_PATH}/Build"
141+
tar -C "${DERIVED_DATA_PATH}/Build" -xzf "${BUILD_PRODUCTS_ARCHIVE}"
142+
143+
- name: Set snapshot export directory
144+
# Xcode strips the TEST_RUNNER_ prefix and forwards the rest into the
145+
# test runner process, which is how the snapshot tests discover where
146+
# to write PNGs.
147+
run: echo "TEST_RUNNER_SNAPSHOTS_EXPORT_DIR=${SNAPSHOT_UPLOAD_BASE_DIR}/${{ matrix.slug }}" >> "$GITHUB_ENV"
148+
85149
- name: Resolve xctestrun file
86150
run: |
87151
XCTESTRUN_PATH="$(find "${DERIVED_DATA_PATH}/Build/Products" -name '*.xctestrun' -print -quit)"
@@ -91,40 +155,63 @@ jobs:
91155
fi
92156
echo "XCTESTRUN_PATH=${XCTESTRUN_PATH}" >> "$GITHUB_ENV"
93157
94-
- name: Generate snapshot images (iPhone 17 Pro Max)
95-
env:
96-
TEST_RUNNER_SNAPSHOTS_EXPORT_DIR: ${{ env.SNAPSHOT_UPLOAD_BASE_DIR }}/iphone-17-pro-max
97-
run: |
98-
set -o pipefail && xcodebuild test-without-building \
99-
-xctestrun "${XCTESTRUN_PATH}" \
100-
-destination 'platform=iOS Simulator,name=iPhone 17 Pro Max,arch=arm64' \
101-
-only-testing:HackerNewsTests/HackerNewsSnapshotTest \
102-
-resultBundlePath ../SnapshotResults-iphone-17-pro-max.xcresult \
103-
| xcpretty
158+
- name: Boot simulator
159+
run: xcrun simctl boot "${{ matrix.simulator_name }}" || true
104160

105-
- name: Generate snapshot images (iPhone 17e)
106-
env:
107-
TEST_RUNNER_SNAPSHOTS_EXPORT_DIR: ${{ env.SNAPSHOT_UPLOAD_BASE_DIR }}/iphone-17e
108-
run: |
109-
set -o pipefail && xcodebuild test-without-building \
110-
-xctestrun "${XCTESTRUN_PATH}" \
111-
-destination 'platform=iOS Simulator,name=iPhone 17e,arch=arm64' \
112-
-only-testing:HackerNewsTests/HackerNewsSnapshotTest \
113-
-resultBundlePath ../SnapshotResults-iphone-17e.xcresult \
114-
| xcpretty
161+
- name: Prepare snapshot export directory
162+
run: mkdir -p "${TEST_RUNNER_SNAPSHOTS_EXPORT_DIR}"
115163

116-
- name: Generate snapshot images (iPad)
117-
env:
118-
TEST_RUNNER_SNAPSHOTS_EXPORT_DIR: ${{ env.SNAPSHOT_UPLOAD_BASE_DIR }}/ipad-air-11-inch-m4
164+
- name: Generate snapshot images
119165
run: |
120166
set -o pipefail && xcodebuild test-without-building \
121167
-xctestrun "${XCTESTRUN_PATH}" \
122-
-destination 'platform=iOS Simulator,name=iPad Air 11-inch (M4),arch=arm64' \
168+
-destination 'platform=iOS Simulator,name=${{ matrix.simulator_name }},arch=arm64' \
123169
-only-testing:HackerNewsTests/HackerNewsSnapshotTest \
124-
-resultBundlePath ../SnapshotResults-ipad-air-11-inch-m4.xcresult \
170+
-resultBundlePath "../SnapshotResults-${{ matrix.slug }}.xcresult" \
125171
| xcpretty
126172
127173
- name: List generated snapshot files
174+
run: |
175+
echo "Generated snapshot files for ${{ matrix.simulator_name }}:"
176+
find "${TEST_RUNNER_SNAPSHOTS_EXPORT_DIR}" -type f | sort
177+
echo
178+
echo "Total PNG images: $(find "${TEST_RUNNER_SNAPSHOTS_EXPORT_DIR}" -type f -name '*.png' | wc -l | tr -d ' ')"
179+
180+
- name: Upload generated snapshots
181+
uses: actions/upload-artifact@v7
182+
with:
183+
name: ${{ matrix.slug }}
184+
path: ${{ env.TEST_RUNNER_SNAPSHOTS_EXPORT_DIR }}
185+
if-no-files-found: error
186+
187+
# Aggregate every per-sim artifact and upload the combined set to Sentry
188+
# in a single fastlane invocation.
189+
upload_snapshots:
190+
runs-on: macos-26
191+
needs: generate_snapshots
192+
193+
steps:
194+
- name: Checkout
195+
uses: actions/checkout@v6
196+
with:
197+
fetch-depth: 0
198+
199+
- name: Set up Ruby env
200+
uses: ruby/setup-ruby@v1
201+
with:
202+
ruby-version: 3.3.10
203+
bundler-cache: true
204+
205+
- name: Setup gems
206+
run: exec ../.github/scripts/ios/setup.sh
207+
208+
- name: Download generated snapshots
209+
uses: actions/download-artifact@v5
210+
with:
211+
path: ${{ env.SNAPSHOT_UPLOAD_BASE_DIR }}
212+
pattern: "*"
213+
214+
- name: List aggregated snapshot files
128215
run: |
129216
echo "Generated snapshot files:"
130217
find "${SNAPSHOT_UPLOAD_BASE_DIR}" -type f | sort

.github/workflows/ios_sentry_upload_swift_snapshots.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
name: Sentry iOS Upload (Swift Snapshot Testing)
1+
name: Sentry Snapshots Upload (Swift Snapshot Testing)
22

33
on:
44
push:

0 commit comments

Comments
 (0)