Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci-aarch64-fresh-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ jobs:
name: fresh install + native build (aarch64 / glibc)
runs-on: ubuntu-24.04-arm
timeout-minutes: 60
env:
# Verbose every mcpp invocation — cold bootstrap path (src/cli.cppm).
MCPP_VERBOSE: "1"
steps:
- name: System info
run: |
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/ci-fresh-install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ jobs:
name: Linux fresh install
runs-on: ubuntu-24.04
timeout-minutes: 60
env:
# 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

Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/ci-linux-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ jobs:
timeout-minutes: 45
env:
MCPP_HOME: /home/runner/.mcpp
# NOTE: do NOT force MCPP_VERBOSE here. The e2e suite includes tests that
# assert mcpp's DEFAULT (quiet) output — e.g. 48_build_error_output and
# 53_namespaced_cache_label — which forced verbose would break. Verbose is
# set only in the fresh-install workflows (cold bootstrap, no such asserts).
# A specific test that needs verbose passes `--verbose` itself.
steps:
- uses: actions/checkout@v4

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ jobs:
# MCPP_HOME pinned so the cache key below restores into the
# same path mcpp resolves at runtime.
MCPP_HOME: /home/runner/.mcpp
# Verbose every mcpp invocation for richer CI diagnostics (src/cli.cppm).
MCPP_VERBOSE: "1"
steps:
- uses: actions/checkout@v4

Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci-macos.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ jobs:
name: macOS ARM64 — xlings LLVM end-to-end
runs-on: macos-15
timeout-minutes: 30
# NOTE: no MCPP_VERBOSE here — this job runs the e2e suite, which includes
# tests asserting mcpp's default quiet output (48/53). Verbose is forced only
# in the fresh-install workflows.
steps:
- uses: actions/checkout@v4

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/ci-windows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ jobs:
timeout-minutes: 45
env:
MCPP_HOME: C:\Users\runneradmin\.mcpp
# NOTE: no MCPP_VERBOSE — this job runs the e2e suite, which asserts mcpp's
# default quiet output (48/53). Verbose is forced only in fresh-install.
steps:
- uses: actions/checkout@v4

Expand Down
2 changes: 2 additions & 0 deletions .github/workflows/cross-build-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ jobs:
qemu_bin: qemu-aarch64-static
env:
MCPP_HOME: /home/runner/.mcpp
# Verbose every mcpp invocation for richer CI diagnostics (src/cli.cppm).
MCPP_VERBOSE: "1"
steps:
- uses: actions/checkout@v4

Expand Down
25 changes: 25 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,31 @@
> 本文件追踪 `mcpp-community/mcpp` 公开仓的版本演进。
> 格式参考 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.1.0/)。

## [0.0.70] — 2026-06-29

### 修复

- **首次初始化在海外网络与 GitHub 托管 CI 上的冷启动失败(`index missing`;patchelf / ninja
bootstrap 失败)**:`mcpp self env` 为新建的 `MCPP_HOME` 播种 `.xlings.json` 时,将 `mirror` 字段
硬编码为 `"CN"`。xlings 的 `normalize_mirror_` 仅接受 `GLOBAL` 与 `CN` 两个合法取值,故 `"CN"`
被直接采用并解析至 gitcode,致使 xlings 内置的区域探测 `detect_install_mirror_()` 被跳过——该例程
经 `tinyhttps::probe_latency` 测量 github 与 gitcode 的连接延迟,择可达且更低延迟者。在美国区域的
runner 上,gitcode 不可达或显著较慢(实测 github 70 ms、gitcode 1060 ms),由此索引与沙箱的冷
bootstrap 失败。本版将播种值改为 `"auto"`:`normalize_mirror_("auto")` 判定为非法取值,xlings 视其
为未设置并执行自身探测,在美国区域解析至 GLOBAL、在中国大陆解析至 CN。镜像选择的职责由此归还
xlings(其已基于 tinyhttps 实现该机制),mcpp 不再代为决策。播种仅在 `.xlings.json` 不存在时发生,
显式的 `mcpp self config --mirror CN|GLOBAL` 配置不会被覆盖。

### 新增

- **`MCPP_VERBOSE` 环境变量**:取非空且非 `"0"` 的值时,为每一次 mcpp 调用启用 verbose 日志,涵盖
e2e 脚本中未携带 flag 的 `$MCPP` 调用,便于 CI 诊断。该变量与既有的 `MCPP_LOG_LEVEL`(仅控制文件
日志级别)互补;显式 `--quiet` 仍具有更高优先级。该变量已在 fresh-install 等 workflow 中启用,但
不含运行「默认静默」输出断言的 e2e 套件。
- **`update_index` 冷启动重试**:索引同步为网络 git 操作,单次瞬时故障原会直接导致冷启动失败。本版
改为有界退避重试(至多 3 次,退避 2 s / 4 s);成功路径于首次尝试即返回,稳态无额外延迟,仅失败
时方触发退避。

## [0.0.69] — 2026-06-29

### 新增
Expand Down
2 changes: 1 addition & 1 deletion mcpp.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mcpp"
version = "0.0.69"
version = "0.0.70"
description = "Modern C++ build & package management tool"
license = "Apache-2.0"
authors = ["mcpp-community"]
Expand Down
8 changes: 8 additions & 0 deletions src/cli.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,14 @@ int run(int argc, char** argv) {
else if (a == "--no-color") mcpp::ui::disable_color();
else if (a == "--verbose" || a == "-v") mcpp::log::set_verbose(true);
}
// Env override (observability, esp. CI): MCPP_VERBOSE=<non-empty, not "0">
// turns on verbose logging for EVERY mcpp invocation — including the ones
// nested inside e2e test scripts that call $MCPP without flags. Lets a
// workflow flip on diagnostics globally with one env var. An explicit
// --quiet still wins (it is processed above and gates the verbose sinks).
if (const char* v = std::getenv("MCPP_VERBOSE");
v && *v && std::string_view(v) != "0")
mcpp::log::set_verbose(true);

// ─── top-level --help / -h / --version intercept ────────────────────
// cmdline auto-handles these but its formatter doesn't match the
Expand Down
7 changes: 6 additions & 1 deletion src/config.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,13 @@ bool write_default_xlings_json(const std::filesystem::path& path,
// construct a temporary Env with home = path.parent_path().
mcpp::xlings::Env env;
env.home = path.parent_path();
// No explicit --mirror: seed "auto" so xlings' own adaptive mirror module
// (latency-probed, with per-download failover) picks the best reachable
// host. The historic hardcoded "CN" FORCED the CN mirror and disabled that
// mechanism, stranding overseas users and GitHub-hosted CI on a
// slow/unreachable gitcode. An explicit --mirror always wins (else branch).
if (mirror_override.empty())
mcpp::xlings::seed_xlings_json(env, pairs);
mcpp::xlings::seed_xlings_json(env, pairs); // default = "auto"
else
mcpp::xlings::seed_xlings_json(env, pairs, mirror_override);
return std::filesystem::exists(path);
Expand Down
2 changes: 1 addition & 1 deletion src/toolchain/fingerprint.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import mcpp.toolchain.detect;

export namespace mcpp::toolchain {

inline constexpr std::string_view MCPP_VERSION = "0.0.69";
inline constexpr std::string_view MCPP_VERSION = "0.0.70";

struct FingerprintInputs {
Toolchain toolchain;
Expand Down
51 changes: 32 additions & 19 deletions src/xlings.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -225,22 +225,17 @@ int install_direct(const Env& env, std::string_view target, bool quiet = false);

// Write .xlings.json seed file.
//
// TODO(mirror-default): the default `"CN"` is the historical setting for
// the project's initial Chinese-mainland user base, but it bites overseas
// users (and CI on GitHub-hosted runners) — the first network roundtrip
// goes through a CN mirror that is slow/unreachable for them. The
// `mcpp self config --mirror X` flow now passes the user's choice as an
// override through to here, so they can pick the right mirror BEFORE the
// first download. Longer term, consider:
// (a) flip the default to "GLOBAL" and have CN users opt in via
// `mcpp self config --mirror CN` (smaller blast radius once docs
// cover the switch); or
// (b) auto-detect on first init (env hint like LANG, a quick HEAD probe
// to github.com vs. ghproxy with a tight timeout, and pin the
// winning value into .xlings.json).
// The `mirror` default is "auto": xlings' own adaptive mirror module
// (xlings.core.mirror.adaptive — latency-probed with per-download failover and
// failure penalisation) then picks the best reachable host per download. This
// replaces the historic hardcoded "CN", which FORCED the CN mirror and disabled
// that mechanism — stranding overseas users and GitHub-hosted CI on a
// slow/unreachable gitcode. An explicit `mcpp self config --mirror CN|GLOBAL`
// still writes that fixed value (config priority). Mirror selection is xlings'
// responsibility; mcpp just declines to override it by default.
void seed_xlings_json(const Env& env,
std::span<const std::pair<std::string,std::string>> repos,
std::string_view mirror = "CN");
std::string_view mirror = "auto");

// Persist the xlings mirror selection in .xlings.json via xlings itself.
int config_show(const Env& env);
Expand Down Expand Up @@ -1232,11 +1227,29 @@ bool is_official_package_index_fresh(const Env& env,

int update_index(const Env& env, bool quiet) {
std::string cmd = build_command_prefix(env) + " update 2>&1";
int rc = mcpp::platform::process::run_streaming(cmd,
[quiet](std::string_view line) {
if (!quiet) std::println("{}", line);
});
if (rc == 0) mark_known_indexes_refreshed(env);
// The index sync is a network git operation; a single transient blip (DNS,
// TLS reset, a mirror hiccup) otherwise fails a cold `mcpp self env` /
// first-run init outright (e.g. CI's index/sandbox bootstrap). Retry with
// linear backoff. The success path returns on the FIRST attempt — zero
// added latency in steady state; only a genuine failure pays the backoff.
constexpr int kMaxAttempts = 3;
int rc = 0;
for (int attempt = 1; attempt <= kMaxAttempts; ++attempt) {
rc = mcpp::platform::process::run_streaming(cmd,
[quiet](std::string_view line) {
if (!quiet) std::println("{}", line);
});
if (rc == 0) { mark_known_indexes_refreshed(env); return 0; }
if (attempt < kMaxAttempts) {
int delay = attempt * 2; // 2s, then 4s
mcpp::log::verbose("index", std::format(
"index update attempt {}/{} failed (rc {}); retrying in {}s",
attempt, kMaxAttempts, rc, delay));
std::this_thread::sleep_for(std::chrono::seconds(delay));
}
}
mcpp::log::verbose("index", std::format(
"index update failed after {} attempts (rc {})", kMaxAttempts, rc));
return rc;
}

Expand Down
8 changes: 6 additions & 2 deletions tests/e2e/38_self_config_mirror.sh
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,13 @@ source "$(dirname "$0")/_inherit_toolchain.sh"
exit 1
}

grep -q '"mirror": "CN"' "$MCPP_HOME/registry/.xlings.json" || {
# Default (no explicit --mirror): mcpp seeds "auto" so xlings' own region
# detection (probe github vs gitcode) picks the reachable/faster mirror, instead
# of mcpp hardcoding one. An explicit `mcpp self config --mirror X` still pins a
# concrete value (asserted below).
grep -q '"mirror": "auto"' "$MCPP_HOME/registry/.xlings.json" || {
cat "$MCPP_HOME/registry/.xlings.json"
echo "FAIL: default mirror should be CN"
echo "FAIL: default mirror should be auto (defer to xlings region detection)"
exit 1
}

Expand Down
Loading