GitHub Labels
1. Overview
Every EMS repository carries the same seven labels. Five are applied by machines. Two are applied by a person, and each of those two does something — it changes how a pull request is handled, not merely how it reads.
The set is small on purpose, and the purpose is evidence rather than taste. Across all repositories and more than a thousand pull requests, exactly two labels have ever been applied by a human being. Every other labelled pull request was labelled by Dependabot. A vocabulary that people do not apply is not a taxonomy; it is a control that reports clean because nobody operates it. Designing a richer one would produce the same result more elaborately.
This is the opposite shape to Work Item Tags, and deliberately so. The reason is that the two systems carry different questions.
2. Why this vocabulary is not shaped like the Azure DevOps one
Azure DevOps holds work: what is wrong, who wants it, which outcome needs it, how bad it would be. Those questions survive for months and are asked of the whole backlog at once, so they need an index — which is what a faceted tag vocabulary is.
A pull request holds a change in flight. It is open for days, it has one author, and the questions asked of it are answered by things GitHub already tracks: which files it touches, whether the suite is green, who reviewed it, which branch it targets. There is no third question needing an index. A pull request label that classifies the change duplicates the diff.
What remains is the narrow class of facts that are true of a pull request, are not visible from the diff or the checks, and change what somebody does next. There are two of those, and five more that a machine can apply for free.
3. The labels
| Label | Applied by | Meaning and effect |
|---|---|---|
|
Dependabot |
A dependency bump. Feeds Dependency Update Review |
|
Dependabot |
The bump is to a GitHub Actions workflow, not to application code |
|
Dependabot |
The bump is in the Maven ecosystem |
|
Dependabot |
The bump is in the npm ecosystem |
|
Release automation |
A release or hotfix pull request. Distinguishes automation traffic from authored change in a crowded list |
|
A person |
Do not merge, for a reason outside the checks — an unreleased dependency, a coordinated deploy, a decision pending. The triage sweep treats it as a stop |
|
A person, or a scanner |
The change addresses a security exposure. Deliberately the same string as the Azure DevOps facet, so one term finds both sides |
hold is the only label whose absence is load-bearing. An unlabelled pull request is mergeable once its checks are green; that is what the absence means, and it is why hold must never be applied as a comment-substitute on a pull request that is merely awaiting review.
The four Dependabot labels are created and applied by Dependabot without configuration. They are listed here because they are part of the vocabulary and because the dependency review process reads them, not because anyone maintains them.
4. What was removed, and why
Every repository was created carrying GitHub’s stock label set: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. A handful of repositories had also drifted extras — New, web, UX, backend.
None of these survive, for two separate reasons.
Six of them are written for public contribution. good first issue, help wanted, question, wontfix, invalid and duplicate exist to route and to let down contributors from outside a project. EMS has no public participation. Every one of these was a control with no subject.
The rest classify issues, and issues moved to Azure DevOps. The newest GitHub issue in any EMS repository predates the move. What remains is an archive of several dozen closed and stale issues, and bug, enhancement and documentation were the only classification on them. Deleting the labels removes that classification, which is accepted: the archive is not consulted, Azure DevOps is the record of work, and a live label that exists to annotate a dead archive will be applied to living pull requests by anyone who sees it in the picker. That is the failure the deletion prevents.
GitHub Issues are not used in EMS. Work is raised in Azure DevOps. This is why the vocabulary has no issue-triage labels at all, and why adding one is a signal that the wrong system is being used rather than that the vocabulary is short.
5. Keeping the repositories identical
The set is applied to every repository from one list, so that drift is corrected rather than accumulated. Drift is what produced New, web, UX and backend — each added to a single repository, each invisible from the other twenty-four.
# The vocabulary. Machine-applied labels are included so the colours stay consistent
# across repositories that Dependabot has not yet touched.
cat > /tmp/ems-labels.tsv <<'EOF'
dependencies 0366d6 Dependency bump
github_actions 000000 Bump to a GitHub Actions workflow
java ffa221 Bump in the Maven ecosystem
javascript 168700 Bump in the npm ecosystem
release 0E8A16 Release or hotfix pull request
hold B60205 Do not merge — reason outside the checks
risk:security D93F0B Addresses a security exposure
EOF
REPOS=$(grep -v '^#' bootstrap/repos.list | awk 'NF{print $2}' \
| sed 's|[email protected]:||; s|\.git$||')
for repo in $REPOS; do
# Remove everything outside the vocabulary
gh label list --repo "$repo" --limit 100 --json name --jq '.[].name' \
| grep -vxF -f <(cut -f1 /tmp/ems-labels.tsv) \
| while read -r stale; do
gh label delete "$stale" --repo "$repo" --yes
done
# Create or correct every label in the vocabulary
while IFS=$'\t' read -r name colour desc; do
gh label create "$name" --repo "$repo" --color "$colour" \
--description "$desc" --force
done < /tmp/ems-labels.tsv
done
--force makes the create idempotent: it updates colour and description where the label already exists, so the script is a reconciliation rather than a one-time migration. Run it after adding a repository, and after any change to this page.
6. Extending the vocabulary
A new label must clear a higher bar than a new work item tag, because the evidence is that labels are not applied.
State what a person or a workflow does differently when the label is present. If the answer is "sees it in the list", the label is a comment and belongs in the pull request body. If the answer describes a property of the change itself, the diff already carries it.
A label that a workflow reads — one that gates, routes, or is queried by automation — clears the bar by construction, because something breaks when it is missing. hold is the model.
Adding a label changes this page and the list in the script above, and is applied to every repository in the same change. A label on one repository is drift, however useful it is there.
7. Related
-
Work Item Tags — the Azure DevOps vocabulary, and why it is richer
-
Repository Rules — the branch protection and pull request check standard
-
Dependency Update Review — the process that reads the Dependabot labels