diff --git a/README.md b/README.md index fd06457..13c9a41 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ The experimental checks are disabled by default: |----------|---------------------------------------------------------------------------------------------------------------------------------------------| | notowned | **[Not Owned File Checker]**

Reports if a given repository contain files that do not have specified owners in CODEOWNERS file. | -To enable experimental check set `EXPERIMENTAL_CHECKS=notowned` environment variable. +To enable experimental check set `EXPERIMENTAL_CHECKS=notowned` environment variable. Check the [Configuration](#configuration) section for more info on how to enable and configure given checks. @@ -117,24 +117,25 @@ Check the [Configuration](#configuration) section for more info on how to enable Use the following environment variables to configure the application: -| Name | Default | Description | -|-----|:--------|:------------| -| REPOSITORY_PATH * | | Path to your repository on your local machine. | -| GITHUB_ACCESS_TOKEN| | GitHub access token. Instruction for creating a token can be found [here](./docs/gh-token.md). If not provided, the owners validating functionality may not work properly. For example, you may reach the API calls quota or, if you are setting GitHub Enterprise base URL, an unauthorized error may occur. | -| GITHUB_BASE_URL| https://api.github.com/ | GitHub base URL for API requests. Defaults to the public GitHub API but can be set to a domain endpoint to use with GitHub Enterprise. | -| GITHUB_UPLOAD_URL | https://uploads.github.com/ | GitHub upload URL for uploading files.

It is taken into account only when `GITHUB_BASE_URL` is also set. If only `GITHUB_BASE_URL` is provided, this parameter defaults to the `GITHUB_BASE_URL` value. | -| CHECKS| - | List of checks to be executed. By default, all checks are executed. Possible values: `files`,`owners`,`duppatterns`,`syntax`. | -| EXPERIMENTAL_CHECKS | - | The comma-separated list of experimental checks that should be executed. By default, all experimental checks are turned off. Possible values: `notowned`.| -| CHECK_FAILURE_LEVEL | `warning` | Defines the level on which the application should treat check issues as failures. Defaults to `warning`, which treats both errors and warnings as failures, and exits with error code 3. Possible values are `error` and `warning`. | -| 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"`. | -| 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` | +| Name | Default | Description | +|------------------------------------------------|:--------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| REPOSITORY_PATH * | | Path to your repository on your local machine. | +| GITHUB_ACCESS_TOKEN | | GitHub access token. Instruction for creating a token can be found [here](./docs/gh-token.md). If not provided, the owners validating functionality may not work properly. For example, you may reach the API calls quota or, if you are setting GitHub Enterprise base URL, an unauthorized error may occur. | +| GITHUB_BASE_URL | `https://api.github.com/` | GitHub base URL for API requests. Defaults to the public GitHub API but can be set to a domain endpoint to use with GitHub Enterprise. | +| GITHUB_UPLOAD_URL | `https://uploads.github.com/` | GitHub upload URL for uploading files.

It is taken into account only when `GITHUB_BASE_URL` is also set. If only `GITHUB_BASE_URL` is provided, this parameter defaults to the `GITHUB_BASE_URL` value. | +| CHECKS | - | List of checks to be executed. By default, all checks are executed. Possible values: `files`,`owners`,`duppatterns`,`syntax`. | +| EXPERIMENTAL_CHECKS | - | The comma-separated list of experimental checks that should be executed. By default, all experimental checks are turned off. Possible values: `notowned`. | +| CHECK_FAILURE_LEVEL | `warning` | Defines the level on which the application should treat check issues as failures. Defaults to `warning`, which treats both errors and warnings as failures, and exits with error code 3. Possible values are `error` and `warning`. | +| 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. | +| 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 #### Exit status codes -Application exits with different status codes which allow you to easily distinguish between error categories. +Application exits with different status codes which allow you to easily distinguish between error categories. | Code | Description | |:-----:|:------------| @@ -144,7 +145,7 @@ Application exits with different status codes which allow you to easily distingu ## Contributing -Contributions are greatly appreciated! The project follows the typical GitHub pull request model. See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. +Contributions are greatly appreciated! The project follows the typical GitHub pull request model. See [CONTRIBUTING.md](CONTRIBUTING.md) for more details. ## Roadmap diff --git a/action.yml b/action.yml index 3d04fc8..7e16ed9 100644 --- a/action.yml +++ b/action.yml @@ -47,6 +47,11 @@ inputs: description: "The comma-separated list of owners that should not be validated. Example: @owner1,@owner2,@org/team1,example@email.com." required: false + owner_checker_allow_unowned_patterns: + description: "Specifies whether CODEOWNERS may have unowned files. For example, `/infra/oncall-rotator/oncall-config.yml` doesn't have owner and this is not reported." + default: "true" + required: false + runs: using: 'docker' image: 'docker://mszostok/codeowners-validator:v0.6.0' diff --git a/internal/check/duplicated_pattern.go b/internal/check/duplicated_pattern.go index 456a86c..e9ac3ed 100644 --- a/internal/check/duplicated_pattern.go +++ b/internal/check/duplicated_pattern.go @@ -36,7 +36,7 @@ func (d *DuplicatedPattern) Check(ctx context.Context, in Input) (Output, error) for name, entries := range patterns { if len(entries) > 1 { - msg := fmt.Sprintf("Pattern %q is defined %d times in lines: \n%s", name, len(entries), d.listFormatFunc(entries)) + msg := fmt.Sprintf("Pattern %q is defined %d times in lines:\n%s", name, len(entries), d.listFormatFunc(entries)) bldr.ReportIssue(msg) } } diff --git a/internal/check/duplicated_pattern_test.go b/internal/check/duplicated_pattern_test.go index b88252c..20a75b5 100644 --- a/internal/check/duplicated_pattern_test.go +++ b/internal/check/duplicated_pattern_test.go @@ -18,7 +18,7 @@ func TestDuplicatedPattern(t *testing.T) { "Should report info about duplicated entries": { codeownersInput: ` * @global-owner1 @global-owner2 - + /build/logs/ @doctocat /build/logs/ @doctocat @@ -29,21 +29,21 @@ func TestDuplicatedPattern(t *testing.T) { { Severity: check.Error, LineNo: nil, - Message: `Pattern "/build/logs/" is defined 2 times in lines: + Message: `Pattern "/build/logs/" is defined 2 times in lines: * 4: with owners: [@doctocat] * 5: with owners: [@doctocat]`, }, { Severity: check.Error, LineNo: nil, - Message: `Pattern "/script" is defined 2 times in lines: + Message: `Pattern "/script" is defined 2 times in lines: * 7: with owners: [@mszostok] * 8: with owners: [m.t@g.com]`, }, }, }, "Should not report any issues with correct CODEOWNERS file": { - codeownersInput: check.FixtureValidCODEOWNERS, + codeownersInput: FixtureValidCODEOWNERS, expectedIssues: nil, }, } @@ -54,7 +54,7 @@ func TestDuplicatedPattern(t *testing.T) { sut := check.NewDuplicatedPattern() // when - out, err := sut.Check(context.TODO(), check.LoadInput(tc.codeownersInput)) + out, err := sut.Check(context.TODO(), LoadInput(tc.codeownersInput)) // then require.NoError(t, err) diff --git a/internal/check/file_exists_test.go b/internal/check/file_exists_test.go index ea0dd07..4c82472 100644 --- a/internal/check/file_exists_test.go +++ b/internal/check/file_exists_test.go @@ -169,7 +169,7 @@ func TestFileExists(t *testing.T) { defer cancel() // when - in := check.LoadInput(tc.codeownersInput) + in := LoadInput(tc.codeownersInput) in.RepoDir = tmp out, err := fchecker.Check(ctx, in) @@ -191,7 +191,7 @@ func TestFileExistCheckFileSystemFailure(t *testing.T) { err = os.MkdirAll(filepath.Join(tmpdir, "foo"), 0222) require.NoError(t, err) - in := check.LoadInput("* @pico") + in := LoadInput("* @pico") in.RepoDir = tmpdir ctx, cancel := context.WithTimeout(context.Background(), 30*time.Millisecond) diff --git a/internal/check/helpers_test.go b/internal/check/helpers_test.go index 087be84..9fb24f0 100644 --- a/internal/check/helpers_test.go +++ b/internal/check/helpers_test.go @@ -1,7 +1,12 @@ -package check +package check_test import ( "strings" + "testing" + + "github.com/mszostok/codeowners-validator/internal/check" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" "github.com/mszostok/codeowners-validator/pkg/codeowners" ) @@ -20,10 +25,21 @@ var FixtureValidCODEOWNERS = ` /script m.t@g.com ` -func LoadInput(in string) Input { +func LoadInput(in string) check.Input { r := strings.NewReader(in) - return Input{ + return check.Input{ CodeownersEntries: codeowners.ParseCodeowners(r), } } + +func assertIssue(t *testing.T, expIssue *check.Issue, gotIssues []check.Issue) { + t.Helper() + + if expIssue != nil { + require.Len(t, gotIssues, 1) + assert.EqualValues(t, *expIssue, gotIssues[0]) + } else { + assert.Empty(t, gotIssues) + } +} diff --git a/internal/check/not_owned_file.go b/internal/check/not_owned_file.go index 7d28bc6..55baf9c 100644 --- a/internal/check/not_owned_file.go +++ b/internal/check/not_owned_file.go @@ -73,7 +73,7 @@ func (c *NotOwnedFile) Check(ctx context.Context, in Input) (output Output, err lsOut := strings.TrimSpace(out) if lsOut != "" { lines := strings.Split(lsOut, "\n") - msg := fmt.Sprintf("Found %d not owned files (skipped patterns: %q): \n%s", len(lines), c.skipPatternsList(), c.ListFormatFunc(lines)) + msg := fmt.Sprintf("Found %d not owned files (skipped patterns: %q):\n%s", len(lines), c.skipPatternsList(), c.ListFormatFunc(lines)) bldr.ReportIssue(msg) } diff --git a/internal/check/package_test.go b/internal/check/package_test.go index 730ca96..f75df2f 100644 --- a/internal/check/package_test.go +++ b/internal/check/package_test.go @@ -33,7 +33,7 @@ func TestRespectingCanceledContext(t *testing.T) { cancel() // when - out, err := sut.Check(ctx, check.LoadInput(check.FixtureValidCODEOWNERS)) + out, err := sut.Check(ctx, LoadInput(FixtureValidCODEOWNERS)) // then assert.True(t, errors.Is(err, context.Canceled)) diff --git a/internal/check/valid_owner.go b/internal/check/valid_owner.go index b3e1e67..232086c 100644 --- a/internal/check/valid_owner.go +++ b/internal/check/valid_owner.go @@ -19,16 +19,24 @@ type ValidOwnerConfig struct { // More info about the @ghost user: https://docs.github.com/en/free-pro-team@latest/github/setting-up-and-managing-your-github-user-account/deleting-your-user-account // Tip on how @ghost can be used: https://github.community/t5/How-to-use-Git-and-GitHub/CODEOWNERS-file-with-a-NOT-file-type-condition/m-p/31013/highlight/true#M8523 IgnoredOwners []string `envconfig:"default=@ghost"` + // AllowUnownedPatterns 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` this file is not owned by anyone. + AllowUnownedPatterns bool `envconfig:"default=true"` } // ValidOwner validates each owner type ValidOwner struct { - ghClient *github.Client - orgMembers *map[string]struct{} - orgName string - orgTeams []*github.Team - orgRepoName string - ignOwners map[string]struct{} + ghClient *github.Client + orgMembers *map[string]struct{} + orgName string + orgTeams []*github.Team + orgRepoName string + ignOwners map[string]struct{} + allowUnownedPatterns bool } // NewValidOwner returns new instance of the ValidOwner @@ -44,10 +52,11 @@ func NewValidOwner(cfg ValidOwnerConfig, ghClient *github.Client) (*ValidOwner, } return &ValidOwner{ - ghClient: ghClient, - orgName: split[0], - orgRepoName: split[1], - ignOwners: ignOwners, + ghClient: ghClient, + orgName: split[0], + orgRepoName: split[1], + ignOwners: ignOwners, + allowUnownedPatterns: cfg.AllowUnownedPatterns, }, nil } @@ -69,6 +78,11 @@ func (v *ValidOwner) Check(ctx context.Context, in Input) (Output, error) { checkedOwners := map[string]struct{}{} for _, entry := range in.CodeownersEntries { + if len(entry.Owners) == 0 && !v.allowUnownedPatterns { + bldr.ReportIssue("Missing owner, at least one owner is required", WithEntry(entry), WithSeverity(Warning)) + continue + } + for _, ownerName := range entry.Owners { if ctxutil.ShouldExit(ctx) { return Output{}, ctx.Err() diff --git a/internal/check/valid_owner_export_test.go b/internal/check/valid_owner_export_test.go new file mode 100644 index 0000000..7dcf313 --- /dev/null +++ b/internal/check/valid_owner_export_test.go @@ -0,0 +1,5 @@ +package check + +func IsValidOwner(owner string) bool { + return isEmailAddress(owner) || isGithubUser(owner) || isGithubTeam(owner) +} diff --git a/internal/check/valid_owner_test.go b/internal/check/valid_owner_test.go index 17ec8e6..8297d88 100644 --- a/internal/check/valid_owner_test.go +++ b/internal/check/valid_owner_test.go @@ -1,9 +1,11 @@ -package check +package check_test import ( "context" "testing" + "github.com/mszostok/codeowners-validator/internal/check" + "github.com/mszostok/codeowners-validator/internal/ptr" "github.com/stretchr/testify/require" @@ -43,7 +45,7 @@ func TestValidOwnerChecker(t *testing.T) { for tn, tc := range tests { t.Run(tn, func(t *testing.T) { // when - result := isValidOwner(tc.owner) + result := check.IsValidOwner(tc.owner) assert.Equal(t, tc.isValid, result) }) } @@ -52,7 +54,7 @@ func TestValidOwnerChecker(t *testing.T) { func TestValidOwnerCheckerIgnoredOwner(t *testing.T) { t.Run("Should ignore owner", func(t *testing.T) { // given - ownerCheck, err := NewValidOwner(ValidOwnerConfig{ + ownerCheck, err := check.NewValidOwner(check.ValidOwnerConfig{ Repository: "org/repo", IgnoredOwners: []string{"@owner1"}, }, nil) @@ -69,31 +71,50 @@ func TestValidOwnerCheckerIgnoredOwner(t *testing.T) { }) t.Run("Should ignore user only and check the remaining owners", func(t *testing.T) { - // given - ownerCheck, err := NewValidOwner(ValidOwnerConfig{ - Repository: "org/repo", - IgnoredOwners: []string{"@owner1"}, - }, nil) - require.NoError(t, err) - - givenCodeowners := `* @owner1 badOwner` - - expIssue := Issue{ - Severity: Error, - LineNo: ptr.Uint64Ptr(1), - Message: `Not valid owner definition "badOwner"`, + tests := map[string]struct { + codeowners string + issue *check.Issue + allowUnownedPatterns bool + }{ + "No owners": { + codeowners: `*`, + issue: &check.Issue{ + Severity: check.Warning, + LineNo: ptr.Uint64Ptr(1), + Message: "Missing owner, at least one owner is required", + }, + }, + "Bad owner definition": { + codeowners: `* badOwner @owner1`, + issue: &check.Issue{ + Severity: check.Error, + LineNo: ptr.Uint64Ptr(1), + Message: `Not valid owner definition "badOwner"`, + }, + }, + "No owners but allow empty": { + codeowners: `*`, + issue: nil, + allowUnownedPatterns: true, + }, } + for tn, tc := range tests { + t.Run(tn, func(t *testing.T) { + // given + ownerCheck, err := check.NewValidOwner(check.ValidOwnerConfig{ + Repository: "org/repo", + AllowUnownedPatterns: tc.allowUnownedPatterns, + IgnoredOwners: []string{"@owner1"}, + }, nil) + require.NoError(t, err) - // when - out, err := ownerCheck.Check(context.Background(), LoadInput(givenCodeowners)) + // when + out, err := ownerCheck.Check(context.Background(), LoadInput(tc.codeowners)) - // then - require.NoError(t, err) - require.Len(t, out.Issues, 1) - require.EqualValues(t, expIssue, out.Issues[0]) + // then + require.NoError(t, err) + assertIssue(t, tc.issue, out.Issues) + }) + } }) } - -func isValidOwner(owner string) bool { - return isEmailAddress(owner) || isGithubUser(owner) || isGithubTeam(owner) -} diff --git a/internal/check/valid_syntax.go b/internal/check/valid_syntax.go index 1f3f657..bf0232a 100644 --- a/internal/check/valid_syntax.go +++ b/internal/check/valid_syntax.go @@ -32,7 +32,7 @@ func NewValidSyntax() *ValidSyntax { } // Check for syntax issues in your CODEOWNERS file. -func (ValidSyntax) Check(ctx context.Context, in Input) (Output, error) { +func (v *ValidSyntax) Check(ctx context.Context, in Input) (Output, error) { var bldr OutputBuilder for _, entry := range in.CodeownersEntries { @@ -44,10 +44,6 @@ func (ValidSyntax) Check(ctx context.Context, in Input) (Output, error) { bldr.ReportIssue("Missing pattern", WithEntry(entry)) } - if len(entry.Owners) == 0 { - bldr.ReportIssue("Missing owner, at least one owner is required", WithEntry(entry)) - } - ownersLoop: for _, item := range entry.Owners { switch { diff --git a/internal/check/valid_syntax_test.go b/internal/check/valid_syntax_test.go index f1a1019..e74522e 100644 --- a/internal/check/valid_syntax_test.go +++ b/internal/check/valid_syntax_test.go @@ -15,19 +15,15 @@ import ( func TestValidSyntaxChecker(t *testing.T) { tests := map[string]struct { codeowners string - issue check.Issue + issue *check.Issue }{ "No owners": { codeowners: `*`, - issue: check.Issue{ - Severity: check.Error, - LineNo: ptr.Uint64Ptr(1), - Message: "Missing owner, at least one owner is required", - }, + issue: nil, }, "Bad username": { codeowners: `pkg/github.com/** @-`, - issue: check.Issue{ + issue: &check.Issue{ Severity: check.Warning, LineNo: ptr.Uint64Ptr(1), Message: "Owner '@-' does not look like a GitHub username or team name", @@ -35,7 +31,7 @@ func TestValidSyntaxChecker(t *testing.T) { }, "Bad org": { codeowners: `* @bad+org`, - issue: check.Issue{ + issue: &check.Issue{ Severity: check.Warning, LineNo: ptr.Uint64Ptr(1), Message: "Owner '@bad+org' does not look like a GitHub username or team name", @@ -43,7 +39,7 @@ func TestValidSyntaxChecker(t *testing.T) { }, "Bad team name on first place": { codeowners: `* @org/+not+a+good+name`, - issue: check.Issue{ + issue: &check.Issue{ Severity: check.Warning, LineNo: ptr.Uint64Ptr(1), Message: "Owner '@org/+not+a+good+name' does not look like a GitHub username or team name", @@ -51,7 +47,7 @@ func TestValidSyntaxChecker(t *testing.T) { }, "Bad team name on second place": { codeowners: `* @org/hakuna-matata @org/-a-team`, - issue: check.Issue{ + issue: &check.Issue{ Severity: check.Warning, LineNo: ptr.Uint64Ptr(1), Message: "Owner '@org/-a-team' does not look like a GitHub username or team name", @@ -59,7 +55,7 @@ func TestValidSyntaxChecker(t *testing.T) { }, "Doesn't look like username, team name, nor email": { codeowners: `* something_weird`, - issue: check.Issue{ + issue: &check.Issue{ Severity: check.Error, LineNo: ptr.Uint64Ptr(1), Message: "Owner 'something_weird' does not look like an email", @@ -67,7 +63,7 @@ func TestValidSyntaxChecker(t *testing.T) { }, "Comment in pattern line": { codeowners: `* @org/hakuna-matata # this should be an error`, - issue: check.Issue{ + issue: &check.Issue{ Severity: check.Error, LineNo: ptr.Uint64Ptr(1), Message: "Comment (# sign) is not allowed in line with pattern entry. The correct format is: pattern owner1 ... ownerN", @@ -78,13 +74,12 @@ func TestValidSyntaxChecker(t *testing.T) { t.Run(tn, func(t *testing.T) { // when out, err := check.NewValidSyntax(). - Check(context.Background(), check.LoadInput(tc.codeowners)) + Check(context.Background(), LoadInput(tc.codeowners)) // then require.NoError(t, err) - require.Len(t, out.Issues, 1) - assert.EqualValues(t, tc.issue, out.Issues[0]) + assertIssue(t, tc.issue, out.Issues) }) } } @@ -106,11 +101,6 @@ func TestValidSyntaxZeroValueEntry(t *testing.T) { Severity: check.Error, Message: "Missing pattern", }, - { - LineNo: ptr.Uint64Ptr(0), - Severity: check.Error, - Message: "Missing owner, at least one owner is required", - }, } // when @@ -120,6 +110,6 @@ func TestValidSyntaxZeroValueEntry(t *testing.T) { // then require.NoError(t, err) - require.Len(t, out.Issues, 2) + require.Len(t, out.Issues, len(expIssues)) assert.EqualValues(t, expIssues, out.Issues) } diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go index 8473d1e..4990ae4 100644 --- a/tests/integration/integration_test.go +++ b/tests/integration/integration_test.go @@ -1,3 +1,4 @@ +//go:build integration // +build integration package integration @@ -120,9 +121,10 @@ func TestCheckFailures(t *testing.T) { { name: "owners", envs: Envs{ - "CHECKS": "owners", - "OWNER_CHECKER_REPOSITORY": "gh-codeowners/codeowners-samples", - "GITHUB_ACCESS_TOKEN": os.Getenv("GITHUB_TOKEN"), + "CHECKS": "owners", + "OWNER_CHECKER_REPOSITORY": "gh-codeowners/codeowners-samples", + "OWNER_CHECKER_ALLOW_UNOWNED_PATTERNS": "false", + "GITHUB_ACCESS_TOKEN": os.Getenv("GITHUB_TOKEN"), }, }, { diff --git a/tests/integration/testdata/TestCheckFailures/duppatterns.golden.txt b/tests/integration/testdata/TestCheckFailures/duppatterns.golden.txt index 612c30f..4a6addc 100644 --- a/tests/integration/testdata/TestCheckFailures/duppatterns.golden.txt +++ b/tests/integration/testdata/TestCheckFailures/duppatterns.golden.txt @@ -1,5 +1,5 @@ ==> Executing Duplicated Pattern Checker () - [err] Pattern "/some/awesome/dir" is defined 2 times in lines: + [err] Pattern "/some/awesome/dir" is defined 2 times in lines: * 10: with owners: [@mszostok @owner-a] * 11: with owners: [@octocat] diff --git a/tests/integration/testdata/TestCheckFailures/notowned.golden.txt b/tests/integration/testdata/TestCheckFailures/notowned.golden.txt index 5e4f0f7..9769af2 100644 --- a/tests/integration/testdata/TestCheckFailures/notowned.golden.txt +++ b/tests/integration/testdata/TestCheckFailures/notowned.golden.txt @@ -1,6 +1,5 @@ ==> Executing [Experimental] Not Owned File Checker () - [err] Found 3 not owned files (skipped patterns: "*"): - * .github/workflows/cron.yml + [err] Found 2 not owned files (skipped patterns: "*"): * .gitignore * CODEOWNERS diff --git a/tests/integration/testdata/TestCheckFailures/owners.golden.txt b/tests/integration/testdata/TestCheckFailures/owners.golden.txt index 024a2ef..cb9f0f9 100644 --- a/tests/integration/testdata/TestCheckFailures/owners.golden.txt +++ b/tests/integration/testdata/TestCheckFailures/owners.golden.txt @@ -39,5 +39,6 @@ [err] line 15: Team "warriors" does not have permissions associated with the repository "codeowners-samples". [err] line 15: Team "wolf-pack" does not have permissions associated with the repository "codeowners-samples". [err] line 17: Team "not-existing-team" does not exist in organization "gh-codeowners". + [war] line 23: Missing owner, at least one owner is required 1 check(s) executed, 1 failure(s)