|
1 | 1 | # type: ignore |
| 2 | +import typing as t |
2 | 3 | import os |
3 | 4 | import pathlib |
4 | 5 | from unittest import TestCase, mock |
|
14 | 15 | from sqlmesh.integrations.github.cicd import command |
15 | 16 | from sqlmesh.integrations.github.cicd.config import GithubCICDBotConfig, MergeMethod |
16 | 17 | from sqlmesh.integrations.github.cicd.controller import ( |
| 18 | + GithubController, |
17 | 19 | GithubCheckConclusion, |
18 | 20 | GithubCheckStatus, |
19 | 21 | ) |
@@ -1152,6 +1154,7 @@ def test_comment_command_deploy_prod( |
1152 | 1154 | User(username="test", github_username="test_github", roles=[UserRole.REQUIRED_APPROVER]) |
1153 | 1155 | ] |
1154 | 1156 | controller._context.invalidate_environment = mocker.MagicMock() |
| 1157 | + assert not controller.forward_only_plan |
1155 | 1158 |
|
1156 | 1159 | github_output_file = tmp_path / "github_output.txt" |
1157 | 1160 |
|
@@ -1366,3 +1369,84 @@ def test_comment_command_deploy_prod_no_deploy_detected_yet( |
1366 | 1369 |
|
1367 | 1370 | # required approvers are irrelevant because /deploy command is enabled |
1368 | 1371 | assert "SQLMesh - Has Required Approval" not in controller._check_run_mapping |
| 1372 | + |
| 1373 | + |
| 1374 | +def test_deploy_prod_forward_only( |
| 1375 | + github_client, |
| 1376 | + make_controller: t.Callable[..., GithubController], |
| 1377 | + make_mock_check_run, |
| 1378 | + make_mock_issue_comment, |
| 1379 | + tmp_path: pathlib.Path, |
| 1380 | + mocker: MockerFixture, |
| 1381 | +): |
| 1382 | + """ |
| 1383 | + Scenario: |
| 1384 | + - PR is created with a branch name indicating that plans should be forward-only |
| 1385 | + - PR is not merged |
| 1386 | + - Tests passed |
| 1387 | + - PR Merge Method defined |
| 1388 | + - Deploy command has been triggered |
| 1389 | +
|
| 1390 | + Outcome: |
| 1391 | + - "Prod Environment Synced" step should show a tip explaining how to retroactively apply forward-only changes to old data |
| 1392 | + - Bot Comment should show the same tip |
| 1393 | + """ |
| 1394 | + mock_repo = github_client.get_repo() |
| 1395 | + mock_repo.create_check_run = mocker.MagicMock( |
| 1396 | + side_effect=lambda **kwargs: make_mock_check_run(**kwargs) |
| 1397 | + ) |
| 1398 | + |
| 1399 | + created_comments = [] |
| 1400 | + mock_issue = mock_repo.get_issue() |
| 1401 | + mock_issue.create_comment = mocker.MagicMock( |
| 1402 | + side_effect=lambda comment: make_mock_issue_comment( |
| 1403 | + comment=comment, created_comments=created_comments |
| 1404 | + ) |
| 1405 | + ) |
| 1406 | + mock_issue.get_comments = mocker.MagicMock(side_effect=lambda: created_comments) |
| 1407 | + |
| 1408 | + mock_pull_request = mock_repo.get_pull() |
| 1409 | + mock_pull_request.get_reviews = mocker.MagicMock(lambda: []) |
| 1410 | + mock_pull_request.merged = False |
| 1411 | + mock_pull_request.merge = mocker.MagicMock() |
| 1412 | + mock_pull_request.head.ref = "unit-test-forward-only" |
| 1413 | + |
| 1414 | + controller = make_controller( |
| 1415 | + "tests/fixtures/github/pull_request_synchronized.json", |
| 1416 | + github_client, |
| 1417 | + bot_config=GithubCICDBotConfig( |
| 1418 | + merge_method=MergeMethod.SQUASH, |
| 1419 | + enable_deploy_command=True, |
| 1420 | + foward_only_branch_suffix="-forward-only", |
| 1421 | + ), |
| 1422 | + mock_out_context=False, |
| 1423 | + ) |
| 1424 | + |
| 1425 | + # create existing prod to apply against |
| 1426 | + controller._context.plan(auto_apply=True) |
| 1427 | + |
| 1428 | + github_output_file = tmp_path / "github_output.txt" |
| 1429 | + |
| 1430 | + # then, run a deploy with forward_only set |
| 1431 | + assert controller.forward_only_plan |
| 1432 | + with mock.patch.dict(os.environ, {"GITHUB_OUTPUT": str(github_output_file)}): |
| 1433 | + command._deploy_production(controller) |
| 1434 | + |
| 1435 | + # Prod Environment Synced step should be successful |
| 1436 | + assert "SQLMesh - Prod Environment Synced" in controller._check_run_mapping |
| 1437 | + prod_checks_runs = controller._check_run_mapping["SQLMesh - Prod Environment Synced"].all_kwargs |
| 1438 | + assert len(prod_checks_runs) == 2 |
| 1439 | + assert GithubCheckStatus(prod_checks_runs[0]["status"]).is_in_progress |
| 1440 | + assert GithubCheckStatus(prod_checks_runs[1]["status"]).is_completed |
| 1441 | + assert prod_checks_runs[1]["output"]["title"] == "Deployed to Prod" |
| 1442 | + assert GithubCheckConclusion(prod_checks_runs[1]["conclusion"]).is_success |
| 1443 | + |
| 1444 | + # PR comment should be updated with forward-only tip |
| 1445 | + assert len(created_comments) == 1 |
| 1446 | + assert ( |
| 1447 | + """> [!TIP] |
| 1448 | +> In order to see this forward-only plan retroactively apply to historical intervals on the production model, run the below for date ranges in scope: |
| 1449 | +> |
| 1450 | +> `$ sqlmesh plan --restate-model sushi.customer_revenue_by_day --start YYYY-MM-dd --end YYYY-MM-DD`""" |
| 1451 | + in created_comments[0].body |
| 1452 | + ) |
0 commit comments