diff --git a/.github/workflows/ci-fresh-install.yml b/.github/workflows/ci-fresh-install.yml new file mode 100644 index 0000000..a40c60a --- /dev/null +++ b/.github/workflows/ci-fresh-install.yml @@ -0,0 +1,161 @@ +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 does NOT run on PRs — only on push to main, manual trigger, and daily schedule. +# Failures here mean the released mcpp has issues, not that the PR is broken. + +on: + push: + branches: [ main ] + 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: true + +jobs: + # ────────────────────────────────────────────────────────────────── + # Linux: gcc@16.1.0, musl-gcc@15.1.0, llvm@20.1.7 + # ────────────────────────────────────────────────────────────────── + linux-fresh: + name: Linux fresh install + runs-on: ubuntu-24.04 + timeout-minutes: 60 + steps: + - uses: actions/checkout@v4 + + - name: Install xlings + mcpp + env: + XLINGS_NON_INTERACTIVE: '1' + run: | + curl -fsSL https://github.com/d2learn/xlings/releases/download/v0.4.30/xlings-0.4.30-linux-x86_64.tar.gz | tar -xzf - -C /tmp + /tmp/xlings-0.4.30-linux-x86_64/subos/default/bin/xlings self install + export PATH="$HOME/.xlings/subos/default/bin:$PATH" + xlings install mcpp -y + echo "$HOME/.xlings/subos/default/bin" >> "$GITHUB_PATH" + mcpp --version + + - name: "GCC: mcpp new → run" + run: | + cd "$(mktemp -d)" + mcpp new hello_gcc + cd hello_gcc + mcpp run + + - name: "GCC: build mcpp" + run: | + mcpp clean + mcpp build + + - name: "musl-gcc: mcpp new → run" + run: | + mcpp toolchain install gcc 15.1.0-musl + mcpp toolchain default gcc@15.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@15.1.0-musl + mcpp clean + mcpp build + + - name: "LLVM: mcpp new → run" + run: | + mcpp self config --mirror GLOBAL + 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 build + + # ────────────────────────────────────────────────────────────────── + # macOS: llvm@20.1.7 + # ────────────────────────────────────────────────────────────────── + macos-fresh: + name: macOS fresh install + runs-on: macos-15 + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + - name: Install xlings + mcpp + env: + XLINGS_NON_INTERACTIVE: '1' + run: | + curl -fsSL https://github.com/d2learn/xlings/releases/download/v0.4.30/xlings-0.4.30-macosx-arm64.tar.gz | tar -xzf - -C /tmp + /tmp/xlings-0.4.30-macosx-arm64/subos/default/bin/xlings self install + export PATH="$HOME/.xlings/subos/default/bin:$PATH" + xlings install mcpp -y + echo "$HOME/.xlings/subos/default/bin" >> "$GITHUB_PATH" + mcpp --version + + - name: "LLVM: mcpp new → run" + run: | + cd "$(mktemp -d)" + mcpp new hello_mac + cd hello_mac + mcpp run + + - name: "LLVM: build mcpp" + run: | + mcpp clean + mcpp build + + # ────────────────────────────────────────────────────────────────── + # Windows: llvm@20.1.7 + MSVC STL + # ────────────────────────────────────────────────────────────────── + windows-fresh: + name: Windows fresh install + runs-on: windows-latest + timeout-minutes: 30 + steps: + - uses: actions/checkout@v4 + + - name: Install xlings + mcpp + shell: pwsh + env: + XLINGS_NON_INTERACTIVE: '1' + run: | + Invoke-WebRequest -Uri "https://github.com/d2learn/xlings/releases/download/v0.4.30/xlings-0.4.30-windows-x86_64.zip" -OutFile "$env:TEMP\xlings.zip" + Expand-Archive -Path "$env:TEMP\xlings.zip" -DestinationPath "$env:TEMP\xlings-extract" -Force + & "$env:TEMP\xlings-extract\xlings-0.4.30-windows-x86_64\subos\default\bin\xlings.exe" self install + $xlingsbin = "$env:USERPROFILE\.xlings\subos\default\bin" + $env:PATH = "$xlingsbin;$env:PATH" + xlings install mcpp -y + $xlingsbin | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 + mcpp --version + + - 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 + + - name: "LLVM: build mcpp" + shell: pwsh + run: | + mcpp clean + mcpp build diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 6343b67..116f154 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -306,14 +306,14 @@ jobs: "$MCPP" toolchain default llvm@20.1.7 bash tests/e2e/run_all.sh - - name: Self-host smoke (freshly-built mcpp builds itself again) + - name: "Toolchain: LLVM — build mcpp (self-host)" run: | MCPP=$(find target -path "*/bin/mcpp" | head -1) MCPP=$(cd "$(dirname "$MCPP")" && pwd)/$(basename "$MCPP") test -x "$MCPP" - export PATH="$(dirname "$MCPP"):$PATH" + cp "$MCPP" /tmp/mcpp-fresh + MCPP=/tmp/mcpp-fresh + "$MCPP" toolchain default llvm@20.1.7 + "$MCPP" clean "$MCPP" build "$MCPP" --version - echo ":: Self-host smoke PASS" - - # Fresh user experience test moved to ci-fresh-install.yml (PR #63) diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index 90d5412..9c50b17 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -96,19 +96,29 @@ jobs: export MCPP="$MCPP_SELF" export MCPP_VENDORED_XLINGS="$XLINGS_BIN" export MCPP_E2E_TOOLCHAIN_MIRROR=GLOBAL - "$MCPP_SELF" self config --mirror GLOBAL 2>/dev/null || true - "$MCPP_SELF" toolchain default llvm@20.1.7 2>/dev/null || true + "$MCPP_SELF" self config --mirror GLOBAL + "$MCPP_SELF" toolchain default llvm@20.1.7 bash tests/e2e/run_all.sh - - name: Self-host smoke (freshly-built mcpp builds itself again) + - name: "Toolchain: LLVM — mcpp new → run" shell: bash run: | export MCPP_VENDORED_XLINGS="$XLINGS_BIN" - "$MCPP_SELF" build - "$MCPP_SELF" --version - echo ":: Self-host smoke PASS" + TMP=$(mktemp -d) + cd "$TMP" + "$MCPP_SELF" new hello_win + cd hello_win + "$MCPP_SELF" run - # Fresh user experience test moved to ci-fresh-install.yml (PR #63) + - name: "Toolchain: LLVM — build mcpp (self-host)" + shell: bash + run: | + export MCPP_VENDORED_XLINGS="$XLINGS_BIN" + cp "$MCPP_SELF" /tmp/mcpp-fresh.exe + MCPP=/tmp/mcpp-fresh.exe + "$MCPP" toolchain default llvm@20.1.7 + "$MCPP" clean --bmi-cache + "$MCPP" build 2>&1 | tee build.log; grep -q "Resolved llvm@20.1.7" build.log - name: Package Windows release zip id: package @@ -118,9 +128,12 @@ jobs: WRAPPER="mcpp-${VERSION}-windows-x86_64" ZIPNAME="${WRAPPER}.zip" + MCPP_BIN=$(find target -name "mcpp.exe" -path "*/bin/*" | head -1) + test -n "$MCPP_BIN" || { echo "FAIL: no mcpp.exe in target/"; exit 1; } + STAGING=$(mktemp -d) mkdir -p "$STAGING/$WRAPPER/bin" "$STAGING/$WRAPPER/registry/bin" - cp "$MCPP_SELF" "$STAGING/$WRAPPER/bin/mcpp.exe" + cp "$MCPP_BIN" "$STAGING/$WRAPPER/bin/mcpp.exe" printf '@echo off\r\n"%%~dp0bin\\mcpp.exe" %%*\r\n' > "$STAGING/$WRAPPER/mcpp.bat" cp README.md "$STAGING/$WRAPPER/" 2>/dev/null || true cp LICENSE "$STAGING/$WRAPPER/" 2>/dev/null || true diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e42abf9..c98c7f3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -128,39 +128,29 @@ jobs: "$MCPP" toolchain default gcc@16.1.0 bash tests/e2e/run_all.sh - - name: Self-host smoke (freshly-built mcpp builds itself again) + - name: Save freshly-built mcpp for toolchain tests run: | MCPP=$(realpath "$(find target -type f -name mcpp -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2)") - "$MCPP" build - "$MCPP" test + cp "$MCPP" /tmp/mcpp-fresh + echo "MCPP=/tmp/mcpp-fresh" >> "$GITHUB_ENV" - - name: "Toolchain: GCC — mcpp new → build → run" + - name: "Toolchain: GCC — build mcpp + test" run: | - MCPP=$(realpath "$(find target -type f -name mcpp -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2)") - "$MCPP" toolchain default gcc@16.1.0 - TMP=$(mktemp -d) - cd "$TMP" - "$MCPP" new hello_gcc - cd hello_gcc - "$MCPP" run + "$MCPP" clean + "$MCPP" build 2>&1 | tee build.log; grep -q "Resolved gcc@16.1.0" build.log + "$MCPP" test - - name: "Toolchain: musl-gcc — mcpp new → build → run" + - name: "Toolchain: musl-gcc — build mcpp (--target)" run: | - MCPP=$(realpath "$(find target -type f -name mcpp -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2)") - "$MCPP" toolchain default gcc@15.1.0-musl - TMP=$(mktemp -d) - cd "$TMP" - "$MCPP" new hello_musl - cd hello_musl - "$MCPP" run + "$MCPP" clean + "$MCPP" build --target x86_64-linux-musl 2>&1 | tee build.log; grep -q "Resolved gcc@15.1.0-musl" build.log - - name: "Toolchain: LLVM — install + mcpp new → build → run" + - name: "Toolchain: LLVM — build mcpp" run: | - MCPP=$(realpath "$(find target -type f -name mcpp -printf '%T@ %p\n' | sort -rn | head -1 | cut -d' ' -f2)") "$MCPP" toolchain install llvm 20.1.7 - "$MCPP" toolchain default llvm@20.1.7 - TMP=$(mktemp -d) - cd "$TMP" - "$MCPP" new hello_llvm - cd hello_llvm - "$MCPP" run + # Override project toolchain to use LLVM for this build + sed -i 's/^default = "gcc@16.1.0"/default = "llvm@20.1.7"/' mcpp.toml + "$MCPP" clean + "$MCPP" build 2>&1 | tee build.log; grep -q "Resolved llvm@20.1.7" build.log + # Restore + sed -i 's/^default = "llvm@20.1.7"/default = "gcc@16.1.0"/' mcpp.toml