@@ -13,7 +13,7 @@ def __init__(self):
1313 super ().__init__ ()
1414 self .DAYS_BEFORE_STALE_WARNING = 7
1515 self .DAYS_BEFORE_UNASSIGN = 14
16- self .DAYS_BEFORE_CLOSE = 60
16+ self .DAYS_BEFORE_FINAL_FOLLOWUP = 60
1717
1818 @staticmethod
1919 def _commit_activity_date_for_author (commit , pr_author ):
@@ -244,69 +244,31 @@ def unassign_linked_issues(self, pr):
244244 print (f"Error processing linked issues for PR #{ pr .number } : { e } " )
245245 return 0
246246
247- def close_stale_pr (self , pr , days_inactive ):
248- if pr .state == "closed" :
249- print (f"PR #{ pr .number } is already closed, skipping" )
250- return True
247+ def send_final_followup (self , pr , days_inactive ):
251248 try :
252249 pr_author = pr .user .login if pr .user else None
253250 if not pr_author :
254251 return False
255- close_lines = [
256- "<!-- bot:closed -->" ,
257- f"Hi @{ pr_author } 👋," ,
258- "" ,
259- (
260- "This pull request has been automatically"
261- " closed due to"
262- f" **{ days_inactive } days of inactivity**."
263- " After changes were requested,"
264- " the PR remained inactive."
265- ),
266- "" ,
267- (
268- "We understand that life gets busy,"
269- " and we appreciate your initial"
270- " contribution! 💙"
271- ),
252+ followup_lines = [
253+ "<!-- bot:final_followup -->" ,
254+ f"Hi @{ pr_author } ," ,
272255 "" ,
273- ("**The door is always open**" " for you to come back:" ),
274- (
275- "- You can **reopen this PR** at any time"
276- " if you'd like to continue working on it"
277- ),
278- ("- Feel free to push new commits" " addressing the requested changes" ),
279256 (
280- "- If you reopen the PR, the linked issue "
281- " will be reassigned to you"
257+ f"This PR has been inactive for ** { days_inactive } days** "
258+ " since changes were requested. Are you still working on it? "
282259 ),
283260 "" ,
284261 (
285- "If you have any questions or need help, "
286- " don't hesitate to reach out. "
287- " We're here to support you! "
262+ "If yes, push new commits or reply to let us know. "
263+ " If you've moved on, please close the PR or comment "
264+ " so another contributor can pick it up. "
288265 ),
289- "" ,
290- ("Thank you for your interest in" " contributing to OpenWISP! 🙏" ),
291266 ]
292- try :
293- pr .create_issue_comment ("\n " .join (close_lines ))
294- except Exception as comment_error :
295- print (
296- f"Warning: Could not post closing comment"
297- f" on PR #{ pr .number } : { comment_error } "
298- )
299- finally :
300- pr .edit (state = "closed" )
301- unassigned_count = self .unassign_linked_issues (pr )
302- print (
303- f"Closed PR #{ pr .number } after"
304- f" { days_inactive } days of inactivity,"
305- f" unassigned { unassigned_count } issues"
306- )
267+ pr .create_issue_comment ("\n " .join (followup_lines ))
268+ print (f"Sent final follow-up for PR #{ pr .number } " )
307269 return True
308270 except Exception as e :
309- print (f"Error closing PR #{ pr .number } : { e } " )
271+ print (f"Error sending final follow-up for PR #{ pr .number } : { e } " )
310272 return False
311273
312274 def mark_pr_stale (self , pr , days_inactive ):
@@ -347,14 +309,6 @@ def mark_pr_stale(self, pr, days_inactive):
347309 " let us know."
348310 " We're happy to help! 🤝"
349311 ),
350- "" ,
351- (
352- "If there's no further activity within"
353- f" **{ self .DAYS_BEFORE_CLOSE - days_inactive } "
354- " more days**, this PR will be"
355- " automatically closed"
356- " (but can be reopened anytime)."
357- ),
358312 ]
359313 pr .create_issue_comment ("\n " .join (unassign_lines ))
360314 unassigned_count = self .unassign_linked_issues (pr )
@@ -463,27 +417,40 @@ def process_stale_prs(self):
463417 " maintainer review, skipping"
464418 )
465419 continue
466- if days_inactive >= self .DAYS_BEFORE_CLOSE :
467- if self .close_stale_pr (pr , days_inactive ):
468- processed_count += 1
469- elif days_inactive >= self .DAYS_BEFORE_UNASSIGN :
470- if not self .has_bot_comment (
471- pr ,
420+ stages = (
421+ (
422+ self .DAYS_BEFORE_STALE_WARNING ,
423+ self .DAYS_BEFORE_UNASSIGN ,
424+ "stale_warning" ,
425+ self .send_stale_warning ,
426+ ),
427+ (
428+ self .DAYS_BEFORE_UNASSIGN ,
429+ None ,
472430 "stale" ,
473- after_date = last_changes_requested ,
474- issue_comments = issue_comments ,
475- ):
476- if self .mark_pr_stale (pr , days_inactive ):
477- processed_count += 1
478- elif days_inactive >= self .DAYS_BEFORE_STALE_WARNING :
479- if not self .has_bot_comment (
431+ self .mark_pr_stale ,
432+ ),
433+ (
434+ self .DAYS_BEFORE_FINAL_FOLLOWUP ,
435+ None ,
436+ "final_followup" ,
437+ self .send_final_followup ,
438+ ),
439+ )
440+ for low , high , marker , action in stages :
441+ if days_inactive < low :
442+ continue
443+ if high is not None and days_inactive >= high :
444+ continue
445+ if self .has_bot_comment (
480446 pr ,
481- "stale_warning" ,
447+ marker ,
482448 after_date = last_changes_requested ,
483449 issue_comments = issue_comments ,
484450 ):
485- if self .send_stale_warning (pr , days_inactive ):
486- processed_count += 1
451+ continue
452+ if action (pr , days_inactive ):
453+ processed_count += 1
487454 except Exception as e :
488455 print (f"Error processing" f" PR #{ pr .number } : { e } " )
489456 continue
0 commit comments