responsibles
GitHub CODEOWNERS as inspiration
Section titled “GitHub CODEOWNERS as inspiration”GitHub supports a file called CODEOWNERS. When defined, a repository can add a policy to Pull Requests that parses the CODEOWNERS file against the actual files changed in the commit. If any files are owned by someone, GitHub enforces a review and awaits approval.
The idea to track ownership is good, but the implementation in GitHub is troublesome:
- GitHub only supports parsing the
CODEOWNERSfile in Pull Requests. - GitHub only supports
CODEOWNERSon paid team organizations - If ownership is given to a team or more than one handle is listed, this is interpreted as everyone in the team or list must approve.
- The documentation says that the
CODEOWNERSfile uses globs that follow most of the same rules used in.gitignorefiles. However, how it differs from globs used in.gitignoreis not clear. It’s documented by example only.
Our own alternative RESPONSIBLES parser
Section titled “Our own alternative RESPONSIBLES parser”We need the following features:
- Our process does not use peer reviews as quality gates. On the contrary, we believe that enforcing hand-overs in a process leads to waste in terms of unevenness, overburden, and ultimately poor quality. In our team, we adhere to XP-like values, based on paired – or even mob – programming, and we work with a concept we call Module Key Responsible (MKR). Each repo has exactly one MKR, who has the opportunity to delegate some responsibility to others. Inspired by the Benevolent Dictator Governance model well-known from many Open Source communities, we aim to engage responsibles already during development. We need the feature that when someone changes files with appointed responsibility, (one of) the responsibles should join or mentor the development of that branch. We want this to happen during development, not after. This should happen when commits are made to development branches.
- GitHub’s
CODEOWNERS, which requires PR approval from all code owners. In contrast, we interpret multiple responsibles in a more trusting manner, calling for eyes-on-code and mentorship from one of the responsibles. We do not enforce arbitrary wait-states. A review is not a quality gate; it’s a collaboration tool. - Due to the somewhat undocumented semantics of GitHub’s
CODEOWNERSfile, we have introduced our own format:RESPONSIBLES. We believe we can achieve what we seek with only two simple glob patterns from the.gitignorepattern format documentation:*and**(described in detail later).
The RESPONSIBLES file
Section titled “The RESPONSIBLES file”The RESPONSIBLES file can be stored in different supported locations — using the same search order as GitHub uses for the CODEOWNERS file:
<repo-root>/.github/<repo-root><repo-root>/docs/
The search stops on the first match of a file named RESPONSIBLES in any of the locations.
Parsing
Section titled “Parsing”During parsing, the RESPONSIBLES file is read from bottom up.
In other words, if multiple patterns define responsibles for the same file, the latest one is used to determine the responsible(s) for a file.
Format
Section titled “Format”A RESPONSIBLES file can contain:
- Comments: Lines where
#is the first non-whitespace character. - Inline comments: Anything following
#is stripped. - Empty lines: Lines that contain nothing or only whitespace.
Each line has the following format:
<file-pattern> <owner1> [<owner2> ... <ownerN>]Where:
<file-pattern>is a glob pattern that matches files in the repository.<owner1> <owner2> ... <ownerN>are GitHub usernames, separated by whitespace (not commas!).
Usernames must be prefixed with @ (e.g., @lakruzz).
Contrary to GitHub’s CODEOWNERS, we do not support teams or emails. This is by deliberate choice: Teams can be secret or private, and it’s not always possible for everyone to look up who’s a member of a given team. Also, it defies our philosophy; a team can no be responsible. It’s one MKR that’s responsible, and the MKR may have delegated some responsibility to others, but these are also named individuals.
Glob patterns
Section titled “Glob patterns”The glob patterns are used to match files in the repository. They are consistent with how git handles glob patterns in the .gitignore file, but only a small subset of the features is implemented.
Globbing is simple: only two globs are supported:
*matches zero or more characters, but not across directory boundaries.**matches zero or more directories.
The simplified (but complete) breakdown of the glob patterns is as follows:
*is equivalent to the RegExp[^/\\]*(matches any character except slash or backslash). With offset in the<repo-root>, it will match files but not directories.**is equivalent to the RegExp.*. It will match any or no character, including slashes, so contrary to*, the**glob will match directories and files alike./is translated to RegExp[/\\]?, matching zero or one of either a slash or a backslash.- Anything else is considered a literal and needs an exact match to define responsibility.
Example file tree:
project/├── RESPONSIBLES├── file1.txt├── dir1/│ ├── file2.txt│ └── dir2/│ └── file3.txt└── file4.txtRESPONSIBLES:
*.txt @lakruzzdir1/* @albertbanke @lakruzzParser:
file1.txtandfile4.txthave@lakruzzas responsible.file2.txthas@albertbanke @lakruzzas joint responsibles.dir2/file3.txtis not under any explicit responsibility.
Since * doesn’t descend into directories, *.txt only matches files in the repo root.
To match any .txt file across directory boundaries (which may have been the intended semantics of the first glob), you would use the glob:
**/*.txtThis will match any .txt file in the repository, regardless of its location.
Semantics
Section titled “Semantics”The committer has already approved: If @lakruzz changes file.txt, it will not trigger an involvement, simply because we imply involvement from the committer.
One or more responsibles
Section titled “One or more responsibles”If an ownership lists more than one responsible, then all responsibles will be invited to the issue, but if the committer is any of the responsibles, then none will be invited. This follows the same logic that implies involvement from the committer.
From the example above:
dir1/* @albertbanke @lakruzz
If either @lakruzz or @albertbanke is the committer of file2.txt, then no trigger is fired. But if @ravvnen is the committer, then both @lakruzz and @albertbanke will receive a mention on the issue @ravvnen is working on.
What if approval from both is required?
Section titled “What if approval from both is required?”That is currently not supported – and probably never will be, since that would imply a review/approval paradigm. This is known to cause inefficient wait states in the process.