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";