fix: report .codeowner files that reference an unregistered team - #116
Open
sarastrasner wants to merge 1 commit into
Open
fix: report .codeowner files that reference an unregistered team#116sarastrasner wants to merge 1 commit into
sarastrasner wants to merge 1 commit into
Conversation
`DirectoryMapper::entries` looks each directory owner up in the team registry and skips the entry when the name does not resolve. Nothing else reports the name, so a typo'd or renamed team in a `.codeowner` is completely silent: the directory inherits the nearest ancestor owner, `generate` emits no line for it, and `validate` exits 0. That makes the file inert while still looking authoritative, and the ownership it was written to express quietly belongs to whichever team owns the parent directory. Annotations and package ownership are already validated against the registry; this extends the same check to directory ownership, reusing the existing `InvalidTeam` error so output and exit codes are unchanged in shape. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.
Problem
DirectoryMapper::entrieslooks each directory owner up in the team registry and skips the entry when the name doesn't resolve:Nothing else reports the unresolved name, so a
.codeownernaming a team that was renamed, deleted, or simply typo'd is completely silent:generateemits no line for that directoryvalidateexits 0The file still looks authoritative, but it's inert — and the ownership it was written to express quietly belongs to whichever team owns the parent directory. Because
validatestays green, these accumulate rather than getting caught on the PR that introduced them.There's also a failure mode where the advice is actively counterproductive: an unresolvable owner drops that directory's line from the generated file, so
validatereportsCODEOWNERS out of dateand points you atcodeowners generate— which "fixes" it by erasing the line, making the real problem disappear.Annotations (
invalid_team_annotation) and package ownership (invalid_package_ownership) are already validated against the registry. Directory ownership is the one surface that isn't.Fix
Adds
invalid_directory_ownershipas a third check invalidate_invalid_team, reusing the existingInvalidTeamerror.Reusing
InvalidTeamkeeps the output shape and exit codes unchanged, which seemed worth preserving given the wrappingcode_ownershipgem parses these category headlines. The consequence is that a.codeownerviolation is reported underFound invalid team annotations, which is now a little loose — though it already coverspackage.yml. Happy to give it its own category instead if you'd prefer; I avoided it only because it changes output the gem consumes.Test
New fixture
tests/fixtures/invalid-directory-codeowner: a nested.codeownernaming an unregistered team, underneath an ancestor.codeownernaming a real one. That shape matters — ownership resolves cleanly to the ancestor, so no other check fires and the generated CODEOWNERS looks entirely reasonable.Before this change that fixture exits
0with empty stdout and stderr. After, it reports:Verification
cargo test— all pass (added 1)cargo clippy --all-targets --all-features -- -D warnings— cleancargo fmt --all -- --check— cleanUnrelated wrinkle, noted in passing
I first tried this as a unit test and hit something you may want to know about: the
ownership!macro insrc/common_test.rsbindstempdir()to a local that drops at the end of the macro block, so the temp project directory is deleted before the caller ever uses the returnedOwnership. Any test that touches the filesystem afterwards —get_codeowners_file(), for instance — silently sees an empty repo and reports a spurious stale-CODEOWNERS diff.Nothing currently depends on it, because every existing caller only reads the already-built in-memory
Project. It does meanOwnership::validate()can't be unit-tested through that helper today, which is why this PR uses an integration test. Happy to open a separate issue or fix it if useful.