11from __future__ import annotations
22
33import logging
4- import typing as t
54
65import click
76
87from sqlmesh .integrations .github .cicd .controller import (
98 GithubCheckConclusion ,
109 GithubCheckStatus ,
1110 GithubController ,
12- MergeMethod ,
11+ TestFailure ,
1312)
1413from sqlmesh .utils .errors import CICDBotError , PlanError
1514
1615logger = logging .getLogger (__name__ )
1716
1817
19- merge_method_option = click .option (
20- "--merge-method" ,
21- type = click .Choice (MergeMethod ), # type: ignore
22- help = "Enables merging PR after successfully deploying to production using the provided method." ,
23- )
24-
25- delete_option = click .option (
26- "--delete" ,
27- is_flag = True ,
28- help = "Delete the PR environment after successfully deploying to production" ,
29- )
30-
31-
3218@click .group (no_args_is_help = True )
3319@click .option (
3420 "--token" ,
@@ -68,13 +54,13 @@ def check_required_approvers(ctx: click.Context) -> None:
6854def _run_tests (controller : GithubController ) -> bool :
6955 controller .update_test_check (status = GithubCheckStatus .IN_PROGRESS )
7056 try :
71- result , failed_output = controller .run_tests ()
57+ result , output = controller .run_tests ()
7258 controller .update_test_check (
7359 status = GithubCheckStatus .COMPLETED ,
7460 # Conclusion will be updated with final status based on test results
7561 conclusion = GithubCheckConclusion .NEUTRAL ,
7662 result = result ,
77- failed_output = failed_output ,
63+ output = output ,
7864 )
7965 return result .wasSuccessful ()
8066 except Exception :
@@ -95,15 +81,17 @@ def _update_pr_environment(controller: GithubController) -> bool:
9581 controller .update_pr_environment_check (status = GithubCheckStatus .IN_PROGRESS )
9682 try :
9783 controller .update_pr_environment ()
98- controller .update_pr_environment_check (
99- status = GithubCheckStatus .COMPLETED , conclusion = GithubCheckConclusion .SUCCESS
84+ conclusion = controller .update_pr_environment_check (status = GithubCheckStatus .COMPLETED )
85+ return conclusion is not None and conclusion .is_success
86+ except Exception as e :
87+ conclusion = controller .update_pr_environment_check (
88+ status = GithubCheckStatus .COMPLETED , exception = e
10089 )
101- return True
102- except PlanError :
103- controller . update_pr_environment_check (
104- status = GithubCheckStatus . COMPLETED , conclusion = GithubCheckConclusion . ACTION_REQUIRED
90+ return (
91+ conclusion is not None
92+ and not conclusion . is_failure
93+ and not conclusion . is_action_required
10594 )
106- return False
10795
10896
10997@github .command ()
@@ -113,21 +101,43 @@ def update_pr_environment(ctx: click.Context) -> None:
113101 _update_pr_environment (ctx .obj ["github" ])
114102
115103
116- def _deploy_production (
117- controller : GithubController ,
118- merge_method : t .Optional [MergeMethod ],
119- delete_environment_after_deploy : bool = True ,
120- ) -> bool :
104+ def _gen_prod_plan (controller : GithubController ) -> bool :
105+ controller .update_prod_plan_preview_check (status = GithubCheckStatus .IN_PROGRESS )
106+ try :
107+ plan_summary = controller .get_plan_summary (controller .prod_plan )
108+ controller .update_prod_plan_preview_check (
109+ status = GithubCheckStatus .COMPLETED ,
110+ conclusion = GithubCheckConclusion .SUCCESS ,
111+ summary = plan_summary ,
112+ )
113+ return bool (plan_summary )
114+ except Exception as e :
115+ controller .update_prod_plan_preview_check (
116+ status = GithubCheckStatus .COMPLETED ,
117+ conclusion = GithubCheckConclusion .FAILURE ,
118+ summary = str (e ),
119+ )
120+ return False
121+
122+
123+ @github .command ()
124+ @click .pass_context
125+ def gen_prod_plan (ctx : click .Context ) -> None :
126+ """Generates the production plan"""
127+ controller = ctx .obj ["github" ]
128+ controller .update_prod_plan_preview_check (status = GithubCheckStatus .IN_PROGRESS )
129+ _gen_prod_plan (controller )
130+
131+
132+ def _deploy_production (controller : GithubController ) -> bool :
121133 controller .update_prod_environment_check (status = GithubCheckStatus .IN_PROGRESS )
122134 try :
123135 controller .deploy_to_prod ()
124136 controller .update_prod_environment_check (
125137 status = GithubCheckStatus .COMPLETED , conclusion = GithubCheckConclusion .SUCCESS
126138 )
127- if merge_method :
128- controller .merge_pr (merge_method = merge_method )
129- if delete_environment_after_deploy :
130- controller .delete_pr_environment ()
139+ controller .try_merge_pr ()
140+ controller .try_invalidate_pr_environment ()
131141 return True
132142 except PlanError :
133143 controller .update_prod_environment_check (
@@ -137,27 +147,22 @@ def _deploy_production(
137147
138148
139149@github .command ()
140- @merge_method_option
141- @delete_option
142150@click .pass_context
143- def deploy_production (
144- ctx : click .Context , merge_method : t .Optional [MergeMethod ], delete : bool
145- ) -> None :
151+ def deploy_production (ctx : click .Context ) -> None :
146152 """Deploys the production environment"""
147- _deploy_production (
148- ctx .obj ["github" ], merge_method = merge_method , delete_environment_after_deploy = delete
149- )
153+ _deploy_production (ctx .obj ["github" ])
150154
151155
152- def _run_all (
153- controller : GithubController ,
154- merge_method : t .Optional [MergeMethod ],
155- delete : bool ,
156- command_namespace : t .Optional [str ] = None ,
157- ) -> None :
156+ def _run_all (controller : GithubController ) -> None :
158157 has_required_approval = False
158+ is_auto_deploying_prod = (
159+ controller .deploy_command_enabled or controller .do_required_approval_check
160+ )
159161 if controller .is_comment_added :
160- command = controller .get_command_from_comment (command_namespace )
162+ if not controller .deploy_command_enabled :
163+ # We aren't using commands so we can just return
164+ return
165+ command = controller .get_command_from_comment ()
161166 if command .is_invalid :
162167 # Probably a comment unrelated to SQLMesh so we do nothing
163168 return
@@ -166,41 +171,70 @@ def _run_all(
166171 else :
167172 raise CICDBotError (f"Unsupported command: { command } " )
168173 controller .update_pr_environment_check (status = GithubCheckStatus .QUEUED )
169- controller .update_prod_environment_check (status = GithubCheckStatus .QUEUED )
174+ controller .update_prod_plan_preview_check (status = GithubCheckStatus .QUEUED )
170175 controller .update_test_check (status = GithubCheckStatus .QUEUED )
176+ if is_auto_deploying_prod :
177+ controller .update_prod_environment_check (status = GithubCheckStatus .QUEUED )
171178 tests_passed = _run_tests (controller )
172- if not has_required_approval and controller .do_required_approval_check :
173- controller .update_required_approval_check (status = GithubCheckStatus .QUEUED )
174- has_required_approval = _check_required_approvers (controller )
175- else :
176- controller .update_required_approval_check (
177- status = GithubCheckStatus .COMPLETED , conclusion = GithubCheckConclusion .SKIPPED
179+ if controller .do_required_approval_check :
180+ if has_required_approval :
181+ controller .update_required_approval_check (
182+ status = GithubCheckStatus .COMPLETED , conclusion = GithubCheckConclusion .SKIPPED
183+ )
184+ else :
185+ controller .update_required_approval_check (status = GithubCheckStatus .QUEUED )
186+ has_required_approval = _check_required_approvers (controller )
187+ if not tests_passed :
188+ controller .update_pr_environment_check (
189+ status = GithubCheckStatus .COMPLETED ,
190+ exception = TestFailure (),
178191 )
179- pr_environment_updated = _update_pr_environment ( controller )
180- if tests_passed and has_required_approval and pr_environment_updated :
181- _deploy_production (
182- controller , merge_method = merge_method , delete_environment_after_deploy = delete
192+ controller . update_prod_plan_preview_check (
193+ status = GithubCheckStatus . COMPLETED ,
194+ conclusion = GithubCheckConclusion . SKIPPED ,
195+ summary = "Unit Test(s) Failed so skipping creating prod plan" ,
183196 )
197+ if is_auto_deploying_prod :
198+ controller .update_prod_environment_check (
199+ status = GithubCheckStatus .COMPLETED ,
200+ conclusion = GithubCheckConclusion .SKIPPED ,
201+ skip_reason = "Unit Test(s) Failed so skipping deploying to production" ,
202+ )
203+ return
204+ pr_environment_updated = _update_pr_environment (controller )
205+ prod_plan_generated = False
206+ if pr_environment_updated :
207+ prod_plan_generated = _gen_prod_plan (controller )
184208 else :
185- controller .update_prod_environment_check (
209+ controller .update_prod_plan_preview_check (
186210 status = GithubCheckStatus .COMPLETED , conclusion = GithubCheckConclusion .SKIPPED
187211 )
212+ if tests_passed and has_required_approval and pr_environment_updated and prod_plan_generated :
213+ _deploy_production (controller )
214+ elif is_auto_deploying_prod :
215+ if not has_required_approval :
216+ skip_reason = (
217+ "Skipped Deploying to Production because a required approver has not approved"
218+ )
219+ elif not pr_environment_updated :
220+ skip_reason = (
221+ "Skipped Deploying to Production because the PR environment was not updated"
222+ )
223+ elif not prod_plan_generated :
224+ skip_reason = (
225+ "Skipped Deploying to Production because the production plan could not be generated"
226+ )
227+ else :
228+ skip_reason = "Skipped Deploying to Production for an unknown reason"
229+ controller .update_prod_environment_check (
230+ status = GithubCheckStatus .COMPLETED ,
231+ conclusion = GithubCheckConclusion .SKIPPED ,
232+ skip_reason = skip_reason ,
233+ )
188234
189235
190236@github .command ()
191- @merge_method_option
192- @delete_option
193- @click .option (
194- "--command_namespace" ,
195- type = str ,
196- help = "Namespace to use for SQLMesh commands. For example if you provide `#SQLMesh` as a value then commands will be expected in the format of `#SQLMesh/<command>`." ,
197- )
198237@click .pass_context
199- def run_all (
200- ctx : click .Context ,
201- merge_method : t .Optional [MergeMethod ],
202- delete : bool ,
203- command_namespace : t .Optional [str ],
204- ) -> None :
238+ def run_all (ctx : click .Context ) -> None :
205239 """Runs all the commands in the correct order."""
206- return _run_all (ctx .obj ["github" ], merge_method , delete , command_namespace )
240+ return _run_all (ctx .obj ["github" ])
0 commit comments