Skip to content

Commit 6c80dc5

Browse files
ci: Cache maintainer lookups and guard against null users
Cache isMaintainer API results to avoid redundant permission checks when the same users appear across multiple referenced issues. Add null guards for issue.user and comment.user, which GitHub's API returns as null for deleted or suspended accounts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0ab97fe commit 6c80dc5

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

.github/workflows/close-unvetted-pr.yml

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,18 +29,24 @@ jobs:
2929
const prAuthor = pullRequest.user.login;
3030
const contributingUrl = `https://github.com/${repo.owner}/${repo.repo}/blob/master/CONTRIBUTING.md`;
3131
32-
// --- Helper: check if a user has admin or maintain permission on a repo ---
32+
// --- Helper: check if a user has admin or maintain permission on a repo (cached) ---
33+
const maintainerCache = new Map();
3334
async function isMaintainer(owner, repoName, username) {
35+
const key = `${owner}/${repoName}:${username}`;
36+
if (maintainerCache.has(key)) return maintainerCache.get(key);
37+
let result = false;
3438
try {
3539
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
3640
owner,
3741
repo: repoName,
3842
username,
3943
});
40-
return ['admin', 'maintain'].includes(data.permission);
44+
result = ['admin', 'maintain'].includes(data.permission);
4145
} catch {
42-
return false;
46+
// noop — result stays false
4347
}
48+
maintainerCache.set(key, result);
49+
return result;
4450
}
4551
4652
// --- Step 1: Check if PR author is a maintainer (admin or maintain role) ---
@@ -170,17 +176,18 @@ jobs:
170176
});
171177
172178
// Also consider the issue author as a participant (opening the issue is a form of discussion)
179+
// Guard against null user (deleted/suspended GitHub accounts)
173180
const prAuthorParticipated =
174-
issue.user.login === prAuthor ||
175-
comments.some(c => c.user.login === prAuthor);
181+
issue.user?.login === prAuthor ||
182+
comments.some(c => c.user?.login === prAuthor);
176183
177184
let maintainerParticipated = false;
178185
if (prAuthorParticipated) {
179-
// Check each commenter (and issue author) for write+ access on the issue's repo
186+
// Check each commenter (and issue author) for admin/maintain access on the issue's repo
180187
const usersToCheck = new Set();
181-
usersToCheck.add(issue.user.login);
188+
if (issue.user?.login) usersToCheck.add(issue.user.login);
182189
for (const comment of comments) {
183-
if (comment.user.login !== prAuthor) {
190+
if (comment.user?.login && comment.user.login !== prAuthor) {
184191
usersToCheck.add(comment.user.login);
185192
}
186193
}

0 commit comments

Comments
 (0)