diff --git a/README.md b/README.md index a609d64..12f0acf 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,11 @@ The script will also lock issues and pull requests that have been closed for 3 months. If the issue was commented on in the last two weeks, a comment will be posted suggesting opening a new issue to continue the discussion. +### Maintainer commands + +The script can execute some actions like updating a PR's branch if requested by +a maintainer through a `giteabot/*` label. + ## Usage Set the following environment variables: diff --git a/src/labels.ts b/src/labels.ts index 01b70fd..dd1a425 100644 --- a/src/labels.ts +++ b/src/labels.ts @@ -12,7 +12,8 @@ import { debounce } from "https://deno.land/std@0.189.0/async/mod.ts"; // manage backports or any other label that causes the bot to act on // detection, such as reviewed/* or backport/* export const isRelevantLabel = (label: string): boolean => { - return label.startsWith("reviewed/") || label.startsWith("backport/"); + return label.startsWith("reviewed/") || label.startsWith("backport/") || + label.startsWith("giteabot/"); }; const maintain = async () => { diff --git a/src/mergeQueue.ts b/src/mergeQueue.ts index 5da7c7f..c036fee 100644 --- a/src/mergeQueue.ts +++ b/src/mergeQueue.ts @@ -1,10 +1,5 @@ -import { - addComment, - fetchPendingMerge, - needsUpdate, - removeLabel, - updatePr, -} from "./github.ts"; +import { fetchPendingMerge, removeLabel } from "./github.ts"; +import * as prActions from "./prActions.ts"; import { debounce } from "https://deno.land/std@0.189.0/async/mod.ts"; const updateBranch = async () => { @@ -13,31 +8,12 @@ const updateBranch = async () => { // update all PRs pending merge (only if they need an update) for (const pr of pendingMerge.items) { - if (!await needsUpdate(pr.number)) continue; - const response = await updatePr(pr.number); - if (response.ok) { - console.info(`Synced PR #${pr.number} in merge queue`); - continue; - } + const err = await prActions.updateBranch(pr); - const body = await response.json(); - if (body.message !== "merge conflict between base and head") { - console.error(`Failed to sync PR #${pr.number} in merge queue`); - console.error(JSON.stringify(body)); - continue; + if (err?.message == "merge conflicts in PR") { + // if there is a merge conflict, we'll remove the reviewed/wait-merge label + await removeLabel(pr.number, "reviewed/wait-merge"); } - - console.info( - `Merge conflict detected in PR #${pr.number} in merge queue`, - ); - // if there is a merge conflict, we'll add a comment to fix the conflicts and remove the reviewed/wait-merge label - await Promise.all([ - addComment( - pr.number, - `@${pr.user.login} please fix the merge conflicts. :tea:`, - ), - removeLabel(pr.number, "reviewed/wait-merge"), - ]); } }; diff --git a/src/prActions.ts b/src/prActions.ts new file mode 100644 index 0000000..2f3ed60 --- /dev/null +++ b/src/prActions.ts @@ -0,0 +1,45 @@ +import { addComment, needsUpdate, removeLabel, updatePr } from "./github.ts"; +import { debounce } from "https://deno.land/std@0.189.0/async/mod.ts"; + +const execute = async ( + label: string, + pr: { number: number; user: { login: string } }, +) => { + if (label === "giteabot/update-branch") { + await updateBranch(pr); + await removeLabel(pr.number, "giteabot/update-branch"); + } +}; + +export const updateBranch = async ( + pr: { number: number; user: { login: string } }, +) => { + if (await needsUpdate(pr.number)) { + const response = await updatePr(pr.number); + if (response.ok) { + console.info(`Synced PR #${pr.number}`); + return; + } + + const body = await response.json(); + if (body.message !== "merge conflict between base and head") { + console.error( + `Failed to sync PR #${pr.number}`, + ); + console.error(JSON.stringify(body)); + } + + console.info( + `Merge conflict detected in PR #${pr.number}`, + ); + // if there is a merge conflict, we'll add a comment to fix the conflicts + await addComment( + pr.number, + `@${pr.user.login} please fix the merge conflicts. :tea:`, + ); + return Error("merge conflicts in PR"); + } +}; + +// make sure we don't trigger too often +export const run = debounce(execute, 8000); diff --git a/src/webhook.ts b/src/webhook.ts index 96baaf4..7926ffa 100644 --- a/src/webhook.ts +++ b/src/webhook.ts @@ -8,6 +8,7 @@ import * as milestones from "./milestones.ts"; import * as lgtm from "./lgtm.ts"; import * as comments from "./comments.ts"; import * as lock from "./lock.ts"; +import * as prActions from "./prActions.ts"; const secret = Deno.env.get("BACKPORTER_GITHUB_SECRET"); @@ -45,6 +46,7 @@ webhook.on( if (labels.isRelevantLabel(payload.label.name)) { labels.run(); mergeQueue.run(); + prActions.run(payload.label.name, payload.pull_request); } }, );