diff --git a/.github/workflows/issue-pr-reminder.yaml b/.github/workflows/issue-pr-reminder.yaml new file mode 100644 index 00000000..b7b4f696 --- /dev/null +++ b/.github/workflows/issue-pr-reminder.yaml @@ -0,0 +1,101 @@ +name: Issue PR Reminder + +on: + schedule: + - cron: '0 * * * *' # Runs every hour, at the start of each hour + workflow_dispatch: + +jobs: + issue-reminder: + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v7 + env: + INTERVAL_HOURS: ${{ vars.CREATE_REMINDER_AFTER_HOURS }} + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const owner = "keyshade-xyz"; + const repo = "keyshade"; + const createReminderAfterHours = process.env.CREATE_REMINDER_AFTER_HOURS || 48; + const now = Date.now(); + + async function listOpenIssuesWithoutPR() { + const allIssues = []; + let page = 1; + let hasNextPage = true; + + while (hasNextPage) { + const issuesResponse = await github.rest.issues.listForRepo({ + owner, + repo, + state: "open", + per_page: 100, + page + }); + + const issuesWithoutPR = issuesResponse.data.filter(issue => !issue.pull_request); + + allIssues.push(...issuesWithoutPR); + + hasNextPage = issues.headers.link && issues.headers.link.includes('rel="next"'); + page++; + } + + return allIssues; + } + + async function listIssueComments(issue) { + const allComments = []; + let page = 1; + let hasNextPage = true; + + while (hasNextPage) { + const issuesResponse = await github.rest.issues.listComments({ + owner, + repo, + issue_number: issue.number, + per_page: 100, + page + }); + + allComments.push(...issuesResponse.data); + + hasNextPage = issues.headers.link && issues.headers.link.includes('rel="next"'); + page++; + } + + return allIssues; + } + + const issues = await listOpenIssuesWithoutPR(); + + issues.forEach(issue => { + const issueCreatedAt = new Date(issue.created_at); + const createReminderAfter = issueCreatedAt.setHours(issueCreatedAt.getHours() + createReminderAfterHours); + + // Check if it's time to create the reminder + if(now < createReminderAfter) { + return; + } + + // Create reminder for each assignee + const comments = await listIssueComments(issue); + + issue.assignees.forEach(assignee => { + const reminder = `@${assignee.login}, please open a draft PR linking this issue!`; + + // Check if the issue already has the reminder + if(comments.some(comment => comment.body === reminder)) { + return; + } + + // Create the reminder + await github.rest.issues.createComment({ + owner, + repo, + issue_number: issue.number, + body: reminder + }); + }); + }); \ No newline at end of file