Repository navigation
222 lines (205 loc) · 10.4 KB
/
Copy pathpython-compatibility.yml
File metadata and controls
222 lines (205 loc) · 10.4 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
name: "Python Compatibility"
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
- cron: '0 4 * * 6'
permissions:
contents: read
# Only pull-request runs may be superseded. GitHub cancels a *pending* run when
# a newer one joins its group, whatever `cancel-in-progress` says, so a shared
# group for main's pushes would leave commits unvalidated; other events key on
# the run id.
concurrency:
group: python-compatibility-${{ github.event_name == 'pull_request' && github.ref || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
# #1660: the matrix below, from .github/python-versions.toml -- see the job of
# the same name in unit-tests.yml.
python-versions:
name: Read the Python versions
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
compatibility: ${{ steps.read.outputs.compatibility }}
compatibility-supported: ${{ steps.read.outputs.compatibility-supported }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
sparse-checkout: |
.github/python-versions.toml
util/_actions.py
util/python_versions.py
sparse-checkout-cone-mode: false
persist-credentials: false
- name: Read .github/python-versions.toml
id: read
run: python3 util/python_versions.py --github-output
# #2243, the owner's option B: unit-tests.yml's `changes`, the same
# util/classify_changes.py step. This workflow is never called, so its own
# pull_request run is every pull_request run, and every other event, a push
# to main included, runs everything. `light` is `true` on a docs-only or a
# test-only diff, neither of which can change what this workflow checks:
# pcapkit/ and util/ compile and import as on the base branch.
changes:
name: Classify changed files
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
light: ${{ steps.classify.outputs.code == 'false' || steps.classify.outputs.test-only == 'true' }}
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 2
- name: Classify the diff
id: classify
env:
OWN_PR: ${{ github.event_name == 'pull_request' }}
run: python3 util/classify_changes.py
compatibility:
# `Compat`, so `gh pr checks` cannot show two `Python 3.N` rows, this and
# Unit Tests', with nothing to tell them apart.
#
# #1633's tiers. A supported leg keeps the plain name, one of ruleset
# 23497679's required contexts. A KTLO leg is suffixed ` (KTLO)`, so no
# required context can match it, and its steps carry `continue-on-error`,
# as in unit-tests.yml's `test` job: job-level, a failed leg's check run
# concludes `failure`, so every commit shows red (#1672). Nothing below
# `requires-python`'s 3.8 runs (#2051).
#
# #2243: the supported legs are required contexts, so a docs-only or
# test-only pull request still runs them, by name, but they skip every
# step that sets up, installs or checks, and pass. A job-level `if:` would
# not do: a matrix job it skips reports one check under its unexpanded
# name, as Unit Tests' docs-only run 40238795866 did, which matches no
# required context, so each would stay pending.
# The KTLO legs, required by nothing, are left out of that matrix.
# `!cancelled()` replaces the implicit `success()`, so a failed `changes`,
# whose `light` is then empty, runs every leg in full.
name: Compat Python ${{ matrix.python-version }}${{ matrix.ktlo && ' (KTLO)' || '' }}
needs: [python-versions, changes]
if: ${{ !cancelled() && needs.python-versions.result == 'success' }}
runs-on: ${{ matrix.os || 'ubuntu-latest' }}
env:
ANNOTATION_LEVEL: ${{ matrix.ktlo && 'warning' || 'error' }}
strategy:
fail-fast: false
# Both tiers, as for unit-tests.yml's `test` job (#1660), which explains
# the `os` pins: a KTLO leg carries `ktlo: true`, and `os` where
# `ubuntu-latest` has no setup-python build for it. A tier change edits
# ruleset 23497679 too.
matrix: ${{ fromJSON(needs.changes.outputs.light == 'true' && needs.python-versions.outputs.compatibility-supported || needs.python-versions.outputs.compatibility) }}
steps:
- name: Skip on a docs-only or test-only diff
if: ${{ needs.changes.outputs.light == 'true' }}
env:
LEG: Python ${{ matrix.python-version }}
run: echo "::notice title=Nothing to check on ${LEG}::A docs-only or test-only diff leaves pcapkit/ and util/ as on the base branch, so this leg passes without checking them (#2243)."
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
id: checkout
if: ${{ needs.changes.outputs.light != 'true' }}
continue-on-error: ${{ matrix.ktlo == true }}
# Every later step waits on this one's `outcome`, so on a light diff,
# where it skips, they skip too.
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
id: python
if: ${{ needs.changes.outputs.light != 'true' }}
continue-on-error: ${{ matrix.ktlo == true }}
with:
python-version: ${{ matrix.python-version }}
# The install needs this leg's interpreter, and the check below needs the
# install, as in unit-tests.yml's `test` job: on a KTLO leg a failed step
# does not stop the job, so each one waits on the `outcome` it needs.
# util/pip_install.py annotates a failed install, as in `test` (#1967).
- name: Install package
id: install
if: ${{ steps.python.outcome == 'success' }}
continue-on-error: ${{ matrix.ktlo == true }}
env:
LEG: Python ${{ matrix.python-version }}${{ matrix.ktlo && ' (KTLO, non-blocking)' || '' }}
run: python util/pip_install.py -e .
# One annotation saying why, so a failed leg -- an install that succeeds
# with sources that do not compile -- is legible from the run summary; a
# warning on a KTLO leg (#1672). Each title escapes `,` as
# `%2C`: the runner splits a command's properties on `,`, so the KTLO
# title would stop at "(KTLO" (actions/runner `ActionCommand.TryParseV2`
# in src/Runner.Common/ActionCommand.cs, at 5f0b3ddcc).
- name: Verify package
id: verify
if: ${{ steps.install.outcome == 'success' }}
continue-on-error: ${{ matrix.ktlo == true }}
shell: bash
env:
LEG: Python ${{ matrix.python-version }}${{ matrix.ktlo && ' (KTLO, non-blocking)' || '' }}
run: |
log="$RUNNER_TEMP/compileall.log"
if ! python -m compileall -q pcapkit > "$log" 2>&1; then
cat "$log"
count=$(awk '/^\*\*\* Error compiling /{n++} END{print n+0}' "$log")
first=$(awk '/^ File "/{sub(/^ /, ""); print; exit}' "$log")
echo "::${ANNOTATION_LEVEL} title=pcapkit does not compile on ${LEG//,/%2C}::$count modules fail to compile, the first at ${first:-an unreported place}; see this step's log."
exit 1
fi
if ! python -c 'import pcapkit; print(pcapkit.__version__)'; then
echo "::${ANNOTATION_LEVEL} title=pcapkit does not import on ${LEG//,/%2C}::See the traceback in this step's log."
exit 1
fi
# #2206: the util/ scripts held to requires-python's 3.8, compiled by 3.8's
# own parser. Their tests' `ast.parse(..., feature_version=(3, 8))` is
# best-effort on a newer interpreter, so this leg is the check. The list is
# the scripts those tests parse at the floor, as
# tests/project/test_compat_util_floor_2206.py pins; the version, an
# exemption in .github/python-versions.toml.
- name: Compile the 3.8-floor util scripts
id: compile-util
if: ${{ steps.install.outcome == 'success' && matrix.python-version == '3.8' }}
continue-on-error: ${{ matrix.ktlo == true }}
shell: bash
env:
LEG: Python ${{ matrix.python-version }}${{ matrix.ktlo && ' (KTLO, non-blocking)' || '' }}
run: |
log="$RUNNER_TEMP/compileall-util.log"
if ! python -m compileall -q \
util/_actions.py util/release_conda.py util/release_published.py \
util/release_reset_build.py util/release_status.py util/release_tags.py \
util/release_tiers.py util/release_upload.py > "$log" 2>&1; then
cat "$log"
count=$(awk '/^\*\*\* Error compiling /{n++} END{print n+0}' "$log")
first=$(awk '/^ File "/{sub(/^ /, ""); print; exit}' "$log")
echo "::${ANNOTATION_LEVEL} title=util/ does not compile on ${LEG//,/%2C}::$count scripts fail to compile, the first at ${first:-an unreported place}; see this step's log."
exit 1
fi
# #1672: the KTLO leg's report -- the same step ends every KTLO matrix
# job; see unit-tests.yml's `test` job for how it works.
- name: KTLO summary
if: ${{ !cancelled() && matrix.ktlo == true }}
continue-on-error: ${{ matrix.ktlo == true }}
shell: bash
env:
LEG: Python ${{ matrix.python-version }}${{ matrix.ktlo && ' (KTLO, non-blocking)' || '' }}
STEPS: ${{ toJSON(steps) }}
JOB_SUMMARY_COPY: ${{ runner.temp }}/job-summary.md
run: /usr/bin/python3 util/leg_summary.py ktlo
# #2030: the job's summary, for the report ci-reports.yml posts, as in
# unit-tests.yml's `test` job: `KTLO summary` copies its lines to
# job-summary.md, and these name the job and upload both.
- name: Name the job summary
if: ${{ always() }}
continue-on-error: true
shell: bash
env:
JOB_NAME: Compat Python ${{ matrix.python-version }}${{ matrix.ktlo && ' (KTLO)' || '' }}
run: if [ -s "$RUNNER_TEMP/job-summary.md" ]; then printf '%s\n' "$JOB_NAME" > "$RUNNER_TEMP/job-summary.name"; fi
- name: Upload the job summary
if: ${{ always() }}
continue-on-error: true
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: job-summary-${{ github.job }}-${{ strategy.job-index }}
path: |
${{ runner.temp }}/job-summary.md
${{ runner.temp }}/job-summary.name
if-no-files-found: ignore
retention-days: 7