mirror of
https://github.com/hwchase17/langchain.git
synced 2026-04-04 11:25:11 +00:00
chore: use repo permissions instead of org membership for maintainer override (#36191)
The `require_issue_link` workflow's maintainer override (reopen PR or remove `missing-issue-link` to bypass enforcement) has never worked. It calls `orgs.getMembershipForUser` to verify the sender is an org member, but `GITHUB_TOKEN` is a GitHub App installation token — not an org member — so the endpoint always returns 403. The catch block only handled 404, so the unhandled 403 crashed the entire job, blocking even the normal issue-link validation from running. ## Changes - Replace `orgs.getMembershipForUser` with `repos.getCollaboratorPermissionLevel` in `senderIsOrgMember()` — checks if the event sender (the user who reopened the PR or removed the label) has write/maintain/admin access on the repo, which works with `GITHUB_TOKEN` and is a better proxy for "maintainer" than org membership
This commit is contained in:
24
.github/workflows/require_issue_link.yml
vendored
24
.github/workflows/require_issue_link.yml
vendored
@@ -74,30 +74,36 @@ jobs:
|
||||
});
|
||||
}
|
||||
|
||||
// ── Helper: check if sender is an active org member ─────────────
|
||||
// ── Helper: check if the user who triggered this event (reopened
|
||||
// the PR / removed the label) has write+ access on the repo ───
|
||||
// Uses the repo collaborator permission endpoint instead of the
|
||||
// org membership endpoint. The org endpoint requires the caller
|
||||
// to be an org member, which GITHUB_TOKEN (an app installation
|
||||
// token) never is — so it always returns 403.
|
||||
async function senderIsOrgMember() {
|
||||
const sender = context.payload.sender?.login;
|
||||
if (!sender) {
|
||||
throw new Error('Event has no sender — cannot check org membership');
|
||||
throw new Error('Event has no sender — cannot check permissions');
|
||||
}
|
||||
try {
|
||||
const { data: membership } = await github.rest.orgs.getMembershipForUser({
|
||||
org: owner,
|
||||
username: sender,
|
||||
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
|
||||
owner, repo, username: sender,
|
||||
});
|
||||
if (membership.state === 'active') {
|
||||
const perm = data.permission;
|
||||
if (['admin', 'maintain', 'write'].includes(perm)) {
|
||||
console.log(`${sender} has ${perm} permission — treating as maintainer`);
|
||||
return { isMember: true, login: sender };
|
||||
}
|
||||
console.log(`${sender} is an org member but state is "${membership.state}"`);
|
||||
console.log(`${sender} has ${perm} permission — not a maintainer`);
|
||||
return { isMember: false, login: sender };
|
||||
} catch (e) {
|
||||
if (e.status === 404) {
|
||||
console.log(`${sender} is not an org member`);
|
||||
console.log(`Cannot check permissions for ${sender} — treating as non-maintainer`);
|
||||
return { isMember: false, login: sender };
|
||||
}
|
||||
const status = e.status ?? 'unknown';
|
||||
throw new Error(
|
||||
`Membership check failed for ${sender} (HTTP ${status}): ${e.message}`,
|
||||
`Permission check failed for ${sender} (HTTP ${status}): ${e.message}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user