Skip to content

Commit db67c7a

Browse files
committed
fix: hermetic test suite (121s→1s) + promote progress/failure UX
- test_cmd_run_env_vars: mock the web-mode readiness probe (real socket.create_connection to a never-listening port made the test spin the full 120s health-check loop; suite 121s → ~1s) - lpb-config release promote: 300s commit timeout (pre-commit hook runs the suite), progress lines for fetch/commit/push, and a per-repo result table + explicit recovery steps on failure instead of a bare 'timed out' error
1 parent 57450f9 commit db67c7a

2 files changed

Lines changed: 55 additions & 10 deletions

File tree

scripts/test_lpb.py

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -835,8 +835,23 @@ def spy_containers_run(*a, **kw):
835835
return ("cid123", "cid123", "", 0)
836836

837837
mod.ContainerClient.containers_run = spy_containers_run
838-
with _OutputCapture():
839-
mod.cmd_run()
838+
839+
# Health-check loop: make the (real) TCP probe succeed and pre-count the
840+
# mocked curl attempts so the readiness wait exits in ~1s instead of
841+
# spinning the full 120s budget (this test only asserts env/volume args).
842+
class _ReadySock:
843+
def close(self):
844+
pass
845+
846+
global _curl_attempts
847+
_curl_attempts = 2 # mocked curl succeeds from attempt 3 onward
848+
_orig_cc = mod.socket.create_connection
849+
mod.socket.create_connection = lambda *a, **k: _ReadySock()
850+
try:
851+
with _OutputCapture():
852+
mod.cmd_run()
853+
finally:
854+
mod.socket.create_connection = _orig_cc
840855
assert mod.cfg.project_name == "tmp"
841856
env_vars = captured.get("env", [])
842857
env_str = "\n".join(env_vars)

support/lpb-config.py

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,10 +1251,13 @@ def _release_repos() -> list[tuple[str, Path, str, str, str]]:
12511251
return repos
12521252

12531253

1254-
def _repo_release_state(path: Path, dev_branch: str, main_branch: str) -> dict:
1254+
def _repo_release_state(path: Path, dev_branch: str, main_branch: str,
1255+
cons: Console | None = None) -> dict:
12551256
"""Fetch and gather per-repo promotion state (non-destructive)."""
12561257
# Explicit refspecs: some clones (e.g. config) have restricted fetch
12571258
# configs that would not create refs/remotes/origin/<dev>.
1259+
if cons is not None:
1260+
cons.info(f" fetching {path.name} …")
12581261
git_auth(path, "fetch", "origin", "--quiet",
12591262
f"+refs/heads/{dev_branch}:refs/remotes/origin/{dev_branch}",
12601263
f"+refs/heads/{main_branch}:refs/remotes/origin/{main_branch}",
@@ -1348,7 +1351,7 @@ def cmd_release_status(cons: Console) -> int:
13481351
cons.error(f"{label:18s} repo missing at {path}")
13491352
problems += 1
13501353
continue
1351-
st = _repo_release_state(path, dev_b, main_b)
1354+
st = _repo_release_state(path, dev_b, main_b, cons)
13521355
feas = st["feasibility"]
13531356
if feas == "unknown":
13541357
mark, note = "❌", "origin refs not found (fetch failed?)"
@@ -1412,7 +1415,7 @@ def cmd_release_promote(*, assume_yes: bool, dry_run: bool, rebase: bool,
14121415
cons.error(f"{label}: repo missing at {path}")
14131416
ok = False
14141417
continue
1415-
st = _repo_release_state(path, dev_b, main_b)
1418+
st = _repo_release_state(path, dev_b, main_b, cons)
14161419
entries.append((label, path, dev_b, main_b, gh, st))
14171420
if st["origin_main"] == "?":
14181421
cons.error(f"{label}: origin/{main_b} does not exist")
@@ -1501,10 +1504,24 @@ def cmd_release_promote(*, assume_yes: bool, dry_run: bool, rebase: bool,
15011504
stable = current[: -len("-dev")]
15021505
vf.write_text(stable + "\n")
15031506
git(path, "add", "VERSION")
1507+
cons.info(f" devstack: committing VERSION {current}{stable} "
1508+
f"on {main_b} …")
1509+
cons.info(" (pre-commit hook runs the test suite — may take a "
1510+
"while)")
15041511
out, err, code = git(path, "commit", "-m",
1505-
f"release: {stable} — stable branch promoted from dev")
1512+
f"release: {stable} — stable branch promoted "
1513+
f"from dev",
1514+
timeout=300)
15061515
if code != 0:
1507-
cons.error(f" devstack: VERSION commit failed: {err.strip()}")
1516+
detail = err.strip() or out.strip() or "unknown error"
1517+
cons.error(f" devstack: VERSION commit failed: {detail}")
1518+
cons.error(" State: main has the merged dev content; the "
1519+
"VERSION change is STAGED (not committed).")
1520+
cons.error(
1521+
f" Recover: cd {path} && "
1522+
f"git commit -m 'release: {stable} — stable branch promoted "
1523+
f"from dev' && git push origin {main_b}"
1524+
)
15081525
failures.append("devstack")
15091526
else:
15101527
cons.info(f" devstack: VERSION {current}{stable} (on {main_b})")
@@ -1521,6 +1538,7 @@ def cmd_release_promote(*, assume_yes: bool, dry_run: bool, rebase: bool,
15211538
push_args = ["push", "origin", main_b]
15221539
if label in rebased:
15231540
push_args = ["push", "--force-with-lease", "origin", main_b]
1541+
cons.info(f" pushing {gh}:{main_b} …")
15241542
out, err, code = git_auth(path, *push_args, timeout=180)
15251543
if code != 0:
15261544
cons.error(f" {label}: push failed: {err.strip() or out.strip()}")
@@ -1531,12 +1549,24 @@ def cmd_release_promote(*, assume_yes: bool, dry_run: bool, rebase: bool,
15311549

15321550
# ── Summary ──
15331551
cons.info("")
1552+
cons.info("Result:")
1553+
for label, path, dev_b, main_b, gh, st in entries:
1554+
if label in failures:
1555+
cons.error(f" ❌ {gh:35s} failed")
1556+
elif label in skipped:
1557+
cons.warn(f" ⏭ {gh:35s} skipped")
1558+
elif _repo_action(st, rebase)[0] == "no-op":
1559+
cons.info(f" ✅ {gh:35s} aligned (no change)")
1560+
else:
1561+
force = " (force)" if label in rebased else ""
1562+
cons.info(f" ✅ {gh:35s} promoted{force}")
15341563
if skipped:
1535-
cons.warn(f"Skipped (local dirty): {', '.join(skipped)}")
1564+
cons.warn(f"Skipped: {', '.join(skipped)} — see notes above")
15361565
if failures:
15371566
cons.error(f"Failed: {', '.join(failures)}")
1538-
cons.error("Stable release INCOMPLETE — fix the repos above and re-run "
1539-
"'lpb-config release promote' (already-promoted repos will "
1567+
cons.error("Stable release INCOMPLETE — complete the failing repo "
1568+
"(recovery steps above), then re-run "
1569+
"'lpb-config release promote' (already-promoted repos "
15401570
"fast-forward or no-op).")
15411571
return 1
15421572
stable_version = (version[:-len("-dev")] if version.endswith("-dev") else version)

0 commit comments

Comments
 (0)