Skip to content

Commit 9e3d7cd

Browse files
gh-142278: Add granular change detection for platforms in CI (#142350)
Co-authored-by: Hugo van Kemenade <[email protected]>
1 parent 97f0a1f commit 9e3d7cd

File tree

3 files changed

+130
-45
lines changed

3 files changed

+130
-45
lines changed

.github/workflows/build.yml

Lines changed: 22 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ jobs:
191191
macOS
192192
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
193193
needs: build-context
194-
if: needs.build-context.outputs.run-tests == 'true'
194+
if: needs.build-context.outputs.run-macos == 'true'
195195
strategy:
196196
fail-fast: false
197197
matrix:
@@ -217,7 +217,7 @@ jobs:
217217
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
218218
${{ fromJSON(matrix.bolt) && '(bolt)' || '' }}
219219
needs: build-context
220-
if: needs.build-context.outputs.run-tests == 'true'
220+
if: needs.build-context.outputs.run-ubuntu == 'true'
221221
strategy:
222222
fail-fast: false
223223
matrix:
@@ -248,7 +248,7 @@ jobs:
248248
runs-on: ${{ matrix.os }}
249249
timeout-minutes: 60
250250
needs: build-context
251-
if: needs.build-context.outputs.run-tests == 'true'
251+
if: needs.build-context.outputs.run-ubuntu == 'true'
252252
strategy:
253253
fail-fast: false
254254
matrix:
@@ -304,7 +304,7 @@ jobs:
304304
runs-on: ${{ matrix.os }}
305305
timeout-minutes: 60
306306
needs: build-context
307-
if: needs.build-context.outputs.run-tests == 'true'
307+
if: needs.build-context.outputs.run-ubuntu == 'true'
308308
strategy:
309309
fail-fast: false
310310
matrix:
@@ -368,7 +368,7 @@ jobs:
368368
build-android:
369369
name: Android (${{ matrix.arch }})
370370
needs: build-context
371-
if: needs.build-context.outputs.run-tests == 'true'
371+
if: needs.build-context.outputs.run-android == 'true'
372372
timeout-minutes: 60
373373
strategy:
374374
fail-fast: false
@@ -390,7 +390,7 @@ jobs:
390390
build-ios:
391391
name: iOS
392392
needs: build-context
393-
if: needs.build-context.outputs.run-tests == 'true'
393+
if: needs.build-context.outputs.run-ios == 'true'
394394
timeout-minutes: 60
395395
runs-on: macos-15
396396
steps:
@@ -413,15 +413,15 @@ jobs:
413413
build-wasi:
414414
name: 'WASI'
415415
needs: build-context
416-
if: needs.build-context.outputs.run-tests == 'true'
416+
if: needs.build-context.outputs.run-wasi == 'true'
417417
uses: ./.github/workflows/reusable-wasi.yml
418418

419419
test-hypothesis:
420420
name: "Hypothesis tests on Ubuntu"
421421
runs-on: ubuntu-24.04
422422
timeout-minutes: 60
423423
needs: build-context
424-
if: needs.build-context.outputs.run-tests == 'true'
424+
if: needs.build-context.outputs.run-ubuntu == 'true'
425425
env:
426426
OPENSSL_VER: 3.0.18
427427
PYTHONSTRICTEXTENSIONBUILD: 1
@@ -528,7 +528,7 @@ jobs:
528528
runs-on: ${{ matrix.os }}
529529
timeout-minutes: 60
530530
needs: build-context
531-
if: needs.build-context.outputs.run-tests == 'true'
531+
if: needs.build-context.outputs.run-ubuntu == 'true'
532532
strategy:
533533
fail-fast: false
534534
matrix:
@@ -581,7 +581,7 @@ jobs:
581581
# ${{ '' } is a hack to nest jobs under the same sidebar category.
582582
name: Sanitizers${{ '' }} # zizmor: ignore[obfuscation]
583583
needs: build-context
584-
if: needs.build-context.outputs.run-tests == 'true'
584+
if: needs.build-context.outputs.run-ubuntu == 'true'
585585
strategy:
586586
fail-fast: false
587587
matrix:
@@ -606,7 +606,7 @@ jobs:
606606
runs-on: ubuntu-latest
607607
timeout-minutes: 60
608608
needs: build-context
609-
if: needs.build-context.outputs.run-tests == 'true'
609+
if: needs.build-context.outputs.run-ubuntu == 'true'
610610
steps:
611611
- uses: actions/checkout@v4
612612
with:
@@ -713,44 +713,32 @@ jobs:
713713
test-hypothesis,
714714
cifuzz,
715715
allowed-skips: >-
716+
${{ !fromJSON(needs.build-context.outputs.run-docs) && 'check-docs,' || '' }}
716717
${{
717-
!fromJSON(needs.build-context.outputs.run-docs)
718+
needs.build-context.outputs.run-tests != 'true'
718719
&& '
719-
check-docs,
720+
check-autoconf-regen,
721+
check-generated-files,
720722
'
721723
|| ''
722724
}}
725+
${{ !fromJSON(needs.build-context.outputs.run-windows-tests) && 'build-windows,' || '' }}
726+
${{ !fromJSON(needs.build-context.outputs.run-ci-fuzz) && 'cifuzz,' || '' }}
727+
${{ !fromJSON(needs.build-context.outputs.run-macos) && 'build-macos,' || '' }}
723728
${{
724-
needs.build-context.outputs.run-tests != 'true'
729+
!fromJSON(needs.build-context.outputs.run-ubuntu)
725730
&& '
726-
check-autoconf-regen,
727-
check-generated-files,
728-
build-macos,
729731
build-ubuntu,
730732
build-ubuntu-ssltests-awslc,
731733
build-ubuntu-ssltests-openssl,
732-
build-android,
733-
build-ios,
734-
build-wasi,
735734
test-hypothesis,
736735
build-asan,
737736
build-san,
738737
cross-build-linux,
739738
'
740739
|| ''
741740
}}
742-
${{
743-
!fromJSON(needs.build-context.outputs.run-windows-tests)
744-
&& '
745-
build-windows,
746-
'
747-
|| ''
748-
}}
749-
${{
750-
!fromJSON(needs.build-context.outputs.run-ci-fuzz)
751-
&& '
752-
cifuzz,
753-
'
754-
|| ''
755-
}}
741+
${{ !fromJSON(needs.build-context.outputs.run-android) && 'build-android,' || '' }}
742+
${{ !fromJSON(needs.build-context.outputs.run-ios) && 'build-ios,' || '' }}
743+
${{ !fromJSON(needs.build-context.outputs.run-wasi) && 'build-wasi,' || '' }}
756744
jobs: ${{ toJSON(needs) }}

.github/workflows/reusable-context.yml

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,31 +17,51 @@ on: # yamllint disable-line rule:truthy
1717
# || 'falsy-branch'
1818
# }}
1919
#
20+
run-android:
21+
description: Whether to run the Android tests
22+
value: ${{ jobs.compute-changes.outputs.run-android }} # bool
23+
run-ci-fuzz:
24+
description: Whether to run the CIFuzz job
25+
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz }} # bool
2026
run-docs:
2127
description: Whether to build the docs
2228
value: ${{ jobs.compute-changes.outputs.run-docs }} # bool
29+
run-ios:
30+
description: Whether to run the iOS tests
31+
value: ${{ jobs.compute-changes.outputs.run-ios }} # bool
32+
run-macos:
33+
description: Whether to run the macOS tests
34+
value: ${{ jobs.compute-changes.outputs.run-macos }} # bool
2335
run-tests:
2436
description: Whether to run the regular tests
2537
value: ${{ jobs.compute-changes.outputs.run-tests }} # bool
26-
run-windows-tests:
27-
description: Whether to run the Windows tests
28-
value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool
38+
run-ubuntu:
39+
description: Whether to run the Ubuntu tests
40+
value: ${{ jobs.compute-changes.outputs.run-ubuntu }} # bool
41+
run-wasi:
42+
description: Whether to run the WASI tests
43+
value: ${{ jobs.compute-changes.outputs.run-wasi }} # bool
2944
run-windows-msi:
3045
description: Whether to run the MSI installer smoke tests
3146
value: ${{ jobs.compute-changes.outputs.run-windows-msi }} # bool
32-
run-ci-fuzz:
33-
description: Whether to run the CIFuzz job
34-
value: ${{ jobs.compute-changes.outputs.run-ci-fuzz }} # bool
47+
run-windows-tests:
48+
description: Whether to run the Windows tests
49+
value: ${{ jobs.compute-changes.outputs.run-windows-tests }} # bool
3550

3651
jobs:
3752
compute-changes:
3853
name: Create context from changed files
3954
runs-on: ubuntu-latest
4055
timeout-minutes: 10
4156
outputs:
57+
run-android: ${{ steps.changes.outputs.run-android }}
4258
run-ci-fuzz: ${{ steps.changes.outputs.run-ci-fuzz }}
4359
run-docs: ${{ steps.changes.outputs.run-docs }}
60+
run-ios: ${{ steps.changes.outputs.run-ios }}
61+
run-macos: ${{ steps.changes.outputs.run-macos }}
4462
run-tests: ${{ steps.changes.outputs.run-tests }}
63+
run-ubuntu: ${{ steps.changes.outputs.run-ubuntu }}
64+
run-wasi: ${{ steps.changes.outputs.run-wasi }}
4565
run-windows-msi: ${{ steps.changes.outputs.run-windows-msi }}
4666
run-windows-tests: ${{ steps.changes.outputs.run-windows-tests }}
4767
steps:

Tools/build/compute-changes.py

Lines changed: 82 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,12 +45,22 @@
4545
SUFFIXES_C_OR_CPP = frozenset({".c", ".h", ".cpp"})
4646
SUFFIXES_DOCUMENTATION = frozenset({".rst", ".md"})
4747

48+
ANDROID_DIRS = frozenset({"Android"})
49+
IOS_DIRS = frozenset({"Apple", "iOS"})
50+
MACOS_DIRS = frozenset({"Mac"})
51+
WASI_DIRS = frozenset({Path("Tools", "wasm")})
52+
4853

4954
@dataclass(kw_only=True, slots=True)
5055
class Outputs:
56+
run_android: bool = False
5157
run_ci_fuzz: bool = False
5258
run_docs: bool = False
59+
run_ios: bool = False
60+
run_macos: bool = False
5361
run_tests: bool = False
62+
run_ubuntu: bool = False
63+
run_wasi: bool = False
5464
run_windows_msi: bool = False
5565
run_windows_tests: bool = False
5666

@@ -63,7 +73,15 @@ def compute_changes() -> None:
6373
outputs = process_changed_files(files)
6474
else:
6575
# Otherwise, just run the tests
66-
outputs = Outputs(run_tests=True, run_windows_tests=True)
76+
outputs = Outputs(
77+
run_android=True,
78+
run_ios=True,
79+
run_macos=True,
80+
run_tests=True,
81+
run_ubuntu=True,
82+
run_wasi=True,
83+
run_windows_tests=True,
84+
)
6785
outputs = process_target_branch(outputs, target_branch)
6886

6987
if outputs.run_tests:
@@ -111,13 +129,31 @@ def get_changed_files(
111129
return frozenset(map(Path, filter(None, map(str.strip, changed_files))))
112130

113131

132+
def get_file_platform(file: Path) -> str | None:
133+
if not file.parts:
134+
return None
135+
first_part = file.parts[0]
136+
if first_part in MACOS_DIRS:
137+
return "macos"
138+
if first_part in IOS_DIRS:
139+
return "ios"
140+
if first_part in ANDROID_DIRS:
141+
return "android"
142+
if len(file.parts) >= 2 and Path(*file.parts[:2]) in WASI_DIRS: # Tools/wasm/
143+
return "wasi"
144+
return None
145+
146+
114147
def process_changed_files(changed_files: Set[Path]) -> Outputs:
115148
run_tests = False
116149
run_ci_fuzz = False
117150
run_docs = False
118151
run_windows_tests = False
119152
run_windows_msi = False
120153

154+
platforms_changed = set()
155+
has_platform_specific_change = True
156+
121157
for file in changed_files:
122158
# Documentation files
123159
doc_or_misc = file.parts[0] in {"Doc", "Misc"}
@@ -126,10 +162,15 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs:
126162
if file.parent == GITHUB_WORKFLOWS_PATH:
127163
if file.name == "build.yml":
128164
run_tests = run_ci_fuzz = True
165+
has_platform_specific_change = False
129166
if file.name == "reusable-docs.yml":
130167
run_docs = True
131168
if file.name == "reusable-windows-msi.yml":
132169
run_windows_msi = True
170+
if file.name == "reusable-macos.yml":
171+
platforms_changed.add("macos")
172+
if file.name == "reusable-wasi.yml":
173+
platforms_changed.add("wasi")
133174

134175
if not (
135176
doc_file
@@ -138,8 +179,13 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs:
138179
):
139180
run_tests = True
140181

141-
if file not in UNIX_BUILD_SYSTEM_FILE_NAMES:
142-
run_windows_tests = True
182+
platform = get_file_platform(file)
183+
if platform is not None:
184+
platforms_changed.add(platform)
185+
else:
186+
has_platform_specific_change = False
187+
if file not in UNIX_BUILD_SYSTEM_FILE_NAMES:
188+
run_windows_tests = True
143189

144190
# The fuzz tests are pretty slow so they are executed only for PRs
145191
# changing relevant files.
@@ -159,12 +205,38 @@ def process_changed_files(changed_files: Set[Path]) -> Outputs:
159205
if file.parts[:2] == ("Tools", "msi"):
160206
run_windows_msi = True
161207

208+
# Check which platform specific tests to run
209+
if run_tests:
210+
if not has_platform_specific_change or not platforms_changed:
211+
run_android = True
212+
run_ios = True
213+
run_macos = True
214+
run_ubuntu = True
215+
run_wasi = True
216+
else:
217+
run_android = "android" in platforms_changed
218+
run_ios = "ios" in platforms_changed
219+
run_macos = "macos" in platforms_changed
220+
run_ubuntu = False
221+
run_wasi = "wasi" in platforms_changed
222+
else:
223+
run_android = False
224+
run_ios = False
225+
run_macos = False
226+
run_ubuntu = False
227+
run_wasi = False
228+
162229
return Outputs(
230+
run_android=run_android,
163231
run_ci_fuzz=run_ci_fuzz,
164232
run_docs=run_docs,
233+
run_ios=run_ios,
234+
run_macos=run_macos,
165235
run_tests=run_tests,
166-
run_windows_tests=run_windows_tests,
236+
run_ubuntu=run_ubuntu,
237+
run_wasi=run_wasi,
167238
run_windows_msi=run_windows_msi,
239+
run_windows_tests=run_windows_tests,
168240
)
169241

170242

@@ -191,11 +263,16 @@ def write_github_output(outputs: Outputs) -> None:
191263
return
192264

193265
with open(os.environ["GITHUB_OUTPUT"], "a", encoding="utf-8") as f:
266+
f.write(f"run-android={bool_lower(outputs.run_android)}\n")
194267
f.write(f"run-ci-fuzz={bool_lower(outputs.run_ci_fuzz)}\n")
195268
f.write(f"run-docs={bool_lower(outputs.run_docs)}\n")
269+
f.write(f"run-ios={bool_lower(outputs.run_ios)}\n")
270+
f.write(f"run-macos={bool_lower(outputs.run_macos)}\n")
196271
f.write(f"run-tests={bool_lower(outputs.run_tests)}\n")
197-
f.write(f"run-windows-tests={bool_lower(outputs.run_windows_tests)}\n")
272+
f.write(f"run-ubuntu={bool_lower(outputs.run_ubuntu)}\n")
273+
f.write(f"run-wasi={bool_lower(outputs.run_wasi)}\n")
198274
f.write(f"run-windows-msi={bool_lower(outputs.run_windows_msi)}\n")
275+
f.write(f"run-windows-tests={bool_lower(outputs.run_windows_tests)}\n")
199276

200277

201278
def bool_lower(value: bool, /) -> str:

0 commit comments

Comments
 (0)