33import textwrap
44
55from collections .abc import AsyncGenerator
6+ from datetime import datetime , timedelta , UTC
67
78import aiohttp
89
@@ -131,6 +132,8 @@ async def _GenerateIssueInfo(
131132 repo : Repository ,
132133 github_url : str ,
133134 ) -> AsyncGenerator [ResultInfo | ErrorInfo ]:
135+ key = (self .__class__ .__name__ , "issues" )
136+
134137 try :
135138 label_counts : dict [str , int ] = {}
136139 total_count = 0
@@ -160,7 +163,7 @@ async def _GenerateIssueInfo(
160163
161164 label_str = f" [{ ', ' .join (issue_labels )} ]" if issue_labels else ""
162165
163- issue_data .append (f"• #{ issue_number } { label_str } { issue_title } (by { issue_author } )" )
166+ issue_data .append (f"- #{ issue_number } { label_str } { issue_title } (by { issue_author } )" )
164167
165168 # Build additional info with issue details
166169 additional_info_lines = [
@@ -182,24 +185,22 @@ async def _GenerateIssueInfo(
182185
183186 yield ResultInfo (
184187 repo ,
185- ( self . __class__ . __name__ , "issues" ) ,
188+ key ,
186189 f"{ total_count :5} 🐛" ,
187190 "\n " .join (additional_info_lines ),
188191 )
189192
190193 except Exception as ex :
191- yield ErrorInfo (
192- repo ,
193- (self .__class__ .__name__ , "issues" ),
194- ex ,
195- )
194+ yield ErrorInfo (repo , key , ex )
196195
197196 # ----------------------------------------------------------------------
198197 async def _GeneratePullRequestInfo (
199198 self ,
200199 repo : Repository ,
201200 github_url : str ,
202201 ) -> AsyncGenerator [ResultInfo | ErrorInfo ]:
202+ key = (self .__class__ .__name__ , "pull_requests" )
203+
203204 try :
204205 total_count = 0
205206 pr_data : list [str ] = []
@@ -216,7 +217,7 @@ async def _GeneratePullRequestInfo(
216217
217218 draft_indicator = "[DRAFT] " if pr_draft else ""
218219
219- pr_data .append (f"• #{ pr_number } { draft_indicator } { pr_title } (by { pr_author } )" )
220+ pr_data .append (f"- #{ pr_number } { draft_indicator } { pr_title } (by { pr_author } )" )
220221
221222 additional_info_lines = [
222223 f"Pull Requests: { github_url } /pulls" ,
@@ -229,24 +230,22 @@ async def _GeneratePullRequestInfo(
229230
230231 yield ResultInfo (
231232 repo ,
232- ( self . __class__ . __name__ , "pull_requests" ) ,
233+ key ,
233234 f"{ total_count :5} 🔀" ,
234235 "\n " .join (additional_info_lines ),
235236 )
236237
237238 except Exception as ex :
238- yield ErrorInfo (
239- repo ,
240- (self .__class__ .__name__ , "pull_requests" ),
241- ex ,
242- )
239+ yield ErrorInfo (repo , key , ex )
243240
244241 # ----------------------------------------------------------------------
245242 async def _GenerateSecurityAlertInfo (
246243 self ,
247244 repo : Repository ,
248245 github_url : str ,
249246 ) -> AsyncGenerator [ResultInfo | ErrorInfo ]:
247+ key = (self .__class__ .__name__ , "security_alerts" )
248+
250249 try :
251250 severity_counts : dict [str , int ] = {
252251 "critical" : 0 ,
@@ -271,7 +270,7 @@ async def _GenerateSecurityAlertInfo(
271270 package = alert .get ("security_vulnerability" , {}).get ("package" , {})
272271
273272 alert_data .append (
274- f"• [{ advisory .get ('severity' , 'unknown' ).upper ()} ] { package .get ('name' , 'unknown' )} : { advisory .get ('summary' , 'No summary' )} "
273+ f"- [{ advisory .get ('severity' , 'unknown' ).upper ()} ] { package .get ('name' , 'unknown' )} : { advisory .get ('summary' , 'No summary' )} "
275274 )
276275
277276 # Build display value with icon based on severity
@@ -303,17 +302,13 @@ async def _GenerateSecurityAlertInfo(
303302
304303 yield ResultInfo (
305304 repo ,
306- ( self . __class__ . __name__ , "security_alerts" ) ,
305+ key ,
307306 display_value ,
308307 "\n " .join (additional_info_lines ),
309308 )
310309
311310 except Exception as ex :
312- yield ErrorInfo (
313- repo ,
314- (self .__class__ .__name__ , "security_alerts" ),
315- ex ,
316- )
311+ yield ErrorInfo (repo , key , ex )
317312
318313 # ----------------------------------------------------------------------
319314 async def _GenerateCICDInfo (
@@ -322,12 +317,20 @@ async def _GenerateCICDInfo(
322317 github_url : str ,
323318 default_branch : str ,
324319 ) -> AsyncGenerator [ResultInfo | ErrorInfo ]:
325- info_key = (self .__class__ .__name__ , "cicd_status" )
320+ key = (self .__class__ .__name__ , "cicd_status" )
326321
327322 try :
328- url = f"https://api.github.com/repos/{ repo .github_owner } /{ repo .github_repo } /actions/runs?branch={ default_branch } &per_page=100"
323+ prev_month = datetime .now (tz = UTC ) - timedelta (days = 30 )
324+
325+ url = f"https://api.github.com/repos/{ repo .github_owner } /{ repo .github_repo } /actions/runs"
329326
330- async with self ._session .get (url ) as response :
327+ params = {
328+ "branch" : default_branch ,
329+ "per_page" : 100 ,
330+ "created" : f">={ prev_month .date ()} " ,
331+ }
332+
333+ async with self ._session .get (url , params = params ) as response :
331334 response .raise_for_status ()
332335 result = await response .json ()
333336
@@ -336,17 +339,18 @@ async def _GenerateCICDInfo(
336339 if not workflow_runs :
337340 yield ResultInfo (
338341 repo ,
339- info_key ,
340- "🔘 " ,
342+ key ,
343+ "- " ,
341344 textwrap .dedent (
342345 """\
343346 CI/CD Status: {github_url}/actions
344347
345- No workflow runs found for branch '{default_branch}'
348+ No workflow runs found for branch '{default_branch}' since '{prev_month}'.
346349 """ ,
347350 ).format (
348351 github_url = github_url ,
349352 default_branch = default_branch ,
353+ prev_month = prev_month .date (),
350354 ),
351355 )
352356 return
@@ -386,7 +390,7 @@ async def _GenerateCICDInfo(
386390 else :
387391 status_label = conclusion or status or "UNKNOWN"
388392
389- run_details .append (f"• [{ status_label } ] { run ['created_at' ]} { run ['path' ]} : { run ['name' ]} " )
393+ run_details .append (f"- [{ status_label } ] { run ['created_at' ]} { run ['path' ]} : { run ['name' ]} " )
390394
391395 # Determine display icon based on priority: failure > in_progress > success
392396 if status_counts ["failure" ] > 0 :
@@ -415,33 +419,29 @@ async def _GenerateCICDInfo(
415419
416420 yield ResultInfo (
417421 repo ,
418- info_key ,
422+ key ,
419423 display_icon ,
420424 "\n " .join (additional_info_lines ),
421425 )
422426
423427 except Exception as ex :
424- yield ErrorInfo (
425- repo ,
426- info_key ,
427- ex ,
428- )
428+ yield ErrorInfo (repo , key , ex )
429429
430430 # ----------------------------------------------------------------------
431- async def _GeneratePaginatedResults (self , raw_url : str ) -> AsyncGenerator [dict ]:
432- url : str | None = f" { raw_url } ? state= open& per_page=100"
431+ async def _GeneratePaginatedResults (self , url : str ) -> AsyncGenerator [dict ]:
432+ params = { " state" : " open" , " per_page" : 100 }
433433 next_page_regex = re .compile (r"<([^>]+)>" )
434434
435435 while url :
436- async with self ._session .get (url ) as response :
436+ async with self ._session .get (url , params = params ) as response :
437437 response .raise_for_status ()
438438
439439 results = await response .json ()
440440
441441 for result in results :
442442 yield result
443443
444- url = None
444+ url : str | None = None
445445 link_header = response .headers .get ("Link" , "" )
446446
447447 for link in link_header .split ("," ):
0 commit comments