diff --git a/.dockerignore b/.dockerignore
index df9a8584..3ac0ee37 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -2,4 +2,4 @@
**
# Allow binary
-!/codeowners-validator
+!/codeowners
diff --git a/.gitignore b/.gitignore
index 210df0fd..62e6c4b9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,6 @@
scripts/
.idea
-codeowners-validator
+/codeowners
dist/
tmp/
bin/
diff --git a/.goreleaser.yml b/.goreleaser.yml
index 8bf525c6..97801da5 100644
--- a/.goreleaser.yml
+++ b/.goreleaser.yml
@@ -1,5 +1,5 @@
builds:
- - id: codeowners-validator
+ - id: codeowners
env:
- CGO_ENABLED=0
goos:
@@ -35,15 +35,15 @@ archives:
dockers:
- dockerfile: Dockerfile
ids:
- - codeowners-validator
+ - codeowners
image_templates:
- - "ghcr.io/mszostok/codeowners-validator:stable"
- - "ghcr.io/mszostok/codeowners-validator:{{ .Tag }}"
- - "ghcr.io/mszostok/codeowners-validator:v{{ .Major }}.{{ .Minor }}"
- - "ghcr.io/mszostok/codeowners-validator:v{{ .Major }}"
- - "mszostok/codeowners-validator:latest"
- - "mszostok/codeowners-validator:{{ .Tag }}"
- - "mszostok/codeowners-validator:v{{ .Major }}.{{ .Minor }}"
+ - "ghcr.io/mszostok/codeowners:stable"
+ - "ghcr.io/mszostok/codeowners:{{ .Tag }}"
+ - "ghcr.io/mszostok/codeowners:v{{ .Major }}.{{ .Minor }}"
+ - "ghcr.io/mszostok/codeowners:v{{ .Major }}"
+ - "mszostok/codeowners:latest"
+ - "mszostok/codeowners:{{ .Tag }}"
+ - "mszostok/codeowners:v{{ .Major }}.{{ .Minor }}"
checksum:
name_template: 'checksums.txt'
@@ -68,11 +68,11 @@ release:
# Default is extracted from the origin remote URL or empty if its private hosted.
github:
owner: mszostok
- name: codeowners-validator
+ name: codeowners
brews:
- - name: codeowners-validator
- homepage: https://github.com/mszostok/codeowners-validator
+ - name: codeowners
+ homepage: https://github.com/mszostok/codeowners
description: Ensures the correctness of your CODEOWNERS file.
license: "Apache License 2.0"
tap:
@@ -82,4 +82,4 @@ brews:
name: Mateusz Szostok
email: szostok.mateusz@gmail.com
test: |
- system "#{bin}/codeowners-validator -v --short"
+ system "#{bin}/codeowners -v --short"
diff --git a/.pre-commit-hooks.yaml b/.pre-commit-hooks.yaml
new file mode 100644
index 00000000..11c3ad33
--- /dev/null
+++ b/.pre-commit-hooks.yaml
@@ -0,0 +1,6 @@
+- id: codeowners
+ name: Validate CODEOWNERS file
+ description: Ensures the correctness of your CODEOWNERS file.
+ language: golang
+ # TODO: types: hardcode expected file location?
+ entry: codeowners validate
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index b47ebec1..ed6d734b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -9,26 +9,26 @@ This document contains contribution guidelines for this repository. Read it befo
## Contributing
-Before proposing or adding changes, check the [existing issues](https://github.com/mszostok/codeowners-validator/issues) and make sure the discussion/work has not already been started to avoid duplication.
+Before proposing or adding changes, check the [existing issues](https://github.com/mszostok/codeowners/issues) and make sure the discussion/work has not already been started to avoid duplication.
-If you'd like to see a new feature implemented, use this [feature request template](https://github.com/mszostok/codeowners-validator/issues/new?assignees=&labels=&template=feature_request.md) to create an issue.
+If you'd like to see a new feature implemented, use this [feature request template](https://github.com/mszostok/codeowners/issues/new?assignees=&labels=&template=feature_request.md) to create an issue.
-Similarly, if you spot a bug, use this [bug report template](https://github.com/mszostok/codeowners-validator/issues/new?assignees=mszostok&labels=bug&template=bug_report.md) to let us know!
+Similarly, if you spot a bug, use this [bug report template](https://github.com/mszostok/codeowners/issues/new?assignees=mszostok&labels=bug&template=bug_report.md) to let us know!
### Ready for action? Start developing!
To start contributing, follow these steps:
-1. Fork the `codeowners-validator` repository.
+1. Fork the `codeowners` repository.
2. Clone the repository locally.
> **TIP:** This project uses Go modules, so you can check it out locally wherever you want. It doesn't need to be checked out in `$GOPATH`.
-3. Set the `codeowners-validator` repository as upstream:
+3. Set the `codeowners` repository as upstream:
```bash
- git remote add upstream git@github.com:mszostok/codeowners-validator.git
+ git remote add upstream git@github.com:mszostok/codeowners.git
```
4. Fetch all the remote branches for this repository:
diff --git a/Dockerfile b/Dockerfile
index 97ee0fd1..26e26f6b 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,9 +6,9 @@ RUN apk --no-cache add ca-certificates git
FROM scratch
-LABEL org.opencontainers.image.source=https://github.com/mszostok/codeowners-validator
+LABEL org.opencontainers.image.source=https://github.com/mszostok/codeowners
-COPY ./codeowners-validator /codeowners-validator
+COPY ./codeowners /codeowners
COPY --from=deps /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt
COPY --from=deps /usr/bin/git /usr/bin/git
@@ -16,4 +16,4 @@ COPY --from=deps /usr/bin/xargs /usr/bin/xargs
COPY --from=deps /lib /lib
COPY --from=deps /usr/lib /usr/lib
-ENTRYPOINT ["/codeowners-validator"]
+ENTRYPOINT ["/codeowners"]
diff --git a/Makefile b/Makefile
index 01284640..ab5db449 100644
--- a/Makefile
+++ b/Makefile
@@ -13,7 +13,7 @@ all: build-race test-unit test-integration test-lint
# When running integration tests on windows machine
# it cannot execute binary without extension.
# It needs to be parametrized, so we can override it on CI.
-export BINARY_PATH = $(ROOT_DIR)/codeowners-validator$(BINARY_EXT)
+export BINARY_PATH = $(ROOT_DIR)/codeowners$(BINARY_EXT)
############
# Building #
diff --git a/README.md b/README.md
index cc5fd98d..971e114a 100644
--- a/README.md
+++ b/README.md
@@ -11,7 +11,7 @@
## Codeowners Validator
-
+
The Codeowners Validator project validates the GitHub [CODEOWNERS](https://help.github.com/articles/about-code-owners/) file based on [specified checks](#checks). It supports public and private GitHub repositories and also GitHub Enterprise installations.
@@ -29,7 +29,7 @@ docker run --rm -v $(pwd):/repo -w /repo \
-e GITHUB_ACCESS_TOKEN="$GH_TOKEN" \
-e EXPERIMENTAL_CHECKS="notowned" \
-e OWNER_CHECKER_REPOSITORY="org-name/rep-name" \
- mszostok/codeowners-validator:v0.7.4
+ mszostok/codeowners:v0.7.4
```
#### Command line
@@ -40,13 +40,13 @@ env REPOSITORY_PATH="." \
GITHUB_ACCESS_TOKEN="$GH_TOKEN" \
EXPERIMENTAL_CHECKS="notowned" \
OWNER_CHECKER_REPOSITORY="org-name/rep-name" \
- codeowners-validator
+ codeowners
```
#### GitHub Action
```yaml
-- uses: mszostok/codeowners-validator@v0.7.4
+- uses: mszostok/codeowners@v0.7.4
with:
checks: "files,owners,duppatterns,syntax"
experimental_checks: "notowned,avoid-shadowing"
@@ -62,44 +62,44 @@ Check the [Configuration](#configuration) section for more info on how to enable
## Installation
-It's highly recommended to install a fixed version of `codeowners-validator`. Releases are available on the [releases page](https://github.com/mszostok/codeowners-validator/releases).
+It's highly recommended to install a fixed version of `codeowners`. Releases are available on the [releases page](https://github.com/mszostok/codeowners/releases).
### macOS & Linux
-`codeowners-validator` is available via [Homebrew](https://brew.sh/index_pl).
+`codeowners` is available via [Homebrew](https://brew.sh/index_pl).
#### Homebrew
| Install | Upgrade |
|--------------------------------------------------|--------------------------------------------------|
-| `brew install mszostok/tap/codeowners-validator` | `brew upgrade mszostok/tap/codeowners-validator` |
+| `brew install mszostok/tap/codeowners` | `brew upgrade mszostok/tap/codeowners` |
#### Install script
```bash
# binary installed into ./bin/
-curl -sfL https://raw.githubusercontent.com/mszostok/codeowners-validator/main/install.sh | sh -s v0.7.4
+curl -sfL https://raw.githubusercontent.com/mszostok/codeowners/main/install.sh | sh -s v0.7.4
-# binary installed into $(go env GOPATH)/bin/codeowners-validator
-curl -sfL https://raw.githubusercontent.com/mszostok/codeowners-validator/main/install.sh | sh -s -- -b $(go env GOPATH)/bin v0.7.4
+# binary installed into $(go env GOPATH)/bin/codeowners
+curl -sfL https://raw.githubusercontent.com/mszostok/codeowners/main/install.sh | sh -s -- -b $(go env GOPATH)/bin v0.7.4
# In alpine linux (as it does not come with curl by default)
-wget -O - -q https://raw.githubusercontent.com/mszostok/codeowners-validator/main/install.sh | sh -s v0.7.4
+wget -O - -q https://raw.githubusercontent.com/mszostok/codeowners/main/install.sh | sh -s v0.7.4
# Print version. Add `--oshort` to print just the version number.
-codeowners-validator version
+codeowners version
```
-You can also download [latest version](https://github.com/mszostok/codeowners-validator/releases/latest) from release page manually.
+You can also download [latest version](https://github.com/mszostok/codeowners/releases/latest) from release page manually.
#### From Sources
-
-You can install `codeowners-validator` with `go install github.com/mszostok/codeowners-validator@v0.7.4`.
+
+You can install `codeowners` with `go install github.com/mszostok/codeowners@v0.7.4`.
> NOTE: please use Go 1.16 or greater.
-This will put `codeowners-validator` in `$(go env GOPATH)/bin`.
+This will put `codeowners` in `$(go env GOPATH)/bin`.
## Checks
@@ -165,6 +165,6 @@ Contributions are greatly appreciated! The project follows the typical GitHub pu
## Roadmap
-The [codeowners-validator roadmap uses GitHub milestones](https://github.com/mszostok/codeowners-validator/milestone/1) to track the progress of the project.
+The [codeowners roadmap uses GitHub milestones](https://github.com/mszostok/codeowners/milestone/1) to track the progress of the project.
They are sorted with priority. First are most important.
diff --git a/action.yml b/action.yml
index 2dae83de..5ac83993 100644
--- a/action.yml
+++ b/action.yml
@@ -1,4 +1,4 @@
-name: "GitHub CODEOWNERS Validator"
+name: "GitHub CODEOWNERS"
description: "GitHub action to ensure the correctness of your CODEOWNERS file."
author: "szostok.mateusz@gmail.com"
@@ -8,7 +8,7 @@ inputs:
required: false
github_app_id:
- description: "Github App ID for authentication. This replaces the GITHUB_ACCESS_TOKEN. Instruction for creating a Github App can be found here: https://github.com/mszostok/codeowners-validator/blob/main/docs/gh-token.md"
+ description: "Github App ID for authentication. This replaces the GITHUB_ACCESS_TOKEN. Instruction for creating a Github App can be found here: https://github.com/mszostok/codeowners/blob/main/docs/gh-token.md"
required: false
github_app_installation_id:
@@ -80,7 +80,7 @@ inputs:
runs:
using: 'docker'
- image: 'docker://ghcr.io/mszostok/codeowners-validator:v0.7.4'
+ image: 'docker://ghcr.io/mszostok/codeowners:v0.7.4'
env:
ENVS_PREFIX: "INPUT"
diff --git a/cmd/codeowners/codeowners.go b/cmd/codeowners/codeowners.go
new file mode 100644
index 00000000..f7a2ff30
--- /dev/null
+++ b/cmd/codeowners/codeowners.go
@@ -0,0 +1,145 @@
+package cmd
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/cobra"
+ "github.com/spf13/pflag"
+ "github.com/spf13/viper"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/config"
+ "go.szostok.io/codeowners/internal/load"
+ "go.szostok.io/codeowners/internal/runner"
+ "go.szostok.io/codeowners/pkg/codeowners"
+ "go.szostok.io/version/extension"
+)
+
+//var severity api.SeverityType
+
+// NewRoot returns a root cobra.Command for the whole Agent utility.
+func RootCmd() *cobra.Command {
+ cfg := &config.Config{}
+
+ rootCmd := &cobra.Command{
+ Use: "codeowners",
+ Short: "Ensures the correctness of your CODEOWNERS file.",
+ SilenceUsage: true,
+ PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+ return InitializeConfig(cmd, cfg, args)
+ },
+ }
+
+ rootCmd.AddCommand(
+ extension.NewVersionCobraCmd(),
+ validateCmd(cfg),
+ )
+
+ return rootCmd
+}
+
+func validateCmd(cfg *config.Config) *cobra.Command {
+
+ var validateCmd = &cobra.Command{
+ Use: "validate",
+ Short: "Validate a CODEOWNERS file",
+
+ Run: func(cmd *cobra.Command, args []string) {
+ log := logrus.New()
+
+ // init checks
+ checks, err := load.Checks(cmd.Context(), cfg)
+ exitOnError(err)
+
+ // init codeowners entries
+ codeownersEntries, err := codeowners.NewFromPath(cfg.RepositoryPath)
+ exitOnError(err)
+
+ // run check runner
+ absRepoPath, err := filepath.Abs(cfg.RepositoryPath)
+ exitOnError(err)
+
+ checkRunner := runner.NewCheckRunner(log, codeownersEntries, absRepoPath, cfg.CheckFailureLevel, checks...)
+ checkRunner.Run(cmd.Context())
+
+ if cmd.Context().Err() != nil {
+ log.Error("Application was interrupted by operating system")
+ os.Exit(2)
+ }
+ if checkRunner.ShouldExitWithCheckFailure() {
+ os.Exit(3)
+ }
+ },
+ }
+ addValidateFlags(validateCmd)
+ return validateCmd
+}
+
+func addValidateFlags(cmd *cobra.Command) {
+ cmd.Flags().StringSlice("checks", nil, "List of checks to be executed")
+ //cmd.Flags().Var(&severity, "check-failure-level", "Defines the level on which the application should treat check issues as failures")
+ cmd.Flags().String("experimental-checks", "", "The comma-separated list of experimental checks that should be executed")
+ cmd.Flags().String("github-access-token", "", "GitHub access token")
+ cmd.Flags().String("github-base-url", "https://api.github.com/", "GitHub base URL for API requests")
+ cmd.Flags().String("github-upload-url", "https://uploads.github.com/", "GitHub upload URL for uploading files")
+ cmd.Flags().String("github-app-id", "", "Github App ID for authentication")
+ cmd.Flags().String("github-app-installation-id", "", "Github App Installation ID")
+ cmd.Flags().String("github-app-private-key", "", "Github App private key in PEM format")
+ cmd.Flags().StringSlice("not-owned-checker-skip-patterns", nil, "The comma-separated list of patterns that should be ignored by not-owned-checker")
+ cmd.Flags().StringSlice("not-owned-checker-subdirectories", nil, "The comma-separated list of subdirectories to check in not-owned-checker")
+ cmd.Flags().Bool("not-owned-checker-trust-workspace", false, "Specifies whether the repository path should be marked as safe")
+ cmd.Flags().String("repository-path", "", "Path to your repository on your local machine")
+ cmd.Flags().String("owner-checker-repository", "", "The owner and repository name separated by slash")
+ cmd.Flags().StringSlice("owner-checker-ignored-owners", []string{"@ghost"}, "The comma-separated list of owners that should not be validated")
+ cmd.Flags().Bool("owner-checker-allow-unowned-patterns", true, "Specifies whether CODEOWNERS may have unowned files")
+ cmd.Flags().Bool("owner-checker-owners-must-be-teams", false, "Specifies whether only teams are allowed as owners of files")
+}
+
+func exitOnError(err error) {
+ if err != nil {
+ logrus.Fatal(err)
+ }
+}
+
+func InitializeConfig(cmd *cobra.Command, cfg *config.Config, args []string) error {
+ v := viper.New()
+
+ // Look for config file, ignore if missing
+ v.SetConfigName(config.DefaultConfigFilename)
+ v.AddConfigPath(".")
+ if err := v.ReadInConfig(); err != nil {
+ if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
+ return err
+ }
+ }
+ // Look for environment variables
+ v.SetEnvPrefix(config.EnvPrefix)
+ v.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
+ v.AutomaticEnv()
+
+ // Bind flags to the configuration struct
+ bindFlags(cmd, v)
+
+ // Unmarshal the configuration into the struct
+ if err := v.Unmarshal(cfg); err != nil {
+ return err
+ }
+ cfg.CheckFailureLevel = api.Warning
+
+ return nil
+}
+
+// Bind each cobra flag to its associated viper configuration environment variable
+func bindFlags(cmd *cobra.Command, v *viper.Viper) {
+ cmd.Flags().VisitAll(func(f *pflag.Flag) {
+ configName := f.Name
+ if !f.Changed && v.IsSet(configName) {
+ val := v.Get(configName)
+ cmd.Flags().Set(f.Name, fmt.Sprintf("%v", val))
+ }
+ v.BindPFlag(configName, f)
+ })
+}
diff --git a/docs/assets/usage.svg b/docs/assets/usage.svg
index 687ed617..8ae9393b 100644
--- a/docs/assets/usage.svg
+++ b/docs/assets/usage.svg
@@ -1 +1 @@
-
+OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\▲▲#Downloadcodeownersbinary/binv0.2.0▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local/binv0.2.0mszostok/codeownersinfocheckingGitHubfortag'v0.2.0'mszostok/codeownersinfofoundversion:0.2.0forv0.2.0/Darwin/x86_64mszostok/codeownersinfoinstalled/usr/local/bin/codeowners▲#CloneexamplerepositorywithsampleCODEOWNERS▲#CloneexamplerepositorywithsampleCODEOWNERS▲gitclonegit@github.com:gh-codeowners/codeowners-samples.gitCloninginto'codeowners-samples'...remote:Enumeratingobjects:8,done.remote:Countingobjects:100%(8/8),done.remote:Compressingobjects:100%(3/3),done.remote:Total8(delta0),reused8(delta0),pack-reused0Receivingobjects:100%(8/8),done.▲#Executecodeownersagainstclonedrepository▲#ExecutecodeownersagainstclonedrepositoryEXPERIMENTAL_CHECKS="notowned"\GITHUB_ACCESS_TOKEN="${GH_TOKEN}"\▲#Downloadcodeownersbinarycodeowners▲envREPOSITORY_PATH="./codeowners-samples"\EXPERIMENTAL_CHECKS="notowned"\GITHUB_ACCESS_TOKEN="${GH_TOKEN}"\OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\codeowners==>ExecutingFileExistChecker(1.240501ms)[err]line13:"/scripts/"doesnotmatchanyfilesinrepository==>ExecutingDuplicatedPatternChecker(1.820841ms)[err]Pattern"/some/awesome/dir"isdefined2timesinlines:*10:withowners:[@mszostok@owner-a]*11:withowners:[@octocat]==>Executing[Experimental]NotOwnedFileChecker(38.920431ms)CheckOK==>ExecutingValidOwnerChecker(1.238375347s)[err]line8:User"@mszostok"isnotamemberoftheorganization[err]line10:User"@owner-a"doesnothavegithubaccount[err]line11:User"@octocat"isnotamemberoftheorganization4check(s)executed,3failure(s)▲▲#Downloadcodeownersbinary▲#Downloadcodeowners-validatorbinary▲#Downloadcodeownersbinary▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners-validator/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local▲curl-sfLhttps://raw.githubusercontent.com/mszostok/codeowners/main/install.sh|sh-s---b/usr/local/binv0.2.0/binv0.2.0/binv0.2.0/binv0.2.0▲#CloneexamplerepositorywithsampleCODEOWNERS▲#CloneexamplerepositorywithsampleCODEOWNERS▲#CloneexamplerepositorywithsampleCODEOWNERS▲#CloneexamplerepositorywithsampleCODEOWNERS▲#CloneexamplerepositorywithsampleCODEOWNERS▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.git▲gitclonegit@github.com:gh-codeowners/codeowners-samples.gitReceivingobjects:12%(1/8)Receivingobjects:100%(8/8)▲#Executecodeownersagainstclonedrepository▲#Executecodeowners-validatoragainstclonedrepository▲#Executecodeownersagainstclonedrepository▲#Executecodeownersagainstclonedrepository▲#Executecodeownersagainstclonedrepository▲envREPOSITORY_PATH="./codeowners-samples"\▲envREPOSITORY_PATH="./codeowners-samples"\▲envREPOSITORY_PATH="./codeowners-samples"\▲envREPOSITORY_PATH="./codeowners-samples"\▲envREPOSITORY_PATH="./codeowners-samples"\EXPERIMENTAL_CHECKS="notowned"\EXPERIMENTAL_CHECKS="notowned"\GITHUB_ACCESS_TOKEN="${GH_TOKEN}"\GITHUB_ACCESS_TOKEN="${GH_TOKEN}"\GITHUB_ACCESS_TOKEN="${GH_TOKEN}"\GITHUB_ACCESS_TOKEN="${GH_TOKEN}"\OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\OWNER_CHECKER_ORGANIZATION_NAME="gh-codeowners"\codeowners-validator[err]
diff --git a/docs/development.md b/docs/development.md
index 6a8e968e..832a43f2 100644
--- a/docs/development.md
+++ b/docs/development.md
@@ -74,7 +74,7 @@ make fix-lint-issues
This project supports the integration tests that are defined in the [tests](../tests) package. The tests are executed against [`gh-codeowners/codeowners-samples`](https://github.com/gh-codeowners/codeowners-samples).
> **CAUTION:** Currently, running the integration tests both on external PRs and locally by external contributors is not supported, as the teams used for testing are visible only to the organization members.
-> At the moment, the `codeowners-validator` repository owner is responsible for running these tests.
+> At the moment, the `codeowners` repository owner is responsible for running these tests.
## Build a binary
@@ -83,6 +83,6 @@ To generate a binary for this project, execute:
make build
```
-This command generates a binary named `codeowners-validator` in the root directory.
+This command generates a binary named `codeowners` in the root directory.
[↑ Back to top](#table-of-contents)
diff --git a/docs/gh-action.md b/docs/gh-action.md
index a57d8c26..ad2b71ba 100644
--- a/docs/gh-action.md
+++ b/docs/gh-action.md
@@ -9,10 +9,10 @@
##
-The [Codeowners Validator](https://github.com/mszostok/codeowners-validator) is available as a GitHub Action.
+The [Codeowners Validator](https://github.com/mszostok/codeowners) is available as a GitHub Action.
-
+
@@ -35,7 +35,7 @@ jobs:
# Checks-out your repository, which is validated in the next step
- uses: actions/checkout@v2
- name: GitHub CODEOWNERS Validator
- uses: mszostok/codeowners-validator@v0.7.4
+ uses: mszostok/codeowners@v0.7.4
# input parameters
with:
# ==== GitHub Auth ====
diff --git a/docs/gh-auth.md b/docs/gh-auth.md
index f41f1b3b..49eb31ae 100644
--- a/docs/gh-auth.md
+++ b/docs/gh-auth.md
@@ -57,7 +57,7 @@ Here are the steps to create a GitHub App and use it for this tool:
```yaml
- name: GitHub CODEOWNERS Validator
- uses: mszostok/codeowners-validator@v0.7.4
+ uses: mszostok/codeowners@v0.7.4
with:
# ...
github_app_id: ${{ secrets.APP_ID }}
diff --git a/docs/investigation/file_exists_checker/glob.md b/docs/investigation/file_exists_checker/glob.md
index 3fd3ed7e..4e8279e1 100644
--- a/docs/investigation/file_exists_checker/glob.md
+++ b/docs/investigation/file_exists_checker/glob.md
@@ -7,7 +7,7 @@ This document describes investigation about [`file exists`](../../../internal/ch
A [CODEOWNERS](https://docs.github.com/en/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax) file uses a pattern that follows the same rules used in [gitignore](https://git-scm.com/docs/gitignore#_pattern_format) files.
The gitignore files support two consecutive asterisks ("**") in patterns that match against the full path name. Unfortunately the core Go library `filepath.Glob` does not support [`**`](https://github.com/golang/go/issues/11862) at all.
-This caused that for some patterns the [`file exists`](../../../internal/check/file_exists.go) checker didn't work properly, see [issue#22](https://github.com/mszostok/codeowners-validator/issues/22).
+This caused that for some patterns the [`file exists`](../../../internal/check/file_exists.go) checker didn't work properly, see [issue#22](https://github.com/mszostok/codeowners/issues/22).
Additionally, we need to support a single asterisk at the beginning of the pattern. For example, `*.js` should check for all JS files in the whole git repository. To achieve that we need to detect that and change from `*.js` to `**/*.js`.
diff --git a/docs/investigation/file_exists_checker/go.mod b/docs/investigation/file_exists_checker/go.mod
index e95d277d..46bab2c8 100644
--- a/docs/investigation/file_exists_checker/go.mod
+++ b/docs/investigation/file_exists_checker/go.mod
@@ -1,4 +1,4 @@
-module github.com/mszostok/codeowners-validator/docs/investigation/file_exists_checker
+module github.com/mszostok/codeowners/docs/investigation/file_exists_checker
go 1.15
diff --git a/docs/release.md b/docs/release.md
index c8725e1d..923f9342 100644
--- a/docs/release.md
+++ b/docs/release.md
@@ -2,7 +2,7 @@
# Release process
-The release of the codeowners-validator tool is performed by the [GoReleaser](https://github.com/goreleaser/goreleaser) which builds Go binaries for several platforms and then creates a GitHub release.
+The release of the codeowners tool is performed by the [GoReleaser](https://github.com/goreleaser/goreleaser) which builds Go binaries for several platforms and then creates a GitHub release.
**Process**
diff --git a/go.mod b/go.mod
index 3550b18f..d7c35fe7 100644
--- a/go.mod
+++ b/go.mod
@@ -1,4 +1,4 @@
-module go.szostok.io/codeowners-validator
+module go.szostok.io/codeowners
go 1.18
@@ -13,22 +13,32 @@ require (
github.com/sebdah/goldie/v2 v2.5.3
github.com/sergi/go-diff v1.1.0 // indirect
github.com/sirupsen/logrus v1.9.0
- github.com/spf13/afero v1.9.2
- github.com/spf13/pflag v1.0.5 // indirect
- github.com/stretchr/testify v1.8.0
+ github.com/spf13/afero v1.9.3
+ github.com/spf13/pflag v1.0.5
+ github.com/stretchr/testify v1.8.2
github.com/vrischmann/envconfig v1.3.0
go.szostok.io/version v1.1.0
- golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa // indirect
- golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 // indirect
- golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99
- golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 // indirect
+ golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
+ golang.org/x/net v0.9.0 // indirect
+ golang.org/x/oauth2 v0.7.0
+ golang.org/x/sys v0.7.0 // indirect
gopkg.in/pipe.v2 v2.0.0-20140414041502-3c2ca4d52544
gopkg.in/src-d/go-git.v4 v4.13.1
- gotest.tools v2.2.0+incompatible
)
require github.com/spf13/cobra v1.5.0
+require (
+ github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/hashicorp/hcl v1.0.0 // indirect
+ github.com/magiconair/properties v1.8.7 // indirect
+ github.com/mitchellh/mapstructure v1.5.0 // indirect
+ github.com/pelletier/go-toml/v2 v2.0.6 // indirect
+ github.com/spf13/jwalterweatherman v1.1.0 // indirect
+ github.com/subosito/gotenv v1.4.2 // indirect
+ gopkg.in/ini.v1 v1.67.0 // indirect
+)
+
require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
@@ -39,8 +49,7 @@ require (
github.com/emirpasic/gods v1.12.0 // indirect
github.com/goccy/go-yaml v1.9.5 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
- github.com/golang/protobuf v1.4.3 // indirect
- github.com/google/go-cmp v0.5.8 // indirect
+ github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-github/v45 v45.2.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
@@ -52,7 +61,6 @@ require (
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect
- github.com/kr/pretty v0.2.1 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
@@ -64,13 +72,14 @@ require (
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
- github.com/spf13/cast v1.3.1 // indirect
+ github.com/spf13/cast v1.5.0 // indirect
+ github.com/spf13/viper v1.15.0
github.com/src-d/gcfg v1.4.0 // indirect
github.com/xanzy/ssh-agent v0.2.1 // indirect
- golang.org/x/text v0.3.4 // indirect
+ golang.org/x/text v0.9.0 // indirect
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
google.golang.org/appengine v1.6.7 // indirect
- google.golang.org/protobuf v1.25.0 // indirect
+ google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index 65d273ca..64fbd923 100644
--- a/go.sum
+++ b/go.sum
@@ -84,6 +84,9 @@ github.com/fatih/color v1.10.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGE
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0=
github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -121,8 +124,10 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -134,9 +139,10 @@ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-github/v41 v41.0.0 h1:HseJrM2JFf2vfiZJ8anY2hqBjdfY1Vlj/K27ueww4gg=
github.com/google/go-github/v41 v41.0.0/go.mod h1:XgmCA5H323A9rtgExdTcnDkcqp6S30AVACCBDOonIxg=
github.com/google/go-github/v45 v45.2.0 h1:5oRLszbrkvxDDqBCNj2hjDZMKmvexaZ1xw/FCD+K3FI=
@@ -171,6 +177,8 @@ github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mO
github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
+github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f h1:7LYC+Yfkj3CTRcShK0KOL/w6iTiKyqqBA9a41Wnggw8=
github.com/hokaccha/go-prettyjson v0.0.0-20211117102719-0474bc63780f/go.mod h1:pFlLw2CfqZiIBOx6BuCeRLCrfxBJipTY0nIOF/VbGcI=
github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
@@ -192,8 +200,7 @@ github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
@@ -202,6 +209,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
+github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
+github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
@@ -219,12 +228,16 @@ github.com/mitchellh/copystructure v1.0.0 h1:Laisrj+bAB6b/yJwB5Bt3ITZhGJdqmxquMK
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/muesli/termenv v0.13.0 h1:wK20DRpJdDX8b7Ek2QfhvqhRQFZ237RGRO0RQ/Iqdy0=
github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo=
+github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
+github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -236,6 +249,7 @@ github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ
github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/scylladb/termtables v0.0.0-20191203121021-c4c0b6d42ff4/go.mod h1:C1a7PQSMz9NShzorzCiG2fk9+xuCgLkPeCvMHYR2OWg=
github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624Y=
@@ -247,19 +261,25 @@ github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXY
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
-github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
-github.com/spf13/cast v1.3.1 h1:nFm6S0SMdyzrzcmThSipiEubIDy8WEXKNZ0UOgiRpng=
+github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
+github.com/spf13/afero v1.9.3/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
+github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
+github.com/spf13/cast v1.5.0/go.mod h1:SpXXQ5YoyJw6s3/6cMTQuxvgRl3PCJiyaX9p6b155UU=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
+github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
+github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.15.0 h1:js3yy885G8xwJa6iOISGFwd+qlUo5AvyXb7CiihdtiU=
+github.com/spf13/viper v1.15.0/go.mod h1:fFcTBJxvhhzSJiZy8n+PeW6t8l+KeT/uTARa0jHOQLA=
github.com/src-d/gcfg v1.4.0 h1:xXbNR5AlLSA315x2UO+fTSSAXCDf+Ar38/6oyGbDKQ4=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
+github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
@@ -267,8 +287,12 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
+github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
+github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/subosito/gotenv v1.4.2 h1:X1TuBLAMDFbaTAChgCBLu3DU3UPyELpnF2jjJ2cz/S8=
+github.com/subosito/gotenv v1.4.2/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
github.com/vrischmann/envconfig v1.3.0 h1:4XIvQTXznxmWMnjouj0ST5lFo/WAYf5Exgl3x82crEk=
github.com/vrischmann/envconfig v1.3.0/go.mod h1:bbvxFYJdRSpXrhS63mBFtKJzkDiNkyArOLXtY6q0kuI=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
@@ -295,8 +319,9 @@ golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa h1:idItI2DDfCokpg0N51B2VtiLdJ4vAuXC9fnCb2gACo4=
golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
+golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -360,8 +385,9 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110 h1:qWPm9rbaAMKs8Bq/9LRpbMqxWRVUAQwMI9fVrssnTfw=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
+golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -370,8 +396,9 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99 h1:5vD4XjIc0X5+kHZjx4UecYdjA6mJo+XXNoaW0EjU5Os=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
+golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -421,17 +448,19 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41 h1:ohgcoMbSofXygzo6AD2I1kz3BFmW1QArPYTtwEM3UXc=
-golang.org/x/sys v0.0.0-20220915200043-7b5979e65e41/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
+golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -577,14 +606,19 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
+google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
+gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/pipe.v2 v2.0.0-20140414041502-3c2ca4d52544 h1:WJH1qsOB4/zb/li+zLMn0vaAUJ5FqPv6HYLI3aQVg1k=
gopkg.in/pipe.v2 v2.0.0-20140414041502-3c2ca4d52544/go.mod h1:UhTeH/yXCK/KY7TX24mqPkaQ7gZeqmWd/8SSS8B3aHw=
gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg=
@@ -604,8 +638,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
-gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/install.sh b/install.sh
index 1182a542..0c94bfa5 100755
--- a/install.sh
+++ b/install.sh
@@ -6,13 +6,13 @@ set -e
usage() {
this=$1
cat < 0 {
msg := fmt.Sprintf("Pattern %q shadows the following patterns:\n%s\nEntries should go from least-specific to most-specific.", entry.Pattern, c.listFormatFunc(shadowed))
- bldr.ReportIssue(msg, WithEntry(entry))
+ bldr.ReportIssue(msg, api.WithEntry(entry))
}
previousEntries = append(previousEntries, entry)
}
@@ -45,7 +46,7 @@ func (c *AvoidShadowing) Check(ctx context.Context, in Input) (output Output, er
return bldr.Output(), nil
}
-// listFormatFunc is a basic formatter that outputs a bullet point list of the pattern.
+// listFormatFunc is a basic formatter that api.Outputs a bullet point list of the pattern.
func (c *AvoidShadowing) listFormatFunc(es []codeowners.Entry) string {
points := make([]string, len(es))
for i, err := range es {
diff --git a/internal/check/avoid_shadowing_test.go b/internal/check/avoid_shadowing_test.go
index 31e05f0b..49a583ff 100644
--- a/internal/check/avoid_shadowing_test.go
+++ b/internal/check/avoid_shadowing_test.go
@@ -4,8 +4,9 @@ import (
"context"
"testing"
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/ptr"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
+ "go.szostok.io/codeowners/internal/ptr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -14,7 +15,7 @@ import (
func TestAvoidShadowing(t *testing.T) {
tests := map[string]struct {
codeownersInput string
- expectedIssues []check.Issue
+ expectedIssues []api.Issue
}{
"Should report info about shadowed entries": {
codeownersInput: `
@@ -32,9 +33,9 @@ func TestAvoidShadowing(t *testing.T) {
/b*/other @o1
/script/* @o2
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(6),
Message: `Pattern "*" shadows the following patterns:
* 2: "/build/logs/"
@@ -42,14 +43,14 @@ func TestAvoidShadowing(t *testing.T) {
Entries should go from least-specific to most-specific.`,
},
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(7),
Message: `Pattern "/s*/" shadows the following patterns:
* 3: "/script"
Entries should go from least-specific to most-specific.`,
},
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(8),
Message: `Pattern "/s*" shadows the following patterns:
* 3: "/script"
@@ -57,14 +58,14 @@ Entries should go from least-specific to most-specific.`,
Entries should go from least-specific to most-specific.`,
},
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(9),
Message: `Pattern "/b*" shadows the following patterns:
* 2: "/build/logs/"
Entries should go from least-specific to most-specific.`,
},
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(10),
Message: `Pattern "/b*/logs" shadows the following patterns:
* 2: "/build/logs/"
diff --git a/internal/check/duplicated_pattern.go b/internal/check/duplicated_pattern.go
index 183a2568..4e5fe461 100644
--- a/internal/check/duplicated_pattern.go
+++ b/internal/check/duplicated_pattern.go
@@ -5,8 +5,9 @@ import (
"fmt"
"strings"
- "go.szostok.io/codeowners-validator/internal/ctxutil"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/ctxutil"
+ "go.szostok.io/codeowners/pkg/codeowners"
)
// DuplicatedPattern validates if CODEOWNERS file does not contain
@@ -19,8 +20,8 @@ func NewDuplicatedPattern() *DuplicatedPattern {
}
// Check searches for doubles paths(patterns) in CODEOWNERS file.
-func (d *DuplicatedPattern) Check(ctx context.Context, in Input) (Output, error) {
- var bldr OutputBuilder
+func (d *DuplicatedPattern) Check(ctx context.Context, in api.Input) (api.Output, error) {
+ var bldr api.OutputBuilder
// TODO(mszostok): decide if the `CodeownersEntries` entry by default should be
// indexed by pattern (`map[string][]codeowners.Entry{}`)
@@ -28,7 +29,7 @@ func (d *DuplicatedPattern) Check(ctx context.Context, in Input) (Output, error)
patterns := map[string][]codeowners.Entry{}
for _, entry := range in.CodeownersEntries {
if ctxutil.ShouldExit(ctx) {
- return Output{}, ctx.Err()
+ return api.Output{}, ctx.Err()
}
patterns[entry.Pattern] = append(patterns[entry.Pattern], entry)
diff --git a/internal/check/duplicated_pattern_test.go b/internal/check/duplicated_pattern_test.go
index 975c293a..f92b787f 100644
--- a/internal/check/duplicated_pattern_test.go
+++ b/internal/check/duplicated_pattern_test.go
@@ -4,7 +4,8 @@ import (
"context"
"testing"
- "go.szostok.io/codeowners-validator/internal/check"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -13,7 +14,7 @@ import (
func TestDuplicatedPattern(t *testing.T) {
tests := map[string]struct {
codeownersInput string
- expectedIssues []check.Issue
+ expectedIssues []api.Issue
}{
"Should report info about duplicated entries": {
codeownersInput: `
@@ -25,16 +26,16 @@ func TestDuplicatedPattern(t *testing.T) {
/script @mszostok
/script m.t@g.com
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: nil,
Message: `Pattern "/build/logs/" is defined 2 times in lines:
* 4: with owners: [@doctocat]
* 5: with owners: [@doctocat]`,
},
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: nil,
Message: `Pattern "/script" is defined 2 times in lines:
* 7: with owners: [@mszostok]
diff --git a/internal/check/file_exists.go b/internal/check/file_exists.go
index 16944d2d..afbdcf38 100644
--- a/internal/check/file_exists.go
+++ b/internal/check/file_exists.go
@@ -6,7 +6,8 @@ import (
"os"
"path/filepath"
- "go.szostok.io/codeowners-validator/internal/ctxutil"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/ctxutil"
"github.com/mattn/go-zglob"
"github.com/pkg/errors"
@@ -18,12 +19,12 @@ func NewFileExist() *FileExist {
return &FileExist{}
}
-func (f *FileExist) Check(ctx context.Context, in Input) (Output, error) {
- var bldr OutputBuilder
+func (f *FileExist) Check(ctx context.Context, in api.Input) (api.Output, error) {
+ var bldr api.OutputBuilder
for _, entry := range in.CodeownersEntries {
if ctxutil.ShouldExit(ctx) {
- return Output{}, ctx.Err()
+ return api.Output{}, ctx.Err()
}
fullPath := filepath.Join(in.RepoDir, f.fnmatchPattern(entry.Pattern))
@@ -32,15 +33,15 @@ func (f *FileExist) Check(ctx context.Context, in Input) (Output, error) {
case err == nil:
case errors.Is(err, os.ErrNotExist):
msg := fmt.Sprintf("%q does not match any files in repository", entry.Pattern)
- bldr.ReportIssue(msg, WithEntry(entry))
+ bldr.ReportIssue(msg, api.WithEntry(entry))
continue
default:
- return Output{}, errors.Wrapf(err, "while checking if there is any file in %s matching pattern %s", in.RepoDir, entry.Pattern)
+ return api.Output{}, errors.Wrapf(err, "while checking if there is any file in %s matching pattern %s", in.RepoDir, entry.Pattern)
}
if len(matches) == 0 {
msg := fmt.Sprintf("%q does not match any files in repository", entry.Pattern)
- bldr.ReportIssue(msg, WithEntry(entry))
+ bldr.ReportIssue(msg, api.WithEntry(entry))
}
}
diff --git a/internal/check/file_exists_test.go b/internal/check/file_exists_test.go
index c137726a..88b2bd73 100644
--- a/internal/check/file_exists_test.go
+++ b/internal/check/file_exists_test.go
@@ -8,8 +8,9 @@ import (
"testing"
"time"
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/ptr"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
+ "go.szostok.io/codeowners/internal/ptr"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -22,7 +23,7 @@ import (
func TestFileExists(t *testing.T) {
tests := map[string]struct {
codeownersInput string
- expectedIssues []check.Issue
+ expectedIssues []api.Issue
paths []string
}{
"Should found JS file": {
@@ -85,20 +86,20 @@ func TestFileExists(t *testing.T) {
// https://github.community/t/codeowners-file-with-a-not-file-type-condition/1423
"Should not match with negation pattern": {
codeownersInput: `
- !/codeowners-validator @pico
+ !/codeowners @pico
`,
paths: []string{
"/somewhere/over/the/rainbow/here/it/is.js",
},
- expectedIssues: []check.Issue{
- newErrIssue(`"!/codeowners-validator" does not match any files in repository`),
+ expectedIssues: []api.Issue{
+ newErrIssue(`"!/codeowners" does not match any files in repository`),
},
},
"Should not found JS file": {
codeownersInput: `
*.js @pico
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"*.js" does not match any files in repository`),
},
},
@@ -106,7 +107,7 @@ func TestFileExists(t *testing.T) {
codeownersInput: `
**/foo @pico
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"**/foo" does not match any files in repository`),
},
},
@@ -114,7 +115,7 @@ func TestFileExists(t *testing.T) {
codeownersInput: `
**/foo.js @pico
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"**/foo.js" does not match any files in repository`),
},
},
@@ -122,7 +123,7 @@ func TestFileExists(t *testing.T) {
codeownersInput: `
**/foo/bar @bello
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"**/foo/bar" does not match any files in repository`),
},
},
@@ -130,7 +131,7 @@ func TestFileExists(t *testing.T) {
codeownersInput: `
**/foo/bar.js @bello
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"**/foo/bar.js" does not match any files in repository`),
},
},
@@ -138,7 +139,7 @@ func TestFileExists(t *testing.T) {
codeownersInput: `
abc/** @bello
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"abc/**" does not match any files in repository`),
},
},
@@ -146,7 +147,7 @@ func TestFileExists(t *testing.T) {
codeownersInput: `
a/**/b @bello
`,
- expectedIssues: []check.Issue{
+ expectedIssues: []api.Issue{
newErrIssue(`"a/**/b" does not match any files in repository`),
},
},
@@ -205,9 +206,9 @@ func TestFileExistCheckFileSystemFailure(t *testing.T) {
assert.Empty(t, out)
}
-func newErrIssue(msg string) check.Issue {
- return check.Issue{
- Severity: check.Error,
+func newErrIssue(msg string) api.Issue {
+ return api.Issue{
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(2),
Message: msg,
}
diff --git a/internal/check/helpers_test.go b/internal/check/helpers_test.go
index 87dd0e99..c217664a 100644
--- a/internal/check/helpers_test.go
+++ b/internal/check/helpers_test.go
@@ -6,9 +6,9 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "go.szostok.io/codeowners-validator/internal/check"
+ "go.szostok.io/codeowners/internal/api"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/pkg/codeowners"
)
var FixtureValidCODEOWNERS = `
@@ -25,15 +25,15 @@ var FixtureValidCODEOWNERS = `
/script m.t@g.com
`
-func LoadInput(in string) check.Input {
+func LoadInput(in string) api.Input {
r := strings.NewReader(in)
- return check.Input{
+ return api.Input{
CodeownersEntries: codeowners.ParseCodeowners(r),
}
}
-func assertIssue(t *testing.T, expIssue *check.Issue, gotIssues []check.Issue) {
+func assertIssue(t *testing.T, expIssue *api.Issue, gotIssues []api.Issue) {
t.Helper()
if expIssue != nil {
diff --git a/internal/check/not_owned_file.go b/internal/check/not_owned_file.go
index b8be0315..59d091ca 100644
--- a/internal/check/not_owned_file.go
+++ b/internal/check/not_owned_file.go
@@ -7,8 +7,9 @@ import (
"path"
"strings"
- "go.szostok.io/codeowners-validator/internal/ctxutil"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/ctxutil"
+ "go.szostok.io/codeowners/pkg/codeowners"
"github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
@@ -43,12 +44,12 @@ func NewNotOwnedFile(cfg NotOwnedFileConfig) *NotOwnedFile {
}
}
-func (c *NotOwnedFile) Check(ctx context.Context, in Input) (output Output, err error) {
+func (c *NotOwnedFile) Check(ctx context.Context, in api.Input) (output api.Output, err error) {
if ctxutil.ShouldExit(ctx) {
- return Output{}, ctx.Err()
+ return api.Output{}, ctx.Err()
}
- var bldr OutputBuilder
+ var bldr api.OutputBuilder
if len(in.CodeownersEntries) == 0 {
bldr.ReportIssue("The CODEOWNERS file is empty. The files in the repository don't have any owner.")
@@ -58,12 +59,12 @@ func (c *NotOwnedFile) Check(ctx context.Context, in Input) (output Output, err
patterns := c.patternsToBeIgnored(in.CodeownersEntries)
if err := c.trustWorkspaceIfNeeded(in.RepoDir); err != nil {
- return Output{}, err
+ return api.Output{}, err
}
statusOut, err := c.GitCheckStatus(in.RepoDir)
if err != nil {
- return Output{}, err
+ return api.Output{}, err
}
if len(statusOut) != 0 {
bldr.ReportIssue("git state is dirty: commit all changes before executing this check")
@@ -73,24 +74,24 @@ func (c *NotOwnedFile) Check(ctx context.Context, in Input) (output Output, err
defer func() {
errReset := c.GitResetCurrentBranch(in.RepoDir)
if err != nil {
- output = Output{}
+ output = api.Output{}
err = multierror.Append(err, errReset).ErrorOrNil()
}
}()
err = c.AppendToGitignoreFile(in.RepoDir, patterns)
if err != nil {
- return Output{}, err
+ return api.Output{}, err
}
err = c.GitRemoveIgnoredFiles(in.RepoDir)
if err != nil {
- return Output{}, err
+ return api.Output{}, err
}
out, err := c.GitListFiles(in.RepoDir)
if err != nil {
- return Output{}, err
+ return api.Output{}, err
}
lsOut := strings.TrimSpace(out)
diff --git a/internal/check/package_test.go b/internal/check/package_test.go
index 98077b72..00b5537a 100644
--- a/internal/check/package_test.go
+++ b/internal/check/package_test.go
@@ -5,24 +5,26 @@ import (
"errors"
"testing"
- "go.szostok.io/codeowners-validator/internal/check"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
+ "go.szostok.io/codeowners/internal/config"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestRespectingCanceledContext(t *testing.T) {
- must := func(checker check.Checker, err error) check.Checker {
+ must := func(checker api.Checker, err error) api.Checker {
require.NoError(t, err)
return checker
}
- checkers := []check.Checker{
+ checkers := []api.Checker{
check.NewDuplicatedPattern(),
check.NewFileExist(),
check.NewValidSyntax(),
check.NewNotOwnedFile(check.NotOwnedFileConfig{}),
- must(check.NewValidOwner(check.ValidOwnerConfig{Repository: "org/repo"}, nil, true)),
+ must(check.NewValidOwner(&config.Config{OwnerCheckerRepository: "org/repo"}, nil, true)),
}
for _, checker := range checkers {
diff --git a/internal/check/valid_owner.go b/internal/check/valid_owner.go
index cfc15122..5b7544f5 100644
--- a/internal/check/valid_owner.go
+++ b/internal/check/valid_owner.go
@@ -7,7 +7,9 @@ import (
"net/mail"
"strings"
- "go.szostok.io/codeowners-validator/internal/ctxutil"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/config"
+ "go.szostok.io/codeowners/internal/ctxutil"
"github.com/google/go-github/v41/github"
"github.com/pkg/errors"
@@ -48,20 +50,21 @@ type ValidOwner struct {
orgName string
orgTeams []*github.Team
orgRepoName string
+ outsideCollaborators *map[string]struct{}
ignOwners map[string]struct{}
allowUnownedPatterns bool
ownersMustBeTeams bool
}
// NewValidOwner returns new instance of the ValidOwner
-func NewValidOwner(cfg ValidOwnerConfig, ghClient *github.Client, checkScopes bool) (*ValidOwner, error) {
- split := strings.Split(cfg.Repository, "/")
+func NewValidOwner(cfg *config.Config, ghClient *github.Client, checkScopes bool) (*ValidOwner, error) {
+ split := strings.Split(cfg.OwnerCheckerRepository, "/")
if len(split) != 2 {
- return nil, errors.Errorf("Wrong repository name. Expected pattern 'owner/repository', got '%s'", cfg.Repository)
+ return nil, errors.Errorf("Wrong repository name. Expected pattern 'owner/repository', got '%s'", cfg.OwnerCheckerRepository)
}
ignOwners := map[string]struct{}{}
- for _, n := range cfg.IgnoredOwners {
+ for _, n := range cfg.OwnerCheckerIgnoredOwners {
ignOwners[n] = struct{}{}
}
@@ -71,8 +74,8 @@ func NewValidOwner(cfg ValidOwnerConfig, ghClient *github.Client, checkScopes bo
orgName: split[0],
orgRepoName: split[1],
ignOwners: ignOwners,
- allowUnownedPatterns: cfg.AllowUnownedPatterns,
- ownersMustBeTeams: cfg.OwnersMustBeTeams,
+ allowUnownedPatterns: cfg.OwnerCheckerAllowUnownedPatterns,
+ ownersMustBeTeams: cfg.OwnerCheckerOwnersMustBeTeams,
}, nil
}
@@ -88,20 +91,20 @@ func NewValidOwner(cfg ValidOwnerConfig, ghClient *github.Client, checkScopes bo
// - if GitHub user then check if have GitHub account
// - if GitHub user then check if he/she is in organization
// - if org team then check if exists in organization
-func (v *ValidOwner) Check(ctx context.Context, in Input) (Output, error) {
- var bldr OutputBuilder
+func (v *ValidOwner) Check(ctx context.Context, in api.Input) (api.Output, error) {
+ var bldr api.OutputBuilder
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))
+ bldr.ReportIssue("Missing owner, at least one owner is required", api.WithEntry(entry), api.WithSeverity(api.Warning))
continue
}
for _, ownerName := range entry.Owners {
if ctxutil.ShouldExit(ctx) {
- return Output{}, ctx.Err()
+ return api.Output{}, ctx.Err()
}
if v.isIgnoredOwner(ownerName) {
@@ -114,7 +117,7 @@ func (v *ValidOwner) Check(ctx context.Context, in Input) (Output, error) {
validFn := v.selectValidateFn(ownerName)
if err := validFn(ctx, ownerName); err != nil {
- bldr.ReportIssue(err.msg, WithEntry(entry))
+ bldr.ReportIssue(err.msg, api.WithEntry(entry))
if err.permanent { // Doesn't make sense to process further
return bldr.Output(), nil
}
@@ -236,7 +239,7 @@ func (v *ValidOwner) validateTeam(ctx context.Context, name string) *validateErr
// repo contains the permissions for the team slug given
// TODO(mszostok): Switch to GraphQL API, see:
- // https://github.com/mszostok/codeowners-validator/pull/62#discussion_r561273525
+ // https://github.com/mszostok/codeowners/pull/62#discussion_r561273525
repo, _, err := v.ghClient.Teams.IsTeamRepoBySlug(ctx, v.orgName, team, org, v.orgRepoName)
if err != nil { // TODO(mszostok): implement retry?
switch err := err.(type) {
@@ -297,6 +300,12 @@ func (v *ValidOwner) validateGitHubUser(ctx context.Context, name string) *valid
}
}
+ if v.outsideCollaborators == nil { // TODO(mszostok): lazy init, make it more robust.
+ if err := v.initOutsideCollaboratorsList(ctx); err != nil {
+ return newValidateError("Cannot initialize outside collaborators list: %v", err).AsPermanent()
+ }
+ }
+
userName := strings.TrimPrefix(name, "@")
_, _, err := v.ghClient.Users.Get(ctx, userName)
if err != nil { // TODO(mszostok): implement retry?
@@ -314,15 +323,18 @@ func (v *ValidOwner) validateGitHubUser(ctx context.Context, name string) *valid
}
_, isMember := (*v.orgMembers)[userName]
- if !isMember {
- return newValidateError("User %q is not a member of the organization", name)
+ _, isOutsideCollaborator := (*v.outsideCollaborators)[userName]
+ if !(isMember || isOutsideCollaborator) {
+ return newValidateError("User %q is not an owner of the repository", name)
}
return nil
}
// There is a method to check if user is a org member
-// client.Organizations.IsMember(context.Background(), "org-name", "user-name")
+//
+// client.Organizations.IsMember(context.Background(), "org-name", "user-name")
+//
// But latency is too huge for checking each single user independent
// better and faster is to ask for all members and cache them.
func (v *ValidOwner) initOrgListMembers(ctx context.Context) error {
@@ -351,6 +363,36 @@ func (v *ValidOwner) initOrgListMembers(ctx context.Context) error {
return nil
}
+// Add all outside collaborators who are part of the repository to
+//
+// outsideCollaborators *map[string]struct{}
+func (v *ValidOwner) initOutsideCollaboratorsList(ctx context.Context) error {
+ opt := &github.ListCollaboratorsOptions{
+ ListOptions: github.ListOptions{PerPage: 100},
+ Affiliation: "outside",
+ }
+
+ var allMembers []*github.User
+ for {
+ collaborators, resp, err := v.ghClient.Repositories.ListCollaborators(ctx, v.orgName, v.orgRepoName, opt)
+ if err != nil {
+ return err
+ }
+ allMembers = append(allMembers, collaborators...)
+ if resp.NextPage == 0 {
+ break
+ }
+ opt.Page = resp.NextPage
+ }
+
+ v.outsideCollaborators = &map[string]struct{}{}
+ for _, u := range allMembers {
+ (*v.outsideCollaborators)[u.GetLogin()] = struct{}{}
+ }
+
+ return nil
+}
+
// Name returns human-readable name of the validator
func (ValidOwner) Name() string {
return "Valid Owner Checker"
diff --git a/internal/check/valid_owner_test.go b/internal/check/valid_owner_test.go
index b42ee651..a683d05c 100644
--- a/internal/check/valid_owner_test.go
+++ b/internal/check/valid_owner_test.go
@@ -4,11 +4,13 @@ import (
"context"
"testing"
- "go.szostok.io/codeowners-validator/internal/check"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
+ "go.szostok.io/codeowners/internal/config"
"github.com/stretchr/testify/require"
- "go.szostok.io/codeowners-validator/internal/ptr"
+ "go.szostok.io/codeowners/internal/ptr"
"github.com/stretchr/testify/assert"
)
@@ -55,9 +57,9 @@ func TestValidOwnerChecker(t *testing.T) {
func TestValidOwnerCheckerIgnoredOwner(t *testing.T) {
t.Run("Should ignore owner", func(t *testing.T) {
// given
- ownerCheck, err := check.NewValidOwner(check.ValidOwnerConfig{
- Repository: "org/repo",
- IgnoredOwners: []string{"@owner1"},
+ ownerCheck, err := check.NewValidOwner(&config.Config{
+ OwnerCheckerRepository: "org/repo",
+ OwnerCheckerIgnoredOwners: []string{"@owner1"},
}, nil, true)
require.NoError(t, err)
@@ -74,21 +76,21 @@ func TestValidOwnerCheckerIgnoredOwner(t *testing.T) {
t.Run("Should ignore user only and check the remaining owners", func(t *testing.T) {
tests := map[string]struct {
codeowners string
- issue *check.Issue
+ issue *api.Issue
allowUnownedPatterns bool
}{
"No owners": {
codeowners: `*`,
- issue: &check.Issue{
- Severity: check.Warning,
+ issue: &api.Issue{
+ Severity: api.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,
+ issue: &api.Issue{
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(1),
Message: `Not valid owner definition "badOwner"`,
},
@@ -102,10 +104,10 @@ func TestValidOwnerCheckerIgnoredOwner(t *testing.T) {
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"},
+ ownerCheck, err := check.NewValidOwner(&config.Config{
+ OwnerCheckerRepository: "org/repo",
+ OwnerCheckerAllowUnownedPatterns: tc.allowUnownedPatterns,
+ OwnerCheckerIgnoredOwners: []string{"@owner1"},
}, nil, true)
require.NoError(t, err)
@@ -123,13 +125,13 @@ func TestValidOwnerCheckerIgnoredOwner(t *testing.T) {
func TestValidOwnerCheckerOwnersMustBeTeams(t *testing.T) {
tests := map[string]struct {
codeowners string
- issue *check.Issue
+ issue *api.Issue
allowUnownedPatterns bool
}{
"Bad owner definition": {
codeowners: `* @owner1`,
- issue: &check.Issue{
- Severity: check.Error,
+ issue: &api.Issue{
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(1),
Message: `Only team owners allowed and "@owner1" is not a team`,
},
@@ -143,10 +145,10 @@ func TestValidOwnerCheckerOwnersMustBeTeams(t *testing.T) {
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,
- OwnersMustBeTeams: true,
+ ownerCheck, err := check.NewValidOwner(&config.Config{
+ OwnerCheckerRepository: "org/repo",
+ OwnerCheckerAllowUnownedPatterns: tc.allowUnownedPatterns,
+ OwnerCheckerOwnersMustBeTeams: true,
}, nil, true)
require.NoError(t, err)
diff --git a/internal/check/valid_syntax.go b/internal/check/valid_syntax.go
index f851e50d..16ffe460 100644
--- a/internal/check/valid_syntax.go
+++ b/internal/check/valid_syntax.go
@@ -6,7 +6,8 @@ import (
"regexp"
"strings"
- "go.szostok.io/codeowners-validator/internal/ctxutil"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/ctxutil"
)
var (
@@ -32,16 +33,16 @@ func NewValidSyntax() *ValidSyntax {
}
// Check for syntax issues in your CODEOWNERS file.
-func (v *ValidSyntax) Check(ctx context.Context, in Input) (Output, error) {
- var bldr OutputBuilder
+func (v *ValidSyntax) Check(ctx context.Context, in api.Input) (api.Output, error) {
+ var bldr api.OutputBuilder
for _, entry := range in.CodeownersEntries {
if ctxutil.ShouldExit(ctx) {
- return Output{}, ctx.Err()
+ return api.Output{}, ctx.Err()
}
if entry.Pattern == "" {
- bldr.ReportIssue("Missing pattern", WithEntry(entry))
+ bldr.ReportIssue("Missing pattern", api.WithEntry(entry))
}
ownersLoop:
@@ -52,12 +53,12 @@ func (v *ValidSyntax) Check(ctx context.Context, in Input) (Output, error) {
case strings.HasPrefix(item, "@"):
if !usernameOrTeamRegexp.MatchString(item) {
msg := fmt.Sprintf("Owner '%s' does not look like a GitHub username or team name", item)
- bldr.ReportIssue(msg, WithEntry(entry), WithSeverity(Warning))
+ bldr.ReportIssue(msg, api.WithEntry(entry), api.WithSeverity(api.Warning))
}
default:
if !emailRegexp.MatchString(item) {
msg := fmt.Sprintf("Owner '%s' does not look like an email", item)
- bldr.ReportIssue(msg, WithEntry(entry))
+ bldr.ReportIssue(msg, api.WithEntry(entry))
}
}
}
diff --git a/internal/check/valid_syntax_test.go b/internal/check/valid_syntax_test.go
index e8a05d37..e7e7aea9 100644
--- a/internal/check/valid_syntax_test.go
+++ b/internal/check/valid_syntax_test.go
@@ -4,9 +4,10 @@ import (
"context"
"testing"
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/ptr"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
+ "go.szostok.io/codeowners/internal/ptr"
+ "go.szostok.io/codeowners/pkg/codeowners"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@@ -15,7 +16,7 @@ import (
func TestValidSyntaxChecker(t *testing.T) {
tests := map[string]struct {
codeowners string
- issue *check.Issue
+ issue *api.Issue
}{
"No owners": {
codeowners: `*`,
@@ -23,40 +24,40 @@ func TestValidSyntaxChecker(t *testing.T) {
},
"Bad username": {
codeowners: `pkg/github.com/** @-`,
- issue: &check.Issue{
- Severity: check.Warning,
+ issue: &api.Issue{
+ Severity: api.Warning,
LineNo: ptr.Uint64Ptr(1),
Message: "Owner '@-' does not look like a GitHub username or team name",
},
},
"Bad org": {
codeowners: `* @bad+org`,
- issue: &check.Issue{
- Severity: check.Warning,
+ issue: &api.Issue{
+ Severity: api.Warning,
LineNo: ptr.Uint64Ptr(1),
Message: "Owner '@bad+org' does not look like a GitHub username or team name",
},
},
"Bad team name on first place": {
codeowners: `* @org/+not+a+good+name`,
- issue: &check.Issue{
- Severity: check.Warning,
+ issue: &api.Issue{
+ Severity: api.Warning,
LineNo: ptr.Uint64Ptr(1),
Message: "Owner '@org/+not+a+good+name' does not look like a GitHub username or team name",
},
},
"Bad team name on second place": {
codeowners: `* @org/hakuna-matata @org/-a-team`,
- issue: &check.Issue{
- Severity: check.Warning,
+ issue: &api.Issue{
+ Severity: api.Warning,
LineNo: ptr.Uint64Ptr(1),
Message: "Owner '@org/-a-team' does not look like a GitHub username or team name",
},
},
"Doesn't look like username, team name, nor email": {
codeowners: `* something_weird`,
- issue: &check.Issue{
- Severity: check.Error,
+ issue: &api.Issue{
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(1),
Message: "Owner 'something_weird' does not look like an email",
},
@@ -81,7 +82,7 @@ func TestValidSyntaxChecker(t *testing.T) {
func TestValidSyntaxZeroValueEntry(t *testing.T) {
// given
- zeroValueInput := check.Input{
+ zeroValueInput := api.Input{
CodeownersEntries: []codeowners.Entry{
{
LineNo: 0,
@@ -90,10 +91,10 @@ func TestValidSyntaxZeroValueEntry(t *testing.T) {
},
},
}
- expIssues := []check.Issue{
+ expIssues := []api.Issue{
{
LineNo: ptr.Uint64Ptr(0),
- Severity: check.Error,
+ Severity: api.Error,
Message: "Missing pattern",
},
}
diff --git a/internal/config/config.go b/internal/config/config.go
new file mode 100644
index 00000000..a8d3ad3c
--- /dev/null
+++ b/internal/config/config.go
@@ -0,0 +1,29 @@
+package config
+
+import "go.szostok.io/codeowners/internal/api"
+
+const (
+ DefaultConfigFilename = "codeowners-config.yaml"
+ EnvPrefix = "CODEOWNERS"
+)
+
+// Config holds the application configuration
+type Config struct {
+ Checks []string `mapstructure:"checks"`
+ CheckFailureLevel api.SeverityType `mapstructure:"check-failure-level"`
+ ExperimentalChecks []string `mapstructure:"experimental-checks"`
+ GithubAccessToken string `mapstructure:"github-access-token"`
+ GithubBaseURL string `mapstructure:"github-base-url"`
+ GithubUploadURL string `mapstructure:"github-upload-url"`
+ GithubAppID int64 `mapstructure:"github-app-id"`
+ GithubAppInstallationID int64 `mapstructure:"github-app-installation-id"`
+ GithubAppPrivateKey string `mapstructure:"github-app-private-key"`
+ NotOwnedCheckerSkipPatterns []string `mapstructure:"not-owned-checker-skip-patterns"`
+ NotOwnedCheckerSubdirectories []string `mapstructure:"not-owned-checker-subdirectories"`
+ NotOwnedCheckerTrustWorkspace bool `mapstructure:"not-owned-checker-trust-workspace"`
+ OwnerCheckerRepository string `mapstructure:"owner-checker-repository"`
+ OwnerCheckerIgnoredOwners []string `mapstructure:"owner-checker-ignored-owners"`
+ OwnerCheckerAllowUnownedPatterns bool `mapstructure:"owner-checker-allow-unowned-patterns"`
+ OwnerCheckerOwnersMustBeTeams bool `mapstructure:"owner-checker-owners-must-be-teams"`
+ RepositoryPath string `mapstructure:"repository-path"`
+}
diff --git a/internal/ctxutil/check_test.go b/internal/ctxutil/check_test.go
index 2ed83856..eb115404 100644
--- a/internal/ctxutil/check_test.go
+++ b/internal/ctxutil/check_test.go
@@ -5,7 +5,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- contextutil "go.szostok.io/codeowners-validator/internal/ctxutil"
+ contextutil "go.szostok.io/codeowners/internal/ctxutil"
)
func TestShouldExit(t *testing.T) {
diff --git a/internal/envconfig/envconfig.go b/internal/envconfig/envconfig.go
deleted file mode 100644
index 625a7ce9..00000000
--- a/internal/envconfig/envconfig.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package envconfig
-
-import (
- "os"
-
- "github.com/vrischmann/envconfig"
-)
-
-// Init the given config. Supports also envs prefix if set.
-func Init(conf interface{}) error {
- envPrefix := os.Getenv("ENVS_PREFIX")
- return envconfig.InitWithPrefix(conf, envPrefix)
-}
diff --git a/internal/envconfig/envconfig_test.go b/internal/envconfig/envconfig_test.go
deleted file mode 100644
index 2a2b7c77..00000000
--- a/internal/envconfig/envconfig_test.go
+++ /dev/null
@@ -1,46 +0,0 @@
-package envconfig_test
-
-import (
- "os"
- "testing"
-
- "go.szostok.io/codeowners-validator/internal/envconfig"
-
- "github.com/stretchr/testify/require"
- "gotest.tools/assert"
-)
-
-type testConfig struct {
- Key1 string
-}
-
-func TestInit(t *testing.T) {
- t.Run("Should read env variable without prefix", func(t *testing.T) {
- // given
- var cfg testConfig
-
- require.NoError(t, os.Setenv("KEY1", "test-value"))
-
- // when
- err := envconfig.Init(&cfg)
-
- // then
- require.NoError(t, err)
- assert.Equal(t, "test-value", cfg.Key1)
- })
-
- t.Run("Should read env variable with prefix", func(t *testing.T) {
- // given
- var cfg testConfig
-
- require.NoError(t, os.Setenv("ENVS_PREFIX", "TEST_PREFIX"))
- require.NoError(t, os.Setenv("TEST_PREFIX_KEY1", "test-value"))
-
- // when
- err := envconfig.Init(&cfg)
-
- // then
- require.NoError(t, err)
- assert.Equal(t, "test-value", cfg.Key1)
- })
-}
diff --git a/internal/github/client.go b/internal/github/client.go
index 6abc2bf6..2e1cdbb9 100644
--- a/internal/github/client.go
+++ b/internal/github/client.go
@@ -8,39 +8,30 @@ import (
"github.com/bradleyfalzon/ghinstallation/v2"
- "go.szostok.io/codeowners-validator/pkg/url"
+ "go.szostok.io/codeowners/internal/config"
+ "go.szostok.io/codeowners/pkg/url"
"github.com/google/go-github/v41/github"
"golang.org/x/oauth2"
)
-type ClientConfig struct {
- AccessToken string `envconfig:"optional"`
-
- AppID int64 `envconfig:"optional"`
- AppPrivateKey string `envconfig:"optional"`
- AppInstallationID int64 `envconfig:"optional"`
-
- BaseURL string `envconfig:"optional"`
- UploadURL string `envconfig:"optional"`
- HTTPRequestTimeout time.Duration `envconfig:"default=30s"`
-}
+var httpRequestTimeout int = 30
// Validate validates if provided client options are valid.
-func (c *ClientConfig) Validate() error {
- if c.AccessToken == "" && c.AppID == 0 {
+func Validate(cfg *config.Config) error {
+ if cfg.GithubAccessToken == "" && cfg.GithubAppID == 0 {
return errors.New("GitHub authorization is required, provide ACCESS_TOKEN or APP_ID")
}
- if c.AccessToken != "" && c.AppID != 0 {
+ if cfg.GithubAccessToken != "" && cfg.GithubAppID != 0 {
return errors.New("GitHub ACCESS_TOKEN cannot be provided when APP_ID is specified")
}
- if c.AppID != 0 {
- if c.AppInstallationID == 0 {
+ if cfg.GithubAppID != 0 {
+ if cfg.GithubAppInstallationID == 0 {
return errors.New("GitHub APP_INSTALLATION_ID is required with APP_ID")
}
- if c.AppPrivateKey == "" {
+ if cfg.GithubAppPrivateKey == "" {
return errors.New("GitHub APP_PRIVATE_KEY is required with APP_ID")
}
}
@@ -48,27 +39,31 @@ func (c *ClientConfig) Validate() error {
return nil
}
-func NewClient(ctx context.Context, cfg *ClientConfig) (ghClient *github.Client, isApp bool, err error) {
- if err := cfg.Validate(); err != nil {
+func NewClient(ctx context.Context, cfg *config.Config) (ghClient *github.Client, isApp bool, err error) {
+ if err := Validate(cfg); err != nil {
return nil, false, err
}
- httpClient := http.DefaultClient
+ httpClient := &http.Client{
+ Transport: http.DefaultClient.Transport,
+ CheckRedirect: http.DefaultClient.CheckRedirect,
+ Jar: http.DefaultClient.Jar,
+ Timeout: time.Duration(httpRequestTimeout) * time.Second,
+ }
- if cfg.AccessToken != "" {
+ if cfg.GithubAccessToken != "" {
httpClient = oauth2.NewClient(ctx, oauth2.StaticTokenSource(
- &oauth2.Token{AccessToken: cfg.AccessToken},
+ &oauth2.Token{AccessToken: cfg.GithubAccessToken},
))
- } else if cfg.AppID != 0 {
+ } else if cfg.GithubAppID != 0 {
httpClient, err = createAppInstallationHTTPClient(cfg)
isApp = true
if err != nil {
return
}
}
- httpClient.Timeout = cfg.HTTPRequestTimeout
- baseURL, uploadURL := cfg.BaseURL, cfg.UploadURL
+ baseURL, uploadURL := cfg.GithubBaseURL, cfg.GithubUploadURL
if baseURL == "" {
ghClient = github.NewClient(httpClient)
@@ -84,9 +79,9 @@ func NewClient(ctx context.Context, cfg *ClientConfig) (ghClient *github.Client,
return
}
-func createAppInstallationHTTPClient(cfg *ClientConfig) (client *http.Client, err error) {
+func createAppInstallationHTTPClient(cfg *config.Config) (client *http.Client, err error) {
tr := http.DefaultTransport
- itr, err := ghinstallation.New(tr, cfg.AppID, cfg.AppInstallationID, []byte(cfg.AppPrivateKey))
+ itr, err := ghinstallation.New(tr, cfg.GithubAppID, cfg.GithubAppInstallationID, []byte(cfg.GithubAppPrivateKey))
if err != nil {
return nil, err
}
diff --git a/internal/load/load.go b/internal/load/load.go
index 37172cdd..e27fa96c 100644
--- a/internal/load/load.go
+++ b/internal/load/load.go
@@ -3,47 +3,41 @@ package load
import (
"context"
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/envconfig"
- "go.szostok.io/codeowners-validator/internal/github"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/check"
+ "go.szostok.io/codeowners/internal/config"
+ "go.szostok.io/codeowners/internal/github"
"github.com/pkg/errors"
+ "github.com/vrischmann/envconfig"
)
// For now, it is a good enough solution to init checks. Important thing is to do not require env variables
// and do not create clients which will not be used because of the given checker.
//
// MAYBE in the future the https://github.com/uber-go/dig will be used.
-func Checks(ctx context.Context, enabledChecks, experimentalChecks []string) ([]check.Checker, error) {
- var checks []check.Checker
+func Checks(ctx context.Context, cfg *config.Config) ([]api.Checker, error) {
+ var checks []api.Checker
- if isEnabled(enabledChecks, "syntax") {
+ if isEnabled(cfg.Checks, "syntax") {
checks = append(checks, check.NewValidSyntax())
}
- if isEnabled(enabledChecks, "duppatterns") {
+ if isEnabled(cfg.Checks, "duppatterns") {
checks = append(checks, check.NewDuplicatedPattern())
}
- if isEnabled(enabledChecks, "files") {
+ if isEnabled(cfg.Checks, "files") {
checks = append(checks, check.NewFileExist())
}
- if isEnabled(enabledChecks, "owners") {
- var cfg struct {
- OwnerChecker check.ValidOwnerConfig
- Github github.ClientConfig
- }
- if err := envconfig.Init(&cfg); err != nil {
- return nil, errors.Wrapf(err, "while loading config for %s", "owners")
- }
-
- ghClient, isApp, err := github.NewClient(ctx, &cfg.Github)
+ if isEnabled(cfg.Checks, "owners") {
+ ghClient, isApp, err := github.NewClient(ctx, cfg)
if err != nil {
return nil, errors.Wrap(err, "while creating GitHub client")
}
- owners, err := check.NewValidOwner(cfg.OwnerChecker, ghClient, !isApp)
+ owners, err := check.NewValidOwner(cfg, ghClient, !isApp)
if err != nil {
return nil, errors.Wrap(err, "while enabling 'owners' checker")
}
@@ -55,7 +49,7 @@ func Checks(ctx context.Context, enabledChecks, experimentalChecks []string) ([]
checks = append(checks, owners)
}
- expChecks, err := loadExperimentalChecks(experimentalChecks)
+ expChecks, err := loadExperimentalChecks(cfg.ExperimentalChecks)
if err != nil {
return nil, errors.Wrap(err, "while loading experimental checks")
}
@@ -63,8 +57,8 @@ func Checks(ctx context.Context, enabledChecks, experimentalChecks []string) ([]
return append(checks, expChecks...), nil
}
-func loadExperimentalChecks(experimentalChecks []string) ([]check.Checker, error) {
- var checks []check.Checker
+func loadExperimentalChecks(experimentalChecks []string) ([]api.Checker, error) {
+ var checks []api.Checker
if contains(experimentalChecks, "notowned") {
var cfg struct {
diff --git a/internal/printer/tty.go b/internal/printer/tty.go
index 8bd7fc17..f6b1b2df 100644
--- a/internal/printer/tty.go
+++ b/internal/printer/tty.go
@@ -9,7 +9,7 @@ import (
"time"
"github.com/fatih/color"
- "go.szostok.io/codeowners-validator/internal/check"
+ "go.szostok.io/codeowners/internal/api"
)
// writer used for test purpose
@@ -19,7 +19,7 @@ type TTYPrinter struct {
m sync.RWMutex
}
-func (tty *TTYPrinter) PrintCheckResult(checkName string, duration time.Duration, checkOut check.Output, checkErr error) {
+func (tty *TTYPrinter) PrintCheckResult(checkName string, duration time.Duration, checkOut api.Output, checkErr error) {
tty.m.Lock()
defer tty.m.Unlock()
@@ -48,12 +48,12 @@ func (tty *TTYPrinter) PrintCheckResult(checkName string, duration time.Duration
}
}
-func (*TTYPrinter) severityPrintfFunc(severity check.SeverityType) func(w io.Writer, format string, a ...interface{}) {
+func (*TTYPrinter) severityPrintfFunc(severity api.SeverityType) func(w io.Writer, format string, a ...interface{}) {
p := color.New()
switch severity {
- case check.Warning:
+ case api.Warning:
p.Add(color.FgYellow)
- case check.Error:
+ case api.Error:
p.Add(color.FgRed)
}
diff --git a/internal/printer/tty_test.go b/internal/printer/tty_test.go
index 4eedb7e2..6754146f 100644
--- a/internal/printer/tty_test.go
+++ b/internal/printer/tty_test.go
@@ -7,8 +7,8 @@ import (
"testing"
"time"
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/ptr"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/ptr"
"github.com/sebdah/goldie/v2"
)
@@ -23,24 +23,24 @@ func TestTTYPrinterPrintCheckResult(t *testing.T) {
defer restore()
// when
- tty.PrintCheckResult("Foo Checker", time.Second, check.Output{
- Issues: []check.Issue{
+ tty.PrintCheckResult("Foo Checker", time.Second, api.Output{
+ Issues: []api.Issue{
{
- Severity: check.Error,
+ Severity: api.Error,
LineNo: ptr.Uint64Ptr(42),
Message: "Simulate error in line 42",
},
{
- Severity: check.Warning,
+ Severity: api.Warning,
LineNo: ptr.Uint64Ptr(2020),
Message: "Simulate warning in line 2020",
},
{
- Severity: check.Error,
+ Severity: api.Error,
Message: "Error without line number",
},
{
- Severity: check.Warning,
+ Severity: api.Warning,
Message: "Warning without line number",
},
},
@@ -59,7 +59,7 @@ func TestTTYPrinterPrintCheckResult(t *testing.T) {
defer restore()
// when
- tty.PrintCheckResult("Foo Checker", time.Second, check.Output{
+ tty.PrintCheckResult("Foo Checker", time.Second, api.Output{
Issues: nil,
}, nil)
diff --git a/internal/runner/runner_worker.go b/internal/runner/runner_worker.go
index 5e2f6a11..c52bcc45 100644
--- a/internal/runner/runner_worker.go
+++ b/internal/runner/runner_worker.go
@@ -5,9 +5,9 @@ import (
"sync"
"time"
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/printer"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/internal/api"
+ "go.szostok.io/codeowners/internal/printer"
+ "go.szostok.io/codeowners/pkg/codeowners"
"github.com/sirupsen/logrus"
)
@@ -21,7 +21,7 @@ const (
// Printer prints the checks results
type Printer interface {
- PrintCheckResult(checkName string, duration time.Duration, checkOut check.Output, err error)
+ PrintCheckResult(checkName string, duration time.Duration, checkOut api.Output, err error)
PrintSummary(allCheck int, failedChecks int)
}
@@ -32,15 +32,15 @@ type CheckRunner struct {
log logrus.FieldLogger
codeowners []codeowners.Entry
repoPath string
- treatedAsFailure check.SeverityType
- checks []check.Checker
+ treatedAsFailure api.SeverityType
+ checks []api.Checker
printer Printer
- allFoundIssues map[check.SeverityType]uint32
+ allFoundIssues map[api.SeverityType]uint32
notPassedChecksCnt int
}
// NewCheckRunner is a constructor for CheckRunner
-func NewCheckRunner(log logrus.FieldLogger, co []codeowners.Entry, repoPath string, treatedAsFailure check.SeverityType, checks ...check.Checker) *CheckRunner {
+func NewCheckRunner(log logrus.FieldLogger, co []codeowners.Entry, repoPath string, treatedAsFailure api.SeverityType, checks ...api.Checker) *CheckRunner {
return &CheckRunner{
log: log.WithField("service", "check:runner"),
repoPath: repoPath,
@@ -49,7 +49,7 @@ func NewCheckRunner(log logrus.FieldLogger, co []codeowners.Entry, repoPath stri
checks: checks,
printer: &printer.TTYPrinter{},
- allFoundIssues: map[check.SeverityType]uint32{},
+ allFoundIssues: map[api.SeverityType]uint32{},
}
}
@@ -60,10 +60,10 @@ func (r *CheckRunner) Run(ctx context.Context) {
// TODO(mszostok): timeout per check?
wg.Add(len(r.checks))
for _, c := range r.checks {
- go func(c check.Checker) {
+ go func(c api.Checker) {
defer wg.Done()
startTime := time.Now()
- out, err := c.Check(ctx, check.Input{
+ out, err := c.Check(ctx, api.Input{
CodeownersEntries: r.codeowners,
RepoDir: r.repoPath,
})
@@ -78,7 +78,7 @@ func (r *CheckRunner) Run(ctx context.Context) {
}
func (r *CheckRunner) ShouldExitWithCheckFailure() bool {
- higherOccurredIssue := check.SeverityType(MaxInt)
+ higherOccurredIssue := api.SeverityType(MaxInt)
for key := range r.allFoundIssues {
if higherOccurredIssue > key {
higherOccurredIssue = key
@@ -88,7 +88,7 @@ func (r *CheckRunner) ShouldExitWithCheckFailure() bool {
return higherOccurredIssue <= r.treatedAsFailure
}
-func (r *CheckRunner) collectMetrics(checkOut check.Output, err error) {
+func (r *CheckRunner) collectMetrics(checkOut api.Output, err error) {
r.m.Lock()
defer r.m.Unlock()
for _, i := range checkOut.Issues {
@@ -96,7 +96,7 @@ func (r *CheckRunner) collectMetrics(checkOut check.Output, err error) {
}
if err != nil {
- r.allFoundIssues[check.Error]++
+ r.allFoundIssues[api.Error]++
}
if len(checkOut.Issues) > 0 || err != nil {
diff --git a/main.go b/main.go
index 7987ca8c..a1feca7a 100644
--- a/main.go
+++ b/main.go
@@ -4,33 +4,16 @@ import (
"context"
"os"
"os/signal"
- "path/filepath"
"syscall"
- "github.com/sirupsen/logrus"
- "github.com/spf13/cobra"
- "go.szostok.io/version/extension"
-
- "go.szostok.io/codeowners-validator/internal/check"
- "go.szostok.io/codeowners-validator/internal/envconfig"
- "go.szostok.io/codeowners-validator/internal/load"
- "go.szostok.io/codeowners-validator/internal/runner"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ cmd "go.szostok.io/codeowners/cmd/codeowners"
)
-// Config holds the application configuration
-type Config struct {
- RepositoryPath string
- CheckFailureLevel check.SeverityType `envconfig:"default=warning"`
- Checks []string `envconfig:"optional"`
- ExperimentalChecks []string `envconfig:"optional"`
-}
-
func main() {
ctx, cancelFunc := WithStopContext(context.Background())
defer cancelFunc()
- if err := NewRoot().ExecuteContext(ctx); err != nil {
+ if err := cmd.RootCmd().ExecuteContext(ctx); err != nil {
// error is already handled by `cobra`, we don't want to log it here as we will duplicate the message.
// If needed, based on error type we can exit with different codes.
//nolint:gocritic
@@ -38,12 +21,6 @@ func main() {
}
}
-func exitOnError(err error) {
- if err != nil {
- logrus.Fatal(err)
- }
-}
-
// WithStopContext returns a copy of parent with a new Done channel. The returned
// context's Done channel is closed on of SIGINT or SIGTERM signals.
func WithStopContext(parent context.Context) (context.Context, context.CancelFunc) {
@@ -61,48 +38,3 @@ func WithStopContext(parent context.Context) (context.Context, context.CancelFun
return ctx, cancel
}
-
-// NewRoot returns a root cobra.Command for the whole Agent utility.
-func NewRoot() *cobra.Command {
- rootCmd := &cobra.Command{
- Use: "codeowners-validator",
- Short: "Ensures the correctness of your CODEOWNERS file.",
- SilenceUsage: true,
- Run: func(cmd *cobra.Command, args []string) {
- var cfg Config
- err := envconfig.Init(&cfg)
- exitOnError(err)
-
- log := logrus.New()
-
- // init checks
- checks, err := load.Checks(cmd.Context(), cfg.Checks, cfg.ExperimentalChecks)
- exitOnError(err)
-
- // init codeowners entries
- codeownersEntries, err := codeowners.NewFromPath(cfg.RepositoryPath)
- exitOnError(err)
-
- // run check runner
- absRepoPath, err := filepath.Abs(cfg.RepositoryPath)
- exitOnError(err)
-
- checkRunner := runner.NewCheckRunner(log, codeownersEntries, absRepoPath, cfg.CheckFailureLevel, checks...)
- checkRunner.Run(cmd.Context())
-
- if cmd.Context().Err() != nil {
- log.Error("Application was interrupted by operating system")
- os.Exit(2)
- }
- if checkRunner.ShouldExitWithCheckFailure() {
- os.Exit(3)
- }
- },
- }
-
- rootCmd.AddCommand(
- extension.NewVersionCobraCmd(),
- )
-
- return rootCmd
-}
diff --git a/pkg/codeowners/owners_example_test.go b/pkg/codeowners/owners_example_test.go
index 65532f81..3468b672 100644
--- a/pkg/codeowners/owners_example_test.go
+++ b/pkg/codeowners/owners_example_test.go
@@ -3,7 +3,7 @@ package codeowners_test
import (
"fmt"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/pkg/codeowners"
)
func ExampleNewFromPath() {
diff --git a/pkg/codeowners/owners_test.go b/pkg/codeowners/owners_test.go
index 4b4ae799..0fa54e42 100644
--- a/pkg/codeowners/owners_test.go
+++ b/pkg/codeowners/owners_test.go
@@ -8,7 +8,7 @@ import (
"github.com/spf13/afero"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
- "go.szostok.io/codeowners-validator/pkg/codeowners"
+ "go.szostok.io/codeowners/pkg/codeowners"
)
const sampleCodeownerFile = `
diff --git a/pkg/url/canonical_test.go b/pkg/url/canonical_test.go
index 7d05e190..b1e08cd5 100644
--- a/pkg/url/canonical_test.go
+++ b/pkg/url/canonical_test.go
@@ -4,7 +4,7 @@ import (
"testing"
"github.com/stretchr/testify/assert"
- "go.szostok.io/codeowners-validator/pkg/url"
+ "go.szostok.io/codeowners/pkg/url"
)
func TestCanonicalURLPath(t *testing.T) {
diff --git a/tests/integration/helpers_test.go b/tests/integration/helpers_test.go
index 60d6578e..cd2385bd 100644
--- a/tests/integration/helpers_test.go
+++ b/tests/integration/helpers_test.go
@@ -54,19 +54,30 @@ func CloneRepo(t *testing.T, url string, branch string) (string, func()) {
type Executor struct {
envs map[string]string
+ arguments []string
timeout time.Duration
binaryPath string
}
func Exec() *Executor {
return &Executor{
- envs: map[string]string{},
+ arguments: make([]string, 0),
+ envs: map[string]string{},
}
}
// WithEnv adds given env. Overrides if previously existed
func (s *Executor) WithEnv(key string, value string) *Executor {
- s.envs[key] = value
+ if key == "PATH" {
+ s.envs[key] = value
+ } else {
+ s.envs[envPrefix+key] = value
+ }
+ return s
+}
+
+func (s *Executor) WithArg(argument string) *Executor {
+ s.arguments = append(s.arguments, argument)
return s
}
@@ -83,7 +94,7 @@ func (s *Executor) AwaitResultAtMost(timeout time.Duration) *ExecuteOutput {
var stdout, stderr bytes.Buffer
- cmd := exec.CommandContext(ctx, s.binaryPath)
+ cmd := exec.CommandContext(ctx, s.binaryPath, s.arguments...)
cmd.Stderr = &stderr
cmd.Stdout = &stdout
diff --git a/tests/integration/integration_test.go b/tests/integration/integration_test.go
index 1c56d540..a4bd0112 100644
--- a/tests/integration/integration_test.go
+++ b/tests/integration/integration_test.go
@@ -15,6 +15,7 @@ import (
)
const (
+ envPrefix = "CODEOWNERS_"
binaryPathEnvName = "BINARY_PATH"
codeownersSamplesRepo = "https://github.com/gh-codeowners/codeowners-samples.git"
caseInsensitiveOrgCodeownersSamplesRepo = "https://github.com/GitHubCODEOWNERS/codeowners-samples.git"
@@ -38,7 +39,7 @@ var repositories = []struct {
},
}
-// TestCheckHappyPath tests that codeowners-validator reports no issues for valid CODEOWNERS file.
+// TestCheckHappyPath tests that codeowners reports no issues for valid CODEOWNERS file.
//
// This test is based on golden file.
// If the `-test.update-golden` flag is set then the actual content is written
@@ -100,7 +101,8 @@ func TestCheckSuccess(t *testing.T) {
binaryPath := os.Getenv(binaryPathEnvName)
codeownersCmd := Exec().
Binary(binaryPath).
- // codeowners-validator basic config
+ // codeowners basic config
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", repoDir)
for k, v := range tc.envs {
@@ -159,7 +161,8 @@ func TestCheckSuccess(t *testing.T) {
binaryPath := os.Getenv(binaryPathEnvName)
codeownersCmd := Exec().
Binary(binaryPath).
- // codeowners-validator basic config
+ // codeowners basic config
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", repoDir)
for k, v := range tc.envs {
@@ -180,14 +183,15 @@ func TestCheckSuccess(t *testing.T) {
})
}
-// TestCheckFailures tests that codeowners-validator reports issues for not valid CODEOWNERS file.
+// TestCheckFailures tests that codeowners reports issues for not valid CODEOWNERS file.
//
// This test is based on golden file.
// If the `-test.update-golden` flag is set then the actual content is written
// to the golden file.
//
// To update golden file, run:
-// TEST=TestCheckFailures UPDATE_GOLDEN=true make test-integration
+//
+// TEST=TestCheckFailures UPDATE_GOLDEN=true make test-integration
func TestCheckFailures(t *testing.T) {
type Envs map[string]string
tests := []struct {
@@ -252,7 +256,8 @@ func TestCheckFailures(t *testing.T) {
codeownersCmd := Exec().
Binary(binaryPath).
- // codeowners-validator basic config
+ // codeowners basic config
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", repoDir)
for k, v := range tc.envs {
@@ -274,7 +279,8 @@ func TestCheckFailures(t *testing.T) {
}
// To update golden file, run:
-// TEST=TestOwnerCheckAuthZAndAuthN TOKEN_WITH_NO_SCOPES= UPDATE_GOLDEN=true make test-integration
+//
+// TEST=TestOwnerCheckAuthZAndAuthN TOKEN_WITH_NO_SCOPES= UPDATE_GOLDEN=true make test-integration
func TestOwnerCheckAuthZAndAuthN(t *testing.T) {
t.Parallel()
@@ -284,6 +290,7 @@ func TestOwnerCheckAuthZAndAuthN(t *testing.T) {
// given
codeownersCmd := Exec().
Binary(os.Getenv(binaryPathEnvName)).
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", "not-needed").
WithEnv("CHECKS", "owners").
WithEnv("OWNER_CHECKER_REPOSITORY", "gh-codeowners/codeowners-samples")
@@ -306,6 +313,7 @@ func TestOwnerCheckAuthZAndAuthN(t *testing.T) {
// given
codeownersCmd := Exec().
Binary(os.Getenv(binaryPathEnvName)).
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", "not-needed").
WithEnv("CHECKS", "owners").
WithEnv("OWNER_CHECKER_REPOSITORY", "gh-codeowners/codeowners-samples").
@@ -328,6 +336,7 @@ func TestOwnerCheckAuthZAndAuthN(t *testing.T) {
// given
codeownersCmd := Exec().
Binary(os.Getenv(binaryPathEnvName)).
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", "not-needed").
WithEnv("CHECKS", "owners").
WithEnv("OWNER_CHECKER_REPOSITORY", "gh-codeowners/codeowners-samples").
@@ -350,6 +359,7 @@ func TestOwnerCheckAuthZAndAuthN(t *testing.T) {
// given
codeownersCmd := Exec().
Binary(os.Getenv(binaryPathEnvName)).
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", "not-needed").
WithEnv("CHECKS", "owners").
WithEnv("OWNER_CHECKER_REPOSITORY", "gh-codeowners/private-repo").
@@ -378,6 +388,7 @@ func TestGitHubAppAuth(t *testing.T) {
codeownersCmd := Exec().
Binary(os.Getenv(binaryPathEnvName)).
+ WithArg("validate").
WithEnv("REPOSITORY_PATH", repoDir).
WithEnv("CHECKS", "owners").
WithEnv("OWNER_CHECKER_REPOSITORY", "GitHubCODEOWNERS/codeowners-samples").