Skip to content

Commit f0f191d

Browse files
committed
update readMe
1 parent 2b7379a commit f0f191d

1 file changed

Lines changed: 181 additions & 83 deletions

File tree

README.md

Lines changed: 181 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -1,139 +1,237 @@
11
# Label Sync
22

3-
This repository is a standalone source of truth for GitHub labels.
3+
This repository is a standalone GitHub label management repo for an organization.
44

5-
It stores:
5+
Its job is to:
66

7-
- The canonical label definitions in `config/labels.json`
8-
- The repository blacklist in `config/repositories.json`
9-
- A reusable sync script in `scripts/sync-labels.mjs`
10-
- GitHub Actions workflows to validate config and apply label changes
7+
- keep this repo's label config in sync with the labels currently defined on the repo
8+
- validate config changes automatically
9+
- sync the resulting label set across the rest of the organization
1110

12-
## What This Repo Does
11+
## How It Works
1312

14-
When the sync workflow runs, it:
13+
This repo uses three workflows:
1514

16-
1. Reads the label definitions from `config/labels.json`
17-
2. Discovers every repository in the organization that owns this repo
18-
3. Excludes any repositories listed in `config/repositories.json`
19-
4. Creates any missing labels in each remaining repository
20-
5. Updates label colors and descriptions when they drift
21-
6. Optionally deletes labels that are no longer in the config
15+
1. `Config-Label_Sync`
16+
2. `Validate-Configs`
17+
3. `Org-Label-Sync`
2218

23-
By default, it only creates and updates labels. Deletion is opt-in.
19+
The normal flow is:
20+
21+
1. You run `Org-Label-Sync` manually.
22+
2. It first calls `Config-Label_Sync`.
23+
3. `Config-Label_Sync` reads the labels on this repository and rewrites `config/labels.jsonc` so the file matches the repo's current managed labels.
24+
4. If that file changed, `Config-Label_Sync` commits and pushes the update.
25+
5. That config change triggers `Validate-Configs`.
26+
6. `Org-Label-Sync` then checks out the latest default branch, validates the config again, and syncs labels across the organization.
2427

2528
## Repository Layout
2629

2730
```text
2831
.
2932
|-- .github/
3033
| `-- workflows/
31-
| |-- sync-labels.yml
32-
| `-- validate-config.yml
34+
| |-- config-label-sync.yml
35+
| |-- org-label-sync.yml
36+
| `-- validate-configs.yml
3337
|-- config/
34-
| |-- labels.json
35-
| `-- repositories.json
38+
| |-- auto-pruned-labels.jsonc
39+
| |-- blacklisted-repositories.jsonc
40+
| |-- labels.jsonc
41+
| `-- properties.jsonc
3642
`-- scripts/
37-
`-- sync-labels.mjs
43+
|-- export-properties.mjs
44+
|-- sync-config-labels.mjs
45+
|-- sync-labels.mjs
46+
`-- lib/
47+
`-- config-utils.mjs
3848
```
3949

40-
## Initial Setup
50+
## Config Files
51+
52+
All config files live under `config/` and use `jsonc`, so they can include commented examples at the top.
53+
54+
### `config/properties.jsonc`
55+
56+
This is the general admin config for values that will differ between forks.
57+
58+
Fields:
4159

42-
1. Fork or clone this repository for the organization that will own the label definitions.
43-
2. Add a repository secret named `LABEL_SYNC_TOKEN`.
44-
3. Give that token access to every repository in the organization you want to manage.
45-
4. Update `config/repositories.json` with any repositories you want to exclude.
46-
5. Update `config/labels.json` with your organization's canonical labels.
47-
6. Run the `Validate Config` workflow or open a pull request.
48-
7. Run the `Sync Labels` workflow manually once to confirm the result.
60+
- `organization`: the GitHub organization to sync
61+
- `labelSyncTokenSecretName`: the name of the GitHub Actions secret containing the sync token
62+
- `sourceRepository`: the repo whose labels are treated as the source for `Config-Label_Sync`
63+
- `deleteMissingByDefault`: whether org sync should delete labels that are neither managed nor auto-pruned
4964

50-
## Token Guidance
65+
Example:
5166

52-
Use either:
67+
```jsonc
68+
{
69+
"organization": "your-org-name",
70+
"labelSyncTokenSecretName": "LABEL_SYNC_TOKEN",
71+
"sourceRepository": "your-org-name/label-sync",
72+
"deleteMissingByDefault": false
73+
}
74+
```
5375

54-
- A fine-grained personal access token with access to the target repositories
55-
- A GitHub App installation token surfaced to this workflow by a separate auth step
76+
### `config/labels.jsonc`
5677

57-
This starter repo is wired for a repository secret named `LABEL_SYNC_TOKEN`.
78+
This is the managed label set that gets created or updated across the org.
5879

59-
## Configuration
80+
It is normally maintained automatically by `Config-Label_Sync`, based on the labels currently present on this repository after excluding auto-pruned labels.
6081

61-
### `config/labels.json`
82+
Each label object uses:
6283

63-
This file contains the labels you want everywhere.
84+
- `name`
85+
- `color`
86+
- `description`
6487

65-
```json
88+
Example:
89+
90+
```jsonc
6691
[
6792
{
68-
"name": "bug",
69-
"color": "d73a4a",
70-
"description": "Something is not working"
93+
"name": "priority: high",
94+
"color": "b60205",
95+
"description": "Top-priority work"
7196
}
7297
]
7398
```
7499

75-
Rules:
100+
### `config/auto-pruned-labels.jsonc`
76101

77-
- `name` is required
78-
- `color` is required and should be a 6-character hex value
79-
- `description` is optional
102+
This is the list of labels that should always be removed from synced repositories.
80103

81-
### `config/repositories.json`
104+
The starter file is prefilled with GitHub's default labels:
82105

83-
This file contains the repository blacklist and the global delete behavior.
106+
- `bug`
107+
- `documentation`
108+
- `duplicate`
109+
- `enhancement`
110+
- `good first issue`
111+
- `help wanted`
112+
- `invalid`
113+
- `question`
114+
- `wontfix`
84115

85-
```json
86-
{
87-
"deleteMissing": false,
88-
"blacklist": [
89-
"sandbox-repo",
90-
"octo-org/do-not-touch"
91-
]
92-
}
93-
```
116+
If any of those labels exist on this repo, `Config-Label_Sync` excludes them from `labels.jsonc`. If they exist on target repos, `Org-Label-Sync` deletes them.
117+
118+
### `config/blacklisted-repositories.jsonc`
119+
120+
This is the repo blacklist for org sync.
121+
122+
By default, `Org-Label-Sync` targets every repo in the configured organization. Any repo listed here is skipped.
94123

95-
Notes:
124+
Entries can be either:
96125

97-
- `deleteMissing` applies to every non-blacklisted repository
98-
- Blacklist entries can be either `repo-name` or `owner/repo-name`
99-
- The org name is discovered from the workflow repository owner
100-
- The workflow dispatch input can temporarily force deletion for a run
126+
- `repo-name`
127+
- `owner/repo-name`
128+
129+
Example:
130+
131+
```jsonc
132+
[
133+
"sandbox-repo",
134+
"your-org-name/private-internal-tools"
135+
]
136+
```
101137

102138
## Workflows
103139

104-
### `Validate Config`
140+
### `Config-Label_Sync`
141+
142+
File: `.github/workflows/config-label-sync.yml`
143+
144+
Trigger:
145+
146+
- manual via `workflow_dispatch`
147+
- callable from other workflows via `workflow_call`
148+
149+
What it does:
150+
151+
1. Checks out the default branch
152+
2. Loads shared settings from `config/properties.jsonc`
153+
3. Reads the current labels on the source repository
154+
4. Removes any labels listed in `config/auto-pruned-labels.jsonc`
155+
5. Rewrites `config/labels.jsonc` so it exactly matches the remaining labels
156+
6. Commits and pushes the change if the config was updated
157+
158+
This workflow is the bridge between "the labels on this repo right now" and "the managed config we sync elsewhere."
159+
160+
### `Validate-Configs`
161+
162+
File: `.github/workflows/validate-configs.yml`
163+
164+
Trigger:
105165

106-
Runs on pull requests and manual dispatch. It validates:
166+
- runs automatically on `push` to `config/**`
167+
- runs automatically on `pull_request` changes to `config/**`
107168

108-
- JSON parsing
109-
- Duplicate label names
110-
- Invalid colors
111-
- Invalid repository names
169+
What it does:
112170

113-
### `Sync Labels`
171+
1. Checks out the repo
172+
2. Runs `node scripts/sync-labels.mjs --validate-only`
114173

115-
Runs on:
174+
Validation includes:
116175

117-
- Pushes to `main` when label-sync files change
118-
- Manual dispatch
119-
- Weekly schedule
176+
- JSONC parsing
177+
- required property checks
178+
- duplicate label detection
179+
- duplicate blacklist detection
180+
- invalid colors
181+
- invalid repo names
182+
- overlap detection between `labels.jsonc` and `auto-pruned-labels.jsonc`
120183

121-
Workflow dispatch inputs:
184+
### `Org-Label-Sync`
122185

123-
- `dry_run`: shows planned changes without writing anything
124-
- `delete_missing`: temporarily deletes labels not present in config
186+
File: `.github/workflows/org-label-sync.yml`
187+
188+
Trigger:
189+
190+
- manual via `workflow_dispatch`
191+
192+
Inputs:
193+
194+
- `dry_run`: preview changes without writing them
195+
- `delete_missing`: override `deleteMissingByDefault` for the run
125196
- `repositories`: optional comma-separated subset of discovered repositories
126197

127-
## Safe Default Behavior
198+
What it does:
199+
200+
1. Calls `Config-Label_Sync`
201+
2. Checks out the latest default branch
202+
3. Loads shared settings from `config/properties.jsonc`
203+
4. Validates the updated config
204+
5. Discovers repos in the configured organization
205+
6. Skips repos in `config/blacklisted-repositories.jsonc`
206+
7. Creates or updates labels from `config/labels.jsonc`
207+
8. Deletes labels listed in `config/auto-pruned-labels.jsonc`
208+
9. Optionally deletes any other unmanaged labels if `delete_missing` or `deleteMissingByDefault` is enabled
209+
210+
## Token Requirements
211+
212+
Create a repository secret whose name matches `labelSyncTokenSecretName` in `config/properties.jsonc`.
213+
214+
That token needs enough access to:
215+
216+
- read and update labels on the source repository
217+
- discover repositories in the organization
218+
- read and update labels on target repositories
219+
- push config updates back to this repository when `Config-Label_Sync` changes `labels.jsonc`
128220

129-
This repo is intentionally conservative:
221+
## Setup
130222

131-
- It syncs to the current organization by default, but you can exclude repos with the blacklist
132-
- It does not delete labels unless you explicitly enable that behavior
133-
- It supports dry runs before changing anything
223+
1. Fork or clone this repository into the organization you want to manage.
224+
2. Create the sync token secret in the repo.
225+
3. Update `config/properties.jsonc` for your org and repo.
226+
4. Adjust `config/auto-pruned-labels.jsonc` if you want a different always-delete list.
227+
5. Add any excluded repos to `config/blacklisted-repositories.jsonc`.
228+
6. Set the labels on this repository to the label set you want to manage.
229+
7. Run `Config-Label_Sync` once if you want to populate `config/labels.jsonc` immediately.
230+
8. Run `Org-Label-Sync` to propagate the labels across the organization.
134231

135-
## Suggested Next Edits
232+
## Safe Defaults
136233

137-
- Replace the starter labels with your real org label taxonomy
138-
- Add any repos you want excluded to the blacklist
139-
- Decide whether org-wide `deleteMissing` should stay off
234+
- `labels.jsonc` starts empty until you define or sync labels on this repo
235+
- all repos in the org are targeted unless blacklisted
236+
- GitHub default labels are auto-pruned by default
237+
- deleting unmanaged labels is off by default unless you enable it

0 commit comments

Comments
 (0)