From a14f7afe87cdc267e14406ced66e684c257a443a Mon Sep 17 00:00:00 2001 From: Ben Meadors Date: Wed, 10 Jun 2026 20:04:40 -0500 Subject: [PATCH] fix(workflows): expand trusted author criteria for flasher comments --- .github/workflows/flasher-link-comment.yml | 14 +++++++++----- .github/workflows/flasher-link-placeholder.yml | 8 +++++--- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/.github/workflows/flasher-link-comment.yml b/.github/workflows/flasher-link-comment.yml index ef0cc6e7e..b07d97ba7 100644 --- a/.github/workflows/flasher-link-comment.yml +++ b/.github/workflows/flasher-link-comment.yml @@ -54,12 +54,16 @@ jobs: } const prNumber = pr.number; - // Only comment on PRs authored by members of the organization. - // author_association MEMBER is computed by GitHub and reflects org - // membership (including concealed members); OWNER covers a repo owner. - const allowedAssociations = ['OWNER', 'MEMBER']; + // Restrict to trusted authors. NOTE: author_association is computed for + // the GITHUB_TOKEN, which cannot see *private/concealed* org memberships — + // those members come back as CONTRIBUTOR, not MEMBER. So gating on MEMBER + // alone silently excludes most maintainers. We allow the trusted set the + // token can actually identify (members, collaborators, and anyone with a + // previously merged PR). For strict members-only you'd need an org-read + // App/PAT token to call orgs.checkMembershipForUser. + const allowedAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR', 'CONTRIBUTOR']; if (!allowedAssociations.includes(pr.author_association)) { - core.info(`Author association ${pr.author_association} is not an org member; skipping.`); + core.info(`Author association ${pr.author_association} is not trusted; skipping.`); return; } diff --git a/.github/workflows/flasher-link-placeholder.yml b/.github/workflows/flasher-link-placeholder.yml index 88e66db86..e51a2aad1 100644 --- a/.github/workflows/flasher-link-placeholder.yml +++ b/.github/workflows/flasher-link-placeholder.yml @@ -29,10 +29,12 @@ jobs: const { owner, repo } = context.repo; const pr = context.payload.pull_request; - // Only org members get the flasher comment (matches the real workflow) - const allowedAssociations = ['OWNER', 'MEMBER']; + // Trusted authors only (matches the real workflow). author_association + // can't reflect private org membership for the token, so concealed + // members appear as CONTRIBUTOR — include it, or maintainers are excluded. + const allowedAssociations = ['OWNER', 'MEMBER', 'COLLABORATOR', 'CONTRIBUTOR']; if (!allowedAssociations.includes(pr.author_association)) { - core.info(`Author association ${pr.author_association} is not an org member; skipping.`); + core.info(`Author association ${pr.author_association} is not trusted; skipping.`); return; }