Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 67 additions & 0 deletions .github/workflows/pr-assign-reviewer.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
name: Assign PR Reviewer (round-robin)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

broader q: is there any prior art you were able to find in your research? Does the strands team have anything?

I'm wondering about what happens if the assigned reviewer isn't available (PTO), or busy with another project. Also is there a clear path to overriding the assigned reviewer here if I want someone else to review?

Also wondering if a no-code solution might be simpler. For example, on-call responsible for external PR review for their week, or we delegate these are part of sprint work.


# Auto-assigns one reviewer to each new external PR, so community contributions

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there ideas in the comment here that we don't feel like are expressed clearly below in the implementation, if so why?

# have a named, accountable reviewer instead of sitting in a shared queue. PRs
# authored by someone in AUTHORIZED_USERS are left unassigned. That same list is
# the reviewer pool, so there is no separate roster to maintain.
#
# Uses pull_request_target (same rationale as pr-size.yml): a fork PR's default
# token is read-only and cannot request reviewers, so we need the base-repo token.
# Safe because this workflow ONLY reads PR metadata and assigns a reviewer — it
# never checks out or executes untrusted PR code.
on:
pull_request_target:
types: [opened, ready_for_review]
branches: [main, feat/**]

jobs:
assign-reviewer:
# Skip drafts — assign when a PR is actually ready for review.
if: github.event.pull_request.draft == false
runs-on: codebuild-agentcore-e2e-${{ github.run_id }}-${{ github.run_attempt }}
permissions:
pull-requests: write
steps:
- name: Assign a round-robin reviewer from AUTHORIZED_USERS
uses: actions/github-script@v9
env:
AUTHORIZED_USERS: ${{ secrets.AUTHORIZED_USERS }}
with:
script: |
const pr = context.payload.pull_request;
const { owner, repo } = context.repo;
const author = pr.user.login;
const pool = (process.env.AUTHORIZED_USERS || '')
.split(',')
.map(login => login.trim())
.filter(Boolean)
.sort();

if (pool.length === 0) {
console.log('No reviewers configured in AUTHORIZED_USERS.');
return;
}

// Only external contributions need automatic reviewer assignment.
if (pool.some(login => login.toLowerCase() === author.toLowerCase())) {
console.log(`${author} is in AUTHORIZED_USERS; leaving the PR unassigned.`);
return;
}

// Don't re-assign if a reviewer was already requested (e.g. manual, or a re-run).
if ((pr.requested_reviewers?.length ?? 0) > 0 || (pr.requested_teams?.length ?? 0) > 0) {
console.log('Reviewer(s) already requested; leaving as-is.');
return;
}

// Stateless round-robin: PR number modulo pool size. Deterministic, no state
// file to keep in sync, and spreads load evenly as PR numbers increase.
const reviewer = pool[pr.number % pool.length];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clever :)

console.log(`Requesting review from ${reviewer} (pool of ${pool.length}, author ${author}).`);

await github.rest.pulls.requestReviewers({
owner,
repo,
pull_number: pr.number,
reviewers: [reviewer],
});
Loading