fix: give the catch-all zones a real owner, and catch silent CODEOWNERS breakage - #203
Merged
Merged
Conversation
…RS breakage Two ownership gaps, both of which fail silently. An unregistered service or package had no CODEOWNERS line and resolved through the `*` fallback, so it auto-requested whoever holds `*` rather than anyone who knows it. docs/CODE-OWNERSHIP.md flagged this as "latent, not yet biting" — invisible while every owner is the same person, wrong the moment they diverge. Bare `/services/` and `/packages/` lines now own those two buckets. Their position is load-bearing and inverted relative to pr-zone-check.yml: CODEOWNERS is last-match-wins, so a catch-all must sit ABOVE the specific lines to be overridden by them. Below, it would swallow every service. check-labels.mjs now enforces the position, the presence, and the services/packages -> */other mapping. Second gap: naming an owner who is not a collaborator, or who has read-only access, produces no error anywhere. GitHub simply never requests them — the zone looks owned and reviews go nowhere. codeowners-valid.yml asks GitHub's own parser and fails on it. Verified against a deliberately broken file on a throwaway ref: both an unknown handle and a malformed owner are reported with file, line and column. check-labels.mjs cannot cover this — it sees a line per zone, not whether the handle on that line can review — so it is a separate job. `root` still resolves through `*` and always will: it is not a directory, and "every top-level file" is exactly what `*` already means. No ownership is assigned here; every line is still @qiuethan. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this changes
Closes two CODEOWNERS gaps, both of which fail silently — no error, no red X, reviews just quietly go to the wrong person or nobody.
No ownership is assigned here. Every line is still
@qiuethan; this is the structural groundwork so that adding real owners is safe.Why
1. Unregistered services and packages had no owner
docs/CODE-OWNERSHIP.mdflagged this as "latent, not yet biting":services/otherandpackages/otherhad no CODEOWNERS line and resolved through the*fallback. Invisible while every owner is one person — wrong the moment they diverge, because a new service would auto-request whoever holds*rather than anyone who knows it.Bare
/services/and/packages/lines now own those buckets.Their position is load-bearing, and it's the mirror image of
pr-zone-check.yml:zone_for()Put
/services/below and it swallows every service —services/llmwould be reviewed by the catch-all owner instead of its own.check-labels.mjsnow enforces the position, not just the presence.rootstill resolves through*, and always will: it isn't a directory, and "every top-level file" is exactly what*already means.2. A broken owner entry is completely silent
Name someone who isn't a collaborator, or who has read-only access, and GitHub never requests them and never says why. The zone looks owned. You find out when something merges unreviewed.
codeowners-valid.ymlasks GitHub's own parser (/codeowners/errors) on every change to the file. This is deliberately a separate job fromlabel-consistency— that one is offline and structural (does the zone list agree with itself); this one is a live lookup against org membership.check-labels.mjsstructurally cannot catch it: it sees a line per zone, not whether the handle on that line can review.Zone
.github·docs·scriptsThree zones. The CODEOWNERS change, the check that enforces it, and the doc describing it have to land together or
label-consistencyfails on its own first run.How to verify
Injected failures into a copy of the tree, all caught:
The new workflow was tested against a deliberately broken CODEOWNERS on a throwaway ref (created and deleted via the API). Both failure modes are reported with file, line and column:
That test also caught a bug in my first draft: the API's
messagefield is multi-line (it quotes the offending line and points a caret at the column), which broke both the markdown summary and the annotation. Fixed — summary takes the full message in a code block, annotation takes the first line only.Checklist
stagingand targetingstaging.make labelsclean; all workflow YAML parses; the newrun:block passesbash -n.Deployment notes
Nothing to do at deploy time.
codeowners-validis not a required status check; add it in branch protection if you want it to gate.Anything you're unsure about
The
/services/and/packages/lines change who gets auto-requested for an unregistered service — from the*fallback owner to the workspace catch-all owner. Identical today (both@qiuethan), diverges as soon as owners do. That's the intent, but it's the line to look hardest at.🤖 Generated with Claude Code