GitHub·6 min read·

Auto-Assigning Reviewers and Labeling Pull Requests

Auto-assign reviewers from a rotating team list and label every PR by what it touches, so review load stays fair and nobody misses a change.

NB

Netbay Cloud Team

Netbay Engineering

On this page

A pull request's review destiny is decided before anyone opens the diff: who gets asked, and what the PR is announced as. Teams that leave both to memory end up with the same two reviewers on every change, labels nobody maintains, and week-long gaps where a documentation change sits unowned. Auto-assignment solves the review side with teams and declared rules, and path-aware labelling solves the announcement side by deriving topics from the diff itself — no human memory required.

Three questions for reviewer selection

Good reviewer selection answers three questions about every PR: who understands this code, who has capacity, and who should be learning it. Rule-based assignment handles the first and the second; rotating randomly handles the third. GitHub lets you request reviews from individuals or teams, and teams are the better unit because a team request can be claimed by whichever member is available. If you want declared rules committed in the repo, the auto-assign action reads a small YAML file and does the rest.

yaml
# .github/auto-assign.yml
addReviewers: true
addAssignees: author
numberOfReviewers: 1
skipKeywords:
  - wip
reviewersByFiles:
  'cmd/api/**':
    - netbay/backend
  'web/**':
    - netbay/frontend
  '**/*.md':
    - netbay/docs

The "reviewersByFiles" map mirrors your ownership layout without hard-blocking merges, which makes it a lighter-weight alternative to mandatory codeowner review. A contributor who only touched README files gets a docs reviewer, and the API maintainers are not paged for a typo.

Labelling PRs by what the diff touches

Labels on a PR are metadata that downstream tooling reads — changelog generation, review queues, dashboards. Deriving them from changed paths is far more reliable than asking a human to keep them fresh. The official labeler action consumes a declarative map and optionally syncs so removed paths remove labels.

yaml
# .github/labeler.yml
api:
  - any: ['cmd/api/**', 'internal/gateway/**']
web:
  - any: ['web/**']
docs:
  - any: ['**/*.md', 'docs/**']
dependencies:
  - any: ['go.mod', 'go.sum', 'package.json', 'Cargo.lock']
workflows:
  - any: ['.github/workflows/**']

# .github/workflows/label-pr.yml
name: label-pr
on:
  pull_request_target:
    types: [opened, synchronize]
permissions:
  pull-requests: write
jobs:
  label:
    runs-on: ubuntu-latest
    if: ${{ github.actor != 'dependabot[bot]' }}
    steps:
      - uses: actions/labeler@v5
        with:
          sync-labels: true

The "pull_request_target" event matters here: it runs against the default branch's workflow definition, so untrusted head-branch edits cannot tamper with your labeling logic. And because "dependencies" is derived from lockfiles changing, your release notes script can trust that label later.

Rotation keeps the queue fair

Rule assignment does not, by itself, stop the two-person trap. Add a rotation on top:

  • Prefer team requests over individuals so the team can self-balance.
  • Review a directory's history before asking: pick the least recently pinged eligible member.
  • Scale requested reviewer count with diff surface, not habit.
  • Respect WIP markers and draft status; nobody reviews a moving target.

A quick distribution check makes the load visible:

bash
# who has reviewed the most merged PRs recently?
gh pr list --state merged --search 'merged:>2026-03-01'   --json reviews --jq '.[].reviews[].author.login'   | sort | uniq -c | sort -rn

When the top line is routinely twice the second line, your rotation is not rotating. Two additions keep the fan-out honest: a pull request touching several owned paths should request more than one reviewer so no single person carries a multi-owner change, and a draft PR should never claim a slot at all, because a moving target only teaches reviewers to wait. Team requests plus a rotation handle both, because a review request is a claim on attention — one contributor at a time, in a fair order.

PR review routing PR diff path detect labeler rules labels api docs deps team rotation least recent wins reviewersByFiles picks the owner team requests self-balance capacity fair load, accurate labels audit with gh pr list --json reviews rule where you can, rotate what rules miss

Signs it is working

You will know auto-assignment is paying off when the chatter changes: no more "can anyone take this?" pings in chat, labels that consistently match the PR's content, and a review distribution that no longer requires a spreadsheet. The second-order win is data — every labelled, assigned PR becomes a record you can mine for cycle time, ownership gaps, and knowledge islands. Watch two numbers specifically: median time from open to first review should trend down as assignment gets smarter, and the share of pull requests sitting unreviewed for more than a day should trend toward zero. If either number stays flat, the assignment map is stale — new paths likely exist that no rule covers, and the fallback reviewer is quietly absorbing everything the reviewersByFiles map was meant to route elsewhere.

Takeaway: teams and declared rules put review requests in the right hands, path-derived labels keep PR metadata honest, and a rotation keeps load even. Apply the same habit to the infrastructure behind your repos — automated review tooling, bots, and mirrors run happily on a Lucknow DC01 VPS from Netbay, deployable in under 60 seconds at netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance