-
Notifications
You must be signed in to change notification settings - Fork 642
124 lines (105 loc) · 3.98 KB
/
close-needs-info-issues.yml
File metadata and controls
124 lines (105 loc) · 3.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
name: Close Stale Needs-Info Issues
on:
schedule:
# Run nightly at midnight UTC
- cron: "0 0 * * *"
# Manual trigger for testing
workflow_dispatch:
jobs:
close-stale-needs-info:
name: Close Stale Needs-Info Issues
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Close stale needs-info issues
uses: actions/github-script@v7
with:
script: |
const LABEL = "needs-info";
const BUSINESS_DAYS = 3;
function addBusinessDays(date, days) {
const result = new Date(date);
let added = 0;
while (added < days) {
result.setUTCDate(result.getUTCDate() + 1);
const day = result.getUTCDay();
if (day !== 0 && day !== 6) {
added++;
}
}
return result;
}
// Fetch all open issues with the needs-info label
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
labels: LABEL,
state: "open",
per_page: 100,
});
const now = new Date();
let closedCount = 0;
for (const issue of issues) {
// Skip pull requests (the issues API also returns PRs)
if (issue.pull_request) {
continue;
}
// Find when the needs-info label was most recently applied
const events = await github.paginate(github.rest.issues.listEvents, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
per_page: 100,
});
const labelEvents = events.filter(
(e) =>
e.event === "labeled" &&
e.label?.name === LABEL
);
if (labelEvents.length === 0) {
continue;
}
const lastLabeledAt = new Date(
labelEvents[labelEvents.length - 1].created_at
);
const deadline = addBusinessDays(lastLabeledAt, BUSINESS_DAYS);
if (now < deadline) {
continue;
}
// Check for any comments after the label was applied
const comments = await github.paginate(github.rest.issues.listComments, {
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
since: lastLabeledAt.toISOString(),
per_page: 100,
});
// Filter to comments strictly after the label event
const hasNewComments = comments.some(
(c) => new Date(c.created_at) > lastLabeledAt
);
if (hasNewComments) {
continue;
}
// Close the issue with a comment
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
body:
"This issue has been automatically closed because it was labeled " +
"`needs-info` and received no response for 3 business days. " +
"If you have the requested information, please reply and we will reopen.",
});
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue.number,
state: "closed",
state_reason: "not_planned",
});
closedCount++;
core.info(`Closed issue #${issue.number}: ${issue.title}`);
}
core.info(`Done. Closed ${closedCount} stale needs-info issue(s).`);