|
2 | 2 | // <reference types="@actions/github-script" /> |
3 | 3 |
|
4 | 4 | const { executeExpiredEntityCleanup } = require("./expired_entity_main_flow.cjs"); |
5 | | -const { generateExpiredEntityFooter, getExpiredEntityCautionAlert } = require("./generate_footer.cjs"); |
6 | | -const { formatDateInProjectTimeZone } = require("./project_timezone.cjs"); |
7 | | -const { sanitizeContent } = require("./sanitize_content.cjs"); |
| 5 | +const { addDiscussionComment, closeDiscussionAsOutdated, createClosedRecord, createExpiredEntityHandler } = require("./expired_entity_handler_factory.cjs"); |
8 | 6 | const { getWorkflowMetadata } = require("./workflow_metadata_helpers.cjs"); |
9 | 7 | const { resolveExecutionOwnerRepo } = require("./repo_helpers.cjs"); |
10 | 8 |
|
11 | | -/** |
12 | | - * Add comment to a GitHub Discussion using GraphQL |
13 | | - * @param {any} github - GitHub GraphQL instance |
14 | | - * @param {string} discussionId - Discussion node ID |
15 | | - * @param {string} message - Comment body |
16 | | - * @returns {Promise<{id: string, url: string}>} Comment details |
17 | | - */ |
18 | | -async function addDiscussionComment(github, discussionId, message) { |
19 | | - const result = await github.graphql( |
20 | | - ` |
21 | | - mutation($dId: ID!, $body: String!) { |
22 | | - addDiscussionComment(input: { discussionId: $dId, body: $body }) { |
23 | | - comment { |
24 | | - id |
25 | | - url |
26 | | - } |
27 | | - } |
28 | | - }`, |
29 | | - { dId: discussionId, body: sanitizeContent(message) } |
30 | | - ); |
31 | | - |
32 | | - return result.addDiscussionComment.comment; |
33 | | -} |
34 | | - |
35 | | -/** |
36 | | - * Close a GitHub Discussion as OUTDATED using GraphQL |
37 | | - * @param {any} github - GitHub GraphQL instance |
38 | | - * @param {string} discussionId - Discussion node ID |
39 | | - * @returns {Promise<{id: string, url: string}>} Discussion details |
40 | | - */ |
41 | | -async function closeDiscussionAsOutdated(github, discussionId) { |
42 | | - const result = await github.graphql( |
43 | | - ` |
44 | | - mutation($dId: ID!) { |
45 | | - closeDiscussion(input: { discussionId: $dId, reason: OUTDATED }) { |
46 | | - discussion { |
47 | | - id |
48 | | - url |
49 | | - } |
50 | | - } |
51 | | - }`, |
52 | | - { dId: discussionId } |
53 | | - ); |
54 | | - |
55 | | - return result.closeDiscussion.discussion; |
56 | | -} |
57 | | - |
58 | 9 | /** |
59 | 10 | * Check if a discussion already has an expiration comment and fetch its closed state |
60 | 11 | * @param {any} github - GitHub GraphQL instance |
@@ -106,60 +57,46 @@ async function main() { |
106 | 57 | summaryHeading: "Expired Discussions Cleanup", |
107 | 58 | enableDedupe: true, // Discussions may have duplicates across pages |
108 | 59 | includeSkippedHeading: true, |
109 | | - processEntity: async discussion => { |
110 | | - core.info(` Checking for existing expiration comment and closed state on discussion #${discussion.number}`); |
111 | | - const { hasComment, isClosed } = await hasExpirationComment(github, discussion.id); |
112 | | - |
113 | | - if (isClosed) { |
114 | | - core.warning(` Discussion #${discussion.number} is already closed, skipping`); |
115 | | - return { |
116 | | - status: "skipped", |
117 | | - record: { |
118 | | - number: discussion.number, |
119 | | - url: discussion.url, |
120 | | - title: discussion.title, |
121 | | - }, |
122 | | - }; |
123 | | - } |
124 | | - |
125 | | - if (hasComment) { |
126 | | - core.warning(` Discussion #${discussion.number} already has an expiration comment, skipping to avoid duplicate`); |
127 | | - |
128 | | - core.info(` Attempting to close discussion #${discussion.number} without adding another comment`); |
129 | | - await closeDiscussionAsOutdated(github, discussion.id); |
130 | | - core.info(` ✓ Discussion closed successfully`); |
131 | | - |
132 | | - return { |
133 | | - status: "skipped", |
134 | | - record: { |
135 | | - number: discussion.number, |
136 | | - url: discussion.url, |
137 | | - title: discussion.title, |
138 | | - }, |
139 | | - }; |
140 | | - } |
| 60 | + processEntity: createExpiredEntityHandler({ |
| 61 | + workflowName, |
| 62 | + workflowId, |
| 63 | + runUrl, |
| 64 | + entityNoun: "discussion", |
| 65 | + entityLabel: "Discussion", |
| 66 | + core, |
| 67 | + footerSuffix: "\n\n<!-- gh-aw-closed -->", |
| 68 | + beforeComment: async discussion => { |
| 69 | + core.info(` Checking for existing expiration comment and closed state on discussion #${discussion.number}`); |
| 70 | + const { hasComment, isClosed } = await hasExpirationComment(github, discussion.id); |
| 71 | + |
| 72 | + if (isClosed) { |
| 73 | + core.warning(` Discussion #${discussion.number} is already closed, skipping`); |
| 74 | + return { |
| 75 | + status: "skipped", |
| 76 | + record: createClosedRecord(discussion), |
| 77 | + }; |
| 78 | + } |
141 | 79 |
|
142 | | - const cautionAlert = getExpiredEntityCautionAlert(workflowName, runUrl); |
143 | | - const expirationText = `This discussion was automatically closed because it expired on ${formatDateInProjectTimeZone(discussion.expirationDate) || discussion.expirationDate.toISOString()}.`; |
144 | | - const closingMessage = (cautionAlert ? cautionAlert + "\n\n" : "") + expirationText + generateExpiredEntityFooter(workflowName, runUrl, workflowId) + "\n\n<!-- gh-aw-closed -->"; |
| 80 | + if (hasComment) { |
| 81 | + core.warning(` Discussion #${discussion.number} already has an expiration comment, skipping to avoid duplicate`); |
145 | 82 |
|
146 | | - core.info(` Adding closing comment to discussion #${discussion.number}`); |
147 | | - await addDiscussionComment(github, discussion.id, closingMessage); |
148 | | - core.info(` ✓ Comment added successfully`); |
| 83 | + core.info(` Attempting to close discussion #${discussion.number} without adding another comment`); |
| 84 | + await closeDiscussionAsOutdated(github, discussion.id); |
| 85 | + core.info(` ✓ Discussion closed successfully`); |
149 | 86 |
|
150 | | - core.info(` Closing discussion #${discussion.number} as outdated`); |
151 | | - await closeDiscussionAsOutdated(github, discussion.id); |
152 | | - core.info(` ✓ Discussion closed successfully`); |
| 87 | + return { |
| 88 | + status: "closed", |
| 89 | + record: createClosedRecord(discussion), |
| 90 | + }; |
| 91 | + } |
153 | 92 |
|
154 | | - return { |
155 | | - status: "closed", |
156 | | - record: { |
157 | | - number: discussion.number, |
158 | | - url: discussion.url, |
159 | | - title: discussion.title, |
160 | | - }, |
161 | | - }; |
162 | | - }, |
| 93 | + return undefined; |
| 94 | + }, |
| 95 | + beforeCommentLog: discussion => ` Adding closing comment to discussion #${discussion.number}`, |
| 96 | + beforeCloseLog: discussion => ` Closing discussion #${discussion.number} as outdated`, |
| 97 | + addComment: (discussion, message) => addDiscussionComment(github, discussion.id, message), |
| 98 | + closeEntity: discussion => closeDiscussionAsOutdated(github, discussion.id), |
| 99 | + }), |
163 | 100 | }); |
164 | 101 | } |
165 | 102 |
|
|
0 commit comments