diff --git a/.github/workflows/openkal-compat.yml b/.github/workflows/openkal-compat.yml index 4e9bf3fd..0f475ae1 100644 --- a/.github/workflows/openkal-compat.yml +++ b/.github/workflows/openkal-compat.yml @@ -17,6 +17,10 @@ on: 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" @@ -34,6 +38,22 @@ env: # pins.toml for why this pin, not just validate.yml's, is gated by the # index floor. MCPP_VERSION: "2026.9.20.1" + # 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: @@ -76,6 +96,44 @@ jobs: 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