From 07839ea4f87d5219e6a3d85d55d6dbe28bbe3d85 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 24 May 2026 08:33:01 +0800 Subject: [PATCH 1/2] chore: fail-fast CI hangs + refresh README header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Recent main runs (notably the v0.0.28 bump) burned the full 60-min job budget on `10_env_command.sh` hanging in xlings install on a fresh MCPP_HOME. The hang is intermittent and lives at the network boundary; no fix to xlings itself in this PR — just shorten the feedback loop. CI: - tests/e2e/run_all.sh wraps every test with `timeout 600` (override via E2E_TEST_TIMEOUT). Distinguishes TIMEOUT (exit 124) from regular FAIL and surfaces the offending test name in the summary. Uses `timeout` if available, falls back to `gtimeout` (macOS coreutils), else skips wrapping and relies on the step-level guard. - ci.yml / ci-macos.yml / ci-windows.yml: add `timeout-minutes: 25` to each "E2E suite" step. A hung suite now fails in ~25 min instead of eating the full 60-min job, freeing the toolchain test steps to still run / be diagnosed. README: - Add a prominent links table directly under the badges: docs / quick start / mcpp.toml guide / examples / toolchains on row 1; package index, mcpplibs, forum, Issues, Releases on row 2. - Add live CI status badges for Linux/macOS/Windows; drop the static "Self-hosted" badge that the CI badges now subsume. - Promote Windows x86_64 LLVM/Clang from 🔄 to ✅ (CI is green since v0.0.27); add footnote noting the MSVC BuildTools dependency and the llvm-mingw direction. --- .github/workflows/ci-macos.yml | 3 +++ .github/workflows/ci-windows.yml | 3 +++ .github/workflows/ci.yml | 6 +++++ README.md | 16 ++++++++++--- tests/e2e/run_all.sh | 41 ++++++++++++++++++++++++++++---- 5 files changed, 62 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index 116f154..cb3d55c 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -292,6 +292,9 @@ jobs: "$MCPP" test - name: E2E suite + # See ci.yml — fail-fast on hung tests instead of burning the + # whole job budget. Per-test 600s timeout lives in run_all.sh. + timeout-minutes: 25 run: | MCPP=$(find target -path "*/bin/mcpp" | head -1) MCPP=$(cd "$(dirname "$MCPP")" && pwd)/$(basename "$MCPP") diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index c74b862..b63b99f 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -178,6 +178,9 @@ jobs: - name: E2E suite shell: bash + # See ci.yml — fail-fast on hung tests instead of burning the + # whole job budget. Per-test 600s timeout lives in run_all.sh. + timeout-minutes: 25 run: | export MCPP="$MCPP_SELF" export MCPP_VENDORED_XLINGS="$XLINGS_BIN" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c98c7f3..8592ab5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -104,6 +104,12 @@ jobs: "$MCPP_FRESH" test - name: E2E suite + # Step-level guard: a single hung test (historically 10_env_command.sh + # on slow xlings/network) used to eat the full 60-min job budget. + # Cap the suite at 25 min so a hang fails fast and we still have room + # for the downstream toolchain steps. Per-test 600s timeout lives in + # tests/e2e/run_all.sh and identifies WHICH test hung. + timeout-minutes: 25 run: | # Point the e2e runner at the freshly-built binary, not the # bootstrap one. Tests cd into mktemp -d, so $MCPP must be diff --git a/README.md b/README.md index 367c1d4..8988246 100644 --- a/README.md +++ b/README.md @@ -3,11 +3,17 @@ > 一个 现代C++ 模块化构建工具 — 纯 C++23 模块编写,已实现自举 [![Release](https://img.shields.io/github/v/release/mcpp-community/mcpp)](https://github.com/mcpp-community/mcpp/releases) +[![ci](https://github.com/mcpp-community/mcpp/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci.yml) +[![ci-macos](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml) +[![ci-windows](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml) [![C++23](https://img.shields.io/badge/C%2B%2B-23-blue.svg)](https://en.cppreference.com/w/cpp/23) -[![Self-hosted](https://img.shields.io/badge/build-self--hosted-brightgreen)]() [![Module](https://img.shields.io/badge/module-ok-green.svg)](https://en.cppreference.com/w/cpp/language/modules) [![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](LICENSE) +| [文档](docs/) · [快速开始](docs/00-getting-started.md) · [mcpp.toml 指南](docs/05-mcpp-toml.md) · [示例项目](docs/01-examples.md) · [工具链管理](docs/03-toolchains.md) | +|:---:| +| [包索引 mcpp-index](https://github.com/mcpp-community/mcpp-index) · [模块化库 mcpplibs](https://github.com/mcpplibs) · [社区论坛](https://forum.d2learn.org/category/20) · [Issues](https://github.com/mcpp-community/mcpp/issues) · [Releases](https://github.com/mcpp-community/mcpp/releases) | +

mcpp demo

@@ -209,12 +215,16 @@ import mcpplibs.cmdline; | Linux aarch64 | 🔄 | 🔄 | 🔄 | — | | macOS arm64 | — | — | ✅ *默认* | — | | macOS x86_64 | — | — | 🔄 | — | -| Windows | — | — | 🔄 | 🔄 | +| Windows x86_64 | — | — | ✅ ¹ *默认* | 🔄 | ✅ 已支持 | 🔄 计划中 > *默认*:Linux 默认工具链为 musl-gcc,release 二进制走 musl 全静态; -> macOS ARM64 默认工具链为 LLVM/Clang。 +> macOS ARM64 / Windows x86_64 默认工具链均为 LLVM/Clang。 +> +> ¹ Windows 上 Clang/LLVM 当前依赖系统已安装 **MSVC BuildTools 或 Visual Studio** +> (提供 UCRT、Windows SDK、MSVC STL)。零-MSVC 依赖的 `llvm-mingw` 路线在规划中 +> ([讨论](https://github.com/mcpp-community/mcpp/issues))。 ## 文档 diff --git a/tests/e2e/run_all.sh b/tests/e2e/run_all.sh index 29cc389..c3d7d5a 100755 --- a/tests/e2e/run_all.sh +++ b/tests/e2e/run_all.sh @@ -123,10 +123,28 @@ check_requires() { return 1 # all satisfied → don't skip } +# Per-test timeout: bail out of an individual test that gets stuck (e.g. +# 10_env_command.sh has been observed hanging for the full job budget on +# slow xlings/network combinations). 600s default; override via env. +# Linux + git-bash on Windows have GNU `timeout`; macOS may need `gtimeout` +# (coreutils). If neither is present, we run without a wrapper and rely on +# the step-level GitHub Actions timeout-minutes as the backstop. +E2E_TEST_TIMEOUT="${E2E_TEST_TIMEOUT:-600}" +TIMEOUT_CMD="" +if command -v timeout &>/dev/null; then TIMEOUT_CMD=timeout +elif command -v gtimeout &>/dev/null; then TIMEOUT_CMD=gtimeout +fi +if [[ -n "$TIMEOUT_CMD" ]]; then + echo "Per-test timeout: ${E2E_TEST_TIMEOUT}s (via $TIMEOUT_CMD)" +else + echo "Per-test timeout: (no timeout/gtimeout on PATH)" +fi + PASS=0 FAIL=0 SKIP=0 FAILED_TESTS=() +TIMED_OUT_TESTS=() for test in "$HERE"/[0-9]*.sh; do name="$(basename "$test")" @@ -138,21 +156,36 @@ for test in "$HERE"/[0-9]*.sh; do continue fi echo "=== $name ===" - if MCPP="$MCPP" bash "$test"; then + if [[ -n "$TIMEOUT_CMD" ]]; then + MCPP="$MCPP" "$TIMEOUT_CMD" "$E2E_TEST_TIMEOUT" bash "$test" + else + MCPP="$MCPP" bash "$test" + fi + rc=$? + if [[ $rc -eq 0 ]]; then echo "PASS: $name" ((PASS++)) + elif [[ $rc -eq 124 ]]; then + # GNU timeout: 124 = killed after deadline (TERM); 137 = SIGKILL after grace. + echo "TIMEOUT: $name (exceeded ${E2E_TEST_TIMEOUT}s — likely network / xlings stall)" + ((FAIL++)) + FAILED_TESTS+=("$name (TIMEOUT)") + TIMED_OUT_TESTS+=("$name") else - echo "FAIL: $name" + echo "FAIL: $name (exit $rc)" ((FAIL++)) - FAILED_TESTS+=("$name") + FAILED_TESTS+=("$name (exit $rc)") fi done echo echo "===============================================" echo "E2E Summary: $PASS passed, $FAIL failed, $SKIP skipped" +if [[ ${#TIMED_OUT_TESTS[@]} -gt 0 ]]; then + echo "Timed out: ${TIMED_OUT_TESTS[*]}" +fi if [[ $FAIL -gt 0 ]]; then - echo "Failed: ${FAILED_TESTS[@]}" + echo "Failed: ${FAILED_TESTS[*]}" exit 1 fi exit 0 From f7fdff492e0ab0c56b2a6c2b27e8d3892a566679 Mon Sep 17 00:00:00 2001 From: sunrisepeak Date: Sun, 24 May 2026 09:09:24 +0800 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20rename=20ci.yml=20=E2=86=92=20ci-l?= =?UTF-8?q?inux.yml;=20move=20CI=20status=20into=20README=20table?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Workflow renamed (and `name:` updated) to match the platform-prefixed ci-macos / ci-windows convention. Comment cross-references updated. - README: drop the 3 CI badges from the badges row and add them as the table's last row alongside the docs / community links — keeps the badges row focused on project metadata (release / language / license). --- .github/workflows/{ci.yml => ci-linux.yml} | 10 ++++++---- .github/workflows/ci-macos.yml | 2 +- .github/workflows/ci-windows.yml | 4 ++-- README.md | 4 +--- 4 files changed, 10 insertions(+), 10 deletions(-) rename .github/workflows/{ci.yml => ci-linux.yml} (97%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci-linux.yml similarity index 97% rename from .github/workflows/ci.yml rename to .github/workflows/ci-linux.yml index 8592ab5..36bd0b6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci-linux.yml @@ -1,9 +1,11 @@ -name: ci +name: ci-linux -# Self-host CI: mcpp builds mcpp. The bootstrap mcpp comes from -# `xlings install mcpp` (xim:mcpp in the xlings package index), so -# this workflow no longer depends on a previous-release tarball — the +# Self-host CI on Linux: mcpp builds mcpp. The bootstrap mcpp comes from +# `xlings install mcpp` (xim:mcpp in the xlings package index), so this +# workflow no longer depends on a previous-release tarball — the # chicken-and-egg now lives upstream in the xlings index. +# +# Paired workflows: ci-macos.yml, ci-windows.yml. on: push: diff --git a/.github/workflows/ci-macos.yml b/.github/workflows/ci-macos.yml index cb3d55c..00427ee 100644 --- a/.github/workflows/ci-macos.yml +++ b/.github/workflows/ci-macos.yml @@ -292,7 +292,7 @@ jobs: "$MCPP" test - name: E2E suite - # See ci.yml — fail-fast on hung tests instead of burning the + # See ci-linux.yml — fail-fast on hung tests instead of burning the # whole job budget. Per-test 600s timeout lives in run_all.sh. timeout-minutes: 25 run: | diff --git a/.github/workflows/ci-windows.yml b/.github/workflows/ci-windows.yml index b63b99f..4796bb1 100644 --- a/.github/workflows/ci-windows.yml +++ b/.github/workflows/ci-windows.yml @@ -1,6 +1,6 @@ name: ci-windows -# Windows CI for mcpp — same flow as Linux (ci.yml) and macOS (ci-macos.yml): +# Windows CI for mcpp — same flow as Linux (ci-linux.yml) and macOS (ci-macos.yml): # xlings install mcpp → self-host build → E2E → smoke → package on: @@ -178,7 +178,7 @@ jobs: - name: E2E suite shell: bash - # See ci.yml — fail-fast on hung tests instead of burning the + # See ci-linux.yml — fail-fast on hung tests instead of burning the # whole job budget. Per-test 600s timeout lives in run_all.sh. timeout-minutes: 25 run: | diff --git a/README.md b/README.md index 8988246..20f9ce1 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,6 @@ > 一个 现代C++ 模块化构建工具 — 纯 C++23 模块编写,已实现自举 [![Release](https://img.shields.io/github/v/release/mcpp-community/mcpp)](https://github.com/mcpp-community/mcpp/releases) -[![ci](https://github.com/mcpp-community/mcpp/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci.yml) -[![ci-macos](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml) -[![ci-windows](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml) [![C++23](https://img.shields.io/badge/C%2B%2B-23-blue.svg)](https://en.cppreference.com/w/cpp/23) [![Module](https://img.shields.io/badge/module-ok-green.svg)](https://en.cppreference.com/w/cpp/language/modules) [![License](https://img.shields.io/badge/license-Apache_2.0-blue.svg)](LICENSE) @@ -13,6 +10,7 @@ | [文档](docs/) · [快速开始](docs/00-getting-started.md) · [mcpp.toml 指南](docs/05-mcpp-toml.md) · [示例项目](docs/01-examples.md) · [工具链管理](docs/03-toolchains.md) | |:---:| | [包索引 mcpp-index](https://github.com/mcpp-community/mcpp-index) · [模块化库 mcpplibs](https://github.com/mcpplibs) · [社区论坛](https://forum.d2learn.org/category/20) · [Issues](https://github.com/mcpp-community/mcpp/issues) · [Releases](https://github.com/mcpp-community/mcpp/releases) | +| [![ci-linux](https://github.com/mcpp-community/mcpp/actions/workflows/ci-linux.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-linux.yml) [![ci-macos](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-macos.yml) [![ci-windows](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml/badge.svg?branch=main)](https://github.com/mcpp-community/mcpp/actions/workflows/ci-windows.yml) |

mcpp demo