From 4a4d95241adcaa2621de9fccd25bfc364f1be1d9 Mon Sep 17 00:00:00 2001
From: Nemanja Glumac <31325167+nemanjaglumac@users.noreply.github.com>
Date: Mon, 4 Mar 2024 20:29:55 +0100
Subject: [PATCH] Add the ability to copy required checks from `master` to any
 existing branch (#38873)

* Add the ability to copy required checks from `master` to any existing branch

* tweaks to release check copy script

---------

Co-authored-by: Ryan Laurie <iethree@gmail.com>
---
 release/README.md              | 11 ++++++
 release/package.json           |  1 +
 release/src/required-checks.ts | 64 ++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+)
 create mode 100644 release/src/required-checks.ts

diff --git a/release/README.md b/release/README.md
index b3ed32e7464..f73c28985bf 100644
--- a/release/README.md
+++ b/release/README.md
@@ -60,3 +60,14 @@ In case you want to preview release notes generation, or re-generate them after
 ```sh
 yarn release-offline v0.77.0 1234567890abcdef1234567890abcdef12345678  --changelog > changelog.log
 ```
+
+## Required checks copy
+
+When we cut a new release branch, we want to clone the current set of required checks from master. Over time, we add and remove test suites for master, but we want to keep each release branch consistent with the state of master at the time it was cut. To do this, we can run the following command after cutting a new release branch:
+
+```sh
+yarn copy-required-checks release-x.{version}.x
+```
+
+> [!important]
+> This will overwrite existing checks if they already exist
diff --git a/release/package.json b/release/package.json
index 43bbe02b724..385f5d8b5b6 100644
--- a/release/package.json
+++ b/release/package.json
@@ -11,6 +11,7 @@
     "build": "esbuild src/index.ts --bundle --outfile=dist/index.cjs --platform=node --target=node16",
     "prettier": "prettier --write",
     "release-offline": "tsx release-offline.ts",
+    "copy-required-checks": "tsx ./src/required-checks.ts",
     "test:unit": "jest --testPathPattern unit",
     "test:integration": "jest --testPathPattern integration"
   },
diff --git a/release/src/required-checks.ts b/release/src/required-checks.ts
new file mode 100644
index 00000000000..0da68fd7313
--- /dev/null
+++ b/release/src/required-checks.ts
@@ -0,0 +1,64 @@
+import "dotenv/config";
+import { Octokit } from "@octokit/rest";
+import "zx/globals";
+$.verbose = false;
+
+const { GITHUB_TOKEN, GITHUB_OWNER, GITHUB_REPO } = process.env;
+
+const github = new Octokit({ auth: GITHUB_TOKEN });
+
+const config = {
+  owner: GITHUB_OWNER || "",
+  repo: GITHUB_REPO || "",
+};
+
+const targetBranch = process.argv[2];
+
+if (!targetBranch) {
+  console.error(chalk.red("You must provide a target branch name"));
+  console.log("Usage: ", chalk.blue("yarn copy-required-checks <branch-to-copy-to>"));
+  process.exit(1);
+}
+
+function filterChecks(checks: string[]) {
+  const checksToExclude = ["Decide whether to backport or not"];
+  return checks.filter(check => !checksToExclude.includes(check));
+}
+
+async function setRequiredChecks(branchName: string, masterCheckList: string[]) {
+  await github.rest.repos.updateBranchProtection({
+    ...config,
+    branch: branchName,
+    required_status_checks: {
+      strict: false,
+      contexts: masterCheckList,
+    },
+    restrictions: null,
+    required_pull_request_reviews: null,
+    enforce_admins: true,
+  });
+
+  console.log(chalk.green(`✅ ${masterCheckList.length} required checks copied to ${branchName}`));
+}
+
+async function getRequiredChecksFromMaster() {
+  const { data: masterCheckList } = await github.rest.repos.getAllStatusCheckContexts({
+    ...config,
+    branch: "master",
+  });
+
+  const filteredCheckList = filterChecks(masterCheckList);
+
+  return filteredCheckList;
+}
+
+async function copyRequiredChecksToBranch(branchName: string) {
+  const masterCheckList = await getRequiredChecksFromMaster();
+
+  await setRequiredChecks(branchName, masterCheckList);
+}
+
+copyRequiredChecksToBranch(targetBranch).catch(e => {
+  console.error(e);
+  process.exit(1);
+});
-- 
GitLab