diff --git a/.github/workflows/vouch-check.yml b/.github/workflows/vouch-check.yml index 8cd3e0ad..b03a26d7 100644 --- a/.github/workflows/vouch-check.yml +++ b/.github/workflows/vouch-check.yml @@ -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.