Skip to content

Commit c2acab2

Browse files
committed
ci: automate issue labels and milestones via GitHub Actions
1 parent e9ba5a0 commit c2acab2

File tree

3 files changed

+124
-1
lines changed

3 files changed

+124
-1
lines changed
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
name: Bootstrap Project Metadata
2+
3+
on:
4+
workflow_dispatch:
5+
push:
6+
branches: [main]
7+
paths:
8+
- ".github/workflows/bootstrap-project.yml"
9+
10+
permissions:
11+
contents: read
12+
issues: write
13+
pull-requests: write
14+
15+
jobs:
16+
labels-and-milestones:
17+
runs-on: ubuntu-latest
18+
steps:
19+
- name: Sync labels and milestones
20+
uses: actions/github-script@v7
21+
with:
22+
script: |
23+
const owner = context.repo.owner;
24+
const repo = context.repo.repo;
25+
26+
const labels = [
27+
{ name: "bug", color: "d73a4a", description: "Something is not working" },
28+
{ name: "enhancement", color: "a2eeef", description: "New feature or request" },
29+
{ name: "task", color: "cfd3d7", description: "Implementation or maintenance task" },
30+
{ name: "documentation", color: "0075ca", description: "Documentation improvements" },
31+
{ name: "ci", color: "5319e7", description: "CI/CD related work" },
32+
{ name: "good first issue", color: "7057ff", description: "Good for new contributors" },
33+
{ name: "help wanted", color: "008672", description: "Extra attention is needed" },
34+
{ name: "priority:high", color: "b60205", description: "High priority" },
35+
{ name: "priority:medium", color: "d93f0b", description: "Medium priority" },
36+
{ name: "priority:low", color: "fbca04", description: "Low priority" },
37+
{ name: "version:v0.1.0", color: "1d76db", description: "Planned for v0.1.0" },
38+
{ name: "version:v0.2.0", color: "1d76db", description: "Planned for v0.2.0" },
39+
{ name: "version:v1.0.0", color: "1d76db", description: "Planned for v1.0.0" },
40+
{ name: "version:v1.0.2", color: "1d76db", description: "Planned for v1.0.2" }
41+
];
42+
43+
const milestones = [
44+
{
45+
title: "v0.1.0",
46+
description: "Initial public cleaner release",
47+
due_on: "2026-03-15T00:00:00Z"
48+
},
49+
{
50+
title: "v0.2.0",
51+
description: "GitHub automation and quality iteration",
52+
due_on: "2026-04-15T00:00:00Z"
53+
},
54+
{
55+
title: "v1.0.0",
56+
description: "Stable release",
57+
due_on: "2026-06-01T00:00:00Z"
58+
},
59+
{
60+
title: "v1.0.2",
61+
description: "Public GitHub metadata and docs polish",
62+
due_on: "2026-06-10T00:00:00Z"
63+
}
64+
];
65+
66+
const existingLabels = await github.paginate(
67+
github.rest.issues.listLabelsForRepo,
68+
{ owner, repo, per_page: 100 }
69+
);
70+
const labelMap = new Map(existingLabels.map((l) => [l.name, l]));
71+
72+
for (const label of labels) {
73+
if (labelMap.has(label.name)) {
74+
await github.rest.issues.updateLabel({
75+
owner,
76+
repo,
77+
name: label.name,
78+
color: label.color,
79+
description: label.description
80+
});
81+
} else {
82+
await github.rest.issues.createLabel({
83+
owner,
84+
repo,
85+
name: label.name,
86+
color: label.color,
87+
description: label.description
88+
});
89+
}
90+
}
91+
92+
const existingMilestones = await github.paginate(
93+
github.rest.issues.listMilestones,
94+
{ owner, repo, state: "all", per_page: 100 }
95+
);
96+
const milestoneMap = new Map(existingMilestones.map((m) => [m.title, m]));
97+
98+
for (const milestone of milestones) {
99+
if (milestoneMap.has(milestone.title)) {
100+
const existing = milestoneMap.get(milestone.title);
101+
await github.rest.issues.updateMilestone({
102+
owner,
103+
repo,
104+
milestone_number: existing.number,
105+
title: milestone.title,
106+
description: milestone.description,
107+
due_on: milestone.due_on,
108+
state: "open"
109+
});
110+
} else {
111+
await github.rest.issues.createMilestone({
112+
owner,
113+
repo,
114+
title: milestone.title,
115+
description: milestone.description,
116+
due_on: milestone.due_on
117+
});
118+
}
119+
}

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ gh auth login
7777
./scripts/bootstrap_github_labels.sh
7878
```
7979

80+
Or run the GitHub Action: `Bootstrap Project Metadata` to create labels and milestones automatically.
81+
8082
## GitHub Setup
8183

8284
See `docs/GITHUB_PUBLISH_GUIDE.md` for:

docs/GITHUB_PUBLISH_GUIDE.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ In GitHub repository settings:
3333

3434
## 4. Bootstrap labels and milestones
3535

36-
Requires GitHub CLI (`gh`) and authentication:
36+
Preferred: run GitHub Action `Bootstrap Project Metadata` from the Actions tab.
37+
38+
Alternative with GitHub CLI (`gh`):
3739

3840
```bash
3941
gh auth login

0 commit comments

Comments
 (0)