diff --git a/README.md b/README.md index 55dd48d..4fc3466 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,11 @@ has passed since they were updated. The script can execute some actions like updating a PR's branch if requested by a maintainer through a `giteabot/*` label. +### Last call + +The script will close PRs with the label `pr/last-call` if two weeks have passed +since they were updated. + ## Usage Set the following environment variables: diff --git a/src/github.ts b/src/github.ts index 12d662c..373f654 100644 --- a/src/github.ts +++ b/src/github.ts @@ -53,6 +53,19 @@ export const fetchOpenIssuesWithLabel = async (label: string) => { return json; }; +// returns a list of open PRs with the given label +export const fetchOpenPrsWithLabel = async (label: string) => { + const response = await fetch( + `${GITHUB_API}/search/issues?q=` + + encodeURIComponent( + `is:pr is:open label:${label} repo:go-gitea/gitea`, + ), + { headers: HEADERS }, + ); + const json = await response.json(); + return json; +}; + // returns a list of PRs pending merge (have the label reviewed/wait-merge) export const fetchPendingMerge = async () => { const response = await fetch( @@ -502,3 +515,16 @@ export const closeIssue = async (issueNumber: number) => { ); return response.json(); }; + +// closes the given PR +export const closePr = async (prNumber: number) => { + const response = await fetch( + `${GITHUB_API}/repos/go-gitea/gitea/pulls/${prNumber}`, + { + method: "PATCH", + headers: HEADERS, + body: JSON.stringify({ state: "closed" }), + }, + ); + return response.json(); +}; diff --git a/src/lastCall.ts b/src/lastCall.ts new file mode 100644 index 0000000..cab9c53 --- /dev/null +++ b/src/lastCall.ts @@ -0,0 +1,28 @@ +import { addComment, closePr, fetchOpenPrsWithLabel } from "./github.ts"; + +export const run = async () => { + // get all issues with the label "pr/last-call" + const issuesWithStatusPrLastCall = await fetchOpenPrsWithLabel( + "pr/last-call", + ); + return Promise.all(issuesWithStatusPrLastCall.items.map(handlePr)); +}; + +// close PR if two weeks have passed since it was last updated +const handlePr = async (pr: { + number: number; + updated_at: string; +}) => { + const twoWeeksAgo = (new Date(Date.now() - 1000 * 60 * 60 * 24 * 14)) + .getTime(); + if ((new Date(pr.updated_at)).getTime() < twoWeeksAgo) { + console.log(`Closing PR #${pr.number} due to pr/last-call timeout`); + await addComment( + pr.number, + "This pull request has not had any activity in the past two weeks and is in https://github.com/go-gitea/gitea/labels/pr%2Flast-call state. Therefore, [it is politely refused](https://github.com/go-gitea/gitea/blob/main/CONTRIBUTING.md#final-call). :tea:", + ); + + // close PR + await closePr(pr.number); + } +}; diff --git a/src/webhook.ts b/src/webhook.ts index 91322bd..426d269 100644 --- a/src/webhook.ts +++ b/src/webhook.ts @@ -10,6 +10,7 @@ import * as comments from "./comments.ts"; import * as lock from "./lock.ts"; import * as prActions from "./prActions.ts"; import * as feedback from "./feedback.ts"; +import * as lastCall from "./lastCall.ts"; const secret = Deno.env.get("BACKPORTER_GITHUB_SECRET"); @@ -32,11 +33,12 @@ webhook.on("push", ({ payload }) => { backport.run(); } - // we should take this opportunity to run the label, merge queue, lock, and feedback maintenance + // we should take this opportunity to run the label, merge queue, lock, feedback, and last call maintenance labels.run(); mergeQueue.run(); lock.run(); feedback.run(); + lastCall.run(); }); // on pull request labeling events, run the label and merge queue maintenance