-
Notifications
You must be signed in to change notification settings - Fork 1
125 lines (105 loc) · 4.49 KB
/
sync-roadmap-labels.yml
File metadata and controls
125 lines (105 loc) · 4.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
name: Sync roadmap labels
on:
push:
paths:
- docs/roadmaps/SYNAPSE_IMPLEMENTATION_ROADMAP.md
- docs/roadmaps/SYNAPSE_V2_IMPLEMENTATION_ROADMAP.md
- .github/workflows/sync-roadmap-labels.yml
workflow_dispatch:
permissions:
contents: read
issues: write
jobs:
sync-labels:
runs-on: ubuntu-latest
steps:
- name: Sync labels from roadmap
uses: actions/github-script@v9
with:
script: |
const startToken = '<!-- ROADMAP_LABELS:BEGIN -->';
const endToken = '<!-- ROADMAP_LABELS:END -->';
const repoPaths = [
'docs/roadmaps/SYNAPSE_IMPLEMENTATION_ROADMAP.md',
'docs/roadmaps/SYNAPSE_V2_IMPLEMENTATION_ROADMAP.md',
];
const labels = [];
for (const repoPath of repoPaths) {
const file = await github.rest.repos.getContent({
owner: context.repo.owner,
repo: context.repo.repo,
path: repoPath,
});
if (!file.data || !file.data.content) {
throw new Error(`Unable to read ${repoPath}`);
}
const content = Buffer.from(file.data.content, file.data.encoding || 'base64').toString('utf8');
const start = content.indexOf(startToken);
const end = content.indexOf(endToken);
if (start === -1 || end === -1 || end <= start) {
core.info(`No roadmap label block in ${repoPath}; skipping.`);
continue;
}
const labelBlock = content.slice(start + startToken.length, end);
const jsonMatch = labelBlock.match(/```json\s*([\s\S]*?)```/i);
if (!jsonMatch) {
throw new Error(`Roadmap label block in ${repoPath} must contain a JSON code fence.`);
}
const parsed = JSON.parse(jsonMatch[1]);
labels.push(...(Array.isArray(parsed.labels) ? parsed.labels : []));
}
if (labels.length === 0) {
throw new Error('No labels were defined in the roadmap label block.');
}
const existingLabels = await github.paginate(github.rest.issues.listLabelsForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
});
const existingByName = new Map(existingLabels.map((label) => [label.name, label]));
const summary = { created: 0, updated: 0, unchanged: 0 };
for (const label of labels) {
if (!label || typeof label.name !== 'string' || typeof label.color !== 'string') {
throw new Error('Each label must include a string name and color.');
}
const name = label.name.trim();
const color = label.color.replace(/^#/, '').trim().toUpperCase();
const description = typeof label.description === 'string' ? label.description.trim() : '';
const current = existingByName.get(name);
if (!current) {
await github.rest.issues.createLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name,
color,
description,
});
summary.created += 1;
continue;
}
const needsUpdate =
current.color.toUpperCase() !== color ||
(current.description || '') !== description;
if (needsUpdate) {
await github.rest.issues.updateLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name,
new_name: name,
color,
description,
});
summary.updated += 1;
} else {
summary.unchanged += 1;
}
}
core.summary
.addHeading('Roadmap label sync')
.addTable([
[{ data: 'Created', header: true }, { data: String(summary.created), header: false }],
[{ data: 'Updated', header: true }, { data: String(summary.updated), header: false }],
[{ data: 'Unchanged', header: true }, { data: String(summary.unchanged), header: false }],
])
.addRaw(`\nSource files: ${repoPaths.map((path) => `\`${path}\``).join(', ')}`)
.write();