| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- 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@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0
- 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;
- const teamAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR'];
- for (const item of items) {
- const isPR = !!item.pull_request;
- const kind = isPR ? 'PR' : 'issue';
- if (teamAssociations.includes(item.author_association)) {
- core.info(`Skipping ${kind} #${item.number}: author association is ${item.author_association}`);
- try {
- await github.rest.issues.removeLabel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: item.number,
- name: 'needs:compliance',
- });
- } catch (e) {}
- continue;
- }
- 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('<!-- issue-compliance -->'));
- 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,
- });
- try {
- await github.rest.issues.removeLabel({
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: item.number,
- name: 'needs:compliance',
- });
- } catch (e) {}
- 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`);
- }
|