fix: log progress tracker refresh errors instead of silently swallowing (#3975)

* fix: log progress tracker refresh errors instead of silently swallowing

The bare 'except Exception: pass' in StepTracker._maybe_refresh()
completely hid rendering bugs in the Rich progress display. Now logs
at DEBUG level with full traceback for diagnostics.

* test: add regression test for StepTracker refresh error logging

- Test that _maybe_refresh logs exceptions instead of silently swallowing
- Verify diagnostic message and traceback are recorded in DEBUG logs
- Confirm tracker update completes normally despite refresh callback failure

Requested by Copilot in PR #3975
This commit is contained in:
Quratulain-bilal
2026-08-13 13:25:28 -05:00
committed by GitHub
parent 5a052d36d1
commit 618d16e94b
2 changed files with 25 additions and 1 deletions
+4 -1
View File
@@ -7,6 +7,7 @@ layer, not out of it, to avoid circular imports.
"""
from __future__ import annotations
import logging
import sys
from collections.abc import Callable
@@ -21,6 +22,8 @@ from rich.text import Text
from rich.tree import Tree
from typer.core import TyperGroup
logger = logging.getLogger(__name__)
BANNER = """
███████╗██████╗ ███████╗ ██████╗██╗███████╗██╗ ██╗
██╔════╝██╔══██╗██╔════╝██╔════╝██║██╔════╝╚██╗ ██╔╝
@@ -85,7 +88,7 @@ class StepTracker:
try:
self._refresh_cb()
except Exception:
pass
logger.debug("Progress tracker refresh failed", exc_info=True)
def render(self):
tree = Tree(f"[cyan]{self.title}[/cyan]", guide_style="grey50")
+21
View File
@@ -1,9 +1,12 @@
"""Regression guard: console symbols must remain importable from specify_cli."""
import logging
from specify_cli import (
console,
StepTracker,
select_with_arrows,
)
from specify_cli._console import logger as console_logger
def test_console_symbols_importable():
@@ -39,3 +42,21 @@ def test_select_with_arrows_raises_on_empty_options():
import pytest
with pytest.raises(ValueError, match="at least one option"):
select_with_arrows({})
def test_step_tracker_refresh_error_is_logged(caplog):
"""Regression: _maybe_refresh must log exceptions instead of silently swallowing."""
tracker = StepTracker("test")
def failing_refresh():
raise RuntimeError("simulated refresh failure")
tracker.attach_refresh(failing_refresh)
tracker.add("step1", "Step One")
with caplog.at_level(logging.DEBUG, logger=console_logger.name):
tracker.complete("step1", "done")
assert "Progress tracker refresh failed" in caplog.text
assert "RuntimeError: simulated refresh failure" in caplog.text
assert tracker.steps[0]["status"] == "done"