Skip to content

Commit 9a16a19

Browse files
.github/workflows: add awaiting-user-response.yml
Introduce the workflow to handle the AwaitingUserResponse label that will help clean up stale issues. The intended workflow is as follows: - when a presumably stale issue requires input from the user, it is manually labeled with AwaitingUserResponse; - if this issue is not updated within 90 days, it is closed automatically; - if it is updated, the label is automatically removed. For testing purposes, the update deadline is currently set to two hours (so please do not use AwaitingUserResponse yet!)
1 parent b59dcb8 commit 9a16a19

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
name: Handle AwaitingUserResponse
2+
3+
on:
4+
issues:
5+
types: [labeled]
6+
issue_comment:
7+
types: [created]
8+
schedule:
9+
- cron: '*/15 * * * *' # TODO(glider): change to '0 0 * * *' once we finish testing.
10+
11+
jobs:
12+
handle-awaiting-user-response:
13+
runs-on: ubuntu-latest
14+
15+
steps:
16+
- name: Checkout code
17+
uses: actions/checkout@v3
18+
19+
- name: Handle Issues and Comments
20+
if: github.event_name == 'issues' && github.event.action == 'labeled' || github.event_name == 'issue_comment'
21+
uses: actions/github-script@v6
22+
with:
23+
github-token: ${{ secrets.GITHUB_TOKEN }}
24+
script: |
25+
const { owner, repo, number } = context.issue;
26+
27+
if (context.event_name === 'issues' && context.payload.action === 'labeled') {
28+
const labelName = context.payload.label.name;
29+
30+
if (labelName === 'AwaitingUserResponse') {
31+
// Add a comment notifying the user.
32+
await github.rest.issues.createComment({
33+
owner,
34+
repo,
35+
issue_number: number,
36+
body: 'We are awaiting your response. If we do not hear back from you within 90 days, this issue will be automatically closed.'
37+
});
38+
}
39+
} else if (context.event_name === 'issue_comment') {
40+
const issue = context.payload.issue;
41+
42+
// Check if the "AwaitingUserResponse" label is present.
43+
const labels = issue.labels.map(label => label.name);
44+
if (labels.includes('AwaitingUserResponse')) {
45+
// Remove the label.
46+
await github.rest.issues.removeLabel({
47+
owner,
48+
repo,
49+
issue_number: number,
50+
name: 'AwaitingUserResponse'
51+
});
52+
}
53+
}
54+
55+
- name: Handle Scheduled Cleanup
56+
if: github.event_name == 'schedule'
57+
uses: actions/github-script@v6
58+
with:
59+
github-token: ${{ secrets.GITHUB_TOKEN }}
60+
script: |
61+
const { owner, repo } = context.repo;
62+
63+
// Fetch all open issues with the "AwaitingUserResponse" label.
64+
const issues = await github.paginate(github.rest.issues.listForRepo, {
65+
owner,
66+
repo,
67+
state: 'open',
68+
labels: 'AwaitingUserResponse',
69+
per_page: 100
70+
});
71+
72+
const now = new Date();
73+
74+
for (const issue of issues) {
75+
const timelineEvents = await github.paginate(github.rest.issues.listEventsForTimeline, {
76+
owner,
77+
repo,
78+
issue_number: issue.number,
79+
per_page: 100
80+
});
81+
82+
// Find the latest labeled event for "AwaitingUserResponse".
83+
const labeledEvents = timelineEvents.filter(event =>
84+
event.event === 'labeled' && event.label.name === 'AwaitingUserResponse'
85+
);
86+
87+
if (labeledEvents.length > 0) {
88+
const latestLabelEvent = labeledEvents.reduce((latest, event) =>
89+
new Date(event.created_at) > new Date(latest.created_at) ? event : latest
90+
);
91+
92+
const labelAppliedAt = new Date(latestLabelEvent.created_at);
93+
// TODO(glider): use diffDays instead of diffHours once we finish testing.
94+
// const diffDays = (now - labelAppliedAt) / (1000 * 60 * 60 * 24);
95+
const diffHours = (now - labelAppliedAt) / (1000 * 60 * 60);
96+
97+
//if (diffDays > 90) {
98+
if (diffHours > 2) {
99+
// Close the issue.
100+
await github.rest.issues.update({
101+
owner,
102+
repo,
103+
issue_number: issue.number,
104+
state: 'closed'
105+
});
106+
107+
// Add a comment notifying the user.
108+
await github.rest.issues.createComment({
109+
owner,
110+
repo,
111+
issue_number: issue.number,
112+
body: 'This issue has been automatically closed as it has been marked "AwaitingUserResponse" for more than 90 days with no activity.'
113+
});
114+
}
115+
}
116+
}
117+

0 commit comments

Comments
 (0)