Skip to content

Commit fc5f663

Browse files
ci: auto cleanup migrate/ branches
1 parent 4b575c9 commit fc5f663

File tree

3 files changed

+147
-1
lines changed

3 files changed

+147
-1
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Cleanup Migrate Branches
2+
3+
on:
4+
schedule:
5+
- cron: '0 0 * * *'
6+
workflow_dispatch:
7+
8+
jobs:
9+
cleanup:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
pull-requests: read
14+
steps:
15+
- name: Checkout repository
16+
uses: actions/checkout@v6
17+
with:
18+
fetch-depth: 0
19+
token: ${{ secrets.GITHUB_TOKEN }}
20+
21+
- name: Setup Node.js
22+
uses: actions/setup-node@v6
23+
with:
24+
node-version: "22"
25+
cache: "npm"
26+
27+
- name: Install dependencies
28+
run: npm ci
29+
30+
- name: Run cleanup script
31+
env:
32+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33+
GITHUB_REPOSITORY_OWNER: ${{ github.repository_owner }}
34+
GITHUB_REPOSITORY: ${{ github.repository }}
35+
run: npm run cleanup-branches

migrate/cleanup-branches.ts

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
import { Octokit } from "@octokit/rest";
2+
import { execSync } from "child_process";
3+
4+
const GITHUB_TOKEN = process.env.GITHUB_TOKEN;
5+
const REPO_OWNER = process.env.GITHUB_REPOSITORY_OWNER || "owner";
6+
const REPO_NAME = process.env.GITHUB_REPOSITORY?.split("/")[1] || "cppdoc";
7+
8+
if (!GITHUB_TOKEN) {
9+
console.error("Missing GITHUB_TOKEN");
10+
process.exit(1);
11+
}
12+
13+
const octokit = new Octokit({ auth: GITHUB_TOKEN });
14+
15+
async function getAllOpenPRs() {
16+
const prs = [];
17+
let page = 1;
18+
const perPage = 100;
19+
20+
while (true) {
21+
const { data } = await octokit.pulls.list({
22+
owner: REPO_OWNER,
23+
repo: REPO_NAME,
24+
state: "open",
25+
per_page: perPage,
26+
page,
27+
});
28+
if (data.length === 0) break;
29+
prs.push(...data);
30+
if (data.length < perPage) break;
31+
page++;
32+
}
33+
34+
console.log(`Found ${prs.length} open PRs`);
35+
return prs;
36+
}
37+
38+
async function getAllBranches() {
39+
const branches = [];
40+
let page = 1;
41+
const perPage = 100;
42+
43+
while (true) {
44+
const { data } = await octokit.repos.listBranches({
45+
owner: REPO_OWNER,
46+
repo: REPO_NAME,
47+
per_page: perPage,
48+
page,
49+
});
50+
if (data.length === 0) break;
51+
branches.push(...data);
52+
if (data.length < perPage) break;
53+
page++;
54+
}
55+
56+
console.log(`Found ${branches.length} branches`);
57+
return branches;
58+
}
59+
60+
function filterMigrateBranches(branches: { name: string }[]) {
61+
return branches.filter((b) => b.name.startsWith("migrate/"));
62+
}
63+
64+
async function deleteBranch(branchName: string) {
65+
try {
66+
await octokit.git.deleteRef({
67+
owner: REPO_OWNER,
68+
repo: REPO_NAME,
69+
ref: `heads/${branchName}`,
70+
});
71+
console.log(`Deleted remote branch ${branchName}`);
72+
} catch (error) {
73+
console.error(`Failed to delete branch ${branchName}:`, error);
74+
}
75+
}
76+
77+
async function main() {
78+
console.log("Starting cleanup of migrate branches without open PRs...");
79+
80+
const [prs, branches] = await Promise.all([
81+
getAllOpenPRs(),
82+
getAllBranches(),
83+
]);
84+
85+
const prBranchNames = new Set(prs.map((pr) => pr.head.ref));
86+
console.log("PR branches:", Array.from(prBranchNames));
87+
88+
const migrateBranches = filterMigrateBranches(branches);
89+
console.log("Migrate branches:", migrateBranches.map(b => b.name));
90+
91+
const toDelete = migrateBranches.filter(b => !prBranchNames.has(b.name));
92+
console.log(`Found ${toDelete.length} branches to delete:`);
93+
toDelete.forEach(b => console.log(` - ${b.name}`));
94+
95+
if (toDelete.length === 0) {
96+
console.log("No branches to delete.");
97+
return;
98+
}
99+
100+
for (const branch of toDelete) {
101+
await deleteBranch(branch.name);
102+
}
103+
104+
console.log("Cleanup completed.");
105+
}
106+
107+
main().catch((err) => {
108+
console.error(err);
109+
process.exit(1);
110+
});

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
"preview": "astro preview",
1010
"astro": "astro",
1111
"format": "prettier --write .",
12-
"migrate": "tsx ./migrate/migrate-bot.ts"
12+
"migrate": "tsx ./migrate/migrate-bot.ts",
13+
"cleanup-branches": "tsx ./migrate/cleanup-branches.ts"
1314
},
1415
"dependencies": {
1516
"@astrojs/starlight": "^0.36.2",

0 commit comments

Comments
 (0)