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;

Reply via email to