This is an automated email from the ASF dual-hosted git repository. derrickaw pushed a commit to branch 20261004_addReviewerFaster in repository https://gitbox.apache.org/repos/asf/beam.git
commit 929d0122a8322a22df92fa76e4cbb7c0d3e5fea7 Author: Derrick Williams <[email protected]> AuthorDate: Sun Oct 4 14:15:03 2026 +0000 assign reviewers immediately when PR is marked ready for review --- scripts/ci/pr-bot/README.md | 1 + scripts/ci/pr-bot/processNewPrs.ts | 15 ++++++++++----- scripts/ci/pr-bot/processPrUpdate.ts | 7 ++++++- scripts/ci/pr-bot/shared/checks.ts | 7 ++++--- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/scripts/ci/pr-bot/README.md b/scripts/ci/pr-bot/README.md index 6cb9f0a5fcc..c5c30e9c5c2 100644 --- a/scripts/ci/pr-bot/README.md +++ b/scripts/ci/pr-bot/README.md @@ -37,6 +37,7 @@ The bot consists of three core workflows and a persistent state tracking system: ### 2. PR Updates & Commands (`processPrUpdate.ts`) * Triggered on PR pushes (`synchronize`), draft transitions (`converted_to_draft`, `ready_for_review`), and comments (`issue_comment: created`). * Shifts attention to author (`Next Action: Author`) when a PR is marked as draft (`converted_to_draft`) and back to reviewers (`Next Action: Reviewers`) when taken out of draft (`ready_for_review`) or when the author pushes new commits or posts comments on a non-draft PR. +* When a PR is marked `ready_for_review` and has no reviewers assigned yet, immediately assigns reviewers if it already has matching reviewer labels and passing CI checks. * Removes `slow-review` label upon receiving a comment from a non-author reviewer. * Processes commands like `assign to next reviewer`, `waiting on author`, `stop reviewer notifications`, `assign set of reviewers`, and `remind me after tests pass`. diff --git a/scripts/ci/pr-bot/processNewPrs.ts b/scripts/ci/pr-bot/processNewPrs.ts index fbcd78a0db8..fff2518fe81 100644 --- a/scripts/ci/pr-bot/processNewPrs.ts +++ b/scripts/ci/pr-bot/processNewPrs.ts @@ -44,7 +44,7 @@ import { CheckStatus } from "./shared/checks"; * unless we're supposed to remind the user after tests pass * (in which case that's all we need to do). */ -function needsProcessed(pull: any, prState: typeof Pr): boolean { +export function needsProcessed(pull: any, prState: typeof Pr): boolean { if (github.hasLabel(pull, AWAITING_TRIAGE_LABEL)) { console.log( `Skipping PR ${pull.number} because it has awaiting triage label` @@ -76,7 +76,10 @@ function needsProcessed(pull: any, prState: typeof Pr): boolean { return false; } let timeCutoff = new Date(new Date().getTime() - 20 * 60000); - if (new Date(pull.created_at) > timeCutoff) { + if ( + (!pull.labels || pull.labels.length === 0) && + new Date(pull.created_at) > timeCutoff + ) { console.log( `Skipping PR ${pull.number} because it was created less than 20 minutes ago` ); @@ -186,7 +189,7 @@ async function isAnyGithubReviewerCommitter(pull: any): Promise<boolean> { return false; } -async function processPull( +export async function processPull( pull: any, reviewerConfig: typeof ReviewerConfig, stateClient: typeof PersistentState @@ -365,7 +368,7 @@ async function processPull( Object.values(prState.reviewersAssignedForLabels) ); - github.nextActionReviewers(pull.number, pull.labels); + await github.nextActionReviewers(pull.number, pull.labels); prState.nextAction = "Reviewers"; prState.reviewersAssignedAt = Date.now(); @@ -397,6 +400,8 @@ async function processNewPrs() { } } -processNewPrs(); +if (require.main === module) { + processNewPrs(); +} export {}; diff --git a/scripts/ci/pr-bot/processPrUpdate.ts b/scripts/ci/pr-bot/processPrUpdate.ts index c5b0cf2905b..96cbffe50d5 100644 --- a/scripts/ci/pr-bot/processPrUpdate.ts +++ b/scripts/ci/pr-bot/processPrUpdate.ts @@ -27,6 +27,7 @@ const { getPullAuthorFromPayload, getPullNumberFromPayload, } = require("./shared/githubUtils"); +const { processPull } = require("./processNewPrs"); const { PersistentState } = require("./shared/persistentState"); const { ReviewerConfig } = require("./shared/reviewerConfig"); const { @@ -225,7 +226,11 @@ async function processPrUpdate() { await setNextActionAuthor(payload, pull, stateClient); } else if (payload.action === "ready_for_review") { console.log("Processing ready_for_review action"); - await setNextActionReviewers(payload, pull, stateClient); + if (await areReviewersAssigned(pull, stateClient)) { + await setNextActionReviewers(payload, pull, stateClient); + } else { + await processPull(pull, reviewerConfig, stateClient); + } } // TODO(damccorm) - it would be good to eventually handle the following events here, even though they're not part of the normal workflow // review requested, assigned, label added, label removed diff --git a/scripts/ci/pr-bot/shared/checks.ts b/scripts/ci/pr-bot/shared/checks.ts index 187ff5771f9..9a43c90daf8 100644 --- a/scripts/ci/pr-bot/shared/checks.ts +++ b/scripts/ci/pr-bot/shared/checks.ts @@ -104,9 +104,10 @@ async function getChecksByName( } // Returns checks we should exclude because they are flaky or not always predictive of pr mergability. -// Currently just excludes codecov. -function shouldExcludeCheck(check): boolean { - if (check.name.toLowerCase().indexOf("codecov") != -1) { +// Currently excludes codecov and the pr-bot update check itself (which may be in_progress when checking status). +export function shouldExcludeCheck(check: { name: string }): boolean { + const name = check.name.toLowerCase(); + if (name.indexOf("codecov") != -1 || name === "process-pr-update") { return true; } return false;
