diff --git a/README.md b/README.md index 2752aba..891a1ef 100644 --- a/README.md +++ b/README.md @@ -129,6 +129,7 @@ Use the following environment variables to configure the application: | OWNER_CHECKER_REPOSITORY * | | The owner and repository name separated by slash. For example, gh-codeowners/codeowners-samples. Used to check if GitHub owner is in the given organization. | | OWNER_CHECKER_IGNORED_OWNERS | `@ghost`| The comma-separated list of owners that should not be validated. Example: `"@owner1,@owner2,@org/team1,example@email.com"`. | | OWNER_CHECKER_ALLOW_UNOWNED_PATTERNS | `true` | Specifies whether CODEOWNERS may have unowned files. For example:

`/infra/oncall-rotator/ @sre-team`
`/infra/oncall-rotator/oncall-config.yml`

The `/infra/oncall-rotator/oncall-config.yml` file is not owned by anyone. | +| OWNER_CHEKER_OWNERS_MUST_BE_TEAMS | `false` | Specifies whether only teams are allowed as owners of files | | NOT_OWNED_CHECKER_SKIP_PATTERNS | - | The comma-separated list of patterns that should be ignored by `not-owned-checker`. For example, you can specify `*` and as a result, the `*` pattern from the **CODEOWNERS** file will be ignored and files owned by this pattern will be reported as unowned unless a later specific pattern will match that path. It's useful because often we have default owners entry at the begging of the CODOEWNERS file, e.g. `* @global-owner1 @global-owner2` | * - Required diff --git a/internal/check/valid_owner.go b/internal/check/valid_owner.go index 2bd6f10..6fb98c8 100644 --- a/internal/check/valid_owner.go +++ b/internal/check/valid_owner.go @@ -26,6 +26,8 @@ type ValidOwnerConfig struct { // // The `/infra/oncall-rotator/oncall-config.yml` this file is not owned by anyone. AllowUnownedPatterns bool `envconfig:"default=true"` + // OwnersMustBeTeams specifies whether owners must be teams in the same org as the repository + OwnersMustBeTeams bool `envconfig:"default=false"` } // ValidOwner validates each owner @@ -37,6 +39,7 @@ type ValidOwner struct { orgRepoName string ignOwners map[string]struct{} allowUnownedPatterns bool + ownersMustBeTeams bool } // NewValidOwner returns new instance of the ValidOwner @@ -57,6 +60,7 @@ func NewValidOwner(cfg ValidOwnerConfig, ghClient *github.Client) (*ValidOwner, orgRepoName: split[1], ignOwners: ignOwners, allowUnownedPatterns: cfg.AllowUnownedPatterns, + ownersMustBeTeams: cfg.OwnersMustBeTeams, }, nil } @@ -133,10 +137,10 @@ func (v *ValidOwner) isIgnoredOwner(name string) bool { func (v *ValidOwner) selectValidateFn(name string) func(context.Context, string) *validateError { switch { + case v.ownersMustBeTeams || isGitHubTeam(name): + return v.validateTeam case isGitHubUser(name): return v.validateGitHubUser - case isGitHubTeam(name): - return v.validateTeam case isEmailAddress(name): // TODO(mszostok): try to check if e-mail really exists return func(context.Context, string) *validateError { return nil } @@ -186,6 +190,10 @@ func (v *ValidOwner) validateTeam(ctx context.Context, name string) *validateErr } } + if !isGitHubTeam(name) { + return newValidateError("%s is not a team", name) + } + // called after validation it's safe to work on `parts` slice parts := strings.SplitN(name, "/", 2) org := parts[0]