Documentation
¶
Overview ¶
Package codeowners is a library for working with CODEOWNERS files.
CODEOWNERS files map gitignore-style path patterns to sets of owners, which may be GitHub users, GitHub teams, or email addresses. This library parses the CODEOWNERS file format into rulesets, which may then be used to determine the ownership of files.
Usage ¶
To find the owner of a given file, parse a CODEOWNERS file and call Match() on the resulting ruleset.
ruleset, err := codeowners.ParseFile(file) if err != nil { log.Fatal(err) } rule, err := ruleset.Match("path/to/file") if err != nil { log.Fatal(err) }
Command line interface ¶
A command line interface is also available in the cmd/codeowners package. When run, it will walk the directory tree showing the code owners for each file encountered. The help flag lists available options.
$ codeowners --help
Example ¶
package main import ( "bytes" "fmt" "github.com/hmarr/codeowners" ) func main() { f := bytes.NewBufferString("src/**/*.c @acme/c-developers") ruleset, err := codeowners.ParseFile(f) if err != nil { panic(err) } match, err := ruleset.Match("src/foo.c") fmt.Println(match.Owners) match, err = ruleset.Match("src/foo.rs") fmt.Println(match) }
Output: [@acme/c-developers] <nil>
Index ¶
Examples ¶
Constants ¶
const ( // EmailOwner is the owner type for email addresses. EmailOwner string = "email" // TeamOwner is the owner type for GitHub teams. TeamOwner string = "team" // UsernameOwner is the owner type for GitHub usernames. UsernameOwner string = "username" )
Variables ¶
var DefaultOwnerMatchers = []OwnerMatcher{ OwnerMatchFunc(MatchEmailOwner), OwnerMatchFunc(MatchTeamOwner), OwnerMatchFunc(MatchUsernameOwner), }
DefaultOwnerMatchers is the default set of owner matchers, which includes the GitHub-flavored email, team, and username matchers.
var ErrNoMatch = errors.New("no match")
Functions ¶
func WithOwnerMatchers ¶ added in v1.2.0
func WithOwnerMatchers(mm []OwnerMatcher) parseOption
Types ¶
type ErrInvalidOwnerFormat ¶ added in v1.2.0
type ErrInvalidOwnerFormat struct {
Owner string
}
func (ErrInvalidOwnerFormat) Error ¶ added in v1.2.0
func (err ErrInvalidOwnerFormat) Error() string
type Owner ¶
type Owner struct { // Value is the name of the owner: the email addres, team name, or username. Value string // Type will be one of 'email', 'team', or 'username'. Type string }
Owner represents an owner found in a rule.
func MatchEmailOwner ¶ added in v1.2.0
MatchEmailOwner matches an email address owner. May be provided to WithOwnerMatchers.
func MatchTeamOwner ¶ added in v1.2.0
MatchTeamOwner matches a GitHub team owner. May be provided to WithOwnerMatchers.
func MatchUsernameOwner ¶ added in v1.2.0
MatchUsernameOwner matches a GitHub username owner. May be provided to WithOwnerMatchers.
type OwnerMatchFunc ¶ added in v1.2.0
OwnerMatchFunc is a function that matches a string against a pattern and returns an Owner, or ErrNoMatch if no match was found. It implements the OwnerMatcher interface and may be provided to WithOwnerMatchers to customize owner matching behavior (e.g. to support GitLab-style team names).
type OwnerMatcher ¶ added in v1.2.0
type Rule ¶
type Rule struct { Owners []Owner Comment string LineNumber int // contains filtered or unexported fields }
Rule is a CODEOWNERS rule that maps a gitignore-style path pattern to a set of owners.
func (Rule) RawPattern ¶
RawPattern returns the rule's gitignore-style path pattern.
type Ruleset ¶
type Ruleset []Rule
Ruleset is a collection of CODEOWNERS rules.
func LoadFileFromStandardLocation ¶ added in v0.2.0
LoadFileFromStandardLocation loads and parses a CODEOWNERS file at one of the standard locations for CODEOWNERS files (./, .github/, docs/). If run from a git repository, all paths are relative to the repository root.
func ParseFile ¶
ParseFile parses a CODEOWNERS file, returning a set of rules. To override the default owner matchers, pass WithOwnerMatchers() as an option.
Example ¶
package main import ( "bytes" "fmt" "github.com/hmarr/codeowners" ) func main() { f := bytes.NewBufferString("src/**/*.go @acme/go-developers # Go code") ruleset, err := codeowners.ParseFile(f) if err != nil { panic(err) } fmt.Println(len(ruleset)) fmt.Println(ruleset[0].RawPattern()) fmt.Println(ruleset[0].Owners[0].String()) fmt.Println(ruleset[0].Comment) }
Output: 1 src/**/*.go @acme/go-developers Go code
Example (CustomOwnerMatchers) ¶
package main import ( "bytes" "fmt" "regexp" "github.com/hmarr/codeowners" ) func main() { validUsernames := []string{"the-a-team", "the-b-team"} usernameRegexp := regexp.MustCompile(`\A@([a-zA-Z0-9\-]+)\z`) f := bytes.NewBufferString("src/**/*.go @the-a-team # Go code") ownerMatchers := []codeowners.OwnerMatcher{ codeowners.OwnerMatchFunc(codeowners.MatchEmailOwner), codeowners.OwnerMatchFunc(func(s string) (codeowners.Owner, error) { // Custom owner matcher that only matches valid usernames match := usernameRegexp.FindStringSubmatch(s) if match == nil { return codeowners.Owner{}, codeowners.ErrNoMatch } for _, t := range validUsernames { if t == match[1] { return codeowners.Owner{Value: match[1], Type: codeowners.TeamOwner}, nil } } return codeowners.Owner{}, codeowners.ErrNoMatch }), } ruleset, err := codeowners.ParseFile(f, codeowners.WithOwnerMatchers(ownerMatchers)) if err != nil { panic(err) } fmt.Println(len(ruleset)) fmt.Println(ruleset[0].RawPattern()) fmt.Println(ruleset[0].Owners[0].String()) fmt.Println(ruleset[0].Comment) }
Output: 1 src/**/*.go @the-a-team Go code
func (Ruleset) Match ¶
Match finds the last rule in the ruleset that matches the path provided. When determining the ownership of a file using CODEOWNERS, order matters, and the last matching rule takes precedence.
Example ¶
package main import ( "bytes" "fmt" "github.com/hmarr/codeowners" ) func main() { f := bytes.NewBufferString("src/**/*.go @acme/go-developers # Go code") ruleset, _ := codeowners.ParseFile(f) match, _ := ruleset.Match("src") fmt.Println("src", match != nil) match, _ = ruleset.Match("src/foo.go") fmt.Println("src/foo.go", match != nil) match, _ = ruleset.Match("src/foo/bar.go") fmt.Println("src/foo/bar.go", match != nil) match, _ = ruleset.Match("src/foo.rs") fmt.Println("src/foo.rs", match != nil) }
Output: src false src/foo.go true src/foo/bar.go true src/foo.rs false