This is an automated email from the ASF dual-hosted git repository.

damccorm pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/beam.git


The following commit(s) were added to refs/heads/master by this push:
     new 5fa6ef8a3b4 [PR Bot] Pause review reminders on draft PRs and update 
Next Action state (#40314)
5fa6ef8a3b4 is described below

commit 5fa6ef8a3b4edf642147aa2550a1990f5fab0425
Author: Danny McCormick <[email protected]>
AuthorDate: Mon Sep 28 15:41:59 2026 +0000

    [PR Bot] Pause review reminders on draft PRs and update Next Action state 
(#40314)
---
 .github/workflows/pr-bot-pr-updates.yml      |  2 +-
 scripts/ci/pr-bot/README.md                  |  6 +++---
 scripts/ci/pr-bot/findPrsNeedingAttention.ts | 15 +++++++++++++-
 scripts/ci/pr-bot/processPrUpdate.ts         | 30 +++++++++++++++++++++++++++-
 scripts/ci/pr-bot/shared/constants.ts        |  1 +
 5 files changed, 48 insertions(+), 6 deletions(-)

diff --git a/.github/workflows/pr-bot-pr-updates.yml 
b/.github/workflows/pr-bot-pr-updates.yml
index dc5ae6672f8..66fab767fd6 100644
--- a/.github/workflows/pr-bot-pr-updates.yml
+++ b/.github/workflows/pr-bot-pr-updates.yml
@@ -16,7 +16,7 @@
 name: pr-bot-pr-updates
 on:
   pull_request_target:
-    types: ["synchronize"] # Synchronize is the action that runs after pushes 
to the user branch
+    types: ["synchronize", "converted_to_draft", "ready_for_review"]
   issue_comment:
     types: [created]
 permissions: read-all
diff --git a/scripts/ci/pr-bot/README.md b/scripts/ci/pr-bot/README.md
index 6c2e944be78..6cb9f0a5fcc 100644
--- a/scripts/ci/pr-bot/README.md
+++ b/scripts/ci/pr-bot/README.md
@@ -35,13 +35,13 @@ The bot consists of three core workflows and a persistent 
state tracking system:
 * Sets `Next Action: Reviewers` label.
 
 ### 2. PR Updates & Commands (`processPrUpdate.ts`)
-* Triggered on PR pushes (`synchronize`) and comments (`issue_comment: 
created`).
-* Shifts attention back to reviewers (`Next Action: Reviewers`) when author 
pushes new commits or posts comments.
+* 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.
 * 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`.
 
 ### 3. Reviewer Reminders & Stale PRs (`findPrsNeedingAttention.ts`)
-* Runs daily to identify PRs needing action.
+* Runs daily to identify PRs needing action (skipping draft PRs, PRs with 
notifications silenced, or PRs labeled `awaiting triage`).
 * Flags PRs awaiting reviewer response as `slow-review` if inactive for ≥ 7 
days (or ≥ 2 weekdays without comments).
 * If still no response after 2 more weekdays, reassigns to new reviewers, 
removes `slow-review`, and adds `reassigned-reviewers`.
 * **Stale PR Cutoff**: If a PR has both `reassigned-reviewers` and `Next 
Action: Reviewers` labels and review started > 60 days ago, it stops reviewer 
assignment loops and adds `awaiting triage`. PRs labeled `awaiting triage` are 
skipped.
diff --git a/scripts/ci/pr-bot/findPrsNeedingAttention.ts 
b/scripts/ci/pr-bot/findPrsNeedingAttention.ts
index 46514671be0..4b1d97201f9 100644
--- a/scripts/ci/pr-bot/findPrsNeedingAttention.ts
+++ b/scripts/ci/pr-bot/findPrsNeedingAttention.ts
@@ -29,6 +29,7 @@ const {
   REASSIGNED_REVIEWERS_LABEL,
   AWAITING_TRIAGE_LABEL,
   NEXT_ACTION_REVIEWERS_LABEL,
+  AUTHOR_ACTION,
 } = require("./shared/constants");
 const { hasLabel } = github;
 const ONE_DAY_MS = 24 * 60 * 60 * 1000;
@@ -165,6 +166,15 @@ async function processPull(
     console.log(`Skipping PR ${pull.number} - awaiting triage`);
     return;
   }
+  if (pull.draft) {
+    if (hasLabel(pull, NEXT_ACTION_REVIEWERS_LABEL)) {
+      await github.nextActionAuthor(pull.number, pull.labels);
+      prState.nextAction = AUTHOR_ACTION;
+      await stateClient.writePrState(pull.number, prState);
+    }
+    console.log(`Skipping PR ${pull.number} - draft`);
+    return;
+  }
 
   const sixtyDaysAgo = new Date(Date.now() - 60 * ONE_DAY_MS);
   const initialReviewDate = prState.reviewersAssignedAt
@@ -187,7 +197,10 @@ async function processPull(
     return;
   }
 
-  if (hasLabel(pull, SLOW_REVIEW_LABEL)) {
+  if (
+    hasLabel(pull, SLOW_REVIEW_LABEL) &&
+    hasLabel(pull, NEXT_ACTION_REVIEWERS_LABEL)
+  ) {
     const lastModified = new Date(pull.updated_at);
     const twoWeekDaysAgo = getTwoWeekdaysAgo();
     console.log(
diff --git a/scripts/ci/pr-bot/processPrUpdate.ts 
b/scripts/ci/pr-bot/processPrUpdate.ts
index 3cfd873f37f..c5b0cf2905b 100644
--- a/scripts/ci/pr-bot/processPrUpdate.ts
+++ b/scripts/ci/pr-bot/processPrUpdate.ts
@@ -22,6 +22,7 @@ const { processCommand } = require("./shared/userCommand");
 const {
   addPrComment,
   getGitHubClient,
+  nextActionAuthor,
   nextActionReviewers,
   getPullAuthorFromPayload,
   getPullNumberFromPayload,
@@ -35,6 +36,7 @@ const {
   REPO,
   SLOW_REVIEW_LABEL,
   REVIEWERS_ACTION,
+  AUTHOR_ACTION,
 } = require("./shared/constants");
 
 // Removes the slow label if the pr has been reviewed and returns an updated 
payload.
@@ -127,13 +129,17 @@ async function processPrComment(
 }
 
 /*
- * On pr push or author comment, we should put the attention set back on the 
reviewers
+ * On pr push, ready_for_review, or author comment, we should put the 
attention set back on the reviewers
  */
 async function setNextActionReviewers(
   payload: any,
   pull: any,
   stateClient: typeof PersistentState
 ) {
+  if (pull.draft) {
+    console.log("PR is a draft, not shifting attention to reviewers");
+    return;
+  }
   if (!(await areReviewersAssigned(pull, stateClient))) {
     console.log("No reviewers assigned, dont need to manipulate attention 
set");
     return;
@@ -146,6 +152,22 @@ async function setNextActionReviewers(
   await stateClient.writePrState(pull.number, prState);
 }
 
+/*
+ * When a PR is marked as draft, set the next action state to Author
+ */
+async function setNextActionAuthor(
+  payload: any,
+  pull: any,
+  stateClient: typeof PersistentState
+) {
+  const existingLabels =
+    pull.labels || payload.issue?.labels || payload.pull_request?.labels;
+  await nextActionAuthor(pull.number, existingLabels);
+  let prState = await stateClient.getPrState(pull.number);
+  prState.nextAction = AUTHOR_ACTION;
+  await stateClient.writePrState(pull.number, prState);
+}
+
 async function processPrUpdate() {
   const reviewerConfig = new ReviewerConfig(PATH_TO_CONFIG_FILE);
   const context = github.context;
@@ -198,6 +220,12 @@ async function processPrUpdate() {
       } else if (payload.action === "review_requested") {
         console.log("Processing review_requested action");
         await setNextActionReviewers(payload, pull, stateClient);
+      } else if (payload.action === "converted_to_draft") {
+        console.log("Processing converted_to_draft action");
+        await setNextActionAuthor(payload, pull, stateClient);
+      } else if (payload.action === "ready_for_review") {
+        console.log("Processing ready_for_review action");
+        await setNextActionReviewers(payload, pull, 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/constants.ts 
b/scripts/ci/pr-bot/shared/constants.ts
index 9b4751b26ab..6f523de0acd 100644
--- a/scripts/ci/pr-bot/shared/constants.ts
+++ b/scripts/ci/pr-bot/shared/constants.ts
@@ -29,6 +29,7 @@ export const PATH_TO_METRICS_CSV = path.resolve(
 );
 export const BOT_NAME = "github-actions";
 export const REVIEWERS_ACTION = "Reviewers";
+export const AUTHOR_ACTION = "Author";
 export const SLOW_REVIEW_LABEL = "slow-review";
 export const NO_MATCHING_LABEL = "no-matching-label";
 export const REASSIGNED_REVIEWERS_LABEL = "reassigned-reviewers";

Reply via email to