Skip to content

Commit 6cf1f71

Browse files
authored
Chore(cicd_bot): Tidy up failure output (#4964)
1 parent 3a872dc commit 6cf1f71

File tree

5 files changed

+48
-16
lines changed

5 files changed

+48
-16
lines changed

sqlmesh/core/console.py

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -289,11 +289,17 @@ def show_row_diff(
289289

290290
class BaseConsole(abc.ABC):
291291
@abc.abstractmethod
292-
def log_error(self, message: str) -> None:
292+
def log_error(self, message: str, *args: t.Any, **kwargs: t.Any) -> None:
293293
"""Display error info to the user."""
294294

295295
@abc.abstractmethod
296-
def log_warning(self, short_message: str, long_message: t.Optional[str] = None) -> None:
296+
def log_warning(
297+
self,
298+
short_message: str,
299+
long_message: t.Optional[str] = None,
300+
*args: t.Any,
301+
**kwargs: t.Any,
302+
) -> None:
297303
"""Display warning info to the user.
298304
299305
Args:
@@ -3090,15 +3096,23 @@ def consume_captured_errors(self) -> str:
30903096
finally:
30913097
self._errors = []
30923098

3093-
def log_warning(self, short_message: str, long_message: t.Optional[str] = None) -> None:
3099+
def log_warning(
3100+
self,
3101+
short_message: str,
3102+
long_message: t.Optional[str] = None,
3103+
*args: t.Any,
3104+
**kwargs: t.Any,
3105+
) -> None:
30943106
if short_message not in self._warnings:
30953107
self._warnings.append(short_message)
3096-
super().log_warning(short_message, long_message)
3108+
if kwargs.pop("print", True):
3109+
super().log_warning(short_message, long_message)
30973110

3098-
def log_error(self, message: str) -> None:
3111+
def log_error(self, message: str, *args: t.Any, **kwargs: t.Any) -> None:
30993112
if message not in self._errors:
31003113
self._errors.append(message)
3101-
super().log_error(message)
3114+
if kwargs.pop("print", True):
3115+
super().log_error(message)
31023116

31033117
def log_skipped_models(self, snapshot_names: t.Set[str]) -> None:
31043118
if snapshot_names:
@@ -3135,6 +3149,11 @@ def __init__(self, **kwargs: t.Any) -> None:
31353149
kwargs.pop("alert_block_collapsible_threshold", 200)
31363150
)
31373151

3152+
# capture_only = True: capture but dont print to console
3153+
# capture_only = False: capture and also print to console
3154+
self.warning_capture_only = kwargs.pop("warning_capture_only", False)
3155+
self.error_capture_only = kwargs.pop("error_capture_only", False)
3156+
31383157
super().__init__(
31393158
**{**kwargs, "console": RichConsole(no_color=True, width=kwargs.pop("width", None))}
31403159
)
@@ -3409,6 +3428,12 @@ def stop_promotion_progress(self, success: bool = True) -> None:
34093428
super().stop_promotion_progress(success)
34103429
self._print("\n")
34113430

3431+
def log_warning(self, short_message: str, long_message: t.Optional[str] = None) -> None:
3432+
super().log_warning(short_message, long_message, print=not self.warning_capture_only)
3433+
3434+
def log_error(self, message: str) -> None:
3435+
super().log_error(message, print=not self.error_capture_only)
3436+
34123437
def log_success(self, message: str) -> None:
34133438
self._print(message)
34143439

@@ -3435,19 +3460,24 @@ def log_test_results(self, result: ModelTextTestResult, target_dialect: str) ->
34353460

34363461
def log_skipped_models(self, snapshot_names: t.Set[str]) -> None:
34373462
if snapshot_names:
3438-
msg = " " + "\n ".join(snapshot_names)
3439-
self._print(f"**Skipped models**\n\n{msg}")
3463+
self._print(f"**Skipped models**")
3464+
for snapshot_name in snapshot_names:
3465+
self._print(f"* `{snapshot_name}`")
3466+
self._print("")
34403467

34413468
def log_failed_models(self, errors: t.List[NodeExecutionFailedError]) -> None:
34423469
if errors:
3443-
self._print("\n```\nFailed models\n")
3470+
self._print("**Failed models**")
34443471

34453472
error_messages = _format_node_errors(errors)
34463473

34473474
for node_name, msg in error_messages.items():
3448-
self._print(f" **{node_name}**\n\n{msg}")
3475+
self._print(f"* `{node_name}`\n")
3476+
self._print(" ```")
3477+
self._print(msg)
3478+
self._print(" ```")
34493479

3450-
self._print("```\n")
3480+
self._print("")
34513481

34523482
def show_linter_violations(
34533483
self, violations: t.List[RuleViolation], model: Model, is_error: bool = False

sqlmesh/integrations/github/cicd/command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def github(ctx: click.Context, token: str) -> None:
3030
"""Github Action CI/CD Bot. See https://sqlmesh.readthedocs.io/en/stable/integrations/github/ for details"""
3131
# set a larger width because if none is specified, it auto-detects 80 characters when running in GitHub Actions
3232
# which can result in surprise newlines when outputting dates to backfill
33-
set_console(MarkdownConsole(width=1000))
33+
set_console(MarkdownConsole(width=1000, warning_capture_only=True, error_capture_only=True))
3434
ctx.obj["github"] = GithubController(
3535
paths=ctx.obj["paths"],
3636
token=token,

sqlmesh/integrations/github/cicd/controller.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -603,11 +603,11 @@ def _get_pr_environment_summary_action_required(
603603

604604
def _get_pr_environment_summary_failure(self, exception: t.Optional[Exception] = None) -> str:
605605
console_output = self._console.consume_captured_output()
606+
failure_msg = ""
606607

607608
if isinstance(exception, PlanError):
608-
failure_msg = f"Plan application failed.\n"
609609
if exception.args and (msg := exception.args[0]) and isinstance(msg, str):
610-
failure_msg += f"\n{msg}\n"
610+
failure_msg += f"*{msg}*\n"
611611
if console_output:
612612
failure_msg += f"\n{console_output}"
613613
elif isinstance(exception, (SQLMeshError, SqlglotError, ValueError)):
@@ -713,6 +713,7 @@ def update_pr_environment(self) -> None:
713713
Creates a PR environment from the logic present in the PR. If the PR contains changes that are
714714
uncategorized, then an error will be raised.
715715
"""
716+
self._console.consume_captured_output() # clear output buffer
716717
self._context.apply(self.pr_plan) # will raise if PR environment creation fails
717718

718719
# update PR info comment

tests/integrations/github/cicd/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def _make_function(
117117

118118
orig_console = get_console()
119119
try:
120-
set_console(MarkdownConsole())
120+
set_console(MarkdownConsole(warning_capture_only=True, error_capture_only=True))
121121

122122
return GithubController(
123123
paths=paths,

tests/integrations/github/cicd/test_integration.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1582,7 +1582,8 @@ def test_error_msg_when_applying_plan_with_bug(
15821582
assert GithubCheckConclusion(pr_checks_runs[2]["conclusion"]).is_failure
15831583
assert pr_checks_runs[2]["output"]["title"] == "PR Virtual Data Environment: hello_world_2"
15841584
summary = pr_checks_runs[2]["output"]["summary"].replace("\n", "")
1585-
assert 'Failed models **"memory"."sushi"."waiter_revenue_by_day"**' in summary
1585+
assert '**Skipped models*** `"memory"."sushi"."top_waiters"`' in summary
1586+
assert '**Failed models*** `"memory"."sushi"."waiter_revenue_by_day"`' in summary
15861587
assert 'Binder Error: Referenced column "non_existing_col" not found in FROM clause!' in summary
15871588

15881589
assert "SQLMesh - Prod Plan Preview" in controller._check_run_mapping

0 commit comments

Comments
 (0)