0.3.4 — cancel a request in flight with a std::stop_token #68
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: ['[email protected]', '[email protected]'] | |
| 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, [email protected]) | |
| 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 }}[email protected] | |
| - name: Select the toolchain | |
| run: | | |
| mcpp toolchain install llvm 22.1.8 | |
| mcpp toolchain default [email protected] | |
| 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. A fresh | |
| # runner's default is the gcc mcpp installed first, and with it | |
| # x86_64-windows-musl was refused as "cannot be built on this host" even | |
| # though the example's own `[toolchain]` names llvm, the one the openkal | |
| # runtime supplies that target for. | |
| # | |
| # 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: Build and run above openkal | |
| if: matrix.target != 'x86_64-windows-musl' | |
| working-directory: examples/openkal | |
| run: | | |
| set -o pipefail | |
| mcpp run --toolchain [email protected] --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 [email protected] --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', '[email protected]'] | |
| 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 |