Files
hermes-agent/tests/scripts/test_release_progress.py
ethernet bfa4f5098c feat(release): the stable sequencer narrates what it is doing
A publication run sat silent for 8+ minutes while it downloaded ~20 GB,
with no way to tell which phase it was in or why a claim was held.

scripts/releases/progress.py logs to stderr (stdout stays the JSON steps)
with GitHub ::group::/::notice::/::error:: markers:

- every git/gh/docker command the sequencer runs, with its time and result
- discovery counts, and each claim's state with the reason (run attempt
  and conclusion, draft location, abandon marker, receipt/release match)
- the plan: why each version advances, is skipped, or is held
- each step as a timed group: publish (receipt digests) and advance
- the channel advance's phases, plus per-file progress for the handoff
  fetch and candidate materialize downloads (the slow part)
- the head before and after, and a top-level ::error:: on failure
2026-10-12 02:13:17 -04:00

42 lines
1.5 KiB
Python

"""Release progress logging: stderr only, grouped, and commands stay readable."""
import subprocess
import pytest
from scripts.releases import progress
def test_logged_run_logs_each_command_and_its_outcome(capsys):
run = progress.logged_run(lambda argv: "a\nb")
assert run(["git", "ls-remote", "origin"]) == "a\nb"
err = capsys.readouterr().err
assert " $ git ls-remote origin" in err
assert "ok in" in err and "(2 lines)" in err
# Wrapping twice does not double the logs.
assert progress.logged_run(run) is run
def test_logged_run_logs_a_failure_and_reraises(capsys):
def fail(argv):
raise subprocess.CalledProcessError(128, argv)
with pytest.raises(subprocess.CalledProcessError):
progress.logged_run(fail)(["git", "push", "origin", "refs/tags/v1.2.3"])
assert "failed after" in capsys.readouterr().err
def test_long_arguments_are_cut_and_newlines_escaped():
shown = progress.describe_command(["gh", "api", "--raw-field", "body=" + "x" * 500 + "\nmore"])
assert "…(+" in shown and "\n" not in shown
assert len(shown) < 260
def test_group_balances_and_reports_failure(capsys):
with pytest.raises(RuntimeError):
with progress.group("Advance"):
raise RuntimeError("nope")
err = capsys.readouterr().err
assert err.startswith("::group::Advance\n")
assert "✗ Advance failed after" in err and "RuntimeError: nope" in err
assert err.rstrip().endswith("::endgroup::")