Getting started

edit

Install the package

Add the Meziantou.Framework.CodeOwners package to a project:

dotnet package add Meziantou.Framework.CodeOwners

The examples of this documentation omit the using directives: they need using Meziantou.Framework.CodeOwners;.

Parse a file

Read the content of the file and pass it to CodeOwnersFile.Parse, with the dialect of the host of the repository:

string content = File.ReadAllText(filePath); // For instance, .github/CODEOWNERS
CodeOwnersFile file = CodeOwnersFile.Parse(content, CodeOwnersDialect.GitHub);

// Comments and blank lines are not entries
Assert.HasCount(2, file.Entries);

CodeOwnersEntry docs = file.Entries[1];
Assert.Equal("/docs/", docs.Pattern);
Assert.Equal(["org/docs-team", "docs@example.com"], docs.Owners.Select(owner => owner.Name));
  • The parser takes the content, not a path: read the file yourself.
  • Entries holds one CodeOwnersEntry per pattern line, in the order of the file. Comments and blank lines are not entries.
  • Each entry has a Pattern and its Owners. A username or a team is stored without its leading @.

Parse throws a CodeOwnersParseException when the file is invalid. Use TryParse to get false instead: see Handling errors.

Choose the dialect

The two hosts do not read the same file the same way:

  • CodeOwnersDialect.GitHub reads a pattern and its owners on each line. A line that starts with [ is a pattern, as [ opens a character class.
  • CodeOwnersDialect.GitLab adds sections: a line such as [Docs] or ^[Docs] starts a section, and the owners can be roles such as @@maintainer.

The same content can give different entries:

const string Content = """
    [Docs]
    *.md @docs-team
    """;

// GitHub reads "[Docs]" as a pattern, with no owners
var github = CodeOwnersFile.Parse(Content, CodeOwnersDialect.GitHub);
Assert.Equal(["[Docs]", "*.md"], github.Entries.Select(entry => entry.Pattern));

// GitLab reads it as the header of a section
var gitlab = CodeOwnersFile.Parse(Content, CodeOwnersDialect.GitLab);
CodeOwnersEntry entry = Assert.Single(gitlab.Entries);
Assert.Equal("*.md", entry.Pattern);
Assert.Equal("Docs", entry.Section?.Name);

A file without sections and roles gives the same entries with both dialects. Pick the dialect of the host that reads the file, so that your tool and the host agree.

Next steps