From 08860b4742588b05afe97225de2ce69512c869a4 Mon Sep 17 00:00:00 2001 From: Azeem Shaikh Date: Thu, 16 Mar 2023 02:58:09 +0530 Subject: [PATCH] Initial implementation of go-git client (#2720) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Azeem Shaikh Signed-off-by: Batuhan Apaydın --- .github/workflows/slsa-goreleaser.yml | 53 ++++++- clients/git/client.go | 209 ++++++++++++++++++++++++++ clients/git/e2e_test.go | 155 +++++++++++++++++++ clients/git/gitrepo_suite_test.go | 39 +++++ go.mod | 9 +- go.sum | 22 ++- 6 files changed, 476 insertions(+), 11 deletions(-) create mode 100644 clients/git/client.go create mode 100644 clients/git/e2e_test.go create mode 100644 clients/git/gitrepo_suite_test.go diff --git a/.github/workflows/slsa-goreleaser.yml b/.github/workflows/slsa-goreleaser.yml index e8613250899f..1e9f0568ae4d 100644 --- a/.github/workflows/slsa-goreleaser.yml +++ b/.github/workflows/slsa-goreleaser.yml @@ -13,6 +13,8 @@ jobs: runs-on: ubuntu-latest outputs: ldflags: ${{ steps.ldflags.outputs.value }} + go-binary-name: ${{ steps.build.outputs.go-binary-name }} + tag_name: ${{ steps.tag.outputs.tag_name }} steps: - id: checkout uses: actions/checkout@ac593985615ec2ede58e132d2e21d2b1cbd6127c # v2.3.4 @@ -21,7 +23,9 @@ jobs: - id: ldflags run: | echo "value=$(./scripts/version-ldflags)" >> "$GITHUB_OUTPUT" - + - name: Set tag output + id: tag + run: echo "tag_name=${GITHUB_REF#refs/*/}" >> "$GITHUB_OUTPUT" # Trusted builder. build: permissions: @@ -29,7 +33,52 @@ jobs: contents: write actions: read needs: args - uses: slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml@bdd89e60dc5387d8f819bebc702987956bcd4913 # v1.2.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/builder_go_slsa3.yml@v1.5.0 #7f4fdb871876c23e455853d694197440c5a91506 with: go-version: 1.19 evaluated-envs: "VERSION_LDFLAGS:${{needs.args.outputs.ldflags}}" + upload-tag-name: "${{ needs.args.outputs.tag_name }}" + + verification: + needs: + - build + runs-on: ubuntu-latest + permissions: read-all + steps: + # Note: this will be replaced with the GHA in the future. + - name: Install the verifier + uses: slsa-framework/slsa-verifier/actions/installer@v2.0.1 + + # - name: Download assets + # env: + # GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # ATT_FILE_NAME: "scorecard-linux-amd64.intoto.jsonl" + # ARTIFACT: ${{ needs.build.outputs.go-binary-name }} + # run: | + # set -euo pipefail + + # gh -R "$GITHUB_REPOSITORY" release download "$GITHUB_REF_NAME" -p $ARTIFACT + # gh -R "$GITHUB_REPOSITORY" release download "$GITHUB_REF_NAME" -p "$ATT_FILE_NAME" + + - name: Download the artifact + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: "${{ needs.build.outputs.go-binary-name }}.intoto.jsonl" + + - name: Download the artifact + uses: actions/download-artifact@9bc31d5ccc31df68ecc42ccf4149144866c47d8a # v3.0.2 + with: + name: ${{ needs.build.outputs.go-binary-name }} + + - name: Verify assets + env: + ARTIFACT: ${{ needs.build.outputs.go-binary-name }} + ATT_FILE_NAME: "${{ needs.build.outputs.go-binary-name }}.intoto.jsonl" + run: | + set -euo pipefail + + echo "Verifying $ARTIFACT using $ATT_FILE_NAME" + slsa-verifier verify-artifact --provenance-path "$ATT_FILE_NAME" \ + --source-uri "github.com/$GITHUB_REPOSITORY" \ + --source-tag "${{ needs.args.outputs.tag_name }}" \ + "$ARTIFACT" \ No newline at end of file diff --git a/clients/git/client.go b/clients/git/client.go new file mode 100644 index 000000000000..f205229e8357 --- /dev/null +++ b/clients/git/client.go @@ -0,0 +1,209 @@ +// Copyright 2021 OpenSSF Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package git defines helper functions for clients.RepoClient interface. +package git + +import ( + "errors" + "fmt" + "io" + "os" + "path/filepath" + "regexp" + "strings" + "sync" + + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + cp "github.com/otiai10/copy" + + "github.com/ossf/scorecard/v4/clients" +) + +const repoDir = "repo*" + +var ( + errNilCommitFound = errors.New("nil commit found") + errEmptyQuery = errors.New("query is empty") +) + +type Client struct { + gitRepo *git.Repository + worktree *git.Worktree + listCommits *sync.Once + tempDir string + errListCommits error + commits []clients.Commit + commitDepth int +} + +func (c *Client) InitRepo(uri, commitSHA string, commitDepth int) error { + // cleanup previous state, if any. + c.Close() + c.listCommits = new(sync.Once) + c.commits = nil + + // init + c.commitDepth = commitDepth + tempDir, err := os.MkdirTemp("", repoDir) + if err != nil { + return fmt.Errorf("os.MkdirTemp: %w", err) + } + + // git clone + const filePrefix = "file://" + if strings.HasPrefix(uri, filePrefix) { + if err := cp.Copy(strings.TrimPrefix(uri, filePrefix), tempDir); err != nil { + return fmt.Errorf("cp.Copy: %w", err) + } + c.gitRepo, err = git.PlainOpen(tempDir) + if err != nil { + return fmt.Errorf("git.PlainOpen: %w", err) + } + } else { + c.gitRepo, err = git.PlainClone(tempDir, false /*isBare*/, &git.CloneOptions{ + URL: uri, + Progress: os.Stdout, + }) + if err != nil { + return fmt.Errorf("git.PlainClone: %w", err) + } + } + c.tempDir = tempDir + c.worktree, err = c.gitRepo.Worktree() + if err != nil { + return fmt.Errorf("git.Worktree: %w", err) + } + + // git checkout + if commitSHA != clients.HeadSHA { + if err := c.worktree.Checkout(&git.CheckoutOptions{ + Hash: plumbing.NewHash(commitSHA), + Force: true, // throw away any unsaved changes. + }); err != nil { + return fmt.Errorf("git.Worktree: %w", err) + } + } + + return nil +} + +func (c *Client) ListCommits() ([]clients.Commit, error) { + c.listCommits.Do(func() { + commitIter, err := c.gitRepo.Log(&git.LogOptions{ + Order: git.LogOrderCommitterTime, + }) + if err != nil { + c.errListCommits = fmt.Errorf("git.CommitObjects: %w", err) + return + } + c.commits = make([]clients.Commit, 0, c.commitDepth) + for i := 0; i < c.commitDepth; i++ { + commit, err := commitIter.Next() + if err != nil && !errors.Is(err, io.EOF) { + c.errListCommits = fmt.Errorf("commitIter.Next: %w", err) + return + } + // No more commits. + if errors.Is(err, io.EOF) { + break + } + + if commit == nil { + // Not sure in what case a nil commit is returned. Fail explicitly. + c.errListCommits = fmt.Errorf("%w", errNilCommitFound) + return + } + + c.commits = append(c.commits, clients.Commit{ + SHA: commit.Hash.String(), + Message: commit.Message, + CommittedDate: commit.Committer.When, + Committer: clients.User{ + Login: commit.Committer.Email, + }, + }) + } + }) + return c.commits, c.errListCommits +} + +func (c *Client) Search(request clients.SearchRequest) (clients.SearchResponse, error) { + // Pattern + if request.Query == "" { + return clients.SearchResponse{}, errEmptyQuery + } + queryRegexp, err := regexp.Compile(request.Query) + if err != nil { + return clients.SearchResponse{}, fmt.Errorf("regexp.Compile: %w", err) + } + grepOpts := &git.GrepOptions{ + Patterns: []*regexp.Regexp{queryRegexp}, + } + + // path/filename + var pathExpr string + switch { + case request.Path != "" && request.Filename != "": + pathExpr = filepath.Join(fmt.Sprintf("^%s", request.Path), + fmt.Sprintf(".*%s$", request.Filename)) + case request.Path != "": + pathExpr = fmt.Sprintf("^%s", request.Path) + case request.Filename != "": + pathExpr = filepath.Join(".*", fmt.Sprintf("%s$", request.Filename)) + } + if pathExpr != "" { + pathRegexp, err := regexp.Compile(pathExpr) + if err != nil { + return clients.SearchResponse{}, fmt.Errorf("regexp.Compile: %w", err) + } + grepOpts.PathSpecs = append(grepOpts.PathSpecs, pathRegexp) + } + + // Grep + grepResults, err := c.worktree.Grep(grepOpts) + if err != nil { + return clients.SearchResponse{}, fmt.Errorf("git.Grep: %w", err) + } + + ret := clients.SearchResponse{} + for _, grepResult := range grepResults { + ret.Results = append(ret.Results, clients.SearchResult{ + Path: grepResult.FileName, + }) + } + ret.Hits = len(grepResults) + return ret, nil +} + +// TODO(#1709): Implement below fns using go-git. +func (c *Client) SearchCommits(request clients.SearchCommitsOptions) ([]clients.Commit, error) { + return nil, nil +} + +func (c *Client) ListFiles(predicate func(string) (bool, error)) ([]string, error) { + return nil, nil +} + +func (c *Client) GetFileContent(filename string) ([]byte, error) { + return nil, nil +} + +func (c *Client) Close() error { + if err := os.RemoveAll(c.tempDir); err != nil && !os.IsNotExist(err) { + return fmt.Errorf("os.RemoveAll: %w", err) + } + return nil +} diff --git a/clients/git/e2e_test.go b/clients/git/e2e_test.go new file mode 100644 index 000000000000..758fc04883c2 --- /dev/null +++ b/clients/git/e2e_test.go @@ -0,0 +1,155 @@ +// Copyright 2021 OpenSSF Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package git + +import ( + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/ossf/scorecard/v4/clients" +) + +var _ = DescribeTable("Test ListCommits commit-depth for HEAD", + func(uri string) { + const commitSHA = clients.HeadSHA + const commitDepth = 1 + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + commits, err := client.ListCommits() + Expect(err).To(BeNil()) + Expect(len(commits)).Should(BeEquivalentTo(commitDepth)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard"), + Entry("Local", "file://../../"), + Entry("GitLab", "https://gitlab.haskell.org/haskell/filepath"), +) + +var _ = DescribeTable("Test ListCommits commit-depth and latest commit at [0]", + func(uri, commitSHA string) { + const commitDepth = 10 + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + commits, err := client.ListCommits() + Expect(err).To(BeNil()) + Expect(len(commits)).Should(BeEquivalentTo(commitDepth)) + Expect(commits[0].SHA).Should(BeEquivalentTo(commitSHA)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard", "c06ac740cc49fea404c54c036000731d5ea6ebe3"), + Entry("Local", "file://../../", "c06ac740cc49fea404c54c036000731d5ea6ebe3"), + Entry("GitLab", "https://gitlab.haskell.org/haskell/filepath", "98f8bba9eac8c7183143d290d319be7df76c258b"), +) + +var _ = DescribeTable("Test ListCommits without enough commits", + func(uri string) { + const commitSHA = "dc1835b7ffe526969d65436b621e171e3386771e" + const commitDepth = 10 + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + commits, err := client.ListCommits() + Expect(err).To(BeNil()) + Expect(len(commits)).Should(BeEquivalentTo(3)) + Expect(commits[0].SHA).Should(BeEquivalentTo(commitSHA)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard"), + Entry("Local", "file://../../"), + // TODO(#1709): Add equivalent test for GitLab. +) + +var _ = DescribeTable("Test Search across a repo", + func(uri string) { + const ( + commitSHA = "c06ac740cc49fea404c54c036000731d5ea6ebe3" + commitDepth = 10 + ) + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + resp, err := client.Search(clients.SearchRequest{ + Query: "github/codeql-action/analyze", + }) + Expect(err).To(BeNil()) + Expect(resp.Hits).Should(BeNumerically(">=", 1)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard"), + Entry("Local", "file://../../"), + // TODO(#1709): Add equivalent test for GitLab. +) + +var _ = DescribeTable("Test Search within a path", + func(uri string) { + const ( + commitSHA = "c06ac740cc49fea404c54c036000731d5ea6ebe3" + commitDepth = 10 + ) + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + resp, err := client.Search(clients.SearchRequest{ + Query: "github/codeql-action/analyze", + Path: ".github/workflows", + }) + Expect(err).To(BeNil()) + Expect(resp.Hits).Should(BeEquivalentTo(1)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard"), + Entry("Local", "file://../../"), + // TODO(#1709): Add equivalent test for GitLab. +) + +var _ = DescribeTable("Test Search within a filename", + func(uri string) { + const ( + commitSHA = "c06ac740cc49fea404c54c036000731d5ea6ebe3" + commitDepth = 10 + ) + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + resp, err := client.Search(clients.SearchRequest{ + Query: "github/codeql-action/analyze", + Filename: "codeql-analysis.yml", + }) + Expect(err).To(BeNil()) + Expect(resp.Hits).Should(BeEquivalentTo(1)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard"), + Entry("Local", "file://../../"), + // TODO(#1709): Add equivalent test for GitLab. +) + +var _ = DescribeTable("Test Search within path and filename", + func(uri string) { + const ( + commitSHA = "c06ac740cc49fea404c54c036000731d5ea6ebe3" + commitDepth = 10 + ) + client := &Client{} + Expect(client.InitRepo(uri, commitSHA, commitDepth)).To(BeNil()) + resp, err := client.Search(clients.SearchRequest{ + Query: "github/codeql-action/analyze", + Path: ".github/workflows", + Filename: "codeql-analysis.yml", + }) + Expect(err).To(BeNil()) + Expect(resp.Hits).Should(BeEquivalentTo(1)) + Expect(client.Close()).To(BeNil()) + }, + Entry("GitHub", "https://github.com/ossf/scorecard"), + Entry("Local", "file://../../"), + // TODO(#1709): Add equivalent test for GitLab. +) diff --git a/clients/git/gitrepo_suite_test.go b/clients/git/gitrepo_suite_test.go new file mode 100644 index 000000000000..71979819ef4e --- /dev/null +++ b/clients/git/gitrepo_suite_test.go @@ -0,0 +1,39 @@ +// Copyright 2021 OpenSSF Scorecard Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package git + +import ( + "os" + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestGitRepo(t *testing.T) { + // TODO(#1709): GitHub tests are taking >10m to run slowing down CI/CD. + // Need to fix that before re-enabling. + // TODO(#1709): Local tests require fake Git repo to be available in CI/CD + // environment. + if val, exists := os.LookupEnv("RUN_GIT_E2E"); !exists || val == "0" { + t.Skip() + } + if val, exists := os.LookupEnv("SKIP_GINKGO"); exists && val == "1" { + t.Skip() + } + t.Parallel() + RegisterFailHandler(Fail) + RunSpecs(t, "GitRepo Suite") +} diff --git a/go.mod b/go.mod index e4e59a232440..656c4f13fb8a 100644 --- a/go.mod +++ b/go.mod @@ -26,7 +26,7 @@ require ( github.com/jszwec/csvutil v1.8.0 github.com/moby/buildkit v0.11.4 github.com/olekukonko/tablewriter v0.0.5 - github.com/onsi/gomega v1.24.2 + github.com/onsi/gomega v1.27.0 github.com/shurcooL/githubv4 v0.0.0-20201206200315-234843c633fa github.com/shurcooL/graphql v0.0.0-20200928012149-18c5c3165e3a // indirect github.com/sirupsen/logrus v1.9.0 @@ -35,7 +35,7 @@ require ( go.opencensus.io v0.24.0 gocloud.dev v0.26.0 golang.org/x/text v0.7.0 - golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2 + golang.org/x/tools v0.6.0 google.golang.org/genproto v0.0.0-20221118155620-16455021b5e6 google.golang.org/protobuf v1.28.1 gopkg.in/yaml.v2 v2.4.0 @@ -49,7 +49,8 @@ require ( github.com/gobwas/glob v0.2.3 github.com/google/osv-scanner v1.2.1-0.20230302232134-592acbc2539b github.com/mcuadros/go-jsonschema-generator v0.0.0-20200330054847-ba7a369d4303 - github.com/onsi/ginkgo/v2 v2.7.0 + github.com/onsi/ginkgo/v2 v2.8.3 + github.com/otiai10/copy v1.9.0 sigs.k8s.io/release-utils v0.6.0 ) @@ -67,8 +68,10 @@ require ( github.com/CycloneDX/cyclonedx-go v0.7.0 // indirect github.com/cloudflare/circl v1.1.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect github.com/google/gofuzz v1.1.0 // indirect + github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 // indirect github.com/googleapis/gnostic v0.4.1 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-retryablehttp v0.7.1 // indirect diff --git a/go.sum b/go.sum index 9b462823b9b5..2e59f7bb0713 100644 --- a/go.sum +++ b/go.sum @@ -406,6 +406,8 @@ github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I= +github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= @@ -525,6 +527,7 @@ github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20210506205249-923b5ab0fc1a/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= @@ -779,8 +782,8 @@ github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.14.2/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= -github.com/onsi/ginkgo/v2 v2.7.0 h1:/XxtEV3I3Eif/HobnVx9YmJgk8ENdRsuUmM+fLCFNow= -github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.8.3 h1:RpbK1G8nWPNaCVFBWsOGnEQQGgASi6b8fxcWBvDYjxQ= +github.com/onsi/ginkgo/v2 v2.8.3/go.mod h1:6OaUA8BCi0aZfmzYT/q9AacwTzDpNbxILUT+TlBq6MY= github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= @@ -788,13 +791,20 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDsH8xc= -github.com/onsi/gomega v1.24.2 h1:J/tulyYK6JwBldPViHJReihxxZ+22FHs0piGjQAvoUE= -github.com/onsi/gomega v1.24.2/go.mod h1:gs3J10IS7Z7r7eXRoNJIrNqU4ToQukCJhFtKrWgHWnk= +github.com/onsi/gomega v1.27.0 h1:QLidEla4bXUuZVFa4KX6JHCsuGgbi85LC/pCHrt/O08= +github.com/onsi/gomega v1.27.0/go.mod h1:i189pavgK95OSIipFBa74gC2V4qrQuvjuyGEr3GmbXA= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= +github.com/otiai10/copy v1.9.0 h1:7KFNiCgZ91Ru4qW4CWPf/7jqtxLagGRmIxWldPP9VY4= +github.com/otiai10/copy v1.9.0/go.mod h1:hsfX19wcn0UWIHUQ3/4fHuehhk2UyArQ9dVFAn3FczI= +github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE= +github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs= +github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo= +github.com/otiai10/mint v1.4.0 h1:umwcf7gbpEwf7WFzqmWwSv0CzbeMsae2u9ZvpP8j2q4= +github.com/otiai10/mint v1.4.0/go.mod h1:gifjb2MYOoULtKLqUAEILUG/9KONW6f7YsJ6vQLTlFI= github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o= github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= @@ -1347,8 +1357,8 @@ golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2 h1:v0FhRDmSCNH/0EurAT6T8KRY4aNuUhz6/WwBMxG+gvQ= -golang.org/x/tools v0.5.1-0.20230117180257-8aba49bb5ea2/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= +golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/vuln v0.0.0-20230118164824-4ec8867cc0e6 h1:XZD8apnMaMVuqE3ZEzf5JJncKMlOsMnnov7U+JRT/d4= golang.org/x/vuln v0.0.0-20230118164824-4ec8867cc0e6/go.mod h1:cBP4HMKv0X+x96j8IJWCKk0eqpakBmmHjKGSSC0NaYE= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=