Problem
Label taxonomy drifts across evalops/* repos. evalops/platform has a rich set (architecture-review, operational, sync, upstream-absorbed, security, go, javascript, dependencies, etc.) while sibling repos like evalops/maestro only carried the GitHub defaults until architecture-review was manually backfilled. With 50+ repos in the org, any taxonomy decision made today will be wrong somewhere tomorrow unless the source-of-truth → sync path is in place.
Concrete cost today:
- Cross-repo
gh issue list --label architecture-review --search "org:evalops" misses results when sibling repos lack the label
- Agents (and future teammates) can't reason uniformly about issue state across the org
- Every new service repo created from
evalops/template-go-service re-inherits whatever labels were current when the template was last edited — no mechanism enforces ongoing parity
Proposal
Formalize the canonical label set in this .github repo as source of truth, and sync it to every evalops/* repo via a GitHub Actions workflow. Fits the feedback_gitops_only.md spirit: declarative source-of-truth, reconciliation loop, no imperative one-off gh label create drift.
Source of truth
Canonical YAML committed to this repo (proposed: labels.yml at repo root, or .github/labels.yml):
labels:
- name: architecture-review
description: Cross-service architecture review requested
color: "5319e7"
- name: operational
description: Operational practices, runbooks, and reliability
color: "0e8a16"
- name: security
description: Security vulnerabilities and hardening
color: "d73a4a"
- name: sync
description: Crossover sync between standalone repos and _import/ mirrors
color: "1d76db"
# … full canonical set
Sync mechanism (two options, prefer push model)
Push model (recommended): centralized workflow in evalops/.github that enumerates evalops/* repos and reconciles labels against labels.yml.
- Pros: single dashboard for sync history, no per-repo code required, easy to exempt repos
- Cons: needs a PAT or GitHub App installation with
issues:write across the org
Pull model: reusable workflow (evalops/.github/.github/workflows/sync-labels.yml@main) each repo calls on schedule.
- Pros: per-repo opt-in, composes cleanly with per-repo labels
- Cons: harder to track org-wide compliance, boilerplate multiplied across 50+ repos
Merge semantics
- Additive by default — never deletes repo-local labels (templates like
go, javascript are platform-specific and shouldn't propagate)
- Updates
color and description to match canonical file when a name matches
- Dry-run on PRs to
labels.yml, apply on push to main
- Per-repo opt-out via a sentinel file (e.g.,
.github/labels-sync.disabled)
Acceptance criteria
Prior art
crazy-max/ghaction-github-labeler — declarative, well-maintained
EndBug/label-sync — YAML → labels, simple surface
micnncim/action-label-syncer — supports multiple repos via input list
Prefer pinned third-party action + declarative YAML over bespoke gh CLI scripting — matches the repo's existing disposition toward actionlint + workflow-security-guardrails + SHA-pinned actions.
Non-goals
- Migrating existing issues between labels (separate effort if a label is renamed)
- Synchronizing issue templates, PR templates, or CODEOWNERS — those belong in their own reusable-workflow rollouts
- Cross-org label parity (only evalops/* is in scope)
Follow-ups once this lands
Same pattern applies to: reusable CI workflow rollouts, CODEOWNERS templates, issue templates, branch protection rules. Labels are the cheapest place to prove the pattern works before committing to the heavier rollouts.
Problem
Label taxonomy drifts across evalops/* repos.
evalops/platformhas a rich set (architecture-review,operational,sync,upstream-absorbed,security,go,javascript,dependencies, etc.) while sibling repos likeevalops/maestroonly carried the GitHub defaults untilarchitecture-reviewwas manually backfilled. With 50+ repos in the org, any taxonomy decision made today will be wrong somewhere tomorrow unless the source-of-truth → sync path is in place.Concrete cost today:
gh issue list --label architecture-review --search "org:evalops"misses results when sibling repos lack the labelevalops/template-go-servicere-inherits whatever labels were current when the template was last edited — no mechanism enforces ongoing parityProposal
Formalize the canonical label set in this
.githubrepo as source of truth, and sync it to every evalops/* repo via a GitHub Actions workflow. Fits thefeedback_gitops_only.mdspirit: declarative source-of-truth, reconciliation loop, no imperative one-offgh label createdrift.Source of truth
Canonical YAML committed to this repo (proposed:
labels.ymlat repo root, or.github/labels.yml):Sync mechanism (two options, prefer push model)
Push model (recommended): centralized workflow in
evalops/.githubthat enumeratesevalops/*repos and reconciles labels againstlabels.yml.issues:writeacross the orgPull model: reusable workflow (
evalops/.github/.github/workflows/sync-labels.yml@main) each repo calls on schedule.Merge semantics
go,javascriptare platform-specific and shouldn't propagate)coloranddescriptionto match canonical file when a name matcheslabels.yml, apply on push tomain.github/labels-sync.disabled)Acceptance criteria
labels.ymlcommitted toevalops/.githubwith the canonical set (seeded fromevalops/platform's current labels)labels.ymlon main, (b) weekly schedule, (c) manualworkflow_dispatchtemplate-go-serviceupdated to rely on the sync rather than bootstrapping its own labelsPrior art
crazy-max/ghaction-github-labeler— declarative, well-maintainedEndBug/label-sync— YAML → labels, simple surfacemicnncim/action-label-syncer— supports multiple repos via input listPrefer pinned third-party action + declarative YAML over bespoke
ghCLI scripting — matches the repo's existing disposition towardactionlint+workflow-security-guardrails+ SHA-pinned actions.Non-goals
Follow-ups once this lands
Same pattern applies to: reusable CI workflow rollouts, CODEOWNERS templates, issue templates, branch protection rules. Labels are the cheapest place to prove the pattern works before committing to the heavier rollouts.