Skip to content

Commit e0dd61a

Browse files
authored
fix(gha): updating stale workflow logic (#636)
1 parent 085bc7f commit e0dd61a

2 files changed

Lines changed: 61 additions & 48 deletions

File tree

.github/workflows/label-pr-review-state.yml

Lines changed: 59 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -6,76 +6,89 @@ on:
66
workflow_dispatch:
77

88
permissions:
9-
pull-requests: read
10-
issues: write
9+
pull-requests: write
10+
11+
concurrency:
12+
group: label-pr-review-state
13+
cancel-in-progress: false
1114

1215
jobs:
1316
reconcile:
1417
runs-on: ubuntu-latest
1518
steps:
1619
- name: Reconcile PR review state labels
17-
uses: actions/github-script@v7
20+
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8
1821
with:
1922
script: |
2023
const { owner, repo } = context.repo;
2124
const stateLabels = ['awaiting-author', 'awaiting-review'];
25+
const failures = [];
2226
2327
const prs = await github.paginate(github.rest.pulls.list, {
2428
owner, repo, state: 'open', per_page: 100,
2529
});
2630
2731
for (const pr of prs) {
28-
const reviews = await github.paginate(github.rest.pulls.listReviews, {
29-
owner, repo, pull_number: pr.number, per_page: 100,
30-
});
32+
try {
33+
const reviews = await github.paginate(github.rest.pulls.listReviews, {
34+
owner, repo, pull_number: pr.number, per_page: 100,
35+
});
3136
32-
// Reviews are returned chronologically, so later entries replace
33-
// each reviewer's earlier decision.
34-
const latest = new Map();
35-
for (const r of reviews) {
36-
if (r.state !== 'COMMENTED') {
37-
latest.set(r.user.login, r);
37+
// Reviews are returned chronologically, so later entries replace
38+
// each reviewer's earlier decision.
39+
const latest = new Map();
40+
for (const r of reviews) {
41+
if (r.state !== 'COMMENTED') {
42+
latest.set(r.user.login, r);
43+
}
3844
}
39-
}
4045
41-
const changeRequestReviewers = [...latest.entries()]
42-
.filter(([, review]) => review.state === 'CHANGES_REQUESTED')
43-
.map(([login]) => login);
44-
const requestedReviewers = new Set(
45-
pr.requested_reviewers.map(reviewer => reviewer.login),
46-
);
46+
const changeRequestReviewers = [...latest.entries()]
47+
.filter(([, review]) => review.state === 'CHANGES_REQUESTED')
48+
.map(([login]) => login);
49+
const requestedReviewers = new Set(
50+
pr.requested_reviewers.map(reviewer => reviewer.login),
51+
);
4752
48-
let desiredLabel = null;
49-
if (changeRequestReviewers.length > 0) {
50-
desiredLabel = changeRequestReviewers.every(
51-
reviewer => requestedReviewers.has(reviewer),
52-
)
53-
? 'awaiting-review'
54-
: 'awaiting-author';
55-
}
53+
let desiredLabel = null;
54+
if (changeRequestReviewers.length > 0) {
55+
desiredLabel = changeRequestReviewers.every(
56+
reviewer => requestedReviewers.has(reviewer),
57+
)
58+
? 'awaiting-review'
59+
: 'awaiting-author';
60+
}
5661
57-
const currentLabels = new Set(pr.labels.map(label => label.name));
58-
for (const label of stateLabels) {
59-
if (label !== desiredLabel && currentLabels.has(label)) {
60-
await github.rest.issues.removeLabel({
61-
owner, repo, issue_number: pr.number, name: label,
62+
const currentLabels = new Set(pr.labels.map(label => label.name));
63+
for (const label of stateLabels) {
64+
if (label !== desiredLabel && currentLabels.has(label)) {
65+
await github.rest.issues.removeLabel({
66+
owner, repo, issue_number: pr.number, name: label,
67+
});
68+
}
69+
}
70+
71+
if (desiredLabel && !currentLabels.has(desiredLabel)) {
72+
await github.rest.issues.addLabels({
73+
owner, repo, issue_number: pr.number, labels: [desiredLabel],
6274
});
6375
}
64-
}
6576
66-
if (desiredLabel && !currentLabels.has(desiredLabel)) {
67-
await github.rest.issues.addLabels({
68-
owner, repo, issue_number: pr.number, labels: [desiredLabel],
69-
});
77+
if (
78+
desiredLabel !== 'awaiting-author' &&
79+
currentLabels.has('stale-awaiting-author')
80+
) {
81+
await github.rest.issues.removeLabel({
82+
owner, repo, issue_number: pr.number,
83+
name: 'stale-awaiting-author',
84+
});
85+
}
86+
} catch (error) {
87+
failures.push(`#${pr.number}: ${error.message}`);
88+
core.error(`Failed to reconcile PR #${pr.number}: ${error.message}`);
7089
}
90+
}
7191
72-
if (
73-
desiredLabel !== 'awaiting-author' &&
74-
currentLabels.has('stale-awaiting-author')
75-
) {
76-
await github.rest.issues.removeLabel({
77-
owner, repo, issue_number: pr.number,
78-
name: 'stale-awaiting-author',
79-
});
80-
}
92+
if (failures.length > 0) {
93+
core.setFailed(`Failed to reconcile ${failures.length} PR(s): ${failures.join('; ')}`);
8194
}

.github/workflows/stale.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
name: 60-day inactivity
1515
runs-on: ubuntu-latest
1616
steps:
17-
- uses: actions/stale@v9
17+
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
1818
with:
1919
repo-token: ${{ secrets.GITHUB_TOKEN }}
2020

@@ -38,7 +38,7 @@ jobs:
3838
name: 14-day author inactivity after requested changes
3939
runs-on: ubuntu-latest
4040
steps:
41-
- uses: actions/stale@v9
41+
- uses: actions/stale@5bef64f19d7facfb25b37b414482c7164d639639 # v9
4242
with:
4343
repo-token: ${{ secrets.GITHUB_TOKEN }}
4444

0 commit comments

Comments
 (0)