Repository navigation
358 lines (323 loc) · 15.2 KB
/
Copy pathci.yml
File metadata and controls
358 lines (323 loc) · 15.2 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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
name: CI
# THE BUILD TOOL IS NAMED HERE AND NOWHERE ELSE.
#
# This workflow used to install it through `.xlings.json', a workspace pin that
# `actions/checkout' places in the working directory before anything else runs.
# Two consequences followed and neither was visible in a passing log:
#
# * every `mcpp' invocation in this repository resolved to the pinned version
# rather than to the one the job had installed, because that pin is read
# from the current directory;
# * the pin named 0.0.13, from 2026-05. The index no longer serves the
# toolchain packages a build tool of that age asks for, so `mcpp build'
# ended at `package 'xim:glibc@>=2.39' not found' before compiling a line.
#
# The pin file is removed. The version is an environment variable, so the two
# places that need it, the install and the cache, cannot drift apart again.
on:
push:
branches: [master]
pull_request:
# A CANARY, BECAUSE THIS ROTTED WHERE NOTHING WOULD LOOK.
#
# The breakage above occurred between 2026-07-11 and 2026-08-29 and nothing
# reported it: master received no pushes in that window, so the first run to
# meet it was a contributor's pull request, whose author had no way to
# distinguish a broken environment from a broken change.
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:
env:
# 2026.9.30.2 and not earlier: 2026.9.28.3 refused x86_64-windows-musl
# ("cannot be built on this host") before the dependency graph that supplies
# its system side, openkal-llvm-runtime, had been resolved.
MCPP_VERSION: 2026.9.30.2
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
jobs:
# ── Linux, under both standard libraries ─────────────────────────────────────
#
# WHY TWO TOOLCHAINS. The job used to run whatever mcpp installed by default on
# a fresh runner, which is gcc and libstdc++, and nothing ran the tests under
# libc++. libc++ is the standard library of every other job below — macOS and
# openkal — and of mcpp's own default where a developer has chosen llvm; the
# cancellation tests met a libc++ defect that libstdc++ does not have
# (tests/test_cancel.cpp, at the top), and no job here could have seen it.
build:
name: build + test (linux x86_64, ${{ matrix.toolchain }})
runs-on: ubuntu-latest
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
toolchain: ['gcc@16.1.0', 'llvm@22.1.8']
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
# --retry-all-errors and not --retry alone: the first covers a
# transient HTTP status and a timeout, and what this step actually
# meets is a failure of the transport. Observed in this ecosystem as
# `curl: (35) Recv failure: Connection reset by peer', thirteen
# seconds into a job, before anything was built.
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
# The version this job runs is the version it prints. A pin that is
# not read is the failure this file exists to stop repeating.
mcpp --version
# A runner outside China reaches the mirrors this names. The CN set is
# for a developer's machine and is slower or unreachable from here.
mcpp self config --mirror GLOBAL
# The toolchain mcpp bootstraps is decided by the version pinned above, so
# that version and the toolchain are the whole of the key.
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry
key: mcpp-sandbox-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }}-${{ matrix.toolchain }}
- name: Select the toolchain
run: |
spec='${{ matrix.toolchain }}'
mcpp toolchain install "${spec%@*}" "${spec#*@}"
mcpp toolchain default "$spec"
mcpp toolchain list
- name: Build with mcpp
run: mcpp build
# Most of these are hermetic: `test_framing` needs nothing, and `test_pool`,
# `test_proxy` and `test_cancel` script their own servers on 127.0.0.1. The
# eight in `test_download` and `test_resolver` reach httpbin.org and
# one.one.one.one; a network failure among them is distinguishable in the
# log by the endpoint it names.
- name: Run tests
run: mcpp test
# A TEMPLATE IS PART OF THE RELEASE THAT SHIPS IT, AND `mcpp new` CAN ONLY
# REACH ONE THAT IS ALREADY PUBLISHED. Checking them after the release
# makes the first person to run `mcpp new` the one who finds out they do
# not compile, so this renders them the way the scaffolder does and builds
# them against this commit. It has already caught one: `import std`
# carries no `stdout` macro, so a progress bar flushed through it did not
# compile in a generated project while compiling fine in this repository.
- name: Smoke-test the project templates
run: bash tools/template_smoke.sh
# ── macOS ────────────────────────────────────────────────────────────────────
#
# THE README NAMES macOS, AND UNTIL THIS JOB NOTHING RAN THERE. The
# differences are real and in this library's own code: SO_NOSIGPIPE rather
# than MSG_NOSIGNAL (src/platform.cppm), /dev/urandom as mbedTLS's entropy,
# the system CA bundle's location, and poll(2) on a socket whose connect is in
# progress, which the cancellation slices wait on.
macos:
name: build + test (macos arm64, llvm@22.1.8)
runs-on: macos-15
timeout-minutes: 45
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry
key: mcpp-sandbox-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }}-llvm@22.1.8
- name: Select the toolchain
run: |
mcpp toolchain install llvm 22.1.8
mcpp toolchain default llvm@22.1.8
mcpp toolchain list
- name: Build with mcpp
run: mcpp build
- name: Run tests
run: mcpp test
# ── The same sources, on a different kernel ABI ──────────────────────────────
#
# WHY THIS IS A SEPARATE JOB AND NOT A STEP. It resolves a different toolchain
# (llvm rather than gcc) and a different everything below the program — musl
# ported onto openkal, libc++ configured for that musl, and openkal-linux
# beneath both. Sharing a job would mean sharing a cache key between two
# stacks that have nothing in common but the source tree.
#
# WHAT IT CATCHES THAT THE JOB ABOVE CANNOT. `Socket::write` sends with
# MSG_NOSIGNAL and `connect_addrinfo` sets SO_NOSIGPIPE, and which of those
# exists is decided by the C library rather than by the operating system —
# openkal-musl defines the first and not the second. A `#ifdef` that is wrong
# about that compiles cleanly here and fails there, which is exactly how
# 5e7d66f reached master.
#
# FOUR TARGETS, THE ONES mcpp-index MEASURES tinyhttps ON (its
# tests/openkal/pins.toml). aarch64-linux-musl runs under qemu, through the
# runner examples/openkal names. x86_64-windows-musl is built here and run on
# Windows itself by the job after this one: wine took anywhere from four to
# more than thirty minutes to install on these runners, and Windows is the
# system the program is for. The Windows target is where every handshake used
# to fail for want of entropy (src/tls.cppm); it has no name resolution, so its
# network step reports "no network" and the cancellation check, which needs
# none, is what runs.
openkal:
name: build + run (${{ matrix.target }}, above openkal)
runs-on: ubuntu-24.04
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
target: ['x86_64-linux-gnu', 'x86_64-linux-musl', 'x86_64-windows-musl', 'aarch64-linux-musl']
steps:
- uses: actions/checkout@v4
- name: Install xlings
run: |
curl -fsSL --retry 3 --retry-all-errors --retry-delay 2 \
https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Install the runner
if: matrix.target == 'aarch64-linux-musl'
timeout-minutes: 15
env:
DEBIAN_FRONTEND: noninteractive
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq --no-install-recommends qemu-user > /dev/null
qemu-aarch64 --version | head -1
- name: Cache mcpp sandbox
uses: actions/cache@v4
with:
path: ~/.xlings/data/xpkgs/xim-x-mcpp/${{ env.MCPP_VERSION }}/registry
key: mcpp-openkal-${{ runner.os }}-mcpp${{ env.MCPP_VERSION }}-${{ matrix.target }}
# The example builds the library from this checkout (`path = "../.."`) and
# takes the stack beneath it from the index, so what is tested is this
# commit against the published openkal packages.
#
# The toolchain is named, as mcpp-index's measurement names it, and
# installed beforehand: on a fresh runner x86_64-windows-musl was refused
# as "cannot be built on this host" while llvm was not yet installed, though
# the Linux targets, which install it on demand, built.
#
# It cancels a handshake against a local listener, which needs no network,
# and then makes one HTTPS request; it reports "no network" rather than
# failing when there is none, so a runner without egress reports "not run"
# instead of "broken". A certificate the client refused is a failure, not
# an absence of network. The build, the link, the framing parsers and the
# cancellation are checked either way.
- name: Install llvm
run: mcpp toolchain install llvm 22.1.8
- name: Build and run above openkal
if: matrix.target != 'x86_64-windows-musl'
working-directory: examples/openkal
run: |
set -o pipefail
mcpp run --toolchain llvm@22.1.8 --target '${{ matrix.target }}' 2>&1 | tee run.log
grep -q '^cancellation: ok' run.log
# A static PE executable that imports only system DLLs, so it runs on any
# Windows as it is.
- name: Build for Windows above openkal
if: matrix.target == 'x86_64-windows-musl'
working-directory: examples/openkal
run: |
mcpp build --toolchain llvm@22.1.8 --target x86_64-windows-musl
mkdir -p "$RUNNER_TEMP/smoke"
cp target/x86_64-windows-musl/*/bin/smoke.exe "$RUNNER_TEMP/smoke/"
- uses: actions/upload-artifact@v4
if: matrix.target == 'x86_64-windows-musl'
with:
name: smoke-x86_64-windows-musl
path: ${{ runner.temp }}/smoke/smoke.exe
if-no-files-found: error
openkal-windows:
name: run (x86_64-windows-musl, above openkal, on Windows)
needs: openkal
runs-on: windows-2022
timeout-minutes: 15
defaults:
run:
shell: bash
steps:
- uses: actions/download-artifact@v4
with:
name: smoke-x86_64-windows-musl
# Above openkal the Windows certificate store is not read (README,
# "Platforms"), so the program is given a bundle: Git for Windows's, copied
# beside it, because openkal resolves a relative name against the working
# directory and names no absolute path.
- name: Run above openkal
run: |
set -o pipefail
cp "/c/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt" ca-bundle.crt
SSL_CERT_FILE=ca-bundle.crt ./smoke.exe 2>&1 | tee run.log
grep -q '^cancellation: ok' run.log
# ── Windows ──────────────────────────────────────────────────────────────────
#
# WHY THIS JOB EXISTS. Windows keeps no bundle file, so on a Windows Sockets
# build `load_ca_certs` reads the system's ROOT store through the Win32 API
# (src/ca_bundle.cppm). That code is compiled on no other platform, and a job
# elsewhere can show neither that it builds nor that the roots it returns
# verify a real certificate chain. `test_ca_store` asserts both.
#
# AND THE HERMETIC TESTS RUN HERE TOO. They script their own servers on
# 127.0.0.1, and Windows Sockets is where `poll` is `WSAPoll`, a connect in
# progress is reported differently, and the cancellation slices were never
# run before this job ran them.
windows:
name: build + test (windows x86_64, ${{ matrix.toolchain }})
runs-on: windows-2022
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
toolchain: ['msvc@system', 'llvm@20.1.7']
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- name: Install xlings
shell: pwsh
run: |
irm https://d2learn.org/xlings-install.ps1.txt | iex
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Select the toolchain
run: |
spec='${{ matrix.toolchain }}'
case "$spec" in
msvc*) mcpp toolchain default msvc ;;
*) mcpp toolchain install "${spec%@*}" "${spec#*@}"
mcpp toolchain default "$spec" ;;
esac
mcpp toolchain list
- name: The system store verifies a public chain
run: |
mcpp test test_ca_store 2>&1 | tee tests.log
grep -q '^test_ca_store \.\.\. ok' tests.log
- name: The hermetic tests
run: |
set -o pipefail
for t in test_framing test_tls_verify test_pool test_proxy test_cancel; do
mcpp test "$t" 2>&1 | tee "$t.log"
grep -q "^$t \.\.\. ok" "$t.log"
done