diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index a42f3546..ff9df6ca 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -24,7 +24,7 @@ jobs: - name: test run: | - go test -race -covermode=atomic -coverprofile=coverage.out ./... + go test -covermode=atomic -coverprofile=coverage.out ./... - name: coverage uses: codecov/codecov-action@v3 diff --git a/Dockerfile b/Dockerfile index 90a90898..d18efdfb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,7 @@ ARG JFROG_VERSION=1.33.2 ADD https://releases.jfrog.io/artifactory/jfrog-cli/v1/${JFROG_VERSION}/jfrog-cli-linux-amd64/jfrog /bin/jfrog RUN chmod a+x /bin/jfrog +RUN chmod -R 777 /tmp ############################################################################## ## docker build --no-cache --target certs -t vela-artifactory:certs . ## @@ -27,6 +28,7 @@ RUN apk add --update --no-cache ca-certificates FROM scratch COPY --from=binary /bin/jfrog /bin/jfrog +COPY --from=binary /tmp /tmp COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt diff --git a/Makefile b/Makefile index 00e3a89b..23f2474c 100644 --- a/Makefile +++ b/Makefile @@ -86,7 +86,7 @@ fix: test: @echo @echo "### Testing Go Code" - @go test -race ./... + @go test ./... # The `test-cover` target is intended to run # the tests for the Go source code and then diff --git a/cmd/vela-artifactory/artifactoryservice.go b/cmd/vela-artifactory/artifactoryservice.go deleted file mode 100644 index 1ee71144..00000000 --- a/cmd/vela-artifactory/artifactoryservice.go +++ /dev/null @@ -1,15 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package main - -import ( - "github.com/jfrog/jfrog-client-go/artifactory/services" - "github.com/jfrog/jfrog-client-go/artifactory/services/utils" -) - -type ArtifactoryServicesManager interface { - UploadFiles(...services.UploadParams) ([]utils.FileInfo, int, int, error) - Copy(services.MoveCopyParams) (int, int, error) - GetPathsToDelete(services.DeleteParams) ([]utils.ResultItem, error) - DeleteFiles([]utils.ResultItem) (int, error) -} diff --git a/cmd/vela-artifactory/config.go b/cmd/vela-artifactory/config.go index 5aa924ea..afa9e874 100644 --- a/cmd/vela-artifactory/config.go +++ b/cmd/vela-artifactory/config.go @@ -9,6 +9,8 @@ import ( "github.com/jfrog/jfrog-client-go/artifactory" "github.com/jfrog/jfrog-client-go/artifactory/auth" + "github.com/jfrog/jfrog-client-go/config" + "github.com/jfrog/jfrog-client-go/http/httpclient" "github.com/jfrog/jfrog-client-go/utils/log" "github.com/sirupsen/logrus" @@ -16,17 +18,19 @@ import ( // Config represents the plugin configuration for Artifactory config information. type Config struct { - // action to perform against the Artifactory instance + // Action to perform against the Artifactory instance Action string + // Token for communication with the Artifactory instance + Token string // API key for communication with the Artifactory instance APIKey string - // enables pretending to perform the action against the Artifactory instance + // DryRun enables pretending to perform the action against the Artifactory instance DryRun bool - // password for communication with the Artifactory instance + // Password for communication with the Artifactory instance Password string - // full url to Artifactory instance + // URL points to the Artifactory instance URL string - // user name for communication with the Artifactory instance + // Username for communication with the Artifactory instance Username string } @@ -51,10 +55,16 @@ func (c *Config) New() (*artifactory.ArtifactoryServicesManager, error) { details.SetUser(c.Username) } - // check if API key is provided - if len(c.APIKey) > 0 { + // check if Access/Identity token is provided + if len(c.Token) > 0 && !httpclient.IsApiKey(c.Token) { + // set Access/Identity token for Artifactory details + details.SetAccessToken(c.APIKey) + } else if len(c.APIKey) > 0 && httpclient.IsApiKey(c.APIKey) { // check if API key is provided // set API key for Artifactory details details.SetApiKey(c.APIKey) + } else if len(c.APIKey) > 0 && !httpclient.IsApiKey(c.APIKey) { + // set Access/Identity token for Artifactory details + details.SetAccessToken(c.APIKey) } // check if password is provided @@ -70,8 +80,8 @@ func (c *Config) New() (*artifactory.ArtifactoryServicesManager, error) { ) // create new Artifactory config from details - config, err := artifactory.NewConfigBuilder(). - SetArtDetails(details). + config, err := config.NewConfigBuilder(). + SetServiceDetails(details). SetDryRun(c.DryRun). Build() if err != nil { @@ -79,12 +89,12 @@ func (c *Config) New() (*artifactory.ArtifactoryServicesManager, error) { } // create new Artifactory client from config and details - client, err := artifactory.New(&details, config) + client, err := artifactory.New(config) if err != nil { return nil, err } - return client, nil + return &client, nil } // Validate verifies the Config is properly configured. diff --git a/cmd/vela-artifactory/config_test.go b/cmd/vela-artifactory/config_test.go index 5e0d0701..617d806b 100644 --- a/cmd/vela-artifactory/config_test.go +++ b/cmd/vela-artifactory/config_test.go @@ -4,17 +4,19 @@ package main import ( "testing" + + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" ) func TestArtifactory_Config_New(t *testing.T) { // setup types c := &Config{ Action: "copy", - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, } got, err := c.New() @@ -31,11 +33,11 @@ func TestArtifactory_Config_Validate(t *testing.T) { // setup types c := &Config{ Action: "copy", - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, } err := c.Validate() @@ -47,11 +49,11 @@ func TestArtifactory_Config_Validate(t *testing.T) { func TestArtifactory_Config_Validate_NoAction(t *testing.T) { // setup types c := &Config{ - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, } err := c.Validate() @@ -65,8 +67,8 @@ func TestArtifactory_Config_Validate_NoAPIKeyOrPassword(t *testing.T) { c := &Config{ Action: "copy", DryRun: false, - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, } err := c.Validate() @@ -80,9 +82,9 @@ func TestArtifactory_Config_Validate_NoAPIKey(t *testing.T) { c := &Config{ Action: "copy", DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + Password: mock.Password, + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, } err := c.Validate() @@ -96,9 +98,9 @@ func TestArtifactory_Config_Validate_NoPassword(t *testing.T) { c := &Config{ Action: "copy", DryRun: false, - APIKey: "superSecretAPIKey", - URL: "https://myarti.com/artifactory", - Username: "octocat", + APIKey: mock.APIKey, + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, } err := c.Validate() @@ -112,9 +114,9 @@ func TestArtifactory_Config_Validate_NoUrl(t *testing.T) { c := &Config{ Action: "copy", DryRun: false, - APIKey: "superSecretAPIKey", - Password: "superSecretPassword", - Username: "octocat", + APIKey: mock.APIKey, + Username: mock.Username, + Password: mock.Password, } err := c.Validate() @@ -128,8 +130,8 @@ func TestArtifactory_Config_Validate_NoUsername(t *testing.T) { c := &Config{ Action: "copy", DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", + Password: mock.Password, + URL: mock.InvalidArtifactoryServerURL, } err := c.Validate() @@ -143,7 +145,7 @@ func TestArtifactory_Config_Validate_NoAuth(t *testing.T) { c := &Config{ Action: "copy", DryRun: false, - URL: "https://myarti.com/artifactory", + URL: mock.InvalidArtifactoryServerURL, } err := c.Validate() diff --git a/cmd/vela-artifactory/copy.go b/cmd/vela-artifactory/copy.go index 5bbe4248..94b29c35 100644 --- a/cmd/vela-artifactory/copy.go +++ b/cmd/vela-artifactory/copy.go @@ -5,6 +5,7 @@ package main import ( "fmt" + "github.com/jfrog/jfrog-client-go/artifactory" "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/jfrog/jfrog-client-go/artifactory/services/utils" @@ -15,25 +16,25 @@ const copyAction = "copy" // Copy represents the plugin configuration for copy information. type Copy struct { - // enables removing source file directory hierarchy + // Flat is a flag that enables removing source file directory hierarchy Flat bool - // enables copying sub-directories from source + // Recursive is a flag that enables copying sub-directories from source Recursive bool - // source path to artifact(s) to copy + // Path is the source path to artifact(s) to copy Path string - // target path to copy artifact(s) to + // Target is the path to copy artifact(s) to Target string } // Exec formats and runs the commands for copying artifacts in Artifactory. -func (c *Copy) Exec(cli ArtifactoryServicesManager) error { +func (c *Copy) Exec(cli artifactory.ArtifactoryServicesManager) error { logrus.Trace("running copy with provided configuration") // create new copy parameters p := services.NewMoveCopyParams() // add copy configuration to copy parameters - p.ArtifactoryCommonParams = &utils.ArtifactoryCommonParams{ + p.CommonParams = &utils.CommonParams{ Pattern: c.Path, Recursive: c.Recursive, Target: c.Target, diff --git a/cmd/vela-artifactory/copy_test.go b/cmd/vela-artifactory/copy_test.go index 69ead987..b181f323 100644 --- a/cmd/vela-artifactory/copy_test.go +++ b/cmd/vela-artifactory/copy_test.go @@ -2,17 +2,53 @@ package main -import "testing" +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" +) + +func TestArtifactory_Copy_Exec(t *testing.T) { + // setup types + s := httptest.NewServer(mock.Handlers()) + + p := &Plugin{ + Config: &Config{ + Action: "copy", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + URL: s.URL, + Username: mock.Username, + Password: mock.Password, + }, + Copy: &Copy{ + Flat: false, + Recursive: false, + Path: "foo/bar", + Target: "bar/foo", + }, + Delete: &Delete{}, + SetProp: &SetProp{}, + Upload: &Upload{}, + } + + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) + } +} func TestArtifactory_Copy_Exec_Error(t *testing.T) { // setup types config := &Config{ Action: "copy", - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "http://localhost:8081/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, } cli, err := config.New() @@ -27,7 +63,7 @@ func TestArtifactory_Copy_Exec_Error(t *testing.T) { Target: "bar/foo", } - err = c.Exec(cli) + err = c.Exec(*cli) if err == nil { t.Errorf("Exec should have returned err") } diff --git a/cmd/vela-artifactory/delete.go b/cmd/vela-artifactory/delete.go index c712521a..6ae689cb 100644 --- a/cmd/vela-artifactory/delete.go +++ b/cmd/vela-artifactory/delete.go @@ -7,6 +7,7 @@ import ( "github.com/sirupsen/logrus" + "github.com/jfrog/jfrog-client-go/artifactory" "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/jfrog/jfrog-client-go/artifactory/services/utils" ) @@ -15,21 +16,21 @@ const deleteAction = "delete" // Delete represents the plugin configuration for delete information. type Delete struct { - // enables removing sub-directories for the artifact(s) in the path + // Recursive is a flag that enables removing sub-directories for the artifact(s) in the path Recursive bool - // target path to artifact(s) to remove + // Path is the target path to artifact(s) to remove Path string } // Exec formats and runs the commands for removing artifacts in Artifactory. -func (d *Delete) Exec(cli ArtifactoryServicesManager) error { +func (d *Delete) Exec(cli artifactory.ArtifactoryServicesManager) error { logrus.Trace("running delete with provided configuration") // create new delete parameters p := services.NewDeleteParams() // add delete configuration to delete parameters - p.ArtifactoryCommonParams = &utils.ArtifactoryCommonParams{ + p.CommonParams = &utils.CommonParams{ Pattern: d.Path, Recursive: d.Recursive, } diff --git a/cmd/vela-artifactory/delete_test.go b/cmd/vela-artifactory/delete_test.go index 50597210..897e72ab 100644 --- a/cmd/vela-artifactory/delete_test.go +++ b/cmd/vela-artifactory/delete_test.go @@ -2,17 +2,80 @@ package main -import "testing" +import ( + "net/http/httptest" + "testing" + + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" +) + +func TestArtifactory_Delete_Exec(t *testing.T) { + // setup types + s := httptest.NewServer(mock.Handlers()) + + p := &Plugin{ + Config: &Config{ + Action: "delete", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + URL: s.URL, + Username: mock.Username, + Password: mock.Password, + }, + Copy: &Copy{}, + Delete: &Delete{ + Recursive: false, + Path: "foo/bar", + }, + SetProp: &SetProp{}, + Upload: &Upload{}, + } + + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) + } +} + +func TestArtifactory_Delete_Exec_NotFound(t *testing.T) { + // setup types + s := httptest.NewServer(mock.Handlers()) + + p := &Plugin{ + Config: &Config{ + Action: "delete", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + URL: s.URL, + Username: mock.Username, + Password: mock.Password, + }, + Copy: &Copy{}, + Delete: &Delete{ + Recursive: false, + Path: "bar/bar/foo", + }, + SetProp: &SetProp{}, + Upload: &Upload{}, + } + + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) + } +} func TestArtifactory_Delete_Exec_Error(t *testing.T) { // setup types config := &Config{ Action: "copy", - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "http://localhost:8081/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, } cli, err := config.New() @@ -25,7 +88,7 @@ func TestArtifactory_Delete_Exec_Error(t *testing.T) { Path: "foo/bar", } - err = d.Exec(cli) + err = d.Exec(*cli) if err == nil { t.Errorf("Exec should have returned err") } diff --git a/cmd/vela-artifactory/docker_promote.go b/cmd/vela-artifactory/docker_promote.go index 41131e4a..3d64fd26 100644 --- a/cmd/vela-artifactory/docker_promote.go +++ b/cmd/vela-artifactory/docker_promote.go @@ -7,109 +7,182 @@ import ( "fmt" "time" + "github.com/jfrog/jfrog-client-go/artifactory" + "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/sirupsen/logrus" - goarty "github.com/target/go-arty/v2/artifactory" ) const dockerPromoteAction = "docker-promote" // DockerPromote represents the plugin configuration for setting a Docker Promotion. type DockerPromote struct { - // Docker repository in Artifactory for the move or copy + // SourceRepo is the Docker repository in Artifactory to use as the source for move or copy + SourceRepo string + // TargetRepo is the Docker repository in Artifactory to use as the destination for move or copy TargetRepo string - // source Docker registry to promote an image from + // DockerRegistry is the source Docker registry to promote an image from DockerRegistry string - // target Docker registry to promote an image to (uses 'DockerRegistry' if empty) + // TargetDockerRegistry is the target Docker registry to promote an image to (uses 'DockerRegistry' if empty) TargetDockerRegistry string - // tag name of image to promote (promotes all tags if empty) - Tag string - // target tag to assign the image after promotion + // SourceTag is the name of image to promote (promotes all tags if empty) + SourceTag string + // TargetTags are the target tags to assign to the image after promotion TargetTags []string - // set to copy instead of moving the image (default: true) + // Copy is a flag to set to copy instead of moving the image (default: true) Copy bool - // An optional value to set an item property to add a promoted date. + // PromoteProperty is an optional value to set an item property to add a promoted date. PromoteProperty bool } // Exec formats and runs the commands for uploading artifacts in Artifactory. -func (p *DockerPromote) Exec(c *Config) error { +func (p *DockerPromote) Exec(cli artifactory.ArtifactoryServicesManager) error { logrus.Trace("running docker-promote with provided configuration") - // create go-arty client for interacting with Docker promotion - // https://github.com/target/go-arty - client, err := goarty.NewClient(c.URL, nil) - if err != nil { - return err - } - - // set basic authentication on client - client.Authentication.SetBasicAuth(c.Username, c.Password) + var payloads []*services.DockerPromoteParams - // set the auth token if user passed token - if len(c.APIKey) != 0 { - client.Authentication.SetTokenAuth(c.APIKey) + if len(p.TargetTags) == 0 { + logrus.Trace("no tags to promote") } - var payloads []*goarty.ImagePromotion - for _, t := range p.TargetTags { - payload := &goarty.ImagePromotion{ - TargetRepo: goarty.String(p.TargetRepo), - DockerRepository: goarty.String(p.DockerRegistry), - TargetDockerRepository: goarty.String(p.TargetDockerRegistry), - Tag: goarty.String(p.Tag), - TargetTag: goarty.String(t), - Copy: goarty.Bool(p.Copy), + // avoid assigning parameters via constructor to ensure promote endpoint is constructed properly + params := services.NewDockerPromoteParams( + "", + "", + "", + ) + + params.SourceRepo = p.SourceRepo + params.TargetRepo = p.TargetRepo + + // assign source repo to target repo when not provided, to ensure backwards compatibility + // with existing configurations that assume source repo is not required + if len(params.SourceRepo) == 0 { + params.SourceRepo = params.TargetRepo + } + + params.SourceDockerImage = p.DockerRegistry + params.TargetDockerImage = p.TargetDockerRegistry + + // use DockerRegistry as TargetDockerRegistry when a target is not set + if len(params.TargetDockerImage) == 0 { + params.TargetDockerImage = params.SourceDockerImage } - payloads = append(payloads, payload) + params.SourceTag = p.SourceTag + params.TargetTag = t + params.Copy = p.Copy + + payloads = append(payloads, ¶ms) - pretty, err := json.MarshalIndent(payload, "", " ") + pretty, err := json.MarshalIndent(params, "", " ") if err != nil { return err } - logrus.Tracef("Created payload for target tag %s: %s", t, string(pretty)) + logrus.Tracef("created payload for target tag %s: %s", t, string(pretty)) } for _, payload := range payloads { - logrus.Debugf("Promoting target tag %s", payload.GetTargetTag()) + logrus.Infof("Promoting tag %s to target %s", payload.GetSourceTag(), payload.GetTargetTag()) - _, _, err := client.Docker.PromoteImage(p.TargetRepo, payload) + err := cli.PromoteDocker(*payload) if err != nil { return err } + // recursively assign promoted_on property based on plugin configuration if p.PromoteProperty { - var promotedImagePath string - - if payload.GetTargetDockerRepository() != "" { - promotedImagePath = fmt.Sprintf( - "%s/%s", - payload.GetTargetDockerRepository(), - payload.GetTargetTag(), - ) - } else { - promotedImagePath = fmt.Sprintf( - "%s/%s", - payload.GetDockerRepository(), - payload.GetTargetTag(), - ) - } + logrus.Infof("Setting promote properties for %s/%s/%s", + payload.TargetRepo, + payload.TargetDockerImage, + payload.TargetTag) - properties := make(map[string][]string) + // setup base property params ts := time.Now().UTC().Format(time.RFC3339) - properties["promoted_on"] = append(properties["promoted_on"], ts) + promotedOnProperty := fmt.Sprintf("promoted_on=%s", ts) + propsParams := services.NewPropsParams() + propsParams.Props = promotedOnProperty + + // setup base search params + searchParams := services.NewSearchParams() + searchParams.Recursive = true + searchParams.IncludeDirs = true + + // this is required to set properties on the image's folder artifact + imageFolderSearchPattern := fmt.Sprintf( + "%s/%s/%s", + payload.TargetRepo, + payload.TargetDockerImage, + payload.TargetTag, + ) + + logrus.Tracef("searching files using pattern %s", imageFolderSearchPattern) + + searchParams.Pattern = imageFolderSearchPattern + + imageFolderReader, err := cli.SearchFiles(searchParams) + if err != nil { + return err + } + + defer imageFolderReader.Close() + + // assign the files found to be used in SetProps + propsParams.Reader = imageFolderReader - _, err = client.Storage.SetItemProperties(payload.GetTargetRepo(), promotedImagePath, properties) + logrus.Tracef("assigning property [%s] to %d matched images", promotedOnProperty, len(imageFolderReader.GetFilesPaths())) + + imageFolderSuccess, err := cli.SetProps(propsParams) + if err != nil { + return err + } + + // setup base search params + searchParams = services.NewSearchParams() + searchParams.Recursive = true + searchParams.IncludeDirs = true + + // this is required to set properties on the image's folder artifact + imageContentsSearchPattern := fmt.Sprintf( + "%s/%s/%s/*", + payload.TargetRepo, + payload.TargetDockerImage, + payload.TargetTag, + ) + + logrus.Tracef("searching files using pattern %s", imageContentsSearchPattern) + + searchParams.Pattern = imageContentsSearchPattern + + imageContentsReader, err := cli.SearchFiles(searchParams) if err != nil { return err } + + defer imageContentsReader.Close() + + // assign the files found to be used in SetProps + propsParams.Reader = imageContentsReader + + logrus.Tracef("assigning property [%s] to %d matched images", promotedOnProperty, len(imageContentsReader.GetFilesPaths())) + + imageContentsSuccess, err := cli.SetProps(propsParams) + if err != nil { + return err + } + + totalSuccess := imageFolderSuccess + imageContentsSuccess + if totalSuccess > 0 { + logrus.Infof("Successfully assigned property [%s] to %d image files.", promotedOnProperty, totalSuccess) + } else { + logrus.Info("Promote properties not assigned to any images.") + } } - logrus.Infof("Promotion ended successfully for tag %s for target tag %s", - payload.GetTag(), - payload.GetTargetTag()) + logrus.Infof("Promotion ended successfully for tag %s promoted to target tag %s", + payload.SourceTag, + payload.TargetTag) } return nil diff --git a/cmd/vela-artifactory/docker_promote_test.go b/cmd/vela-artifactory/docker_promote_test.go index 4b84fb67..ce380e99 100644 --- a/cmd/vela-artifactory/docker_promote_test.go +++ b/cmd/vela-artifactory/docker_promote_test.go @@ -6,58 +6,64 @@ import ( "net/http/httptest" "testing" - "github.com/target/go-arty/v2/artifactory/fixtures/docker" + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" ) func TestArtifactory_DockerPromote_Exec(t *testing.T) { - // Create http test server from our fake API handler - s := httptest.NewServer(docker.FakeHandler()) - // setup types - config := &Config{ - Action: "docker-promote", - APIKey: "superSecretAPIKey", - DryRun: false, - Password: "superSecretPassword", - URL: s.URL, - Username: "octocat", + s := httptest.NewServer(mock.Handlers()) + + p := &Plugin{ + Config: &Config{ + Action: "docker-promote", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + URL: s.URL, + Username: mock.Username, + Password: mock.Password, + }, + Copy: &Copy{}, + Delete: &Delete{}, + DockerPromote: &DockerPromote{ + TargetRepo: "docker", + DockerRegistry: "github/octocat", + }, + SetProp: &SetProp{}, + Upload: &Upload{}, } - tests := []struct { - dockerPromote *DockerPromote - want *error - }{ - { // dockerPromote that does not have a promoteProperty - dockerPromote: &DockerPromote{ - TargetRepo: "docker", - DockerRegistry: "github/octocat", - TargetTags: []string{"test"}, - PromoteProperty: false, - }, - want: nil, + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) + } +} + +func TestArtifactory_DockerPromote_Exec_Error(t *testing.T) { + // setup types + p := &Plugin{ + Config: &Config{ + Action: "docker-promote", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, - //TODO: investigate ways of combining handlers - // - // Go-Arty API docs for handlers: - // "github.com/target/go-arty/artifactory/fixtures/docker" - // "github.com/target/go-arty/artifactory/fixtures/storage" - // - // { // dockerPromote that does have a promoteProperty - // dockerPromote: &DockerPromote{ - // TargetRepo: "docker", - // DockerRegistry: "github/octocat", - // TargetTags: []string{"test"}, - // PromoteProperty: true, - // }, - // want: nil, - // }, + Copy: &Copy{}, + Delete: &Delete{}, + DockerPromote: &DockerPromote{ + TargetRepo: "docker", + DockerRegistry: "github/octocat", + }, + SetProp: &SetProp{}, + Upload: &Upload{}, } - for _, test := range tests { - err := test.dockerPromote.Exec(config) - if err != nil { - t.Errorf("Exec should have returned err: %v", err) - } + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) } } diff --git a/cmd/vela-artifactory/main.go b/cmd/vela-artifactory/main.go index 8eef0c0c..59a875e7 100644 --- a/cmd/vela-artifactory/main.go +++ b/cmd/vela-artifactory/main.go @@ -97,6 +97,12 @@ func main() { Name: "config.api_key", Usage: "API key for communication with the Artifactory instance", }, + &cli.StringFlag{ + EnvVars: []string{"PARAMETER_TOKEN", "ARTIFACTORY_TOKEN"}, + FilePath: "/vela/parameters/artifactory/token,/vela/secrets/artifactory/token", + Name: "config.token", + Usage: "Access/Identity token for communication with the Artifactory instance", + }, &cli.StringFlag{ EnvVars: []string{"PARAMETER_PASSWORD", "ARTIFACTORY_PASSWORD"}, FilePath: "/vela/parameters/artifactory/password,/vela/secrets/artifactory/password", @@ -133,11 +139,17 @@ func main() { // Docker Promote Flags + &cli.StringFlag{ + EnvVars: []string{"PARAMETER_SOURCE_REPO", "ARTIFACTORY_SOURCE_REPO"}, + FilePath: "/vela/parameters/artifactory/source_repo,/vela/secrets/artifactory/source_repo", + Name: "docker_promote.source_repo", + Usage: "source Docker repository in Artifactory for the move or copy", + }, &cli.StringFlag{ EnvVars: []string{"PARAMETER_TARGET_REPO", "ARTIFACTORY_TARGET_REPO"}, FilePath: "/vela/parameters/artifactory/target_repo,/vela/secrets/artifactory/target_repo", Name: "docker_promote.target_repo", - Usage: "Docker repository in Artifactory for the move or copy", + Usage: "destination Docker repository in Artifactory for the move or copy", }, &cli.StringFlag{ EnvVars: []string{"PARAMETER_DOCKER_REGISTRY", "ARTIFACTORY_DOCKER_REGISTRY"}, @@ -154,7 +166,7 @@ func main() { &cli.StringFlag{ EnvVars: []string{"PARAMETER_TAG", "ARTIFACTORY_TAG"}, FilePath: "/vela/parameters/artifactory/tag,/vela/secrets/artifactory/tag", - Name: "docker_promote.tag", + Name: "docker_promote.source_tag", Usage: "tag name of image to promote (promotes all tags if empty)", }, &cli.StringSliceFlag{ @@ -264,6 +276,7 @@ func run(c *cli.Context) error { // config configuration Config: &Config{ Action: c.String("config.action"), + Token: c.String("config.token"), APIKey: c.String("config.api_key"), DryRun: c.Bool("config.dry_run"), Password: c.String("config.password"), @@ -284,10 +297,11 @@ func run(c *cli.Context) error { }, // docker-promote configuration DockerPromote: &DockerPromote{ + SourceRepo: c.String("docker_promote.source_repo"), TargetRepo: c.String("docker_promote.target_repo"), DockerRegistry: c.String("docker_promote.docker_registry"), TargetDockerRegistry: c.String("docker_promote.target_docker_registry"), - Tag: c.String("docker_promote.tag"), + SourceTag: c.String("docker_promote.source_tag"), TargetTags: c.StringSlice("docker_promote.target_tags"), Copy: c.Bool("docker_promote.copy"), PromoteProperty: c.Bool("docker_promote.props"), diff --git a/cmd/vela-artifactory/mock/fixtures/repositories.json b/cmd/vela-artifactory/mock/fixtures/repositories.json new file mode 100644 index 00000000..0395c8a8 --- /dev/null +++ b/cmd/vela-artifactory/mock/fixtures/repositories.json @@ -0,0 +1,10 @@ +{ + "repositories": [ + "docker-dev", + "docker-test", + "docker-stage", + "docker-prod", + "hello-world", + "hello-cloud" + ] +} \ No newline at end of file diff --git a/cmd/vela-artifactory/mock/fixtures/search.json b/cmd/vela-artifactory/mock/fixtures/search.json new file mode 100644 index 00000000..180bf230 --- /dev/null +++ b/cmd/vela-artifactory/mock/fixtures/search.json @@ -0,0 +1,10 @@ +{ + "results": [ + { + "uri": "http://localhost:8081/artifactory/api/storage/foo/bar/file.json" + }, + { + "uri": "http://localhost:8081/artifactory/api/foo/bar/file.txt" + } + ] +} \ No newline at end of file diff --git a/cmd/vela-artifactory/mock/fixtures/tags.json b/cmd/vela-artifactory/mock/fixtures/tags.json new file mode 100644 index 00000000..cdd8881e --- /dev/null +++ b/cmd/vela-artifactory/mock/fixtures/tags.json @@ -0,0 +1,10 @@ +{ + "name": "docker-dev", + "tags": [ + "0.1.0", + "0.2.0", + "0.3.0", + "0.4.0", + "0.5.0" + ] + } \ No newline at end of file diff --git a/cmd/vela-artifactory/mock/fixtures/version.json b/cmd/vela-artifactory/mock/fixtures/version.json new file mode 100644 index 00000000..983de946 --- /dev/null +++ b/cmd/vela-artifactory/mock/fixtures/version.json @@ -0,0 +1,3 @@ +{ + "version": "7.63.12" +} \ No newline at end of file diff --git a/cmd/vela-artifactory/mock/mock.go b/cmd/vela-artifactory/mock/mock.go new file mode 100644 index 00000000..cec3a7ef --- /dev/null +++ b/cmd/vela-artifactory/mock/mock.go @@ -0,0 +1,104 @@ +// SPDX-License-Identifier: Apache-2.0 + +package mock + +import ( + "fmt" + "net/http" + "os" + "strings" + + "github.com/gin-gonic/gin" +) + +const ( + InvalidArtifactoryServerURL = "http://localhost:8081/artifactory" + Username = "octocat" + APIKey = "superSecretAPIKey" + Password = "superSecretPassword" + Token = "superSecretToken" +) + +// Handlers returns an http.Handler group that is capable of handling +// Artifactory API requests and returning mock responses. +func Handlers() http.Handler { + gin.SetMode(gin.TestMode) + + e := gin.New() + + e.GET("/api/system/version", getVersion) + e.POST("/api/search/aql", search) + e.POST("/api/copy", copyArtifact) + e.DELETE("/", deleteArtifact) + e.GET("/api/docker/:registry/v2/_catalog", getRepositories) + e.GET("/api/docker/:registry/v2/docker-dev/tags/list", getTags) + e.POST("/api/docker/:registry/v2/promote", promoteImage) + e.PUT("/api/storage", setProp) + e.PUT("/foo/bar", uploadFiles) + + return e +} + +func getVersion(c *gin.Context) { + c.String(200, loadFixture("mock/fixtures/version.json")) +} + +func search(c *gin.Context) { + c.String(200, loadFixture("mock/fixtures/search.json")) +} + +func copyArtifact(c *gin.Context) { + c.JSON(200, "Copy ended successfully") +} + +func deleteArtifact(c *gin.Context) { + c.JSON(204, "Delete ended successfully") +} + +func setProp(c *gin.Context) { + c.JSON(204, "Property set successfully") +} + +func uploadFiles(c *gin.Context) { + c.JSON(200, map[string]interface{}{ + "checksums": map[string]interface{}{"checksum": "abcxyz123"}, + }) +} + +func getRepositories(c *gin.Context) { + registry := c.Param("registry") + + if strings.Contains(registry, "not-found") { + c.JSON(404, fmt.Sprintf("Registry %s does not exist", registry)) + return + } + + c.String(200, loadFixture("mock/fixtures/repositories.json")) +} + +func getTags(c *gin.Context) { + registry := c.Param("registry") + + if strings.Contains(registry, "not-found") { + c.JSON(404, fmt.Sprintf("Registry %s does not exist", registry)) + return + } + + c.String(200, loadFixture("mock/fixtures/tags.json")) +} + +func promoteImage(c *gin.Context) { + registry := c.Param("registry") + + if strings.Contains(registry, "not-found") { + c.JSON(404, fmt.Sprintf("Registry %s does not exist", registry)) + return + } + + c.JSON(200, "Promotion ended successfully") +} + +func loadFixture(file string) string { + data, _ := os.ReadFile(file) + return string(data) +} diff --git a/cmd/vela-artifactory/mock/testdata/baz.txt b/cmd/vela-artifactory/mock/testdata/baz.txt new file mode 100644 index 00000000..0c759a44 --- /dev/null +++ b/cmd/vela-artifactory/mock/testdata/baz.txt @@ -0,0 +1 @@ +test123 \ No newline at end of file diff --git a/cmd/vela-artifactory/plugin.go b/cmd/vela-artifactory/plugin.go index 2c26da64..0b6af016 100644 --- a/cmd/vela-artifactory/plugin.go +++ b/cmd/vela-artifactory/plugin.go @@ -17,17 +17,17 @@ var ( // Plugin represents the configuration loaded for the plugin. type Plugin struct { - // config arguments loaded for the plugin + // Config stores arguments loaded for the plugin Config *Config - // copy arguments loaded for the plugin + // Copy arguments loaded for the plugin Copy *Copy - // delete arguments loaded for the plugin + // Delete arguments loaded for the plugin Delete *Delete - // docker-promote arguments loaded for the plugin + // DockerPromote arguments loaded for the plugin DockerPromote *DockerPromote - // set-prop arguments loaded for the plugin + // SetProp arguments loaded for the plugin SetProp *SetProp - // upload arguments loaded for the plugin + // Upload arguments loaded for the plugin Upload *Upload } @@ -45,19 +45,19 @@ func (p *Plugin) Exec() error { switch p.Config.Action { case copyAction: // execute copy action - return p.Copy.Exec(cli) + return p.Copy.Exec(*cli) case deleteAction: // execute delete action - return p.Delete.Exec(cli) + return p.Delete.Exec(*cli) case dockerPromoteAction: // execute docker-promote action - return p.DockerPromote.Exec(p.Config) + return p.DockerPromote.Exec(*cli) case setPropAction: // execute set-prop action - return p.SetProp.Exec(cli) + return p.SetProp.Exec(*cli) case uploadAction: // execute upload action - return p.Upload.Exec(cli) + return p.Upload.Exec(*cli) default: return fmt.Errorf( "%w: %s (Valid actions: %s, %s, %s, %s, %s)", diff --git a/cmd/vela-artifactory/plugin_test.go b/cmd/vela-artifactory/plugin_test.go index 26ba8398..fc5db4fd 100644 --- a/cmd/vela-artifactory/plugin_test.go +++ b/cmd/vela-artifactory/plugin_test.go @@ -3,168 +3,22 @@ package main import ( - "net/http/httptest" "testing" - "github.com/target/go-arty/v2/artifactory/fixtures/docker" + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" ) -func TestArtifactory_Plugin_Exec_Copy(t *testing.T) { - // setup types - p := &Plugin{ - Config: &Config{ - Action: "copy", - APIKey: "superSecretAPIKey", - DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", - }, - Copy: &Copy{ - Flat: false, - Recursive: false, - Path: "foo/bar", - Target: "bar/foo", - }, - Delete: &Delete{}, - SetProp: &SetProp{}, - Upload: &Upload{}, - } - - err := p.Exec() - if err == nil { - t.Errorf("Exec should have returned err") - } -} - -func TestArtifactory_Plugin_Exec_Delete(t *testing.T) { - // setup types - p := &Plugin{ - Config: &Config{ - Action: "delete", - APIKey: "superSecretAPIKey", - DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", - }, - Copy: &Copy{}, - Delete: &Delete{ - Recursive: false, - Path: "foo/bar", - }, - SetProp: &SetProp{}, - Upload: &Upload{}, - } - - err := p.Exec() - if err == nil { - t.Errorf("Exec should have returned err") - } -} - -func TestArtifactory_Plugin_Exec_DockerPromote(t *testing.T) { - // Create http test server from our fake API handler - s := httptest.NewServer(docker.FakeHandler()) - - // setup types - p := &Plugin{ - Config: &Config{ - Action: "docker-promote", - APIKey: "superSecretAPIKey", - DryRun: false, - Password: "superSecretPassword", - URL: s.URL, - Username: "octocat", - }, - Copy: &Copy{}, - Delete: &Delete{}, - DockerPromote: &DockerPromote{ - TargetRepo: "docker", - DockerRegistry: "github/octocat", - }, - SetProp: &SetProp{}, - Upload: &Upload{}, - } - - err := p.Exec() - if err != nil { - t.Errorf("Exec should have returned err") - } -} - -func TestArtifactory_Plugin_Exec_SetProp(t *testing.T) { - // setup types - p := &Plugin{ - Config: &Config{ - Action: "set-prop", - APIKey: "superSecretAPIKey", - DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", - }, - Copy: &Copy{}, - Delete: &Delete{}, - SetProp: &SetProp{ - Path: "foo/bar", - Props: []*Prop{ - { - Name: "foo", - Value: "bar", - }, - }, - RawProps: `[{"name": "single", "value": "foo"}]`, - }, - Upload: &Upload{}, - } - - err := p.Exec() - if err == nil { - t.Errorf("Exec should have returned err") - } -} - -func TestArtifactory_Plugin_Exec_Upload(t *testing.T) { - // setup types - p := &Plugin{ - Config: &Config{ - Action: "upload", - APIKey: "superSecretAPIKey", - DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", - }, - Copy: &Copy{}, - Delete: &Delete{}, - SetProp: &SetProp{}, - Upload: &Upload{ - Flat: true, - IncludeDirs: false, - Recursive: true, - Regexp: false, - Path: "foo/bar", - Sources: []string{"baz.txt"}, - }, - } - - err := p.Exec() - if err == nil { - t.Errorf("Exec should have returned err") - } -} - func TestArtifactory_Plugin_Exec_InvalidAction(t *testing.T) { // setup types p := &Plugin{ Config: &Config{ Action: "foobar", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, @@ -183,11 +37,12 @@ func TestArtifactory_Plugin_Validate(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "copy", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{ Flat: false, @@ -234,11 +89,12 @@ func TestArtifactory_Plugin_Validate_InvalidAction(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "foobar", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, @@ -274,11 +130,12 @@ func TestArtifactory_Plugin_Validate_NoCopy(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "copy", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, @@ -298,11 +155,12 @@ func TestArtifactory_Plugin_Validate_NoDelete(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "delete", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, @@ -322,11 +180,12 @@ func TestArtifactory_Plugin_Validate_NoDockerPromote(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "docker-promote", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, @@ -346,11 +205,12 @@ func TestArtifactory_Plugin_Validate_NoSetProp(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "set-prop", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, @@ -370,11 +230,12 @@ func TestArtifactory_Plugin_Validate_NoUpload(t *testing.T) { p := &Plugin{ Config: &Config{ Action: "upload", - APIKey: "superSecretAPIKey", + Token: mock.Token, + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "https://myarti.com/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, }, Copy: &Copy{}, Delete: &Delete{}, diff --git a/cmd/vela-artifactory/prop.go b/cmd/vela-artifactory/prop.go index 6975f175..ca8d75c4 100644 --- a/cmd/vela-artifactory/prop.go +++ b/cmd/vela-artifactory/prop.go @@ -58,25 +58,25 @@ func (p *Prop) Validate() error { // SetProp represents the plugin configuration for setting property information. type SetProp struct { - // target path to artifact(s) to set properties + // Path is the target path to artifact(s) to set properties Path string - // properties to set on the artifact(s) + // Props are properties to set on the artifact(s) Props []*Prop - // raw input of properties provided for plugin + // RawProps is raw input of properties provided for plugin RawProps string - // enables setting properties on sub-directories for the artifact(s) in the path + // Recursive is a flag that enables setting properties on sub-directories for the artifact(s) in the path Recursive bool } // Exec formats and runs the commands for setting properties on artifacts in Artifactory. -func (s *SetProp) Exec(cli *artifactory.ArtifactoryServicesManager) error { +func (s *SetProp) Exec(cli artifactory.ArtifactoryServicesManager) error { logrus.Trace("running set-prop with provided configuration") // create new search parameters searchParams := services.NewSearchParams() // add search configuration to search parameters - searchParams.ArtifactoryCommonParams = &utils.ArtifactoryCommonParams{ + searchParams.CommonParams = &utils.CommonParams{ Pattern: s.Path, Recursive: s.Recursive, } @@ -91,7 +91,7 @@ func (s *SetProp) Exec(cli *artifactory.ArtifactoryServicesManager) error { p := services.NewPropsParams() // add property configuration to property parameters - p.Items = files + p.Reader = files p.Props = s.String() // send API call to set properties for artifacts in Artifactory diff --git a/cmd/vela-artifactory/prop_test.go b/cmd/vela-artifactory/prop_test.go index cc0184a8..77c8b5a0 100644 --- a/cmd/vela-artifactory/prop_test.go +++ b/cmd/vela-artifactory/prop_test.go @@ -3,10 +3,48 @@ package main import ( + "net/http/httptest" "reflect" "testing" + + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" ) +func TestArtifactory_Prop_Exec(t *testing.T) { + // setup types + s := httptest.NewServer(mock.Handlers()) + + p := &Plugin{ + Config: &Config{ + Action: "set-prop", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + Password: mock.Password, + URL: s.URL, + Username: mock.Username, + }, + Copy: &Copy{}, + Delete: &Delete{}, + SetProp: &SetProp{ + Path: "foo/bar", + Props: []*Prop{ + { + Name: "foo", + Value: "bar", + }, + }, + RawProps: `[{"name": "single", "value": "foo"}]`, + }, + Upload: &Upload{}, + } + + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) + } +} + func TestArtifactory_Prop_String_Value(t *testing.T) { // setup types p := &Prop{ @@ -110,11 +148,11 @@ func TestArtifactory_SetProp_Exec_Error(t *testing.T) { // setup types config := &Config{ Action: "set-prop", - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "http://localhost:8081/artifactory", - Username: "octocat", + Password: mock.Password, + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, } cli, err := config.New() @@ -133,7 +171,7 @@ func TestArtifactory_SetProp_Exec_Error(t *testing.T) { RawProps: `[{"name": "single", "value": "foo"}]`, } - err = s.Exec(cli) + err = s.Exec(*cli) if err == nil { t.Errorf("Exec should have returned err") } diff --git a/cmd/vela-artifactory/testdata/mock.go b/cmd/vela-artifactory/testdata/mock.go deleted file mode 100644 index 1ddec384..00000000 --- a/cmd/vela-artifactory/testdata/mock.go +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package fixtures - -import ( - "net/http" - - "github.com/gin-gonic/gin" -) - -// Handler returns an http.Handler that is capable of handling a variety of mock -// Artifactory requests and returning mock responses. -func Handler() http.Handler { - gin.SetMode(gin.TestMode) - - e := gin.New() - e.GET("/the-repo-key/project", getRepo) - e.GET("/the-repo-key/project/filename.tar2", getFile) - - return e -} - -func getRepo(c *gin.Context) { - c.String(200, "") -} - -func getFile(c *gin.Context) { - c.String(200, "") -} diff --git a/cmd/vela-artifactory/testdata/upload-args.json b/cmd/vela-artifactory/testdata/upload-args.json deleted file mode 100644 index 88bd2267..00000000 --- a/cmd/vela-artifactory/testdata/upload-args.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "sources": ["some/new/source"], - "path": "file/path", - "dryrun": true -} diff --git a/cmd/vela-artifactory/upload.go b/cmd/vela-artifactory/upload.go index dd7bd5f5..0f6e00cb 100644 --- a/cmd/vela-artifactory/upload.go +++ b/cmd/vela-artifactory/upload.go @@ -7,6 +7,7 @@ import ( "github.com/sirupsen/logrus" + "github.com/jfrog/jfrog-client-go/artifactory" "github.com/jfrog/jfrog-client-go/artifactory/services" "github.com/jfrog/jfrog-client-go/artifactory/services/utils" ) @@ -30,7 +31,7 @@ type Upload struct { } // Exec formats and runs the commands for uploading artifacts in Artifactory. -func (u *Upload) Exec(cli ArtifactoryServicesManager) error { +func (u *Upload) Exec(cli artifactory.ArtifactoryServicesManager) error { logrus.Trace("running upload with provided configuration") // iterate through all sources @@ -39,7 +40,7 @@ func (u *Upload) Exec(cli ArtifactoryServicesManager) error { p := services.NewUploadParams() // add upload configuration to upload parameters - p.ArtifactoryCommonParams = &utils.ArtifactoryCommonParams{ + p.CommonParams = &utils.CommonParams{ IncludeDirs: u.IncludeDirs, Pattern: source, Recursive: u.Recursive, @@ -47,10 +48,9 @@ func (u *Upload) Exec(cli ArtifactoryServicesManager) error { Target: u.Path, } p.Flat = u.Flat - p.Retries = 3 // send API call to upload artifacts in Artifactory - _, _, totalFailed, err := cli.UploadFiles(p) + _, totalFailed, err := cli.UploadFiles(p) if totalFailed > 0 || err != nil { return err } diff --git a/cmd/vela-artifactory/upload_test.go b/cmd/vela-artifactory/upload_test.go index e6f7fa56..57499550 100644 --- a/cmd/vela-artifactory/upload_test.go +++ b/cmd/vela-artifactory/upload_test.go @@ -3,22 +3,53 @@ package main import ( - "errors" + "net/http/httptest" "testing" - "github.com/jfrog/jfrog-client-go/artifactory/services" - "github.com/jfrog/jfrog-client-go/artifactory/services/utils" + "github.com/go-vela/vela-artifactory/cmd/vela-artifactory/mock" ) +func TestArtifactory_Plugin_Exec_Upload(t *testing.T) { + // setup types + s := httptest.NewServer(mock.Handlers()) + + p := &Plugin{ + Config: &Config{ + Action: "upload", + Token: mock.Token, + APIKey: mock.APIKey, + DryRun: false, + URL: s.URL, + Username: mock.Username, + Password: mock.Password, + }, + Copy: &Copy{}, + Delete: &Delete{}, + SetProp: &SetProp{}, + Upload: &Upload{ + Flat: true, + IncludeDirs: false, + Recursive: true, + Regexp: false, + Path: "foo/bar", + Sources: []string{"mock/testdata/baz.txt"}, + }, + } + + err := p.Exec() + if err != nil { + t.Errorf("Exec returned err %v", err) + } +} func TestArtifactory_Upload_Exec_Error(t *testing.T) { // setup types config := &Config{ Action: "upload", - APIKey: "superSecretAPIKey", + APIKey: mock.APIKey, DryRun: false, - Password: "superSecretPassword", - URL: "http://localhost:8081/artifactory", - Username: "octocat", + URL: mock.InvalidArtifactoryServerURL, + Username: mock.Username, + Password: mock.Password, } cli, err := config.New() @@ -35,7 +66,7 @@ func TestArtifactory_Upload_Exec_Error(t *testing.T) { Sources: []string{"baz.txt"}, } - err = u.Exec(cli) + err = u.Exec(*cli) if err == nil { t.Errorf("Exec should have returned err") } @@ -89,63 +120,3 @@ func TestArtifactory_Upload_Validate_NoSources(t *testing.T) { t.Errorf("Validate should have returned err") } } - -func TestArtifactory_Upload_Failure_Returns_Error(t *testing.T) { - cli := &MockArtifactoryService{Fail: true} - - u := &Upload{ - Flat: true, - IncludeDirs: false, - Recursive: true, - Regexp: false, - Path: "foo/bar", - Sources: []string{"baz.txt"}, - } - - err := u.Exec(cli) - if err == nil { - t.Errorf("Exec should have returned err") - } -} - -func TestArtifactory_Upload_Success(t *testing.T) { - cli := &MockArtifactoryService{Fail: false} - - u := &Upload{ - Flat: true, - IncludeDirs: false, - Recursive: true, - Regexp: false, - Path: "foo/bar", - Sources: []string{"baz.txt"}, - } - - err := u.Exec(cli) - if err != nil { - t.Errorf("Exec should have returned err") - } -} - -type MockArtifactoryService struct { - Fail bool -} - -func (a *MockArtifactoryService) UploadFiles(...services.UploadParams) ([]utils.FileInfo, int, int, error) { - if a.Fail { - return nil, 0, 1, errors.New("upload failed") - } - - return nil, 0, 0, nil -} - -func (a *MockArtifactoryService) Copy(services.MoveCopyParams) (int, int, error) { - return 0, 0, nil -} - -func (a *MockArtifactoryService) GetPathsToDelete(services.DeleteParams) ([]utils.ResultItem, error) { - return nil, nil -} - -func (a *MockArtifactoryService) DeleteFiles([]utils.ResultItem) (int, error) { - return 0, nil -} diff --git a/go.mod b/go.mod index a3daf78f..ca0ccf7a 100644 --- a/go.mod +++ b/go.mod @@ -5,64 +5,81 @@ go 1.20 require ( github.com/Masterminds/semver/v3 v3.2.1 github.com/ghodss/yaml v1.0.0 + github.com/gin-gonic/gin v1.9.1 github.com/go-vela/types v0.20.1 - github.com/jfrog/jfrog-client-go v0.8.1 + github.com/jfrog/jfrog-client-go v1.34.3 github.com/joho/godotenv v1.5.1 github.com/sirupsen/logrus v1.9.3 - github.com/target/go-arty/v2 v2.3.1 github.com/urfave/cli/v2 v2.25.7 ) require ( + dario.cat/mergo v1.0.0 // indirect + github.com/CycloneDX/cyclonedx-go v0.7.2 // indirect + github.com/Microsoft/go-winio v0.6.1 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c // indirect + github.com/acomagu/bufpipe v1.0.4 // indirect + github.com/andybalholm/brotli v1.0.1 // indirect github.com/bytedance/sonic v1.9.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect - github.com/coreos/go-semver v0.3.0 // indirect + github.com/cloudflare/circl v1.3.3 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect - github.com/dsnet/compress v0.0.1 // indirect - github.com/emirpasic/gods v1.12.0 // indirect - github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db // indirect + github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect + github.com/emirpasic/gods v1.18.1 // indirect + github.com/forPelevin/gomoji v1.1.8 // indirect github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.9.1 // indirect + github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect + github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-git/v5 v5.9.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-playground/validator/v10 v10.14.0 // indirect github.com/goccy/go-json v0.10.2 // indirect - github.com/golang/snappy v0.0.1 // indirect - github.com/google/go-querystring v1.0.0 // indirect + github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect + github.com/golang/snappy v0.0.2 // indirect + github.com/gookit/color v1.5.4 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jfrog/gofrog v1.0.6 // indirect + github.com/jfrog/build-info-go v1.9.13 // indirect + github.com/jfrog/gofrog v1.3.1 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd // indirect + github.com/kevinburke/ssh_config v1.2.0 // indirect + github.com/klauspost/compress v1.11.4 // indirect github.com/klauspost/cpuid/v2 v2.2.4 // indirect + github.com/klauspost/pgzip v1.2.5 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/mholt/archiver v2.1.0+incompatible // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mholt/archiver/v3 v3.5.1 // indirect + github.com/minio/sha256-simd v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/nwaples/rardecode v1.1.0 // indirect github.com/pelletier/go-toml/v2 v2.0.8 // indirect - github.com/pierrec/lz4 v2.5.2+incompatible // indirect + github.com/pierrec/lz4/v4 v4.1.2 // indirect + github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/rivo/uniseg v0.4.3 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/sergi/go-diff v1.1.0 // indirect - github.com/src-d/gcfg v1.4.0 // indirect - github.com/tidwall/gjson v1.9.3 // indirect - github.com/tidwall/match v1.1.1 // indirect - github.com/tidwall/pretty v1.2.0 // indirect + github.com/skeema/knownhosts v1.2.0 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.11 // indirect - github.com/ulikunitz/xz v0.5.8 // indirect - github.com/xanzy/ssh-agent v0.2.1 // indirect + github.com/ulikunitz/xz v0.5.9 // indirect + github.com/xanzy/ssh-agent v0.3.3 // indirect + github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect + github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect golang.org/x/arch v0.3.0 // indirect - golang.org/x/crypto v0.11.0 // indirect - golang.org/x/net v0.12.0 // indirect - golang.org/x/sys v0.10.0 // indirect - golang.org/x/text v0.11.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/mod v0.12.0 // indirect + golang.org/x/net v0.17.0 // indirect + golang.org/x/sys v0.13.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/tools v0.13.0 // indirect google.golang.org/protobuf v1.30.0 // indirect - gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect - gopkg.in/src-d/go-git.v4 v4.13.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 5e26b91d..607d7f38 100644 --- a/go.sum +++ b/go.sum @@ -1,41 +1,45 @@ -github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= +dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= +github.com/CycloneDX/cyclonedx-go v0.7.2 h1:kKQ0t1dPOlugSIYVOMiMtFqeXI2wp/f5DBIdfux8gnQ= +github.com/CycloneDX/cyclonedx-go v0.7.2/go.mod h1:K2bA+324+Og0X84fA8HhN2X066K7Bxz4rpMQ4ZhjtSk= github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7 h1:uSoVVbwJiQipAclBbw+8quDsfcvFjOpI5iCf4p/cqCs= -github.com/alcortesm/tgz v0.0.0-20161220082320-9c5fe88206d7/go.mod h1:6zEj6s6u/ghQa61ZWa/C2Aw3RkjiTBOix7dkqa1VLIs= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239 h1:kFOfPq6dUM1hTo4JG6LR5AXSUEsOjtdm0kw0FtQtMJA= -github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= +github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c h1:kMFnB0vCcX7IL/m9Y5LO+KQYv+t1CQOiFe6+SV2J7bE= +github.com/ProtonMail/go-crypto v0.0.0-20230923063757-afb1ddc0824c/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= +github.com/acomagu/bufpipe v1.0.4 h1:e3H4WUzM3npvo5uv95QuJM3cQspFNtFBzvJ2oNjKIDQ= +github.com/acomagu/bufpipe v1.0.4/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= +github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc= +github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/buger/jsonparser v0.0.0-20180910192245-6acdf747ae99/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= +github.com/bradleyjkemp/cupaloy/v2 v2.8.0 h1:any4BmKE+jGIaMpnU8YgH/I2LPiLBufr6oMMlVBbn9M= +github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM= -github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= +github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= +github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= -github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY= +github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s= github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= -github.com/emirpasic/gods v1.12.0 h1:QAUIPSaCu4G+POclxeqb3F+WPpdKqFGlw36+yOzGlrg= -github.com/emirpasic/gods v1.12.0/go.mod h1:YfzfFFoVP/catgzJb4IKIqXjX78Ha8FMSDh3ymbK86o= -github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db h1:gb2Z18BhTPJPpLQWj4T+rfKHYCHxRHCtRxhKKjRidVw= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/frankban/quicktest v1.7.2 h1:2QxQoC1TS09S7fhCPsrvqYdvP1H5M1P1ih5ABm3BTYk= -github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o= -github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= +github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= +github.com/forPelevin/gomoji v1.1.8 h1:JElzDdt0TyiUlecy6PfITDL6eGvIaxqYH1V52zrd0qQ= +github.com/forPelevin/gomoji v1.1.8/go.mod h1:8+Z3KNGkdslmeGZBC3tCrwMrcPy5GRzAD+gL9NAwMXg= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= @@ -44,9 +48,14 @@ github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= -github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= -github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= -github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= +github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= +github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= +github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8= +github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY= +github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= @@ -58,91 +67,87 @@ github.com/go-vela/types v0.20.1 h1:hHAX0Iij2J7UZ9f3SlXbwNy481CjKzU9CBfkiLuysVE= github.com/go-vela/types v0.20.1/go.mod h1:AXO4oQSygOBQ02fPapsKjQHkx2aQO3zTu7clpvVbXBY= github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= +github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= -github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= -github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= -github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw= +github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/jfrog/gofrog v1.0.5/go.mod h1:4Caxvc8B2K1A798G1Ne+SsUICRPPre4GpgcFqj+EXJ8= -github.com/jfrog/gofrog v1.0.6 h1:yUDxSCw8gTK6vC4PvtG0HTnEOQJSZ+O4lWGCgkev1nU= -github.com/jfrog/gofrog v1.0.6/go.mod h1:HkDzg+tMNw23UryoOv0+LB94BzYcl6MCIoz8Tmlb+s8= -github.com/jfrog/jfrog-client-go v0.8.1 h1:IsYtyuE1Jp2ny3ez8rgbLo0HlKMtyOv6C5bEm5EAUlg= -github.com/jfrog/jfrog-client-go v0.8.1/go.mod h1:K/8CIkJzhmEt/CcQYHnWjbWfjzj4eX6LHXY1UQIfQDg= +github.com/jfrog/build-info-go v1.9.13 h1:OeoGzPVK/O4TOUYk35uL4bXg/hleyqMrjGjjmyLOYrg= +github.com/jfrog/build-info-go v1.9.13/go.mod h1:ujJ8XQZMdT2tMkLSMJNyDd1pCY+duwHdjV+9or9FLIg= +github.com/jfrog/gofrog v1.3.1 h1:QqAwQXCVReT724uga1AYqG/ZyrNQ6f+iTxmzkb+YFQk= +github.com/jfrog/gofrog v1.3.1/go.mod h1:IFMc+V/yf7rA5WZ74CSbXe+Lgf0iApEQLxRZVzKRUR0= +github.com/jfrog/jfrog-client-go v1.34.3 h1:kDfw3FUQQvOsTKFqonIgLlziez6CSX80xCYZIH9YYcg= +github.com/jfrog/jfrog-client-go v1.34.3/go.mod h1:fuxhYzWEkA16+ZV5cP/BJUGjA3SXVKbBoDmb8ZS6J4g= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kevinburke/ssh_config v0.0.0-20180830205328-81db2a75821e/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd h1:Coekwdh0v2wtGp9Gmz1Ze3eVRAWJMLokvN3QjdzCHLY= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= +github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/compress v1.11.4 h1:kz40R/YWls3iqT9zX9AHN3WoVsrAWVyui5sxuLqiXqU= +github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= +github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= 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 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= -github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/matryer/is v1.2.0 h1:92UTHpy8CDwaJ08GqLDzhhuixiBUUD1p3AU6PHddz4A= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mholt/archiver v2.1.0+incompatible h1:1ivm7KAHPtPere1YDOdrY6xGdbMNGRWThZbYh5lWZT0= -github.com/mholt/archiver v2.1.0+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU= -github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= -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.0.0/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo= +github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= +github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM= +github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ= github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= -github.com/pelletier/go-buffruneio v0.2.0/go.mod h1:JkE26KsDizTr40EUHkXVtNPvgGtbSNq5BcowyYOWdKo= -github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= -github.com/pierrec/lz4 v2.3.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pierrec/lz4 v2.5.2+incompatible h1:WCjObylUIOlKy/+7Abdn34TLIkXiA4UWUMhxq9m9ZXI= -github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= -github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM= +github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= +github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= +github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= +github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.4.3 h1:utMvzDsuh3suAEnhH0RdHmoPbU648o6CvXxTx4SBMOw= +github.com/rivo/uniseg v0.4.3/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0= github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= -github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg= -github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= -github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= -github.com/spf13/viper v1.2.1/go.mod h1:P4AexN0a+C9tGAnUFNwDMYYZv3pjFuvmeiMyKRaNVlI= -github.com/src-d/gcfg v1.3.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI= -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/skeema/knownhosts v1.2.0 h1:h9r9cf0+u7wSE+M183ZtMGgOJKiL96brpaz5ekfJCpM= +github.com/skeema/knownhosts v1.2.0/go.mod h1:g4fPeYpque7P0xefxtGzV81ihjC8sX2IqpAoNkjxbMo= 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= @@ -153,85 +158,107 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ 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/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/target/go-arty/v2 v2.3.1 h1:Kt+wxD0Bdv9XfovF6a1GVHi18LNxq0jx1qASVNoegYQ= -github.com/target/go-arty/v2 v2.3.1/go.mod h1:OdpDI+sRvJQ9YWe4Gq+c6tX269zNVGpsEQVcgDPrlQw= -github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= -github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= -github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/terminalstatic/go-xsd-validate v0.1.5 h1:RqpJnf6HGE2CB/lZB1A8BYguk8uRtcvYAPLCF15qguo= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= -github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= -github.com/ulikunitz/xz v0.5.8 h1:ERv8V6GKqVi23rgu5cj9pVfVzJbOqAY2Ntl88O6c2nQ= github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= +github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I= +github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= -github.com/xanzy/ssh-agent v0.2.0/go.mod h1:0NyE30eGUDliuLEHJgYte/zncp2zdTStcOnWhgSqHD8= -github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= +github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= +github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= +github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= -golang.org/x/crypto v0.0.0-20181001203147-e3636079e1a4/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA= -golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= -golang.org/x/net v0.0.0-20180926154720-4dfa2610cdf3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= -golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20180903190138-2b024373dcd9/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190221075227-b4e8571b14e0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/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-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= -golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/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.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= -golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ= +golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0/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 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/src-d/go-billy.v4 v4.3.0/go.mod h1:tm33zBoOwxjYHZIE+OV8bxTWFMJLrconzFMd38aARFk= -gopkg.in/src-d/go-billy.v4 v4.3.2 h1:0SQA1pRztfTFx2miS8sA97XvooFeNOmvUenF4o0EcVg= -gopkg.in/src-d/go-billy.v4 v4.3.2/go.mod h1:nDjArDMp+XMs1aFAESLRjfGSgfvoYN0hDfzEk0GjC98= -gopkg.in/src-d/go-git-fixtures.v3 v3.1.1/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0 h1:ivZFOIltbce2Mo8IjzUHAFoq/IylO9WHhNOAJK+LsJg= -gopkg.in/src-d/go-git-fixtures.v3 v3.5.0/go.mod h1:dLBcvytrw/TYZsNTWCnkNF2DSIlzWYqTe3rJR56Ac7g= -gopkg.in/src-d/go-git.v4 v4.7.0/go.mod h1:CzbUWqMn4pvmvndg3gnh5iZFmSsbhyhUWdI0IQ60AQo= -gopkg.in/src-d/go-git.v4 v4.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= -gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=