How CODEOWNERS really work
All modern code collaboration systems support CODEOWNERS. This is a file that stored in your repository and defines which team is responsible for which parts of code. It helps split responsibility between teams and together with review ensures that all changes are ok.
This article is based on GitHub, but Gitlab and maybe some others should have similar behaviour.
The title is little bit clickbait, but mostly I would like to point to one issue that I think isn’t clearly described in GitHub/Gitlab documentation and could lead to wrong conclusions.
And in the end I will show how we could easily check who is the code owner without committing and then checking in UI who will be set as reviewer with simple Invoke task.
So, in general documentation is pretty simple and focused on couple of teams and 3 folders. Things became worse when we have dozens of teams and huge repo. Some teams own whole folder and then other teams wants to own subfolder there.
And this CODEOWNERS file will work fine:
# team @octo-org/team1 owns whole /folder1/
/folder1/ @octo-org/team1# team @octo-org/team2 owns only subfolder in /folder1 - subfolder1
/folder1/subfolder1/ @octo-org/team2# team @octo-org/team3 owns only subfolder in /folder1 - subfolder2
/folder1/subfolder2/ @octo-org/team3
And you might think that this CODEOWNERS file will act the same, since /folder1/subfolder1/
is more specific than generic /folder1/
# team @octo-org/team2 owns only subfolder in /folder1 - subfolder1
/folder1/subfolder1/ @octo-org/team2# team @octo-org/team3 owns only subfolder in /folder1 - subfolder2
/folder1/subfolder2/ @octo-org/team3# team @octo-org/team1 owns whole /folder1/
/folder1/ @octo-org/team1
But nope, it won’t work, all folders in /folder1/
are owned now by @octo-org/team1
. This happens because CODEOWNERS file is dumb simple and just parsed from top to the bottom and last match wins. There is no priorities.
How to fix this situation?
So far it seems to me that simpliest solution would be to define first global requirements and after that in lower section subfolders overrides (like shown in first example). And add some custom linter to check for errors there, like in second example.
TLDR: don’t expect too much complexity from CODEOWNERS and remember about this nuance.
And now, as I mentioned before, let’s see how we can check if our understanding of owners is matching with reality without committing anything.
We’ll create Invoke task using codeowners python library.
Minimal version looks like this, but you can check full PR#8.
Outputs for examples one and two:
# correct order (example 1)
$ inv codeowners -f folder1/subfolder2
[('TEAM', 'octo-org/team3')]# incorrect (example 2)
$ inv codeowners -f folder1/subfolder2
[('TEAM', '@octo-org/team1')]