diff --git a/.github/workflows/assign-pr-reviewer.yml b/.github/workflows/assign-pr-reviewer.yml new file mode 100644 index 0000000..c493127 --- /dev/null +++ b/.github/workflows/assign-pr-reviewer.yml @@ -0,0 +1,44 @@ +name: Assign PR Reviewer + +# Assigns a reviewer and assignee to open PRs that have neither, and DMs them on +# Slack. Logic lives in cm-agents so every repo runs the same code rather than a +# copy that drifts: causematch/cm-agents/actions/pr-review-bot. +# +# Roster and Slack token are organisation-level, so nothing needs configuring here. + +on: + pull_request: + types: [opened, reopened, ready_for_review] + schedule: + # Safety net for anything the pull_request trigger missed. GitHub + # deprioritises schedules on busy repos, so in practice this fires closer to + # hourly than every 15 minutes. + - cron: '*/15 * * * *' + workflow_dispatch: + +concurrency: + # One shared group, not per-PR: a pull_request run and a scheduled sweep must + # serialise against each other, or both can read "needs a reviewer" before + # either has written anything and assign two different people. + group: assign-pr-reviewer + cancel-in-progress: false + +jobs: + assign: + runs-on: ubuntu-24.04 + timeout-minutes: 10 + permissions: + # All three are load-bearing and an explicit block makes every unlisted + # scope `none`: without contents:read the action itself cannot be fetched, + # without issues:write the assignee step fails (assignees live on the + # issues endpoint even for a PR). No test catches a missing scope. + contents: read + issues: write + pull-requests: write + steps: + - uses: causematch/cm-agents/actions/pr-review-bot@master + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + roster: ${{ vars.PR_REVIEWER_ROSTER }} + slack-token: ${{ secrets.SLACK_BOT_TOKEN }} + weekly-target: ${{ vars.PR_REVIEWER_WEEKLY_TARGET }}