11import traceback
22from contextlib import suppress
3- from dataclasses import dataclass
43from datetime import timedelta
5- from typing import Callable
64
75import djclick as click
86
9- from django .core .mail import send_mail
107from django .utils import timezone
118from django .core .management import call_command
129from django .contrib .auth import get_user_model
1310from django .conf import settings
1411from slack_sdk .errors import SlackApiError
1512
1613from core .githubhelper import GithubAPIClient
14+ from core .management .actions import (
15+ progress_message ,
16+ Action ,
17+ ActionsManager ,
18+ send_notification ,
19+ )
1720from libraries .forms import CreateReportForm
1821from libraries .tasks import update_commits
1922from reports .models import WebsiteStatReport
2326User = get_user_model ()
2427
2528
26- def send_notification (user , message , subject = "Task Started: release_tasks" ):
27- if user .email :
28- send_mail (
29- subject ,
30- message ,
31- settings .DEFAULT_FROM_EMAIL ,
32- [user .email ],
33- )
34-
35-
36- def progress_message (message : str ):
37- click .secho (message , fg = "green" )
38- return f"{ timezone .now ()} : { message } "
39-
40-
41- @dataclass
42- class ReleaseTask :
43- """
44- A distinct task to be completed.
45-
46- Action can be a callable or a list of string arguments to pass to `call_command`
47- """
48-
49- description : str
50- action : Callable | list [str ]
51-
52- def run (self ):
53- if isinstance (self .action , Callable ):
54- self .action ()
55- else :
56- call_command (* self .action )
57-
58-
59- class ReleaseTasksManager :
29+ class ReleaseTasksManager (ActionsManager ):
6030 latest_version : Version | None = None
61- progress_messages : list [str ] = []
6231 handled_commits : dict [str , int ] = {}
6332
6433 def __init__ (self , should_generate_report : bool = False ):
6534 self .should_generate_report = should_generate_report
35+ super ().__init__ ()
36+
37+ def set_tasks (self ):
6638 self .tasks = [
67- ReleaseTask ("Importing versions" , self .import_versions ),
68- ReleaseTask (
39+ Action ("Importing versions" , self .import_versions ),
40+ Action (
6941 "Importing most recent beta version" ,
7042 ["import_beta_release" , "--delete-versions" ],
7143 ),
72- ReleaseTask ("Importing libraries" , ["update_libraries" ]),
73- ReleaseTask (
44+ Action ("Importing libraries" , ["update_libraries" ]),
45+ Action (
7446 "Saving library-version relationships" , self .import_library_versions
7547 ),
76- ReleaseTask ("Adding library maintainers" , ["update_maintainers" ]),
77- ReleaseTask ("Adding library authors" , ["update_authors" ]),
78- ReleaseTask (
48+ Action ("Adding library maintainers" , ["update_maintainers" ]),
49+ Action ("Adding library authors" , ["update_authors" ]),
50+ Action (
7951 "Adding library version authors" , ["update_library_version_authors" ]
8052 ),
81- ReleaseTask ("Importing git commits" , self .handle_commits ),
82- ReleaseTask ("Syncing mailinglist statistics" , ["sync_mailinglist_stats" ]),
83- ReleaseTask ("Updating github issues" , ["update_issues" ]),
84- ReleaseTask ("Updating slack activity buckets" , ["fetch_slack_activity" ]),
85- ReleaseTask ("Updating website statistics" , self .update_website_statistics ),
86- ReleaseTask ("Importing mailing list counts" , self .import_ml_counts ),
87- ReleaseTask ("Generating report" , self .generate_report ),
53+ Action ("Importing git commits" , self .import_commits ),
54+ Action ("Syncing mailinglist statistics" , ["sync_mailinglist_stats" ]),
55+ Action ("Updating github issues" , ["update_issues" ]),
56+ Action ("Updating slack activity buckets" , ["fetch_slack_activity" ]),
57+ Action ("Updating website statistics" , self .update_website_statistics ),
58+ Action ("Importing mailing list counts" , self .import_ml_counts ),
59+ Action ("Generating report" , self .generate_report ),
8860 ]
8961
90- def update_release_data (self ) -> dict [str :int ]:
91- for task in self .tasks :
92- # "Release Task: " prefix for easy log parsing
93- self .progress_messages .append (
94- progress_message (f"Release Task: { task .description } ..." )
95- )
96- task .run ()
97- self .progress_messages .append (
98- progress_message (f"Release Task: Finished { task .description .lower ()} " )
99- )
100- return self .handled_commits
101-
10262 def import_versions (self ):
10363 call_command ("import_versions" )
10464 self .latest_version = Version .objects .most_recent ()
@@ -107,7 +67,7 @@ def import_library_versions(self):
10767 latest_version_number = self .latest_version .name .lstrip ("boost-" )
10868 call_command ("import_library_versions" , min_release = latest_version_number )
10969
110- def handle_commits (self ):
70+ def import_commits (self ):
11171 self .handled_commits = update_commits (min_version = self .latest_version .name )
11272
11373 def update_website_statistics (self ):
@@ -125,9 +85,7 @@ def import_ml_counts(self):
12585
12686 def generate_report (self ):
12787 if not self .should_generate_report :
128- self .progress_messages .append (
129- progress_message ("Skipped - report generation not requested" )
130- )
88+ self .add_progress_message ("Skipped - report generation not requested" )
13189 return
13290 form = CreateReportForm ({"version" : self .latest_version .id })
13391 form .cache_html ()
@@ -136,11 +94,9 @@ def generate_report(self):
13694@locked (1138692 )
13795def run_commands (progress : list [str ], generate_report : bool = False ):
13896 manager = ReleaseTasksManager (should_generate_report = generate_report )
139- handled_commits = manager .update_release_data ()
140-
97+ manager .run_tasks ()
14198 progress .extend (manager .progress_messages )
142-
143- return handled_commits
99+ return manager .handled_commits
144100
145101
146102def bad_credentials () -> list [str ]:
@@ -185,40 +141,38 @@ def command(user_id=None, generate_report=False):
185141 """A long running chain of tasks to import and update library data."""
186142 start = timezone .now ()
187143
188- user = None
189- if user_id :
190- user = User .objects .filter (id = user_id ).first ()
144+ user = User .objects .filter (id = user_id ).first () if user_id else None
191145
192146 progress = ["___Progress Messages___" ]
193147 if missing_creds := bad_credentials ():
194148 progress .append (
195149 progress_message (f"Missing credentials { ', ' .join (missing_creds )} " )
196150 )
197- if user :
198- send_notification (
199- user ,
200- message = "Your task `release_tasks` failed." ,
201- subject = "Task Failed: release_tasks" ,
202- )
151+ send_notification (
152+ user ,
153+ message = "Your task `release_tasks` failed." ,
154+ subject = "Task Failed: release_tasks" ,
155+ )
203156 return
204- if user :
205- send_notification (user , f"Your task `release_tasks` was started at: { start } " )
157+
158+ send_notification (
159+ user ,
160+ f"Your task `release_tasks` was started at: { start } " ,
161+ subject = "Task Started: release_tasks" ,
162+ )
206163
207164 try :
208165 handled_commits = run_commands (progress , generate_report )
209166 end = timezone .now ()
210- progress .append (progress_message (f"All done! Completed in { end - start } " ))
211167 except Exception :
212168 error = traceback .format_exc ()
213169 message = [
214170 f"ERROR: There was an error while running release_tasks.\n \n { error } " ,
215171 "\n " .join (progress ),
216172 ]
217- if user :
218- send_notification (
219- user ,
220- "\n \n " .join (message ),
221- )
173+ send_notification (
174+ user , "\n \n " .join (message ), subject = "Task Failed: release_tasks"
175+ )
222176 raise
223177
224178 zero_commit_libraries = [
@@ -236,9 +190,8 @@ def command(user_id=None, generate_report=False):
236190 for lib , _ in zero_commit_libraries :
237191 zero_commit_message .append (lib )
238192 message .append ("\n " .join (zero_commit_message ))
239- if user :
240- send_notification (
241- user ,
242- "\n \n " .join (message ),
243- subject = "Task Complete: release_tasks" ,
244- )
193+ send_notification (
194+ user ,
195+ "\n \n " .join (message ),
196+ subject = "Task Complete: release_tasks" ,
197+ )
0 commit comments