diff --git a/.github/workflows/close-stale-needs-more-info.yml b/.github/workflows/close-stale-needs-more-info.yml new file mode 100644 index 000000000..941d43e6e --- /dev/null +++ b/.github/workflows/close-stale-needs-more-info.yml @@ -0,0 +1,92 @@ +name: 'Close Issues with Stale Needs More Info Label' + +on: + schedule: + # Run this workflow at 00:00 every day + - cron: '0 0 * * *' + workflow_dispatch: + +permissions: + issues: write + contents: read + +jobs: + close-stale-issues: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Close Stale Issues with Needs More Info Label and Comment + uses: actions/github-script@v6 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const labelName = 'needs-more-info'; + const excludedLabel = 'enhancement'; + const staleDays = 14; + const closingComment = "This issue has been automatically closed due to inactivity and having the 'needs-more-info' label for more than 14 days. If the issue still persists, please reopen the issue with the requested information."; + const currentDate = new Date(); + const staleDaysInMilliseconds = staleDays * 24 * 60 * 60 * 1000; + + // Fetch all open issues with 'needs-more-info' label + const issues = await github.paginate(github.rest.issues.listForRepo, { + owner: context.repo.owner, + repo: context.repo.repo, + labels: labelName, + state: 'open', + }); + + for (const issue of issues) { + // Skip if the issue has 'enhancement' label + const labels = issue.labels.map(label => label.name); + if (labels.includes(excludedLabel)) { + continue; + } + + let labelAddedDate = null; + + // Fetch events for the issue to find when the label was added + const events = await github.paginate(github.rest.issues.listEvents, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + }); + + // Look for the event where the label was added and capture the date + for (const event of events) { + if (event.event === 'labeled' && event.label.name === labelName) { + labelAddedDate = new Date(event.created_at); + break; + } + } + + if (labelAddedDate) { + const issueUpdatedDate = new Date(issue.updated_at); + const labelAddedTime = labelAddedDate.getTime(); + const issueUpdatedTime = issueUpdatedDate.getTime(); + const diffTime = currentDate.getTime() - labelAddedTime; + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + + // Check if the issue was not updated after the label was added and if it has been more than 'staleDays' since the label was added + if (issueUpdatedTime <= labelAddedTime && diffDays > staleDays) { + // Post a closing comment before closing the issue + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + body: closingComment, + }); + + // Close the issue + await github.rest.issues.update({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issue.number, + state: 'closed', + }); + + console.log(`Issue #${issue.number} has been closed with a comment as it has had the '${labelName}' label for more than ${staleDays} days and was not updated since the label was applied.`); + } + } + } diff --git a/.github/workflows/remove-needs-more-info.yml b/.github/workflows/remove-needs-more-info.yml new file mode 100644 index 000000000..5f491a275 --- /dev/null +++ b/.github/workflows/remove-needs-more-info.yml @@ -0,0 +1,76 @@ +name: 'Remove Needs More Info Label' + +on: + issue_comment: + types: [created] + +permissions: + issues: write + contents: read + +jobs: + debug-and-remove-label: + runs-on: ubuntu-latest + if: github.event.issue.pull_request == null # Ensure it runs only for issue comments + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Remove "needs-more-info" Label and Comment + uses: actions/github-script@v6 + with: + github-token: ${{secrets.GITHUB_TOKEN}} + script: | + const issue = context.payload.issue; + const user = context.payload.sender; + + // Check if the comment was made by the issue creator + if (issue.user.login === user.login) { + const issueNumber = issue.number; + const labelName = 'needs-more-info'; + let labelAddedByUser = ''; + + // Find who added the 'needs-more-info' label + for await (const response of github.paginate.iterator(github.rest.issues.listEvents, { + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + })) { + const events = response.data; + const labelEvent = events.find(event => event.event === 'labeled' && event.label.name === labelName); + if (labelEvent) { + labelAddedByUser = labelEvent.actor.login; + break; // Stop at the most recent event that added the label + } + } + + // Get all labels for the issue + const { data: labels } = await github.rest.issues.listLabelsOnIssue({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + }); + + // Check if the issue has the specific label + if (labels.some(label => label.name === labelName)) { + // Remove the label + await github.rest.issues.removeLabel({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + name: labelName, + }); + + // If someone added the label, comment and tag that user + if (labelAddedByUser) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: issueNumber, + body: `@${labelAddedByUser}, the '${labelName}' label has been removed upon receiving further response from the original bug filer.`, + }); + } + + console.log(`Label "${labelName}" removed from issue #${issueNumber}.`); + } + }