Skip to content

Commit 4107d4a

Browse files
committed
feat(observability+resilience): MCPP_VERBOSE env + cold index-update retry
Two changes prompted by an opaque, repeatedly-reproducing CI failure in 75_index_status_offline.sh (a cold `mcpp self env` in a fresh MCPP_HOME whose index/sandbox bootstrap fails fast — root cause swallowed in non-verbose logs; verified NOT related to the feature/capability work, it fails identically on main): 1. MCPP_VERBOSE env override (src/cli.cppm): MCPP_VERBOSE=<non-empty,!=0> turns on verbose logging for EVERY mcpp invocation, including those nested inside e2e test scripts that call $MCPP without flags. An explicit --quiet still wins. Set MCPP_VERBOSE: "1" in all CI workflows (ci-linux, ci-linux-e2e, ci-macos, ci-windows, cross-build-test, ci-fresh-install, ci-aarch64-fresh-install) so failures carry full diagnostics. Complements the existing MCPP_LOG_LEVEL (which only sets the FILE log level, not stderr). 2. update_index retry (src/xlings.cppm): the index sync is a network git op; a single transient blip otherwise fails cold init outright. Bounded retry with linear backoff (3 attempts, 2s/4s). Success returns on the first attempt — zero added latency in steady state; only a real failure pays the backoff. Retry notices go through mcpp::log::verbose (file always, stderr under MCPP_VERBOSE). This PR's own e2e CI run carries MCPP_VERBOSE=1, so it surfaces the real cause of the 75 bootstrap failure for a targeted follow-up.
1 parent dea776e commit 4107d4a

9 files changed

Lines changed: 51 additions & 5 deletions

File tree

‎.github/workflows/ci-aarch64-fresh-install.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ jobs:
3030
name: fresh install + native build (aarch64 / glibc)
3131
runs-on: ubuntu-24.04-arm
3232
timeout-minutes: 60
33+
env:
34+
# Verbose every mcpp invocation — cold bootstrap path (src/cli.cppm).
35+
MCPP_VERBOSE: "1"
3336
steps:
3437
- name: System info
3538
run: |

‎.github/workflows/ci-fresh-install.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ jobs:
3030
name: Linux fresh install
3131
runs-on: ubuntu-24.04
3232
timeout-minutes: 60
33+
env:
34+
# Verbose every mcpp invocation — fresh-install is the cold index/sandbox
35+
# bootstrap path, exactly where extra diagnostics matter (src/cli.cppm).
36+
MCPP_VERBOSE: "1"
3337
steps:
3438
- uses: actions/checkout@v4
3539

‎.github/workflows/ci-linux-e2e.yml‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ jobs:
2828
timeout-minutes: 45
2929
env:
3030
MCPP_HOME: /home/runner/.mcpp
31+
# Verbose every mcpp invocation (incl. those nested in e2e scripts) so CI
32+
# logs carry full diagnostics for failures like a cold index/sandbox
33+
# bootstrap. Honoured via the MCPP_VERBOSE override in src/cli.cppm.
34+
MCPP_VERBOSE: "1"
3135
steps:
3236
- uses: actions/checkout@v4
3337

‎.github/workflows/ci-linux.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ jobs:
3232
# MCPP_HOME pinned so the cache key below restores into the
3333
# same path mcpp resolves at runtime.
3434
MCPP_HOME: /home/runner/.mcpp
35+
# Verbose every mcpp invocation for richer CI diagnostics (src/cli.cppm).
36+
MCPP_VERBOSE: "1"
3537
steps:
3638
- uses: actions/checkout@v4
3739

‎.github/workflows/ci-macos.yml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ jobs:
1919
name: macOS ARM64 — xlings LLVM end-to-end
2020
runs-on: macos-15
2121
timeout-minutes: 30
22+
env:
23+
# Verbose every mcpp invocation for richer CI diagnostics (src/cli.cppm).
24+
MCPP_VERBOSE: "1"
2225
steps:
2326
- uses: actions/checkout@v4
2427

‎.github/workflows/ci-windows.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ jobs:
2121
timeout-minutes: 45
2222
env:
2323
MCPP_HOME: C:\Users\runneradmin\.mcpp
24+
# Verbose every mcpp invocation for richer CI diagnostics (src/cli.cppm).
25+
MCPP_VERBOSE: "1"
2426
steps:
2527
- uses: actions/checkout@v4
2628

‎.github/workflows/cross-build-test.yml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ jobs:
5757
qemu_bin: qemu-aarch64-static
5858
env:
5959
MCPP_HOME: /home/runner/.mcpp
60+
# Verbose every mcpp invocation for richer CI diagnostics (src/cli.cppm).
61+
MCPP_VERBOSE: "1"
6062
steps:
6163
- uses: actions/checkout@v4
6264

‎src/cli.cppm‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,14 @@ int run(int argc, char** argv) {
101101
else if (a == "--no-color") mcpp::ui::disable_color();
102102
else if (a == "--verbose" || a == "-v") mcpp::log::set_verbose(true);
103103
}
104+
// Env override (observability, esp. CI): MCPP_VERBOSE=<non-empty, not "0">
105+
// turns on verbose logging for EVERY mcpp invocation — including the ones
106+
// nested inside e2e test scripts that call $MCPP without flags. Lets a
107+
// workflow flip on diagnostics globally with one env var. An explicit
108+
// --quiet still wins (it is processed above and gates the verbose sinks).
109+
if (const char* v = std::getenv("MCPP_VERBOSE");
110+
v && *v && std::string_view(v) != "0")
111+
mcpp::log::set_verbose(true);
104112

105113
// ─── top-level --help / -h / --version intercept ────────────────────
106114
// cmdline auto-handles these but its formatter doesn't match the

‎src/xlings.cppm‎

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1232,11 +1232,29 @@ bool is_official_package_index_fresh(const Env& env,
12321232

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

0 commit comments

Comments
 (0)