Add reusable workflow to check external contributor status#78
Add reusable workflow to check external contributor status#78solace-mdupls wants to merge 13 commits intomainfrom
Conversation
Add a new reusable workflow that checks if a PR creator is a member of a specified GitHub team. If the creator is not a member, the workflow automatically adds a configurable label (defaults to "external contributor") to the PR. This workflow enables repositories to easily identify and track external contributions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
✨ PR Review
The workflow contains a critical logic error that defeats its entire purpose: it checks the workflow bot's team membership instead of the PR creator's membership.
2 issues detected:
🐞 Bug - Team membership check targets the workflow bot instead of the PR creator 🛠️
Details: The workflow uses listMembershipsForAuthenticatedUser() which checks the authenticated bot token's team memberships, not the PR creator's. This means the workflow will never correctly identify external contributors since it's checking the wrong user's membership status.
File:.github/workflows/check-external-contributor.yml (33-39)
🛠️ A suggested code correction is included in the review comments.🐞 Bug - Required secret GITHUB_TOKEN is defined but not passed to actions that need it
Details: The workflow declares GITHUB_TOKEN as a required secret but never passes it to the github-script actions via the github-token parameter. Both actions will use the default token instead, which may lack necessary org:read permissions for team membership checks. This same issue exists at line 47 for the second github-script action.
File:.github/workflows/check-external-contributor.yml
Generated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Review using Guidelines Learn how
| const { data: teams } = await github.rest.teams.listMembershipsForAuthenticatedUser(); | ||
| const teamSlugs = teams.map(team => team.slug); | ||
| const teamSlug = '${{ inputs.github_team_slug }}'; | ||
|
|
||
| const isMember = teamSlugs.includes(teamSlug); | ||
| console.log(`Looking for team: ${teamSlug}`); | ||
| console.log(`User's teams: ${teamSlugs.join(', ')}`); |
There was a problem hiding this comment.
🐞 Bug - Wrong User Checked: Replace the API call with one that checks the PR creator's team membership. Get the PR creator from context.payload.pull_request.user.login and use github.rest.teams.getMembershipForUserInOrg() with the repository's organization (context.repo.owner), team_slug, and the PR creator's username.
| const { data: teams } = await github.rest.teams.listMembershipsForAuthenticatedUser(); | |
| const teamSlugs = teams.map(team => team.slug); | |
| const teamSlug = '${{ inputs.github_team_slug }}'; | |
| const isMember = teamSlugs.includes(teamSlug); | |
| console.log(`Looking for team: ${teamSlug}`); | |
| console.log(`User's teams: ${teamSlugs.join(', ')}`); | |
| const prCreator = context.payload.pull_request.user.login; | |
| const teamSlug = '${{ inputs.github_team_slug }}'; | |
| const org = context.repo.owner; | |
| let isMember = false; | |
| try { | |
| await github.rest.teams.getMembershipForUserInOrg({ | |
| org: org, | |
| team_slug: teamSlug, | |
| username: prCreator | |
| }); | |
| isMember = true; | |
| } catch (error) { | |
| if (error.status === 404) { | |
| isMember = false; | |
| } else { | |
| throw error; | |
| } | |
| } | |
| console.log(`PR Creator: ${prCreator}`); | |
| console.log(`Looking for team: ${teamSlug}`); |
Is this review accurate? Use 👍 or 👎 to rate it
If you want to tell us more, use /gs feedback e.g. /gs feedback this review doesn't make sense, I disagree, and it keeps repeating over and over
|
Please mark whether you used Copilot to assist coding in this PR
|
Add a new GitHub Action that checks if a PR creator is a member of a specified GitHub team. If the creator is not a member, the action automatically adds a configurable label (defaults to 'external contributor') to the PR. This action enables repositories to easily identify and track external contributions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the check-external-contributor workflow since we've converted it to a reusable GitHub Action (.github/actions/check-external-contributor) which provides better modularity and consistency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace gh CLI calls with github-script action to ensure proper GitHub API permissions for adding labels to issues. This resolves 'Resource not accessible by integration' errors. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move team membership check to github-script to use consistent authentication context. Add error handling to gracefully handle permission issues - defaults to treating users as external contributors if membership cannot be verified. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…andling" This reverts commit 94b4caf.
…ermissions" This reverts commit fdedc15.
…permissions" This reverts commit 19dd374.
… proper permissions"" This reverts commit fdf1dea.
…handling" This reverts commit 472a5cc.
Use github-script for adding labels to ensure proper authentication and permissions. This fixes the 'Resource not accessible by integration' error. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Consolidate action structure by moving check-external-contributor from .github/actions/ to root-level alongside other actions. Add comprehensive README.md for documentation.
| if (error.status === 404) { | ||
| core.setOutput('is_member', 'false'); | ||
| console.log(`⚠️ PR creator is not a member of the team`); | ||
| } else { | ||
| console.log(`⚠️ Could not verify team membership (${error.message}), assuming external contributor`); | ||
| core.setOutput('is_member', 'false'); | ||
| } |
There was a problem hiding this comment.
@johnvincentcorpuz when running this with pull_request_target and testing with a PR using my internal solace-mdupls github account which is part of the solace-ai team, I get a 404 and the resulting "PR creator is not a member of the team". Does the github token I use as part of this workflow have the necessary permissions to read team membership?
Note that I have tried @clarkbains suggestion here to use pull_request_target instead of pull_request, but I cannot seem to trigger the workflow on PRs from external contributors (in this case my personal Github): SolaceLabs/solace-agent-mesh#1120
See thread with Clark: https://solacedotcom.slack.com/archives/C084S3XTD8S/p1772498735212189?thread_ts=1772496075.926289&cid=C084S3XTD8S and used
Summary
Test Plan
🤖 Generated with Claude Code
✨ PR Description
What is the purpose of this change?
Add a reusable GitHub Actions workflow to automatically detect and label pull requests from external contributors who are not members of a specified GitHub team, enabling better visibility and differentiated review processes for external contributions.
How is this accomplished?
check-external-contributor.yml) that can be called from other workflows with configurable inputs for team slug and label nameactions/github-script@v7.0.1(SHA: 60a0d83039c74a4aee543508d2ffcb1c3799cdea) for secure execution of membership checks and label applicationpull-requests: writepermission scope to allow label modificationsAnything reviews should focus on/be aware of?
GITHUB_TOKENsecret to be passed from the calling workflow, which needs sufficient permissions to read team memberships and write PR labelslistMembershipsForAuthenticatedUser()API which retrieves teams for the authenticated user (the actor triggering the workflow), not the PR creator - this may need verification to ensure it checks the correct user's membershipGenerated by LinearB AI and added by gitStream.
AI-generated content may contain inaccuracies. Please verify before using.
💡 Tip: You can customize your AI Description using Guidelines Learn how