mirror of
https://github.com/ModernRelay/omnigraph.git
synced 2026-06-09 01:35:18 +02:00
* codeowners: generator + drift CI + initial roles
Source-of-truth approach to CODEOWNERS: yml is hand-edited, CODEOWNERS
is generated and CI-enforced. Every role change is a reviewable PR
with a permanent in-repo audit trail. No GitHub UI clicks, no shadow
state.
Initial roles:
engineering @aaltshuler owns crates/** + default (.github/,
scripts/, Cargo.*, openapi.json,
everything else not docs)
docs @aaltshuler @ragnorc owns docs/**, README.md, AGENTS.md,
CLAUDE.md, SECURITY.md
Per GitHub semantics, multiple owners on a CODEOWNERS line means "any
one satisfies the review" — for docs, either named member can approve.
Strict "N distinct approvers" would need a CI workaround (not wired
today; tracked for future hardening).
Components:
- .github/codeowners-roles.yml — source of truth. Edit this.
- .github/scripts/render-codeowners.py — generator (PyYAML; ~100 LoC).
- .github/CODEOWNERS — generated. CI rejects hand-edits.
- .github/workflows/codeowners.yml — two checks:
* drift: re-render and assert CODEOWNERS matches.
* noedit: reject PRs that edit CODEOWNERS without editing the yml.
- docs/codeowners.md — explains the source-of-truth pattern, how to
change roles, how to add new roles.
- AGENTS.md topic-index row.
What's NOT in this PR:
- Branch protection on main (separate PR; needs `gh api` call against
the org).
- Required-reviewer enforcement (depends on branch protection landing).
- Required CI status checks (depends on branch protection landing).
- Scheduled rotation (the schedule: block in the yml + a weekly
workflow). Today's roles are stable; rotation isn't needed yet.
- Linear-as-source-of-truth integration (Approach 4 from the design
discussion; deferred).
Verified:
- Generator output is deterministic (idempotent re-runs).
- scripts/check-agents-md.sh OK (28 links, 28 docs).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* codeowners: fix catch-all ordering (Devin review #88)
Devin caught a real bug: GitHub CODEOWNERS uses "last match wins"
semantics, but the generator emitted the catch-all `*` AFTER specific
patterns. Net effect: `*` won for every file, silently nullifying the
docs role and never routing reviews to @ragnorc.
Fix is one-line — emit the default `*` line before iterating the
specific paths. Also:
- Added a regression assertion in the generator: after rendering, the
first non-comment line must start with `*` if a default is
configured. Generator exits non-zero otherwise. Catches the same
class of mistake in any future refactor.
- Rewrote the yml header comment, which incorrectly stated "keep
more-specific paths after broader patterns" (correct for GitHub
semantics but the generator was doing the opposite — so the comment
read as a description of behavior when it was actually a contradicted
intention).
Verified by re-rendering: `*` is now line 12, `crates/**` is line 14,
`docs/**` is line 15, etc. README.md matches both `*` and `README.md`;
`README.md` is later → wins → @aaltshuler + @ragnorc both assigned.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
57 lines
2.1 KiB
YAML
57 lines
2.1 KiB
YAML
# Source of truth for .github/CODEOWNERS.
|
|
#
|
|
# How to change role membership or path assignments:
|
|
# 1. Edit this file.
|
|
# 2. Run `python3 .github/scripts/render-codeowners.py` to regenerate
|
|
# .github/CODEOWNERS.
|
|
# 3. Commit both files in the same PR.
|
|
#
|
|
# CI fails on drift between this source and the generated CODEOWNERS
|
|
# (see .github/workflows/codeowners.yml). CI also rejects direct edits
|
|
# to .github/CODEOWNERS that don't accompany a change here.
|
|
#
|
|
# Why a generator instead of editing CODEOWNERS directly?
|
|
# The yml is the audit trail: `git log .github/codeowners-roles.yml`
|
|
# shows every role change with a reviewable diff and a merge commit.
|
|
# The rendered CODEOWNERS is what GitHub reads at PR time.
|
|
|
|
roles:
|
|
engineering:
|
|
description: >
|
|
All production code under crates/**. Engine, CLI, server,
|
|
compiler. Single owner; review must come from this person.
|
|
members:
|
|
- aaltshuler
|
|
|
|
docs:
|
|
description: >
|
|
Documentation under docs/**, plus repo-level docs (README.md,
|
|
AGENTS.md, CLAUDE.md symlink, SECURITY.md). Either named member
|
|
can approve; both are listed so reviews can route to whoever is
|
|
available.
|
|
members:
|
|
- aaltshuler
|
|
- ragnorc
|
|
|
|
# Path → role mapping. GitHub CODEOWNERS uses "last match wins"
|
|
# semantics — when multiple patterns match a file, only the last
|
|
# matching pattern's owners apply. The generator handles this by
|
|
# emitting `default` as the first `*` line and the specific patterns
|
|
# below afterward, so specific paths override the catch-all.
|
|
#
|
|
# Within this list, order matters only between overlapping specific
|
|
# patterns (the later one wins). Today nothing overlaps; future
|
|
# additions should keep more-specific patterns later.
|
|
paths:
|
|
"crates/**": [engineering]
|
|
"docs/**": [docs]
|
|
"README.md": [docs]
|
|
"AGENTS.md": [docs]
|
|
"CLAUDE.md": [docs]
|
|
"SECURITY.md": [docs]
|
|
|
|
# Catch-all for paths not explicitly mapped (.github/, scripts/,
|
|
# Cargo.toml, Cargo.lock, openapi.json, LICENSE, etc.). Defaults to
|
|
# engineering — every change to repo infrastructure needs the
|
|
# engineering owner's review.
|
|
default: [engineering]
|