Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
110 changes: 92 additions & 18 deletions actions/setup/js/close_expired_discussions.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,39 @@ async function closeDiscussionAsOutdated(github, discussionId) {
return result.closeDiscussion.discussion;
}

/**
* Check if a discussion already has an expiration comment
* @param {any} github - GitHub GraphQL instance
* @param {string} discussionId - Discussion node ID
* @returns {Promise<boolean>} True if expiration comment exists
*/
async function hasExpirationComment(github, discussionId) {
const result = await github.graphql(
`
query($dId: ID!) {
node(id: $dId) {
... on Discussion {
comments(first: 100) {
nodes {
body
}
}
}
}
}`,
{ dId: discussionId }
);

if (!result || !result.node || !result.node.comments) {
return false;
}

const comments = result.node.comments.nodes || [];
const expirationCommentPattern = /<!--\s*gh-aw-closed\s*-->/;

return comments.some(comment => comment.body && expirationCommentPattern.test(comment.body));
}

async function main() {
const owner = context.repo.owner;
const repo = context.repo.repo;
Expand Down Expand Up @@ -281,31 +314,61 @@ async function main() {
const closedDiscussions = [];
const failedDiscussions = [];

let skippedCount = 0;
const skippedDiscussions = [];

for (let i = 0; i < discussionsToClose.length; i++) {
const discussion = discussionsToClose[i];

core.info(`[${i + 1}/${discussionsToClose.length}] Processing discussion #${discussion.number}: ${discussion.url}`);

try {
const closingMessage = `This discussion was automatically closed because it expired on ${discussion.expirationDate.toISOString()}.`;

// Add comment first
core.info(` Adding closing comment to discussion #${discussion.number}`);
await addDiscussionComment(github, discussion.id, closingMessage);
core.info(` ✓ Comment added successfully`);

// Then close the discussion as outdated
core.info(` Closing discussion #${discussion.number} as outdated`);
await closeDiscussionAsOutdated(github, discussion.id);
core.info(` ✓ Discussion closed successfully`);

closedDiscussions.push({
number: discussion.number,
url: discussion.url,
title: discussion.title,
});
// Check if an expiration comment already exists
core.info(` Checking for existing expiration comment on discussion #${discussion.number}`);
const hasComment = await hasExpirationComment(github, discussion.id);

if (hasComment) {
core.warning(` Discussion #${discussion.number} already has an expiration comment, skipping to avoid duplicate`);
skippedDiscussions.push({
number: discussion.number,
url: discussion.url,
title: discussion.title,
});
skippedCount++;

// Still try to close it if it's somehow still open
core.info(` Attempting to close discussion #${discussion.number} without adding another comment`);
await closeDiscussionAsOutdated(github, discussion.id);
core.info(` ✓ Discussion closed successfully`);

closedDiscussions.push({
number: discussion.number,
url: discussion.url,
title: discussion.title,
});
closedCount++;
} else {
const closingMessage = `This discussion was automatically closed because it expired on ${discussion.expirationDate.toISOString()}.\n\n<!-- gh-aw-closed -->`;

// Add comment first
core.info(` Adding closing comment to discussion #${discussion.number}`);
await addDiscussionComment(github, discussion.id, closingMessage);
core.info(` ✓ Comment added successfully`);

// Then close the discussion as outdated
core.info(` Closing discussion #${discussion.number} as outdated`);
await closeDiscussionAsOutdated(github, discussion.id);
core.info(` ✓ Discussion closed successfully`);

closedDiscussions.push({
number: discussion.number,
url: discussion.url,
title: discussion.title,
});

closedCount++;
}

closedCount++;
core.info(`✓ Successfully processed discussion #${discussion.number}: ${discussion.url}`);
} catch (error) {
core.error(`✗ Failed to close discussion #${discussion.number}: ${getErrorMessage(error)}`);
Expand Down Expand Up @@ -336,6 +399,9 @@ async function main() {

summaryContent += `**Closing Summary**\n`;
summaryContent += `- Successfully closed: ${closedCount} discussion(s)\n`;
if (skippedCount > 0) {
summaryContent += `- Skipped (already had comment): ${skippedCount} discussion(s)\n`;
}
if (failedDiscussions.length > 0) {
summaryContent += `- Failed to close: ${failedDiscussions.length} discussion(s)\n`;
}
Expand All @@ -352,6 +418,14 @@ async function main() {
summaryContent += `\n`;
}

if (skippedCount > 0) {
summaryContent += `### Skipped (Already Had Comment)\n\n`;
for (const skipped of skippedDiscussions) {
summaryContent += `- Discussion #${skipped.number}: [${skipped.title}](${skipped.url})\n`;
}
summaryContent += `\n`;
}

if (failedDiscussions.length > 0) {
summaryContent += `### Failed to Close\n\n`;
for (const failed of failedDiscussions) {
Expand Down
Loading