mirror of
https://github.com/NVIDIA/OpenShell.git
synced 2026-10-30 07:33:59 +08:00
fix(ci): fetch author_association via REST API instead of webhook payload (#444)
The webhook payload field context.payload.pull_request.author_association is unreliable under pull_request_target events — it was absent or not populated, causing the previous fix (#442) to still fail. Switch to fetching author_association via pulls.get REST API, which only needs pull-requests permission (already granted) and reliably returns MEMBER for org members regardless of membership visibility. Also removes the redundant orgs.checkMembershipForUser and repos.checkCollaborator fallbacks, which suffered from the same GITHUB_TOKEN permission limitation that started this bug. Co-authored-by: John Myers <johntmyers@users.noreply.github.com>
This commit is contained in:
co-authored by
John Myers
parent
240d0ee3ed
commit
85a3d83d75
@@ -19,7 +19,6 @@ jobs:
|
||||
script: |
|
||||
const author = context.payload.pull_request.user.login;
|
||||
const authorType = context.payload.pull_request.user.type;
|
||||
const authorAssociation = context.payload.pull_request.author_association;
|
||||
|
||||
// Skip bots (dependabot, renovate, github-actions, etc.).
|
||||
if (authorType === 'Bot') {
|
||||
@@ -27,48 +26,27 @@ jobs:
|
||||
return;
|
||||
}
|
||||
|
||||
// Check author_association from the webhook payload. This is set by
|
||||
// GitHub itself and doesn't require extra token permissions, so it
|
||||
// works reliably for org members even when their membership is private.
|
||||
// Fetch author_association via the REST API. The webhook payload
|
||||
// field (context.payload.pull_request.author_association) is
|
||||
// unreliable under pull_request_target — it can be absent or stale.
|
||||
// The pulls.get endpoint only needs pull-requests permission, which
|
||||
// we already have, and reliably returns MEMBER for org members even
|
||||
// when their membership is private.
|
||||
const trustedAssociations = ['MEMBER', 'OWNER', 'COLLABORATOR'];
|
||||
if (trustedAssociations.includes(authorAssociation)) {
|
||||
console.log(`${author} has author_association=${authorAssociation}. Skipping vouch check.`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback: explicit API checks in case author_association is unexpected.
|
||||
|
||||
// Check org membership — members bypass the vouch gate.
|
||||
try {
|
||||
const { status } = await github.rest.orgs.checkMembershipForUser({
|
||||
org: context.repo.owner,
|
||||
username: author,
|
||||
});
|
||||
if (status === 204 || status === 302) {
|
||||
console.log(`${author} is an org member (API). Skipping vouch check.`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.status !== 404) {
|
||||
console.log(`Org membership check error: ${e.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Check collaborator status — direct collaborators bypass.
|
||||
try {
|
||||
const { status } = await github.rest.repos.checkCollaborator({
|
||||
const { data: pr } = await github.rest.pulls.get({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
username: author,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
});
|
||||
if (status === 204) {
|
||||
console.log(`${author} is a collaborator (API). Skipping vouch check.`);
|
||||
const association = pr.author_association;
|
||||
console.log(`${author}: author_association=${association}`);
|
||||
if (trustedAssociations.includes(association)) {
|
||||
console.log(`${author} has author_association=${association}. Skipping vouch check.`);
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
if (e.status !== 404) {
|
||||
console.log(`Collaborator check error: ${e.message}`);
|
||||
}
|
||||
console.log(`Failed to fetch PR author_association: ${e.message}`);
|
||||
}
|
||||
|
||||
// Check the VOUCHED.td file on the dedicated "vouched" branch.
|
||||
|
||||
Reference in New Issue
Block a user