-
Notifications
You must be signed in to change notification settings - Fork 11
261 lines (245 loc) · 11.6 KB
/
Copy pathopenkal-compat.yml
File metadata and controls
261 lines (245 loc) · 11.6 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
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
name: openkal-compat
# Measures the members listed in tests/openkal/members.toml in an openkal graph
# and records the result the site labels packages by. See docs/openkal-compat.md.
#
# It does not gate pull requests that touch other descriptors: openkal is still
# moving, and a label is a statement about a measurement rather than a condition
# of merging. The regression comparison below becomes a required check only when
# the repository variable OPENKAL_RATCHET is `on`.
on:
schedule:
- cron: "0 7 * * 0"
workflow_dispatch:
inputs:
members:
description: "Space-separated members to measure (empty = every listed member)"
required: false
default: ""
mcpp_ref:
description: "Branch of mcpp-community/mcpp to build and measure against (empty = the released pin)"
required: false
default: ""
pull_request:
paths:
- "pkgs/**/*.lua"
- "tests/openkal/**"
- ".xpkgindex/openkal-compat.json"
- ".github/workflows/openkal-compat.yml"
permissions:
contents: read
env:
# Moves together with index.toml's `min_mcpp` and tests/openkal/pins.toml's
# `mcpp` -- the "The pins agree with this workflow" step below fails the
# run if this drifts from pins.toml. See the comment beside `mcpp` in
# pins.toml for why this pin, not just validate.yml's, is gated by the
# index floor.
MCPP_VERSION: "2026.9.21.3"
# CROSS-VALIDATION BEFORE A RELEASE, NOT AFTER IT.
#
# Empty in an ordinary run, so this measurement keeps using the RELEASED
# engine the pin above names. Set it -- workflow_dispatch input, or the
# repository variable -- and the same measurement runs against mcpp built
# from that ref instead.
#
# THIS EXISTS BECAUSE AN ENGINE CHANGE'S REAL LOAD IS HERE. mcpp's own CI
# cannot see a defect that appears only in a real dependency graph; this
# repository holds thirty such graphs and could not see the engine until it
# had been published. 2026.9.20.1 shipped and, within a day, the four
# members that stop at `windows.h` through a borrowed `__CYGWIN__` made a
# second release necessary -- a reading this job could have produced before
# the first one merged. Every ecosystem repository that mcpp's changes reach
# already honours this variable; this workflow was the gap.
MCPP_SOURCE_REF: ${{ github.event.inputs.mcpp_ref || vars.MCPP_SOURCE_REF }}
XLINGS_NON_INTERACTIVE: "1"
jobs:
measure:
name: measure (linux, windows through wine)
runs-on: ubuntu-24.04
timeout-minutes: 240
outputs:
members: ${{ steps.select.outputs.members }}
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
# A pull request measures the members its change can affect; the schedule
# and a request with no members measure every listed member.
- name: Select the members
id: select
shell: bash
run: |
if [ "${{ github.event_name }}" = "pull_request" ]; then
files=$(git diff --name-only "origin/${{ github.base_ref }}...HEAD")
members=$(python3 tests/openkal/compat.py select $files)
else
members="${{ github.event.inputs.members }}"
[ -n "$members" ] || members=$(python3 tests/openkal/compat.py select tests/openkal/)
fi
echo "members=$members" >> "$GITHUB_OUTPUT"
echo "measuring: ${members:-nothing}"
- name: Download mcpp
if: steps.select.outputs.members != ''
shell: bash
run: |
archive="mcpp-${MCPP_VERSION}-linux-x86_64.tar.gz"
curl -L -fsS -o "$archive" \
"https://github.com/mcpp-community/mcpp/releases/download/v${MCPP_VERSION}/${archive}"
tar -xzf "$archive"
root="$PWD/mcpp-${MCPP_VERSION}-linux-x86_64"
echo "$root/bin" >> "$GITHUB_PATH"
echo "MCPP_HOME=$root" >> "$GITHUB_ENV"
# The released engine above is the BOOTSTRAP when a ref is under
# review: mcpp builds itself and there is no other compiler for it
# here.
#
# THE BUILD REPLACES THE BINARY INSIDE THE RELEASED ROOT, rather than
# being prepended to PATH beside its own `target/` directory. An
# earlier revision did the latter and the measurement stopped at
#
# error: xlings binary not found
#
# because a released archive carries a BUNDLED xlings that mcpp
# resolves relative to its own location, and a freshly built binary
# has no such neighbour. Overwriting `bin/mcpp` in place keeps that
# root --- its bundled xlings, its layout, `MCPP_HOME`, the PATH
# entry already exported above --- exactly as the released engine
# left it, and changes only the one file under review.
if [ -n "${MCPP_SOURCE_REF:-}" ]; then
src="$RUNNER_TEMP/mcpp-src"
git clone --quiet --depth 1 --branch "$MCPP_SOURCE_REF" \
https://github.com/mcpp-community/mcpp.git "$src"
# `.xlings.json` at mcpp's root pins the mcpp that compiles mcpp,
# and that pin does not move when mcpp is released, so a build
# inside the checkout would try to install a version the index may
# no longer carry. What is wanted is the source compiled by the
# engine installed above, which removing the file leaves.
rm -f "$src/.xlings.json"
( cd "$src" && "$root/bin/mcpp" build --release )
built=$(find "$src/target" -type f -name mcpp | head -1)
[ -n "$built" ] \
|| { echo "::error::mcpp did not build from $MCPP_SOURCE_REF"; exit 1; }
cp "$built" "$root/bin/mcpp"
# Reported from the path the measurement will actually run, not
# from the build directory: a copy that did not land looks exactly
# like one that did until something has been measured with the
# wrong engine.
echo "under review: $("$root/bin/mcpp" --version) (from $MCPP_SOURCE_REF)"
fi
# The Windows cross headers of the host are installed deliberately. A
# graph that reached them would build differently with them present, so a
# result that is the same here and on a runner without them is evidence
# that the graph is closed. Wine runs the Windows members' tests.
- name: Host headers the graph must not reach, and a runner for Windows
if: steps.select.outputs.members != ''
shell: bash
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq mingw-w64 wine64 > /dev/null
ls /usr/x86_64-w64-mingw32/include/windows.h
command -v wine || sudo ln -s "$(command -v wine64)" /usr/local/bin/wine
wine --version
- name: The pins agree with this workflow
if: steps.select.outputs.members != ''
shell: bash
run: |
pinned=$(sed -n 's/^mcpp *= *"\(.*\)"/\1/p' tests/openkal/pins.toml)
if [ "$pinned" != "$MCPP_VERSION" ]; then
echo "::error::tests/openkal/pins.toml names mcpp $pinned and this workflow installs $MCPP_VERSION"
exit 1
fi
- name: Measure
if: steps.select.outputs.members != ''
shell: bash
run: |
mcpp self config --mirror GLOBAL
args=()
for m in ${{ steps.select.outputs.members }}; do args+=(--member "$m"); done
python3 tests/openkal/compat.py run "${args[@]}" --out openkal-compat.json
- uses: actions/upload-artifact@v4
if: steps.select.outputs.members != ''
with:
name: openkal-compat
path: openkal-compat.json
- name: No published label regressed
if: steps.select.outputs.members != ''
shell: bash
continue-on-error: ${{ vars.OPENKAL_RATCHET != 'on' }}
run: |
python3 tests/openkal/compat.py check \
--results openkal-compat.json --baseline .xpkgindex/openkal-compat.json
- name: Summary
if: always() && steps.select.outputs.members != ''
shell: bash
run: |
[ -f openkal-compat.json ] || exit 0
python3 - <<'PY' >> "$GITHUB_STEP_SUMMARY"
import json
r = json.load(open("openkal-compat.json"))
# Counted per target, and `refused` counted apart from `fails`: a
# member told before compilation that this graph does not supply a
# capability it asked for has been answered correctly, and adding it
# to a failure figure turns that figure into a score the build tool
# is judged by.
tally = {}
for e in r["members"].values():
for t, rec in e["targets"].items():
tally.setdefault(t, {}).setdefault(rec["status"], 0)
tally[t][rec["status"]] += 1
print("| target | runs | builds | fails | refused |")
print("| --- | --- | --- | --- | --- |")
for t in sorted(tally):
c = tally[t]
print(f"| {t} | {c.get('runs',0)} | {c.get('builds',0)} "
f"| {c.get('fails',0)} | {c.get('refused',0)} |")
print()
print("| member | target | result | first diagnostic |")
print("| --- | --- | --- | --- |")
for m, e in sorted(r["members"].items()):
for t, rec in sorted(e["targets"].items()):
d = rec.get("diagnostic", "").replace("|", "\\|")
print(f"| {m} | {t} | {rec['status']} | {d} |")
PY
# Only this job may write. It runs for the default branch only, never for a
# pull request or a measurement requested on another branch.
propose:
name: propose the measurement
needs: measure
if: needs.measure.outputs.members != '' && github.event_name != 'pull_request' && github.event.inputs.members == '' && github.ref == 'refs/heads/main'
runs-on: ubuntu-24.04
permissions:
contents: write
pull-requests: write
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: openkal-compat
# A scheduled or requested measurement that differs from the published file
# is proposed as a pull request rather than committed, so that a label
# changes only through review.
- name: Propose the new measurement
shell: bash
env:
GH_TOKEN: ${{ github.token }}
run: |
python3 - <<'PY'
import json
new = json.load(open("openkal-compat.json"))
old = json.load(open(".xpkgindex/openkal-compat.json"))
same = {k: v for k, v in new.items() if k != "measured"} == \
{k: v for k, v in old.items() if k != "measured"}
open("same.txt", "w").write("1" if same else "0")
PY
if [ "$(cat same.txt)" = "1" ]; then echo "the measurement is unchanged"; exit 0; fi
branch="bot/openkal-compat-$(date +%Y%m%d)"
cp openkal-compat.json .xpkgindex/openkal-compat.json
git config user.name "mcpp-index-bot"
git config user.email "bot@mcpplibs.invalid"
git checkout -b "$branch"
git add .xpkgindex/openkal-compat.json
git commit -m "openkal compatibility: the measurement of $(date +%F)"
git push -f origin "$branch"
gh pr create --base main --head "$branch" \
--title "openkal compatibility: the measurement of $(date +%F)" \
--body "Measured by .github/workflows/openkal-compat.yml run ${{ github.run_id }}. See the run summary for every member and target." \
|| echo "a pull request for $branch already exists"