Skip to content

Commit e51cd57

Browse files
authored
fix: include stack trace bot output (#1592)
1 parent b62dfab commit e51cd57

File tree

2 files changed

+150
-1
lines changed

2 files changed

+150
-1
lines changed

sqlmesh/integrations/github/cicd/controller.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import os
77
import pathlib
88
import re
9+
import traceback
910
import typing as t
1011
import unittest
1112
from enum import Enum
@@ -23,6 +24,7 @@
2324
from sqlmesh.core.plan import LoadedSnapshotIntervals, Plan
2425
from sqlmesh.core.user import User
2526
from sqlmesh.integrations.github.cicd.config import GithubCICDBotConfig
27+
from sqlmesh.utils.concurrency import NodeExecutionFailedError
2628
from sqlmesh.utils.date import now
2729
from sqlmesh.utils.errors import (
2830
CICDBotError,
@@ -727,9 +729,14 @@ def conclusion_handler(
727729
skip_reason = "Unit Test(s) Failed so skipping PR creation"
728730
else:
729731
skip_reason = "A prior stage failed resulting in skipping PR creation."
732+
733+
if isinstance(exception, NodeExecutionFailedError):
734+
failure_msg = f"Node `{exception.node.name}` failed to apply.\n\n**Stack Trace:**\n```\n{traceback.format_exc()}\n```"
735+
else:
736+
failure_msg = f"This is an unexpected error.\n\n**Exception:**\n{exception}"
730737
conclusion_to_summary = {
731738
GithubCheckConclusion.SKIPPED: f":next_track_button: Skipped creating or updating PR Environment `{self.pr_environment_name}`. {skip_reason}",
732-
GithubCheckConclusion.FAILURE: f":x: Failed to create or update PR Environment `{self.pr_environment_name}`. This is an unexpected error.\n**Exception:**\n{exception}",
739+
GithubCheckConclusion.FAILURE: f":x: Failed to create or update PR Environment `{self.pr_environment_name}`.\n{failure_msg}",
733740
GithubCheckConclusion.CANCELLED: f":stop_sign: Cancelled creating or updating PR Environment `{self.pr_environment_name}`",
734741
GithubCheckConclusion.ACTION_REQUIRED: f":warning: Action Required to create or update PR Environment `{self.pr_environment_name}`. There are likely uncateogrized changes. Run `plan` locally to apply these changes. If you want the bot to automatically categorize changes, then check documentation (https://sqlmesh.readthedocs.io/en/stable/integrations/github/) for more information.",
735742
}

tests/integrations/github/cicd/test_integration.py

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1225,3 +1225,145 @@ def test_deploy_comment_pre_categorized(
12251225
12261226
"""
12271227
)
1228+
1229+
1230+
@freeze_time("2023-01-01 15:00:00")
1231+
def test_error_msg_when_applying_plan_with_bug(
1232+
github_client,
1233+
make_controller,
1234+
make_mock_check_run,
1235+
make_mock_issue_comment,
1236+
make_pull_request_review,
1237+
mocker: MockerFixture,
1238+
monkeypatch: pytest.MonkeyPatch,
1239+
):
1240+
"""
1241+
PR with auto-categorization but has a mistake in the model so apply fails
1242+
1243+
Scenario:
1244+
- PR is not merged
1245+
- PR has been approved by a required reviewer
1246+
- Tests passed
1247+
- PR Merge Method defined
1248+
- Delete environment is disabled
1249+
- Bugged change made in PR with auto-categorization
1250+
"""
1251+
mock_repo = github_client.get_repo()
1252+
mock_repo.create_check_run = mocker.MagicMock(
1253+
side_effect=lambda **kwargs: make_mock_check_run(**kwargs)
1254+
)
1255+
1256+
created_comments: t.List[MockIssueComment] = []
1257+
mock_issue = mock_repo.get_issue()
1258+
mock_issue.create_comment = mocker.MagicMock(
1259+
side_effect=lambda comment: make_mock_issue_comment(
1260+
comment=comment, created_comments=created_comments
1261+
)
1262+
)
1263+
mock_issue.get_comments = mocker.MagicMock(side_effect=lambda: created_comments)
1264+
1265+
mock_pull_request = mock_repo.get_pull()
1266+
mock_pull_request.get_reviews = mocker.MagicMock(
1267+
side_effect=lambda: [make_pull_request_review(username="test_github", state="APPROVED")]
1268+
)
1269+
mock_pull_request.merged = False
1270+
mock_pull_request.merge = mocker.MagicMock()
1271+
1272+
controller = make_controller(
1273+
"tests/fixtures/github/pull_request_synchronized.json",
1274+
github_client,
1275+
bot_config=GithubCICDBotConfig(
1276+
merge_method=MergeMethod.MERGE,
1277+
auto_categorize_changes=CategorizerConfig.all_full(),
1278+
invalidate_environment_after_deploy=False,
1279+
),
1280+
mock_out_context=False,
1281+
)
1282+
controller._context.plan("prod", no_prompts=True, auto_apply=True)
1283+
controller._context.users = [
1284+
User(username="test", github_username="test_github", roles=[UserRole.REQUIRED_APPROVER])
1285+
]
1286+
# Make an error by adding a column that doesn't exist
1287+
model = controller._context.get_model("sushi.waiter_revenue_by_day").copy()
1288+
model.query.expressions.append(exp.alias_("non_existing_col", "new_col"))
1289+
controller._context.upsert_model(model)
1290+
1291+
command._run_all(controller)
1292+
1293+
assert "SQLMesh - Run Unit Tests" in controller._check_run_mapping
1294+
test_checks_runs = controller._check_run_mapping["SQLMesh - Run Unit Tests"].all_kwargs
1295+
assert len(test_checks_runs) == 3
1296+
assert GithubCheckStatus(test_checks_runs[0]["status"]).is_queued
1297+
assert GithubCheckStatus(test_checks_runs[1]["status"]).is_in_progress
1298+
assert GithubCheckStatus(test_checks_runs[2]["status"]).is_completed
1299+
assert GithubCheckConclusion(test_checks_runs[2]["conclusion"]).is_success
1300+
assert test_checks_runs[2]["output"]["title"] == "Tests Passed"
1301+
assert (
1302+
test_checks_runs[2]["output"]["summary"].strip()
1303+
== "**Successfully Ran `2` Tests Against `duckdb`**"
1304+
)
1305+
1306+
assert "SQLMesh - PR Environment Synced" in controller._check_run_mapping
1307+
pr_checks_runs = controller._check_run_mapping["SQLMesh - PR Environment Synced"].all_kwargs
1308+
assert len(pr_checks_runs) == 3
1309+
assert GithubCheckStatus(pr_checks_runs[0]["status"]).is_queued
1310+
assert GithubCheckStatus(pr_checks_runs[1]["status"]).is_in_progress
1311+
assert GithubCheckStatus(pr_checks_runs[2]["status"]).is_completed
1312+
assert GithubCheckConclusion(pr_checks_runs[2]["conclusion"]).is_failure
1313+
assert pr_checks_runs[2]["output"]["title"] == "PR Virtual Data Environment: hello_world_2"
1314+
assert (
1315+
'Binder Error: Referenced column "non_existing_col" not found in FROM clause!'
1316+
in pr_checks_runs[2]["output"]["summary"]
1317+
)
1318+
1319+
assert "SQLMesh - Prod Plan Preview" in controller._check_run_mapping
1320+
prod_plan_preview_checks_runs = controller._check_run_mapping[
1321+
"SQLMesh - Prod Plan Preview"
1322+
].all_kwargs
1323+
assert len(prod_plan_preview_checks_runs) == 2
1324+
assert GithubCheckStatus(prod_plan_preview_checks_runs[0]["status"]).is_queued
1325+
assert GithubCheckStatus(prod_plan_preview_checks_runs[1]["status"]).is_completed
1326+
assert GithubCheckConclusion(prod_plan_preview_checks_runs[1]["conclusion"]).is_skipped
1327+
assert (
1328+
prod_plan_preview_checks_runs[1]["output"]["title"]
1329+
== "Skipped generating prod plan preview since PR was not synchronized"
1330+
)
1331+
assert (
1332+
prod_plan_preview_checks_runs[1]["output"]["summary"]
1333+
== "Skipped generating prod plan preview since PR was not synchronized"
1334+
)
1335+
1336+
assert "SQLMesh - Prod Environment Synced" in controller._check_run_mapping
1337+
prod_checks_runs = controller._check_run_mapping["SQLMesh - Prod Environment Synced"].all_kwargs
1338+
assert len(prod_checks_runs) == 2
1339+
assert GithubCheckStatus(prod_checks_runs[0]["status"]).is_queued
1340+
assert GithubCheckStatus(prod_checks_runs[1]["status"]).is_completed
1341+
assert GithubCheckConclusion(prod_checks_runs[1]["conclusion"]).is_skipped
1342+
skip_reason = "Skipped Deploying to Production because the PR environment was not updated"
1343+
assert prod_checks_runs[1]["output"]["title"] == skip_reason
1344+
assert prod_checks_runs[1]["output"]["summary"] == skip_reason
1345+
1346+
assert "SQLMesh - Has Required Approval" in controller._check_run_mapping
1347+
approval_checks_runs = controller._check_run_mapping[
1348+
"SQLMesh - Has Required Approval"
1349+
].all_kwargs
1350+
assert len(approval_checks_runs) == 3
1351+
assert GithubCheckStatus(approval_checks_runs[0]["status"]).is_queued
1352+
assert GithubCheckStatus(approval_checks_runs[1]["status"]).is_in_progress
1353+
assert GithubCheckStatus(approval_checks_runs[2]["status"]).is_completed
1354+
assert GithubCheckConclusion(approval_checks_runs[2]["conclusion"]).is_success
1355+
assert (
1356+
approval_checks_runs[2]["output"]["title"]
1357+
== "Obtained approval from required approvers: test_github"
1358+
)
1359+
assert (
1360+
approval_checks_runs[2]["output"]["summary"]
1361+
== """**List of possible required approvers:**
1362+
- `test_github`
1363+
"""
1364+
)
1365+
1366+
assert len(get_environment_objects(controller, "hello_world_2")) == 0
1367+
assert not mock_pull_request.merge.called
1368+
1369+
assert len(created_comments) == 0

0 commit comments

Comments
 (0)