Skip to content

Commit 91e5e24

Browse files
hugovkAA-Turnerwebknjaz
authored
[3.12] Convert change detection to a Python script (GH-129627) (#130370)
Co-authored-by: Adam Turner <[email protected]> Co-authored-by: Hugo van Kemenade <[email protected]> Co-authored-by: Sviatoslav Sydorenko (Святослав Сидоренко) <[email protected]>
1 parent dd5bf31 commit 91e5e24

File tree

3 files changed

+321
-44
lines changed

3 files changed

+321
-44
lines changed

.github/workflows/build.yml

+38-44
Original file line numberDiff line numberDiff line change
@@ -22,32 +22,32 @@ env:
2222
FORCE_COLOR: 1
2323

2424
jobs:
25-
check_source:
25+
build-context:
2626
name: Change detection
2727
# To use boolean outputs from this job, parse them as JSON.
2828
# Here's some examples:
2929
#
30-
# if: fromJSON(needs.check_source.outputs.run-docs)
30+
# if: fromJSON(needs.build-context.outputs.run-docs)
3131
#
3232
# ${{
33-
# fromJSON(needs.check_source.outputs.run_tests)
33+
# fromJSON(needs.build-context.outputs.run-tests)
3434
# && 'truthy-branch'
3535
# || 'falsy-branch'
3636
# }}
3737
#
38-
uses: ./.github/workflows/reusable-change-detection.yml
38+
uses: ./.github/workflows/reusable-context.yml
3939

4040
check-docs:
4141
name: Docs
42-
needs: check_source
43-
if: fromJSON(needs.check_source.outputs.run-docs)
42+
needs: build-context
43+
if: fromJSON(needs.build-context.outputs.run-docs)
4444
uses: ./.github/workflows/reusable-docs.yml
4545

4646
check_abi:
4747
name: 'Check if the ABI has changed'
4848
runs-on: ubuntu-22.04
49-
needs: check_source
50-
if: needs.check_source.outputs.run_tests == 'true'
49+
needs: build-context
50+
if: needs.build-context.outputs.run-tests == 'true'
5151
steps:
5252
- uses: actions/checkout@v4
5353
with:
@@ -96,8 +96,8 @@ jobs:
9696
container:
9797
image: ghcr.io/python/autoconf:2024.10.16.11360930377
9898
timeout-minutes: 60
99-
needs: check_source
100-
if: needs.check_source.outputs.run_tests == 'true'
99+
needs: build-context
100+
if: needs.build-context.outputs.run-tests == 'true'
101101
steps:
102102
- name: Install Git
103103
run: |
@@ -137,8 +137,8 @@ jobs:
137137
# reproducible: to get the same tools versions (autoconf, aclocal, ...)
138138
runs-on: ubuntu-24.04
139139
timeout-minutes: 60
140-
needs: check_source
141-
if: needs.check_source.outputs.run_tests == 'true'
140+
needs: build-context
141+
if: needs.build-context.outputs.run-tests == 'true'
142142
steps:
143143
- uses: actions/checkout@v4
144144
with:
@@ -153,7 +153,7 @@ jobs:
153153
with:
154154
path: config.cache
155155
# Include env.pythonLocation in key to avoid changes in environment when setup-python updates Python
156-
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.check_source.outputs.config_hash }}-${{ env.pythonLocation }}
156+
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}-${{ env.pythonLocation }}
157157
- name: Install dependencies
158158
run: sudo ./.github/workflows/posix-deps-apt.sh
159159
- name: Add ccache to PATH
@@ -199,8 +199,8 @@ jobs:
199199
name: >-
200200
Windows
201201
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
202-
needs: check_source
203-
if: fromJSON(needs.check_source.outputs.run_tests)
202+
needs: build-context
203+
if: fromJSON(needs.build-context.outputs.run-tests)
204204
strategy:
205205
matrix:
206206
arch:
@@ -218,8 +218,8 @@ jobs:
218218
build_windows_msi:
219219
name: >- # ${{ '' } is a hack to nest jobs under the same sidebar category
220220
Windows MSI${{ '' }}
221-
needs: check_source
222-
if: fromJSON(needs.check_source.outputs.run-win-msi)
221+
needs: build-context
222+
if: fromJSON(needs.build-context.outputs.run-windows-msi)
223223
strategy:
224224
matrix:
225225
arch:
@@ -234,8 +234,8 @@ jobs:
234234
name: >-
235235
macOS
236236
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
237-
needs: check_source
238-
if: needs.check_source.outputs.run_tests == 'true'
237+
needs: build-context
238+
if: needs.build-context.outputs.run-tests == 'true'
239239
strategy:
240240
fail-fast: false
241241
matrix:
@@ -260,32 +260,32 @@ jobs:
260260
free-threading: true
261261
uses: ./.github/workflows/reusable-macos.yml
262262
with:
263-
config_hash: ${{ needs.check_source.outputs.config_hash }}
263+
config_hash: ${{ needs.build-context.outputs.config-hash }}
264264
free-threading: ${{ matrix.free-threading }}
265265
os: ${{ matrix.os }}
266266

267267
build_ubuntu:
268268
name: >-
269269
Ubuntu
270270
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
271-
needs: check_source
272-
if: needs.check_source.outputs.run_tests == 'true'
271+
needs: build-context
272+
if: needs.build-context.outputs.run-tests == 'true'
273273
strategy:
274274
matrix:
275275
free-threading:
276276
- false
277277
# - true
278278
uses: ./.github/workflows/reusable-ubuntu.yml
279279
with:
280-
config_hash: ${{ needs.check_source.outputs.config_hash }}
280+
config_hash: ${{ needs.build-context.outputs.config-hash }}
281281
free-threading: ${{ matrix.free-threading }}
282282

283283
build_ubuntu_ssltests:
284284
name: 'Ubuntu SSL tests with OpenSSL'
285285
runs-on: ${{ matrix.os }}
286286
timeout-minutes: 60
287-
needs: check_source
288-
if: needs.check_source.outputs.run_tests == 'true'
287+
needs: build-context
288+
if: needs.build-context.outputs.run-tests == 'true'
289289
strategy:
290290
fail-fast: false
291291
matrix:
@@ -306,7 +306,7 @@ jobs:
306306
uses: actions/cache@v4
307307
with:
308308
path: config.cache
309-
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.check_source.outputs.config_hash }}
309+
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
310310
- name: Register gcc problem matcher
311311
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
312312
- name: Install dependencies
@@ -345,8 +345,8 @@ jobs:
345345
name: "Hypothesis tests on Ubuntu"
346346
runs-on: ubuntu-24.04
347347
timeout-minutes: 60
348-
needs: check_source
349-
if: needs.check_source.outputs.run_tests == 'true' && needs.check_source.outputs.run_hypothesis == 'true'
348+
needs: build-context
349+
if: needs.build-context.outputs.run-tests == 'true'
350350
env:
351351
OPENSSL_VER: 3.0.15
352352
PYTHONSTRICTEXTENSIONBUILD: 1
@@ -393,7 +393,7 @@ jobs:
393393
uses: actions/cache@v4
394394
with:
395395
path: ${{ env.CPYTHON_BUILDDIR }}/config.cache
396-
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.check_source.outputs.config_hash }}
396+
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
397397
- name: Configure CPython out-of-tree
398398
working-directory: ${{ env.CPYTHON_BUILDDIR }}
399399
run: |
@@ -460,8 +460,8 @@ jobs:
460460
name: 'Address sanitizer'
461461
runs-on: ubuntu-22.04
462462
timeout-minutes: 60
463-
needs: check_source
464-
if: needs.check_source.outputs.run_tests == 'true'
463+
needs: build-context
464+
if: needs.build-context.outputs.run-tests == 'true'
465465
strategy:
466466
matrix:
467467
os: [ubuntu-24.04]
@@ -479,7 +479,7 @@ jobs:
479479
uses: actions/cache@v4
480480
with:
481481
path: config.cache
482-
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.check_source.outputs.config_hash }}
482+
key: ${{ github.job }}-${{ env.IMAGE_OS_VERSION }}-${{ needs.build-context.outputs.config-hash }}
483483
- name: Register gcc problem matcher
484484
run: echo "::add-matcher::.github/problem-matchers/gcc.json"
485485
- name: Install dependencies
@@ -523,23 +523,23 @@ jobs:
523523
name: >-
524524
Thread sanitizer
525525
${{ fromJSON(matrix.free-threading) && '(free-threading)' || '' }}
526-
needs: check_source
527-
if: needs.check_source.outputs.run_tests == 'true'
526+
needs: build-context
527+
if: needs.build-context.outputs.run-tests == 'true'
528528
strategy:
529529
matrix:
530530
free-threading:
531531
- false
532532
uses: ./.github/workflows/reusable-tsan.yml
533533
with:
534-
config_hash: ${{ needs.check_source.outputs.config_hash }}
534+
config_hash: ${{ needs.build-context.outputs.config-hash }}
535535
free-threading: ${{ matrix.free-threading }}
536536

537537
all-required-green: # This job does nothing and is only used for the branch protection
538538
name: All required checks pass
539539
if: always()
540540

541541
needs:
542-
- check_source # Transitive dependency, needed to access `run_tests` value
542+
- build-context # Transitive dependency, needed to access `run-tests` value
543543
- check-docs
544544
- check_autoconf_regen
545545
- check_generated_files
@@ -564,14 +564,14 @@ jobs:
564564
test_hypothesis,
565565
allowed-skips: >-
566566
${{
567-
!fromJSON(needs.check_source.outputs.run-docs)
567+
!fromJSON(needs.build-context.outputs.run-docs)
568568
&& '
569569
check-docs,
570570
'
571571
|| ''
572572
}}
573573
${{
574-
needs.check_source.outputs.run_tests != 'true'
574+
needs.build-context.outputs.run-tests != 'true'
575575
&& '
576576
check_autoconf_regen,
577577
check_generated_files,
@@ -581,12 +581,6 @@ jobs:
581581
build_windows,
582582
build_asan,
583583
build_tsan,
584-
'
585-
|| ''
586-
}}
587-
${{
588-
!fromJSON(needs.check_source.outputs.run_hypothesis)
589-
&& '
590584
test_hypothesis,
591585
'
592586
|| ''
+100
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
name: Reusable build context
2+
3+
on: # yamllint disable-line rule:truthy
4+
workflow_call:
5+
outputs:
6+
# Every referenced step MUST always set its output variable,
7+
# either via ``Tools/build/compute-changes.py`` or in this workflow file.
8+
# Boolean outputs (generally prefixed ``run-``) can then later be used
9+
# safely through the following idiom in job conditionals and other
10+
# expressions. Here's some examples:
11+
#
12+
# if: fromJSON(needs.build-context.outputs.run-tests)
13+
#
14+
# ${{
15+
# fromJSON(needs.build-context.outputs.run-tests)
16+
# && 'truthy-branch'
17+
# || 'falsy-branch'
18+
# }}
19+
#
20+
config-hash:
21+
description: Config hash value for use in cache keys
22+
value: ${{ jobs.compute-changes.outputs.config-hash }} # str
23+
run-docs:
24+
description: Whether to build the docs
25+
value: ${{ jobs.compute-changes.outputs.run-docs }} # bool
26+
run-tests:
27+
description: Whether to run the regular tests
28+
value: ${{ jobs.compute-changes.outputs.run-tests }} # bool
29+
run-windows-msi:
30+
description: Whether to run the MSI installer smoke tests
31+
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
35+
36+
jobs:
37+
compute-changes:
38+
name: Create context from changed files
39+
runs-on: ubuntu-latest
40+
timeout-minutes: 10
41+
outputs:
42+
config-hash: ${{ steps.config-hash.outputs.hash }}
43+
run-ci-fuzz: ${{ steps.changes.outputs.run-ci-fuzz }}
44+
run-docs: ${{ steps.changes.outputs.run-docs }}
45+
run-tests: ${{ steps.changes.outputs.run-tests }}
46+
run-windows-msi: ${{ steps.changes.outputs.run-windows-msi }}
47+
steps:
48+
- name: Set up Python
49+
uses: actions/setup-python@v5
50+
with:
51+
python-version: "3"
52+
53+
- run: >-
54+
echo '${{ github.event_name }}'
55+
56+
- uses: actions/checkout@v4
57+
with:
58+
persist-credentials: false
59+
ref: >-
60+
${{
61+
github.event_name == 'pull_request'
62+
&& github.event.pull_request.head.sha
63+
|| ''
64+
}}
65+
66+
# Adapted from https://github.com/actions/checkout/issues/520#issuecomment-1167205721
67+
- name: Fetch commits to get branch diff
68+
if: github.event_name == 'pull_request'
69+
run: |
70+
set -eux
71+
72+
# Fetch enough history to find a common ancestor commit (aka merge-base):
73+
git fetch origin "${refspec_pr}" --depth=$(( commits + 1 )) \
74+
--no-tags --prune --no-recurse-submodules
75+
76+
# This should get the oldest commit in the local fetched history (which may not be the commit the PR branched from):
77+
COMMON_ANCESTOR=$( git rev-list --first-parent --max-parents=0 --max-count=1 "${branch_pr}" )
78+
DATE=$( git log --date=iso8601 --format=%cd "${COMMON_ANCESTOR}" )
79+
80+
# Get all commits since that commit date from the base branch (eg: main):
81+
git fetch origin "${refspec_base}" --shallow-since="${DATE}" \
82+
--no-tags --prune --no-recurse-submodules
83+
env:
84+
branch_pr: 'origin/${{ github.event.pull_request.head.ref }}'
85+
commits: ${{ github.event.pull_request.commits }}
86+
refspec_base: '+${{ github.event.pull_request.base.sha }}:remotes/origin/${{ github.event.pull_request.base.ref }}'
87+
refspec_pr: '+${{ github.event.pull_request.head.sha }}:remotes/origin/${{ github.event.pull_request.head.ref }}'
88+
89+
# We only want to run tests on PRs when related files are changed,
90+
# or when someone triggers a manual workflow run.
91+
- name: Compute changed files
92+
id: changes
93+
run: python Tools/build/compute-changes.py
94+
env:
95+
GITHUB_DEFAULT_BRANCH: ${{ github.event.repository.default_branch }}
96+
97+
- name: Compute hash for config cache key
98+
id: config-hash
99+
run: |
100+
echo "hash=${{ hashFiles('configure', 'configure.ac', '.github/workflows/build.yml') }}" >> "$GITHUB_OUTPUT"

0 commit comments

Comments
 (0)