ci-fresh-install #205
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-fresh-install | |
| # Fresh install CI — validates the released mcpp binary via xlings. | |
| # Simulates a real first-time user on a clean machine (no caches). | |
| # | |
| # For each platform, tests every supported toolchain: | |
| # 1. mcpp new hello → mcpp run (basic project) | |
| # 2. mcpp build (build mcpp itself from source) | |
| # | |
| # This workflow tests released mcpp, not PR code. | |
| # It runs on release publish, manual trigger, and daily schedule. | |
| on: | |
| # NOTE: `release: published` never fires from the release pipeline — the | |
| # release is created by release.yml with GITHUB_TOKEN, and GitHub | |
| # suppresses workflow triggers from GITHUB_TOKEN-generated events. Kept | |
| # only for releases created manually outside the pipeline. The reliable | |
| # post-release hook is `workflow_run` below: a platform-generated event, | |
| # exempt from that suppression, and requiring no cross-repo PAT. | |
| release: | |
| types: [ published ] | |
| workflow_run: | |
| workflows: [ release ] | |
| types: [ completed ] | |
| workflow_dispatch: | |
| schedule: | |
| # Run daily at 06:00 UTC to catch issues from xlings/runner updates | |
| - cron: '0 6 * * *' | |
| concurrency: | |
| group: ci-fresh-install | |
| cancel-in-progress: false # use false to test in PRs, true to only test released mcpp | |
| # The version under test is DERIVED, once, by the resolve-version job below, | |
| # and every install job consumes that one value. | |
| # | |
| # Two things had to hold, and a hardcoded pin only bought the first: | |
| # | |
| # 1. It must be an explicit version string. Bare `xlings install mcpp` | |
| # resolves "newest in the runner's index copy", so a runner whose copy | |
| # lags silently tests an OLDER binary and reports green. Naming the | |
| # version makes a lagging index fail loudly with `version not found`. | |
| # | |
| # 2. The version the index guard waits for must be the version the jobs | |
| # install. On 2026-07-21 they disagreed: the guard reported "index tracks | |
| # 0.0.102" and the jobs installed 0.0.100 ten seconds later, which then met | |
| # an index whose floor was 0.0.101 (#265). The guard already derived the | |
| # real answer from the releases API and threw it away. | |
| # | |
| # Deriving once and feeding both satisfies (1) and makes (2) structurally | |
| # impossible, instead of relying on a human to keep two hand-edited numbers in | |
| # step with a third that moves on its own. `xlings install mcpp@<derived>` is | |
| # every bit as explicit as `mcpp@<literal>`. | |
| # | |
| # NOT to be confused with the .xlings.json workspace pin, which this used to be | |
| # kept equal to. That one is the BOOTSTRAP compiler for the self-host builds and | |
| # has a different requirement — it must be a released mcpp that can build the | |
| # CURRENT source tree — so it stays hand-maintained. See docs/09-release.md. | |
| jobs: | |
| # ────────────────────────────────────────────────────────────────── | |
| # Linux: gcc@16.1.0, musl-gcc@16.1.0, llvm@20.1.7 | |
| # ────────────────────────────────────────────────────────────────── | |
| # A4: post-release runs race the xim-pkgindex bump (a PR a maintainer | |
| # merges asynchronously) — the 0.0.85 fresh-install failed with | |
| # "version not found: available 0.0.84" 55s after the bump merged. | |
| # Convert the race into a bounded wait: poll the index's mcpp.lua until | |
| # it carries the released version (<=15 min), then let every job run. | |
| # Non-workflow_run triggers (manual, cron, PR) skip the wait. | |
| wait-index: | |
| runs-on: ubuntu-latest | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| timeout-minutes: 20 | |
| outputs: | |
| version: ${{ steps.resolve.outputs.version }} | |
| steps: | |
| # Derive on EVERY trigger, not just post-release. "The newest published | |
| # release" is the version under test whether we got here from the release | |
| # pipeline, from cron, or by hand — only the WAIT below is specific to a | |
| # post-release run, because only then can the index legitimately lag. | |
| - name: Resolve the version under test (newest published release) | |
| id: resolve | |
| run: | | |
| VER=$(curl -fsSL "https://api.github.com/repos/mcpp-community/mcpp/releases/latest" \ | |
| | python3 -c "import json,sys; print(json.load(sys.stdin)['tag_name'].lstrip('v'))") | |
| # A blank version would silently degrade `mcpp@$VER` into bare `mcpp`, | |
| # i.e. straight back to "newest in the runner's index copy" — the exact | |
| # failure this job exists to prevent. Refuse instead. | |
| case "$VER" in | |
| ''|*[!0-9.]*) echo "::error::could not resolve a version from the releases API (got '$VER')"; exit 1 ;; | |
| esac | |
| echo "version=$VER" >> "$GITHUB_OUTPUT" | |
| echo "version under test: $VER" | |
| - name: Wait for the PUBLISHED index artifact to track the released mcpp | |
| if: ${{ github.event_name == 'workflow_run' }} | |
| env: | |
| VER: ${{ steps.resolve.outputs.version }} | |
| run: | | |
| # Poll the ARTIFACT, not the git file. | |
| # | |
| # This used to curl raw.githubusercontent.com/openxlings/xim-pkgindex | |
| # — the index's git source of truth, which updates the instant the | |
| # bump PR merges. But the jobs install from the PUBLISHED ARTIFACT | |
| # (xlings-res/xim-index → pointer → tarball), and that channel lags | |
| # git by however long `Publish Index Artifact` plus release-CDN | |
| # propagation takes. Measured on the 2026.8.3.5 release: this guard | |
| # reported ready, and all 11 jobs then failed with | |
| # [error] package 'mcpp@2026.8.3.5' not found | |
| # A guard that measures a channel nobody installs from is not a guard. | |
| # | |
| # This narrows the window; it cannot close it, because the CDN | |
| # propagates per edge and the runner that polls is not the runner | |
| # that installs. install_released_mcpp.sh retries from the consumer | |
| # side for exactly that residue — this step exists so the retry is | |
| # rarely needed, not so it can be removed. | |
| echo "released: $VER — waiting for the published index artifact..." | |
| for i in $(seq 1 40); do | |
| ptr=$(curl -fsSL "https://github.com/xlings-res/xim-index/releases/download/latest/xim-index-latest.json" 2>/dev/null || true) | |
| # One line on purpose: an indented heredoc inside a YAML block | |
| # scalar is a trap — unindented content silently ends the block. | |
| name=$(printf '%s' "$ptr" | python3 -c 'import json,sys; d=json.load(sys.stdin); n=d.get("indexes",{}).get("xim",d); print(n.get("artifact",{}).get("name",""))' 2>/dev/null || true) | |
| if [ -n "$name" ] && curl -fsSL \ | |
| "https://github.com/xlings-res/xim-index/releases/download/latest/$name" \ | |
| | tar -xzO --wildcards '*pkgs/m/mcpp.lua' 2>/dev/null | grep -q "\"$VER\""; then | |
| echo "published index artifact ($name) tracks $VER (after $((i*30))s)"; exit 0 | |
| fi | |
| sleep 30 | |
| done | |
| echo "::error::the published index artifact never tracked $VER within 20min — check that the xim-pkgindex bump PR merged AND that Publish Index Artifact ran" | |
| exit 1 | |
| - name: No wait needed (manual/cron trigger) | |
| if: ${{ github.event_name != 'workflow_run' }} | |
| run: echo "not a post-release run; skipping index wait" | |
| linux-fresh: | |
| needs: [wait-index] | |
| name: Linux fresh install | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| env: | |
| # The one derived value (see the header comment): every install job names | |
| # the SAME version the index guard waited for, so the two cannot disagree. | |
| MCPP_PIN: ${{ needs.wait-index.outputs.version }} | |
| # Verbose every mcpp invocation — fresh-install is the cold index/sandbox | |
| # bootstrap path, exactly where extra diagnostics matter (src/cli.cppm). | |
| MCPP_VERBOSE: "1" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install xlings + mcpp | |
| env: | |
| XLINGS_NON_INTERACTIVE: '1' | |
| run: | | |
| curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.4.1 | |
| echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" | |
| - name: Install mcpp and config mirror | |
| shell: bash | |
| run: | | |
| # ONE implementation for "make the released mcpp@X be what `mcpp` | |
| # runs, and prove it" — see .github/tools/install_released_mcpp.sh | |
| # for the three defects the inline version had (workspace pin, no | |
| # activation, and waiting on the wrong index channel). | |
| bash .github/tools/install_released_mcpp.sh "${MCPP_PIN}" "$(pwd)" | |
| mcpp self config --mirror GLOBAL | |
| echo "mcpp debug info:" | |
| which mcpp | |
| cat $HOME/.xlings/.xlings.json | |
| - name: "Default: mcpp new → run" | |
| run: | | |
| cd "$(mktemp -d)" | |
| mcpp new hello_gcc | |
| cd hello_gcc | |
| mcpp run | |
| # Template packages exercise the sha256-pinned mcpp-index fetch | |
| # path (user report: `mcpp new ... --template imgui` failed with | |
| # fetch 'imgui@0.0.6' exit 1 on hosts without a sha256sum binary). | |
| - name: "Template: mcpp new --template imgui (fetch path)" | |
| run: | | |
| cd "$(mktemp -d)" | |
| mcpp new abc1 --template imgui | |
| test -f abc1/mcpp.toml | |
| - name: "Default: build mcpp" | |
| run: | | |
| mcpp clean | |
| mcpp run | |
| - name: "musl-gcc: mcpp new → run" | |
| run: | | |
| mcpp toolchain install gcc 16.1.0-musl | |
| mcpp toolchain default gcc@16.1.0-musl | |
| cd "$(mktemp -d)" | |
| mcpp new hello_musl | |
| cd hello_musl | |
| mcpp run | |
| - name: "musl-gcc: build mcpp" | |
| run: | | |
| mcpp toolchain default gcc@16.1.0-musl | |
| mcpp clean | |
| mcpp run | |
| - name: "gcc 16: mcpp new → run" | |
| run: | | |
| mcpp toolchain install gcc 16.1.0 | |
| mcpp toolchain default gcc@16.1.0 | |
| cd "$(mktemp -d)" | |
| mcpp new hello_gcc16 | |
| cd hello_gcc16 | |
| mcpp run | |
| - name: "gcc 16: build mcpp" | |
| run: | | |
| mcpp toolchain default gcc@16.1.0 | |
| mcpp clean | |
| mcpp run | |
| - name: "LLVM: mcpp new → run" | |
| run: | | |
| mcpp toolchain install llvm 20.1.7 | |
| mcpp toolchain default llvm@20.1.7 | |
| cd "$(mktemp -d)" | |
| mcpp new hello_llvm | |
| cd hello_llvm | |
| mcpp run | |
| - name: "LLVM: build mcpp" | |
| run: | | |
| mcpp toolchain default llvm@20.1.7 | |
| mcpp clean | |
| mcpp run | |
| # ────────────────────────────────────────────────────────────────── | |
| # Newer/rolling-glibc distros — reproduction surface for the | |
| # bundled-glibc-vs-host-libtinfo `sh:` crash (host glibc > bundled). | |
| # Plus older-glibc legs (the safe reverse direction) proving the | |
| # musl-static mcpp + self-contained toolchain run end-to-end on old | |
| # hosts. Runs the released mcpp inside distro containers. | |
| # ────────────────────────────────────────────────────────────────── | |
| linux-distro-matrix: | |
| needs: [wait-index] | |
| name: Linux distro (${{ matrix.distro }}) | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ubuntu-24.04 | |
| container: | |
| image: ${{ matrix.image }} | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # findutils (find) is mandatory on every leg: quick_install.sh | |
| # locates the extracted xlings dir with `find`, so a missing find | |
| # fails the install with exit 127 *before* mcpp ever runs. Minimal | |
| # images (opensuse/tumbleweed) ship without it; arch's base merely | |
| # bundles it by luck. List it explicitly everywhere — don't rely on | |
| # the base image. | |
| include: | |
| - distro: fedora-latest | |
| image: fedora:latest | |
| setup: dnf -y install curl bash tar gzip xz git findutils binutils file glibc-langpack-en | |
| - distro: arch | |
| image: archlinux:latest | |
| setup: pacman -Sy --noconfirm curl bash tar gzip xz git findutils binutils file | |
| - distro: tumbleweed | |
| image: opensuse/tumbleweed:latest | |
| setup: zypper -n install curl bash tar gzip xz git findutils binutils file | |
| - distro: debian-testing | |
| image: debian:testing | |
| setup: apt-get update && apt-get -y install curl bash tar gzip xz-utils git ca-certificates binutils findutils file | |
| - distro: ubuntu-2004 | |
| image: ubuntu:20.04 | |
| setup: apt-get update && DEBIAN_FRONTEND=noninteractive apt-get -y install curl bash tar gzip xz-utils git ca-certificates binutils findutils file | |
| - distro: debian-11 | |
| image: debian:11 | |
| setup: apt-get update && apt-get -y install curl bash tar gzip xz-utils git ca-certificates binutils findutils file | |
| env: | |
| # The one derived value (see the header comment): every install job names | |
| # the SAME version the index guard waited for, so the two cannot disagree. | |
| MCPP_PIN: ${{ needs.wait-index.outputs.version }} | |
| XLINGS_NON_INTERACTIVE: '1' | |
| HOME: /root | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install prerequisites (${{ matrix.distro }}) | |
| run: ${{ matrix.setup }} | |
| - name: Install xlings + mcpp | |
| run: | | |
| curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.4.1 | |
| # Deliberately NOT writing to $GITHUB_PATH here. On container | |
| # images that declare no PATH in their config (opensuse/ | |
| # tumbleweed), appending a single dir to GITHUB_PATH makes the | |
| # runner exec later steps' `sh` with only that dir on PATH — | |
| # `sh` (in /usr/bin) vanishes and the next step dies with | |
| # `exec: "sh": ... not found` / exit 127. Each step below already | |
| # exports PATH itself, so the append is redundant anyway. | |
| - name: Configure mcpp | |
| shell: bash | |
| run: | | |
| export PATH="$HOME/.xlings/subos/current/bin:$PATH" | |
| # ONE implementation for "make the released mcpp@X be what `mcpp` | |
| # runs, and prove it" — see .github/tools/install_released_mcpp.sh | |
| # for the three defects the inline version had (workspace pin, no | |
| # activation, and waiting on the wrong index channel). | |
| bash .github/tools/install_released_mcpp.sh "${MCPP_PIN}" "$(pwd)" | |
| mcpp self config --mirror GLOBAL | |
| - name: "Regression: new → run (loader env must not crash /bin/sh)" | |
| run: | | |
| export PATH="$HOME/.xlings/subos/current/bin:$PATH" | |
| cd "$(mktemp -d)" | |
| mcpp new hello_distro | |
| cd hello_distro | |
| mcpp run | |
| - name: "Self-containment: produced binary uses bundled loader" | |
| run: | | |
| export PATH="$HOME/.xlings/subos/current/bin:$PATH" | |
| cd "$(mktemp -d)" && mcpp new hc && cd hc && mcpp build | |
| bin="$(find target -type f -name hc | head -1)" | |
| interp="$(file "$bin" | grep -o 'interpreter [^,]*' | awk '{print $2}')" | |
| echo "interp=$interp" | |
| case "$interp" in | |
| */.mcpp/*|*/registry/*|*xpkgs*) echo "OK bundled loader" ;; | |
| *) echo "FAIL host loader: $interp"; exit 1 ;; | |
| esac | |
| # ────────────────────────────────────────────────────────────────── | |
| # macOS: llvm@20.1.7 | |
| # ────────────────────────────────────────────────────────────────── | |
| macos-fresh: | |
| needs: [wait-index] | |
| name: macOS fresh install | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| # macos-14: the support floor (mcpp ≥0.0.50 / xlings ≥0.4.50 ship | |
| # minos=14.0 static-libc++ binaries). A fresh install passing here | |
| # is the continuous proof of the macOS 14 floor — and of host-tool | |
| # independence (this image has no sha256sum; macos-15 does). | |
| runs-on: macos-14 | |
| timeout-minutes: 30 | |
| env: | |
| # The one derived value (see the header comment): every install job names | |
| # the SAME version the index guard waited for, so the two cannot disagree. | |
| MCPP_PIN: ${{ needs.wait-index.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install xlings | |
| env: | |
| XLINGS_NON_INTERACTIVE: '1' | |
| run: | | |
| # Pinned to kXlingsVersion like every other bootstrap (see | |
| # .github/tools/check_version_pins.sh). Two floors this image needs, | |
| # both long satisfied — do not pin below them: | |
| # v0.4.50+: first xlings whose macosx binary runs on macOS 14 | |
| # (older ones carry minos=15 and refuse to start). | |
| # v0.4.51+: in-process sha256 — this image has no sha256sum | |
| # binary, so pinned fetches failed before it. | |
| curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh | bash -s v2026.8.4.1 | |
| echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH" | |
| - name: Install mcpp and config mirror | |
| shell: bash | |
| run: | | |
| # ONE implementation for "make the released mcpp@X be what `mcpp` | |
| # runs, and prove it" — see .github/tools/install_released_mcpp.sh | |
| # for the three defects the inline version had (workspace pin, no | |
| # activation, and waiting on the wrong index channel). | |
| bash .github/tools/install_released_mcpp.sh "${MCPP_PIN}" "$(pwd)" | |
| mcpp self config --mirror GLOBAL | |
| echo "mcpp debug info:" | |
| which mcpp | |
| cat $HOME/.xlings/.xlings.json | |
| - name: "LLVM: mcpp new → run" | |
| run: | | |
| cd "$(mktemp -d)" | |
| mcpp new hello_mac | |
| cd hello_mac | |
| mcpp run | |
| # Template packages exercise the sha256-pinned mcpp-index fetch | |
| # path — this is what broke on hosts without a sha256sum binary | |
| # (stock macOS / bare Windows) before xlings 0.4.51 hashed | |
| # in-process. | |
| - name: "Template: mcpp new --template imgui (fetch path)" | |
| run: | | |
| cd "$(mktemp -d)" | |
| mcpp new abc1 --template imgui | |
| test -f abc1/mcpp.toml | |
| - name: "LLVM: build mcpp" | |
| run: | | |
| mcpp clean | |
| mcpp run | |
| # ────────────────────────────────────────────────────────────────── | |
| # Windows WITH Visual Studio: llvm@20.1.7 + MSVC STL | |
| # | |
| # Two images, because the OS version is a real variable for a tool that | |
| # touches the UCRT, the Windows SDK and long paths. GitHub publishes no | |
| # Windows 10/11 CLIENT image, so these Server builds are the closest | |
| # available stand-ins: windows-2022 is the Win10 21H2 kernel generation, | |
| # windows-2025 the Win11 24H2 one. What they cannot cover is genuinely | |
| # client-only behaviour — UAC prompts, Defender real-time scanning, the | |
| # long-path policy default — which needs a self-hosted runner. | |
| # ────────────────────────────────────────────────────────────────── | |
| windows-fresh: | |
| needs: [wait-index] | |
| name: Windows fresh install (${{ matrix.image }}) | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: ${{ matrix.image }} | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| image: [windows-2022, windows-2025] | |
| env: | |
| # The one derived value (see the header comment): every install job names | |
| # the SAME version the index guard waited for, so the two cannot disagree. | |
| MCPP_PIN: ${{ needs.wait-index.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install xlings | |
| shell: pwsh | |
| env: | |
| XLINGS_NON_INTERACTIVE: '1' | |
| run: | | |
| irm https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.ps1 | iex | |
| $xlingsbin = "$env:USERPROFILE\.xlings\subos\current\bin" | |
| $env:PATH = "$xlingsbin;$env:PATH" | |
| $xlingsbin | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 | |
| - name: Install mcpp and config mirror | |
| shell: bash | |
| run: | | |
| # ONE implementation for "make the released mcpp@X be what `mcpp` | |
| # runs, and prove it" — see .github/tools/install_released_mcpp.sh | |
| # for the three defects the inline version had (workspace pin, no | |
| # activation, and waiting on the wrong index channel). | |
| bash .github/tools/install_released_mcpp.sh "${MCPP_PIN}" "$(pwd)" | |
| mcpp self config --mirror GLOBAL | |
| cat "$USERPROFILE/.xlings/.xlings.json" || true | |
| - name: "LLVM: mcpp new → run" | |
| shell: pwsh | |
| run: | | |
| $tmp = New-TemporaryFile | ForEach-Object { Remove-Item $_; New-Item -ItemType Directory -Path $_ } | |
| Set-Location $tmp | |
| mcpp new hello_win | |
| Set-Location hello_win | |
| mcpp run | |
| # Template packages exercise the sha256-pinned mcpp-index fetch | |
| # path (user report: `mcpp new abc1 --template imgui` failed with | |
| # fetch 'imgui@0.0.6' exit 1 on bare Windows — no sha256sum binary | |
| # outside git-bash; fixed by xlings 0.4.51 in-process hashing). | |
| - name: "Template: mcpp new --template imgui (fetch path)" | |
| shell: pwsh | |
| run: | | |
| $tmp = New-TemporaryFile | ForEach-Object { Remove-Item $_; New-Item -ItemType Directory -Path $_ } | |
| Set-Location $tmp | |
| mcpp new abc1 --template imgui | |
| if (!(Test-Path abc1/mcpp.toml)) { exit 1 } | |
| - name: "LLVM: build mcpp" | |
| shell: pwsh | |
| run: | | |
| mcpp clean | |
| mcpp run | |
| # ────────────────────────────────────────────────────────────────── | |
| # Windows WITHOUT Visual Studio — the shape of an ordinary user's machine | |
| # | |
| # A stock Windows install ships the UCRT runtime DLLs and nothing else: the | |
| # MSVC STL and the Windows SDK arrive only with Visual Studio's "Desktop | |
| # development with C++" workload. mcpp's Windows default targeted the MSVC | |
| # ABI, so `mcpp new && mcpp build` failed on every such box — and no CI job | |
| # could see it, because every GitHub Windows image ships Visual Studio. | |
| # | |
| # There is no VS-free runner, so the image is masked instead. The risk with | |
| # masking is a false green: miss one of msvc.cppm's three discovery | |
| # strategies (vswhere, environment, well-known paths) and mcpp still finds | |
| # MSVC, takes the ordinary path, and the job passes while proving nothing. | |
| # e2e 182 opens by asserting `mcpp toolchain default msvc` FAILS, which | |
| # turns exactly that into a hard failure. | |
| # ────────────────────────────────────────────────────────────────── | |
| windows-nomsvc-fresh: | |
| needs: [wait-index] | |
| name: Windows fresh install (no Visual Studio) | |
| if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }} | |
| runs-on: windows-2025 | |
| timeout-minutes: 30 | |
| env: | |
| MCPP_PIN: ${{ needs.wait-index.outputs.version }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Mask Visual Studio | |
| shell: pwsh | |
| run: | | |
| $ErrorActionPreference = 'Continue' | |
| # All three of msvc.cppm's discovery strategies converge on | |
| # <vsRoot>\VC\Tools\MSVC, so mask the VC directory rather than the | |
| # Visual Studio root: the root is held open on the runner and | |
| # renaming it is denied, while VC one level down renames fine. | |
| # The runner is disposable, so this is both safe and closer to | |
| # "absent" than any env-only trick would be. | |
| $vswhere = "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" | |
| if (Test-Path $vswhere) { Rename-Item $vswhere "vswhere.exe.masked" } | |
| Get-ChildItem "C:\Program Files*\Microsoft Visual Studio\*\*\VC" ` | |
| -Directory -ErrorAction SilentlyContinue | ForEach-Object { | |
| Rename-Item $_.FullName "$($_.Name).masked" -ErrorAction SilentlyContinue | |
| } | |
| foreach ($v in @('VSINSTALLDIR','VCINSTALLDIR','VCToolsInstallDir', | |
| 'VS170COMNTOOLS','VS160COMNTOOLS','VS150COMNTOOLS')) { | |
| "$v=" | Out-File -Append -FilePath $env:GITHUB_ENV -Encoding utf8 | |
| } | |
| # Check the mask's own postcondition here, where the cause is | |
| # obvious, rather than letting it surface later as a confusing pass. | |
| $left = Get-ChildItem "C:\Program Files*\Microsoft Visual Studio\*\*\VC\Tools\MSVC" ` | |
| -Directory -ErrorAction SilentlyContinue | |
| if ($left) { | |
| Write-Host "FAIL: VC tools still present after masking:" | |
| $left | ForEach-Object { Write-Host " $($_.FullName)" } | |
| exit 1 | |
| } | |
| Write-Host "Visual Studio masked: no VC\Tools\MSVC remains." | |
| - name: Install xlings | |
| shell: pwsh | |
| env: | |
| XLINGS_NON_INTERACTIVE: '1' | |
| run: | | |
| irm https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.ps1 | iex | |
| $xlingsbin = "$env:USERPROFILE\.xlings\subos\current\bin" | |
| $env:PATH = "$xlingsbin;$env:PATH" | |
| $xlingsbin | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 | |
| - name: Install mcpp and config mirror | |
| shell: bash | |
| run: | | |
| # ONE implementation for "make the released mcpp@X be what `mcpp` | |
| # runs, and prove it" — see .github/tools/install_released_mcpp.sh | |
| # for the three defects the inline version had (workspace pin, no | |
| # activation, and waiting on the wrong index channel). | |
| bash .github/tools/install_released_mcpp.sh "${MCPP_PIN}" "$(pwd)" | |
| mcpp self config --mirror GLOBAL | |
| # The self-check, the fallback, persistence, a self-contained exe, and | |
| # the refusal to overrule an explicit [toolchain] — all in e2e 182, so | |
| # the assertions live with the tests rather than in workflow YAML. | |
| - name: "No Visual Studio: fallback to winlibs GCC (e2e 182)" | |
| shell: bash | |
| run: | | |
| MCPP="$(command -v mcpp)" bash tests/e2e/182_windows_no_msvc_fallback.sh |