1010 * exempt labels that have been inactive for 90+ days.
1111 * - Avoids sending duplicate Friendly Reminder comments if one was
1212 * posted within the last 7 days.
13+ * - Moves issues labeled 'discussion' to GitHub Discussions
1314 */
1415
1516const dedent = ( strings , ...values ) => {
@@ -47,10 +48,53 @@ async function fetchAllOpenIssues(github, owner, repo) {
4748 return issues ;
4849}
4950
51+
52+ async function migrateToDiscussion ( github , owner , repo , issue ) {
53+ const discussionCategory = 'General' ;
54+
55+ const { data : categories } = await github . rest . discussions . listCategories ( {
56+ owner,
57+ repo,
58+ } ) ;
59+
60+ const category = categories . find ( cat =>
61+ cat . name . toLowerCase ( ) === discussionCategory . toLowerCase ( )
62+ ) ;
63+
64+ if ( ! category ) {
65+ throw new Error ( `Discussion category '${ discussionCategory } ' not found.` ) ;
66+ }
67+
68+ const { data : discussion } = await github . rest . discussions . create ( {
69+ owner,
70+ repo,
71+ title : issue . title ,
72+ body : `Originally created by @${ issue . user . login } in #${ issue . number } \n\n---\n\n${ issue . body } ` ,
73+ category_id : category . id ,
74+ } ) ;
75+
76+ await github . rest . issues . createComment ( {
77+ owner,
78+ repo,
79+ issue_number : issue . number ,
80+ body : `💬 This issue was moved to [Discussions](${ discussion . html_url } ) for better visibility.` ,
81+ } ) ;
82+
83+ await github . rest . issues . update ( {
84+ owner,
85+ repo,
86+ issue_number : issue . number ,
87+ state : 'closed' ,
88+ } ) ;
89+
90+ return discussion . html_url ;
91+ }
92+
93+
5094const shouldSendReminder = ( issue , exemptLabels , closeLabels ) => {
51- const hasExempt = issue . labels . some ( l => exemptLabels . includes ( l . name ) ) ;
52- const hasClose = issue . labels . some ( l => closeLabels . includes ( l . name ) ) ;
53- return issue . assignees . length > 0 && ! hasExempt && ! hasClose ;
95+ const hasExempt = issue . labels . some ( l => exemptLabels . includes ( l . name ) ) ;
96+ const hasClose = issue . labels . some ( l => closeLabels . includes ( l . name ) ) ;
97+ return issue . assignees . length > 0 && ! hasExempt && ! hasClose ;
5498} ;
5599
56100
@@ -61,17 +105,25 @@ module.exports = async ({ github, context }) => {
61105 const thresholdDays = 90 ;
62106 const exemptLabels = [ 'to-be-discussed' ] ;
63107 const closeLabels = [ 'awaiting-response' ] ;
108+ const discussionLabel = 'discussion' ;
64109 const sevenDays = 7 * 24 * 60 * 60 * 1000 ;
65110
66111 let totalClosed = 0 ;
67112 let totalReminders = 0 ;
68113 let totalSkipped = 0 ;
114+ let totalMigrated = 0 ;
69115
70116 for ( const issue of issues ) {
71117 const isAssigned = issue . assignees && issue . assignees . length > 0 ;
72118 const lastUpdate = new Date ( issue . updated_at ) ;
73119 const daysSinceUpdate = Math . floor ( ( now - lastUpdate ) / ( 1000 * 60 * 60 * 24 ) ) ;
74120
121+ if ( issue . labels . some ( label => label . name === discussionLabel ) ) {
122+ await migrateToDiscussion ( github , owner , repo , issue ) ;
123+ totalMigrated ++ ;
124+ continue ;
125+ }
126+
75127 if ( daysSinceUpdate < thresholdDays ) {
76128 totalSkipped ++ ;
77129 continue ;
@@ -145,5 +197,6 @@ module.exports = async ({ github, context }) => {
145197 Total issues processed: ${ issues . length }
146198 Total issues closed: ${ totalClosed }
147199 Total reminders sent: ${ totalReminders }
200+ Total migrated to discussions: ${ totalMigrated }
148201 Total skipped: ${ totalSkipped } ` ) ;
149202} ;
0 commit comments