From ce26a8e4d88a5de5c734648882e49b5e41af5800 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Sun, 20 Sep 2026 01:39:39 -0700 Subject: [PATCH 1/3] test: require early CLI smoke gate to propagate probe failures --- tests/test_ci_change_areas.py | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/test_ci_change_areas.py b/tests/test_ci_change_areas.py index 4fccc3115621..4b590bcb513a 100644 --- a/tests/test_ci_change_areas.py +++ b/tests/test_ci_change_areas.py @@ -951,6 +951,41 @@ def test_web_instant_navigation_retries_native_tsgo_abort() -> None: assert "retrying once" in block +def test_early_cli_smoke_checks_propagate_failure_and_require_this_build() -> None: + script = workflow_job_step_script("macos-compile-admission", "Run early CLI binary smoke checks") + for failed_probe in ("version", "help", None, "missing-binary"): + with tempfile.TemporaryDirectory() as directory: + root = Path(directory) + derived = root / "derived with spaces" + cli = derived / "Build/Products/Debug/cmux" + cli.parent.mkdir(parents=True) + if failed_probe != "missing-binary": + cli.write_text("#!/bin/sh\nexit 0\n") + cli.chmod(0o755) + (root / "tests").mkdir() + trace = root / "probes.txt" + for probe, filename in (("version", "test_cli_version_memory_guard.py"), + ("help", "test_cli_contract_help.py")): + (root / "tests" / filename).write_text( + "import os,pathlib\n" + + "assert os.environ['CMUX_CLI_BIN'] == " + repr(str(cli)) + "\n" + + "with open(" + repr(str(trace)) + ", 'a') as out: out.write(" + repr(probe + "\n") + ")\n" + + "raise SystemExit(" + ("23" if probe == failed_probe else "0") + ")\n" + ) + result = subprocess.run(["bash", "-e", "-o", "pipefail", "-c", script], cwd=root, + env={**os.environ, "CMUX_COMPILE_ADMISSION_DERIVED_DATA": str(derived)}, + capture_output=True, text=True) + invoked = trace.read_text().splitlines() if trace.exists() else [] + if failed_probe == "missing-binary": + assert result.returncode != 0 and not invoked + elif failed_probe == "version": + assert result.returncode == 23 and invoked == ["version"] + elif failed_probe == "help": + assert result.returncode == 23 and invoked == ["version", "help"] + else: + assert result.returncode == 0 and invoked == ["version", "help"] + + def test_macos_jobs_wait_for_linux_preflight() -> None: # The staged macOS jobs must gate on their direct needs explicitly. # A bare `if: needs.changes.outputs.macos == 'true'` keeps the implicit From bfb43f5a12c562e1b55ab223fb35837c7a3614e9 Mon Sep 17 00:00:00 2001 From: Leo Li Date: Sun, 20 Sep 2026 01:43:50 -0700 Subject: [PATCH 2/3] ci: check CLI version and help before app-host fan-out --- .github/workflows/ci.yml | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2da6cba62abd..c11b3b6daedb 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1726,8 +1726,6 @@ jobs: exit 1 fi - CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_version_memory_guard.py - CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_contract_help.py CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_vm_transfer_progress.py CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_vm_resize.py CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_cloud_hostname.py @@ -2353,8 +2351,7 @@ jobs: "$CMUX_COMPILE_ADMISSION_CAS" \ "$RUNNER_TEMP/cmux-compile-admission.txt" - - name: Package compiled app-host test product - id: package-products + - name: Stage compiled package frameworks run: | set -euo pipefail products="$CMUX_COMPILE_ADMISSION_DERIVED_DATA/Build/Products/Debug" @@ -2370,6 +2367,24 @@ jobs: mkdir -p "$products/PackageFrameworks" rsync -aL "$framework_root/" "$products/PackageFrameworks/" test -f "$products/PackageFrameworks/CmuxAgentJournal_27B6EF8727F6C277_PackageProduct.framework/Versions/A/CmuxAgentJournal_27B6EF8727F6C277_PackageProduct" + + # These no-socket probes take seconds and need only the compiled CLI. + # Fail admission before allocating app-host shards or the runtime job. + - name: Run early CLI binary smoke checks + run: | + set -euo pipefail + CLI_BIN="$CMUX_COMPILE_ADMISSION_DERIVED_DATA/Build/Products/Debug/cmux" + if [ ! -x "$CLI_BIN" ]; then + echo "cmux CLI binary missing from this admission build" >&2 + exit 1 + fi + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_version_memory_guard.py + CMUX_CLI_BIN="$CLI_BIN" python3 tests/test_cli_contract_help.py + + - name: Package compiled app-host test product + id: package-products + run: | + set -euo pipefail python3 scripts/ci/app_host_test_products.py stamp "$CMUX_COMPILE_ADMISSION_DERIVED_DATA" archive="$RUNNER_TEMP/app-host-products.tar.gz" tar -chzf "$archive" -C "$CMUX_COMPILE_ADMISSION_DERIVED_DATA" Build/Products From 5a6322e7ce12dc5ec0fe654b95da169149fc0189 Mon Sep 17 00:00:00 2001 From: Austin Wang Date: Sun, 20 Sep 2026 02:58:24 -0700 Subject: [PATCH 3/3] test: guard early CLI smoke ordering --- tests/test_ci_change_areas.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/test_ci_change_areas.py b/tests/test_ci_change_areas.py index 4b590bcb513a..c6a6dc3aeb90 100644 --- a/tests/test_ci_change_areas.py +++ b/tests/test_ci_change_areas.py @@ -952,6 +952,12 @@ def test_web_instant_navigation_retries_native_tsgo_abort() -> None: def test_early_cli_smoke_checks_propagate_failure_and_require_this_build() -> None: + block = workflow_job_block("macos-compile-admission") + early = block.index(" - name: Run early CLI binary smoke checks") + package = block.index(" - name: Package compiled app-host test product") + upload = block.index(" - name: Upload compiled app-host test product") + assert early < package < upload + script = workflow_job_step_script("macos-compile-admission", "Run early CLI binary smoke checks") for failed_probe in ("version", "help", None, "missing-binary"): with tempfile.TemporaryDirectory() as directory: