name: compliance-close on: schedule: # Run every 30 minutes to check for expired compliance windows - cron: "*/30 * * * *" workflow_dispatch: permissions: contents: read issues: write pull-requests: write jobs: close-non-compliant: runs-on: ubuntu-latest steps: - name: Close non-compliant issues and PRs after 2 hours uses: actions/github-script@v7 with: script: | const { data: items } = await github.rest.issues.listForRepo({ owner: context.repo.owner, repo: context.repo.repo, labels: 'needs:compliance', state: 'open', per_page: 100, }); if (items.length === 0) { core.info('No open issues/PRs with needs:compliance label'); return; } const now = Date.now(); const twoHours = 2 * 60 * 60 * 1000; for (const item of items) { const isPR = !!item.pull_request; const kind = isPR ? 'PR' : 'issue'; const { data: comments } = await github.rest.issues.listComments({ owner: context.repo.owner, repo: context.repo.repo, issue_number: item.number, }); const complianceComment = comments.find(c => c.body.includes('')); if (!complianceComment) continue; const commentAge = now - new Date(complianceComment.created_at).getTime(); if (commentAge < twoHours) { core.info(`${kind} #${item.number} still within 2-hour window (${Math.round(commentAge / 60000)}m elapsed)`); continue; } const closeMessage = isPR ? 'This pull request has been automatically closed because it was not updated to meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) within the 2-hour window.\n\nFeel free to open a new pull request that follows our guidelines.' : 'This issue has been automatically closed because it was not updated to meet our [contributing guidelines](../blob/dev/CONTRIBUTING.md) within the 2-hour window.\n\nFeel free to open a new issue that follows our issue templates.'; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: item.number, body: closeMessage, }); if (isPR) { await github.rest.pulls.update({ owner: context.repo.owner, repo: context.repo.repo, pull_number: item.number, state: 'closed', }); } else { await github.rest.issues.update({ owner: context.repo.owner, repo: context.repo.repo, issue_number: item.number, state: 'closed', state_reason: 'not_planned', }); } core.info(`Closed non-compliant ${kind} #${item.number} after 2-hour window`); }