fix(check_membership): skip roles check for allowlisted bots to eliminate spurious permission warning#34064
Conversation
Co-authored-by: pelikhan <[email protected]>
…ssion warning When an actor matches the `bots:` allowlist in `check_membership.cjs`, move the bot-status verification before the repository permission check. This eliminates the spurious "User permission 'none' does not meet requirements: admin, maintainer, write" warning that was previously emitted by `checkRepositoryPermission` even though the bot was subsequently authorized via the bots allowlist. A bot listed in `on.bots:` is an explicit grant; the roles mismatch (bots typically have "none" repo permission) is expected and not actionable. Checking the bots allowlist first avoids the misleading warning entirely. Also remove the now-unnecessary initial permission check call from the existing bots-allowlist tests and add a regression test that asserts the warning is not emitted when `github-actions[bot]` (or any allowlisted bot) triggers the workflow. Co-authored-by: pelikhan <[email protected]>
Co-authored-by: pelikhan <[email protected]>
There was a problem hiding this comment.
Pull request overview
This PR adjusts the pre-activation membership validation flow to avoid emitting a misleading “permission does not meet requirements” warning when an allowlisted bot triggers a workflow, by checking the bot allowlist before performing any repository permission/roles check. It also updates a couple of workflow/action lock artifacts that appear unrelated to the membership-change goal as currently described.
Changes:
- Reordered bot allowlist evaluation in
check_membership.cjsso allowlisted bots go directly to bot-status verification and skip the repository roles/permission check (removing the spurious warning). - Updated
check_membershiptests to reflect the new call order and added a regression test asserting no roles-mismatch warning for allowlisted bots. - Updated workflow/action lockfiles (e.g.,
docker/setup-buildx-actionpin; developer-docs workflow schedule), which should be confirmed as intentional and ideally called out in the PR description.
Show a summary per file
| File | Description |
|---|---|
| actions/setup/js/check_membership.cjs | Moves allowlisted-bot handling ahead of repo permission checks; adjusts bot_not_active output. |
| actions/setup/js/check_membership.test.cjs | Updates mocks for new call ordering; adds regression test for warning suppression. |
| .github/workflows/release.lock.yml | Updates pinned SHA for docker/setup-buildx-action in the release workflow lock. |
| .github/workflows/developer-docs-consolidator.lock.yml | Updates developer-docs consolidator workflow lock (includes schedule change to weekly). |
| .github/aw/actions-lock.json | Adds lock entry for docker/setup-buildx-action@v4 matching the updated workflow pin. |
Copilot's findings
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comments suppressed due to low confidence (1)
.github/workflows/release.lock.yml:1536
- Second occurrence of the
docker/setup-buildx-actionpin update in this workflow lockfile; if the action bump isn’t part of the intended scope of this PR, consider splitting it out so release workflow dependency updates can be reviewed/rolled back independently of the membership logic change.
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4
- name: Log in to GitHub Container Registry
- Files reviewed: 5/5 changed files
- Comments generated: 4
| // Checking bots first also avoids a spurious "permission does not meet requirements" | ||
| // warning that would otherwise be emitted by the roles check before authorization succeeds. | ||
| if (allowedBots.length > 0 && isAllowedBot(actorToValidate, allowedBots)) { | ||
| core.info(`Checking if actor '${actorToValidate}' is in allowed bots list: ${allowedBots.join(", ")}`); |
| schedule: | ||
| - cron: "19 13 * * *" | ||
| # Friendly format: daily (scattered) | ||
| - cron: "19 13 * * 6" | ||
| # Friendly format: weekly (scattered) |
| - name: Setup Docker Buildx (pre-validation) | ||
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 (source v4) | ||
| uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 # v4 | ||
| - name: Build Docker image (validation only) |
| "docker/setup-buildx-action@v4": { | ||
| "repo": "docker/setup-buildx-action", | ||
| "version": "v4", | ||
| "sha": "d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5" | ||
| }, |
| // mismatch (bots typically have "none" repo permission) is expected and not actionable. | ||
| // Checking bots first also avoids a spurious "permission does not meet requirements" | ||
| // warning that would otherwise be emitted by the roles check before authorization succeeds. | ||
| if (allowedBots.length > 0 && isAllowedBot(actorToValidate, allowedBots)) { |
There was a problem hiding this comment.
@copilot refactor to helper function and add more tests
There was a problem hiding this comment.
Done in the latest commit. The inline bot allowlist block in main() is now extracted into a named async helper checkBotAllowlistAuthorization — it returns { handled: true } when a final decision (authorized/denied) is reached and { handled: false } to fall through to the roles check. The helper is also exported for direct testability.
New tests added:
- actor matches the second entry in a multi-bot allowlist
- allowlist entry with
[bot]suffix is equivalent to the slug form bot_not_activeresult explicitly setsuser_permissionto"bot"- non-404 bot-status failure produces
bot_not_active(not a silent roles fallthrough)
Also fixed the log ordering noted in the review: the "matched the allowed bots list" message is now emitted once, after isAllowedBot() confirms the match, instead of the previous two-line log sequence that appeared after the check had already passed.
Extract the inline bot allowlist block from main() into a named async
helper function `checkBotAllowlistAuthorization`. The helper:
- Returns { handled: false } when the allowlist is empty, the actor
does not match, or the bot-status check fails entirely (falls through
to the standard roles check)
- Returns { handled: true } once a final authorization decision is
reached (authorized_bot or bot_not_active)
- Fixes log ordering: "Actor matched the allowed bots list: ..." is
now emitted after the isAllowedBot() match is confirmed (not redundantly
after confirming it again)
Export the helper for direct testability.
New tests added:
- second entry in a multi-bot allowlist is matched
- allowlist entry with [bot] suffix is treated as equivalent to slug
- bot_not_active result explicitly sets user_permission to "bot"
- non-404 bot status failure yields bot_not_active (not a roles fallthrough)
Co-authored-by: pelikhan <[email protected]>
|
@copilot review all comments |
Co-authored-by: pelikhan <[email protected]>
Reviewed all open comments:
|
Co-authored-by: pelikhan <[email protected]>
Fixed in the latest commit — ran Prettier on |
When a bot in the
on.bots:allowlist triggers a workflow,pre_activation/check_membershipwas emitting aUser permission 'none' does not meet requirements: admin, maintainer, writewarning even though activation succeeded — because the roles check ran before the bot allowlist check.Changes
check_membership.cjs: Move the bots allowlist evaluation beforecheckRepositoryPermission. If the actor matches the allowlist, bot-status verification runs immediately andcheckRepositoryPermissionis never called (eliminating the warning). The roles check only runs for actors not in the allowlist. Thebot_not_activepath now unconditionally uses"bot"foruser_permissionsince there is no longer an initial permission-check result to fall back on.check_membership.test.cjs: Remove the now-unnecessary initialgetCollaboratorPermissionLevelmock from all bots-allowlist test cases. Add a regression test asserting nodoes not meet requirementswarning is emitted when an allowlisted bot (e.g.github-actions[bot]) triggers the workflow.Before (two API calls, warning emitted on first):
After (one API call, no warning):