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

dependencies

Dependabot

A dependency bump. Feeds Dependency Update Review

github_actions

Dependabot

The bump is to a GitHub Actions workflow, not to application code

java

Dependabot

The bump is in the Maven ecosystem

javascript

Dependabot

The bump is in the npm ecosystem

release

Release automation

A release or hotfix pull request. Distinguishes automation traffic from authored change in a crowded list

hold

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

risk:security

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.