From dd422a518444eeec8be3fdfe740fef2b86cec3f4 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Tue, 17 May 2022 21:51:59 +0530 Subject: [PATCH 01/21] metadata: Initial implementation for source metadata from git repo Signed-off-by: Nitish Gupta --- pkg/client/build.go | 2 + pkg/client/metadata.go | 133 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+) create mode 100644 pkg/client/metadata.go diff --git a/pkg/client/build.go b/pkg/client/build.go index 2b5540b68..a2ad3fe57 100644 --- a/pkg/client/build.go +++ b/pkg/client/build.go @@ -325,6 +325,8 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { Version: map[string]interface{}{"declared": version}, Metadata: map[string]interface{}{"url": sourceURL}, } + } else { + projectMetadata.Source = GitMetadata(opts.AppPath) } } diff --git a/pkg/client/metadata.go b/pkg/client/metadata.go new file mode 100644 index 000000000..20918e379 --- /dev/null +++ b/pkg/client/metadata.go @@ -0,0 +1,133 @@ +package client + +import ( + "sort" + "strings" + "time" + + "github.com/buildpacks/lifecycle/platform" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" +) + +type TagInfo struct { + Name string + Message string + Type string + TagHash string + TagTime time.Time +} + +func GitMetadata(appPath string) *platform.ProjectSource { + // appPath2 := "/Users/nitish/OSS/pack" + repo, err := git.PlainOpen(appPath) + if err != nil { + print("unable to open git repo") + } + headRef, err := repo.Head() + if err != nil { + print("unable to parse head") + } + commitTagMap := generateTagsMap(repo) + + describe := parseGitDescribe(repo, headRef, commitTagMap) + refs := parseGitRefs(repo, headRef, commitTagMap) + + projectSource := &platform.ProjectSource{ + Type: "git", + Version: map[string]interface{}{ + "commit": headRef.Hash().String(), + "describe": describe, + }, + Metadata: map[string]interface{}{ + "refs": refs, + "url": "nitis", + }, + } + return projectSource +} + +func generateTagsMap(repo *git.Repository) map[string][]TagInfo { + commitTagMap := make(map[string][]TagInfo) + tags, err := repo.Tags() + if err != nil { + return commitTagMap + } + + tags.ForEach(func(ref *plumbing.Reference) error { + tagObj, err := repo.TagObject(ref.Hash()) + switch err { + case nil: + commitTagMap[tagObj.Target.String()] = append( + commitTagMap[tagObj.Target.String()], + TagInfo{Name: tagObj.Name, Message: tagObj.Message, Type: "annotated", TagHash: ref.Hash().String(), TagTime: tagObj.Tagger.When}, + ) + case plumbing.ErrObjectNotFound: + commitTagMap[ref.Hash().String()] = append( + commitTagMap[ref.Hash().String()], + TagInfo{Name: getRefName(ref.Name().String()), Message: "", Type: "unannotated", TagHash: ref.Hash().String(), TagTime: time.Now()}, + ) + default: + return err + } + return nil + }) + + for _, tagRefs := range commitTagMap { + sort.Slice(tagRefs, func(i, j int) bool { + if tagRefs[i].Type == "annotated" && tagRefs[j].Type == "annotated" { + return tagRefs[i].TagTime.After(tagRefs[j].TagTime) + } + if tagRefs[i].Type == "unannotated" && tagRefs[j].Type == "unannotated" { + return tagRefs[i].Name < tagRefs[j].Name + } + if tagRefs[i].Type == "annotated" && tagRefs[j].Type == "unannotated" { + return true + } + return false + }) + } + return commitTagMap +} + +func parseGitDescribe(repo *git.Repository, headRef *plumbing.Reference, commitTagMap map[string][]TagInfo) string { + logOpts := &git.LogOptions{ + From: headRef.Hash(), + Order: git.LogOrderCommitterTime, + } + commits, err := repo.Log(logOpts) + if err != nil { + print("no commits found") + } + + latestTag := headRef.Hash().String() + for { + commitInfo, err := commits.Next() + if err == nil { + if refs, exists := commitTagMap[commitInfo.Hash.String()]; exists { + latestTag = refs[0].Name + } + } else { + break + } + } + return latestTag +} + +func parseGitRefs(repo *git.Repository, headRef *plumbing.Reference, commitTagMap map[string][]TagInfo) []string { + var parsedRefs []string + parsedRefs = append(parsedRefs, getRefName(headRef.Name().String())) + if refs, exists := commitTagMap[headRef.Hash().String()]; exists { + for _, ref := range refs { + parsedRefs = append(parsedRefs, ref.Name) + } + } + return parsedRefs +} + +func getRefName(ref string) string { + if refSplit := strings.Split(ref, "/"); len(refSplit) == 3 { + return refSplit[2] + } + return "" +} From 4ea4993c9d2a800fba27f93b294f07479d3440ed Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Tue, 17 May 2022 21:52:44 +0530 Subject: [PATCH 02/21] tests: Add partial unit tests for source metadata from git Signed-off-by: Nitish Gupta --- pkg/client/metadata_test.go | 213 ++++++++++++++++++++++++++++++++++++ 1 file changed, 213 insertions(+) create mode 100644 pkg/client/metadata_test.go diff --git a/pkg/client/metadata_test.go b/pkg/client/metadata_test.go new file mode 100644 index 000000000..63c486b2a --- /dev/null +++ b/pkg/client/metadata_test.go @@ -0,0 +1,213 @@ +package client + +import ( + "fmt" + "io/ioutil" + "math/rand" + "os" + "path/filepath" + "sort" + "testing" + "time" + + h "github.com/buildpacks/pack/testhelpers" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing" + "github.com/go-git/go-git/v5/plumbing/object" + "github.com/heroku/color" + "github.com/sclevine/spec" + "github.com/sclevine/spec/report" +) + +func TestMetadata(t *testing.T) { + color.Disable(true) + defer color.Disable(false) + spec.Run(t, "Metadata", testMetadata, spec.Parallel(), spec.Report(report.Terminal{})) +} + +func testMetadata(t *testing.T, when spec.G, it spec.S) { + var ( + tmpDir string + repo *git.Repository + commits []plumbing.Hash + ) + + it.Before(func() { + var err error + + tmpDir, err = ioutil.TempDir("", "test-repo") + h.AssertNil(t, err) + + repo, err = git.PlainInit(tmpDir, false) + h.AssertNil(t, err) + + commits = createCommits(t, repo, tmpDir, 5) + }) + + it.After(func() { + h.AssertNil(t, os.RemoveAll(tmpDir)) + }) + + when("#generateTagsMap", func() { + when("repository has no tags", func() { + it("should return empty map", func() { + commitTagsMap := generateTagsMap(repo) + h.AssertEq(t, len(commitTagsMap), 0) + }) + }) + + when("repository has only unannotated tags", func() { + it("returns correct map if commits only have one tag", func() { + for i := 0; i < 4; i++ { + createUnannotatedTag(t, repo, commits[i]) + } + + commitTagsMap := generateTagsMap(repo) + h.AssertEq(t, len(commitTagsMap), 4) + for i := 0; i < 4; i++ { + tagsInfo, shouldExist := commitTagsMap[commits[i].String()] + h.AssertEq(t, shouldExist, true) + h.AssertNotEq(t, tagsInfo[0].Name, "") + h.AssertEq(t, tagsInfo[0].Type, "unannotated") + h.AssertEq(t, tagsInfo[0].Message, "") + } + _, shouldNotExist := commitTagsMap[commits[3].String()] + h.AssertEq(t, shouldNotExist, true) + }) + + it("returns map sorted by ascending tag name if commits have multiple tags", func() { + for i := 0; i < 4; i++ { + for j := 0; j <= rand.Intn(10); j++ { + createUnannotatedTag(t, repo, commits[i]) + } + } + + commitTagsMap := generateTagsMap(repo) + h.AssertEq(t, len(commitTagsMap), 4) + for i := 0; i < 4; i++ { + tagsInfo, shouldExist := commitTagsMap[commits[i].String()] + h.AssertEq(t, shouldExist, true) + + tagsSortedByName := sort.SliceIsSorted(tagsInfo, func(i, j int) bool { + return tagsInfo[i].Name < tagsInfo[j].Name + }) + h.AssertEq(t, tagsSortedByName, true) + } + }) + }) + + when("repository has only annotated tags", func() { + it("returns correct map if commits only have one tag", func() { + for i := 0; i < 4; i++ { + createAnnotatedTag(t, repo, commits[i]) + } + + commitTagsMap := generateTagsMap(repo) + h.AssertEq(t, len(commitTagsMap), 4) + for i := 0; i < 4; i++ { + tagsInfo, shouldExist := commitTagsMap[commits[i].String()] + h.AssertEq(t, shouldExist, true) + h.AssertNotEq(t, tagsInfo[0].Name, "") + h.AssertEq(t, tagsInfo[0].Type, "annotated") + h.AssertNotEq(t, tagsInfo[0].Message, "") + } + _, shouldNotExist := commitTagsMap[commits[3].String()] + h.AssertEq(t, shouldNotExist, true) + }) + + it("returns map sorted by descending tag creation time if commits have multiple tags", func() { + for i := 0; i < 4; i++ { + for j := 0; j <= rand.Intn(10); j++ { + createAnnotatedTag(t, repo, commits[i]) + } + } + + commitTagsMap := generateTagsMap(repo) + h.AssertEq(t, len(commitTagsMap), 4) + for i := 0; i < 4; i++ { + tagsInfo, shouldExist := commitTagsMap[commits[i].String()] + h.AssertEq(t, shouldExist, true) + + tagsSortedByTime := sort.SliceIsSorted(tagsInfo, func(i, j int) bool { + return tagsInfo[i].TagTime.After(tagsInfo[j].TagTime) + }) + h.AssertEq(t, tagsSortedByTime, true) + } + _, shouldNotExist := commitTagsMap[commits[3].String()] + h.AssertEq(t, shouldNotExist, true) + }) + }) + + when("repository has both annotated and unannotated tags", func() { + it("returns map with annotated tags prior to unnanotated if commits have multiple tags", func() { + for i := 0; i < 4; i++ { + for j := 0; j <= rand.Intn(10); j++ { + createAnnotatedTag(t, repo, commits[i]) + } + for j := 0; j <= rand.Intn(10); j++ { + createUnannotatedTag(t, repo, commits[i]) + } + } + + commitTagsMap := generateTagsMap(repo) + h.AssertEq(t, len(commitTagsMap), 4) + for i := 0; i < 4; i++ { + tagsInfo, shouldExist := commitTagsMap[commits[i].String()] + h.AssertEq(t, shouldExist, true) + + tagsSortedByType := sort.SliceIsSorted(tagsInfo, func(i, j int) bool { + if tagsInfo[i].Type == "annotated" && tagsInfo[j].Type == "unannotated" { + return true + } + return false + }) + h.AssertEq(t, tagsSortedByType, true) + } + }) + }) + }) +} + +func createUnannotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash) { + version := rand.Float32()*10 + float32(rand.Intn(20)) + tagName := fmt.Sprintf("v%f-lw", version) + _, err := repo.CreateTag(tagName, commitHash, nil) + h.AssertNil(t, err) +} + +func createAnnotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash) { + version := rand.Float32()*10 + float32(rand.Intn(20)) + tagName := fmt.Sprintf("v%f-%s", version, h.RandString(5)) + tagMessage := fmt.Sprintf("This is an annotated tag for version - %s", tagName) + tagOpts := git.CreateTagOptions{ + Message: tagMessage, + Tagger: &object.Signature{ + Name: "Test Tagger", + Email: "testtagger@test.com", + When: time.Now().Add(time.Hour*time.Duration(rand.Intn(100)) + time.Minute*time.Duration(rand.Intn(100))), + }, + } + _, err := repo.CreateTag(tagName, commitHash, &tagOpts) + h.AssertNil(t, err) +} + +func createCommits(t *testing.T, repo *git.Repository, repoPath string, numberOfCommits int) []plumbing.Hash { + worktree, err := repo.Worktree() + h.AssertNil(t, err) + + var commitHashes []plumbing.Hash + for i := 0; i < numberOfCommits; i++ { + file, err := ioutil.TempFile(repoPath, h.RandString(10)) + h.AssertNil(t, err) + + _, err = worktree.Add(filepath.Base(file.Name())) + h.AssertNil(t, err) + + commitMsg := fmt.Sprintf("%s %d", "test commit number", i) + commitOpts := git.CommitOptions{} + commitHash, err := worktree.Commit(commitMsg, &commitOpts) + h.AssertNil(t, err) + commitHashes = append(commitHashes, commitHash) + } + return commitHashes +} From 93c0f3b583720f9a1da2e18bf6731244b97dabad Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Wed, 18 May 2022 01:52:38 +0530 Subject: [PATCH 03/21] tests: Update tests and dependencies Signed-off-by: Nitish Gupta --- go.mod | 6 ++ go.sum | 21 ++++ pkg/client/metadata.go | 4 +- pkg/client/metadata_test.go | 189 +++++++++++++++++++++++++++++++++--- 4 files changed, 203 insertions(+), 17 deletions(-) diff --git a/go.mod b/go.mod index af607cb2d..df4a61439 100644 --- a/go.mod +++ b/go.mod @@ -40,6 +40,8 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect github.com/Microsoft/go-winio v0.5.2 // indirect github.com/Microsoft/hcsshim v0.9.2 // indirect + github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect + github.com/acomagu/bufpipe v1.0.3 // indirect github.com/containerd/cgroups v1.0.3 // indirect github.com/containerd/containerd v1.6.3 // indirect github.com/containerd/stargz-snapshotter/estargz v0.11.4 // indirect @@ -48,10 +50,14 @@ require ( github.com/docker/go-units v0.4.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect github.com/gdamore/encoding v1.0.0 // indirect + github.com/go-git/gcfg v1.5.0 // indirect + github.com/go-git/go-billy/v5 v5.3.1 // indirect + github.com/go-git/go-git/v5 v5.4.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-querystring v1.0.0 // indirect + github.com/imdario/mergo v0.3.12 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect diff --git a/go.sum b/go.sum index 66c78a6da..56964ec72 100644 --- a/go.sum +++ b/go.sum @@ -105,11 +105,15 @@ github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:m github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 h1:YoJbenK9C67SkzkDfmQuVln04ygHj3vjZfd9FL+GmQQ= +github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= +github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= +github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= 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/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -425,6 +429,14 @@ github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gliderlabs/ssh v0.2.2 h1:6zsha5zo/TWhRhwqCD3+EarCAgZ2yN28ipRnGPnwkI0= github.com/gliderlabs/ssh v0.2.2/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0= +github.com/go-git/gcfg v1.5.0 h1:Q5ViNfGF8zFgyJWPqYwA7qGFoMTEiBmdlkcfRmpIMa4= +github.com/go-git/gcfg v1.5.0/go.mod h1:5m20vg6GwYabIxaOonVkTdrILxQMpEShl1xiMF4ua+E= +github.com/go-git/go-billy/v5 v5.2.0/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-billy/v5 v5.3.1 h1:CPiOUAzKtMRvolEKw+bG1PLRpT7D3LIs3/3ey4Aiu34= +github.com/go-git/go-billy/v5 v5.3.1/go.mod h1:pmpqyWchKfYfrkb/UVH4otLvyi/5gJlGI4Hb3ZqZ3W0= +github.com/go-git/go-git-fixtures/v4 v4.2.1/go.mod h1:K8zd3kDUAykwTdDCr+I0per6Y6vMiRR/nnVTBtavnB0= +github.com/go-git/go-git/v5 v5.4.2 h1:BXyZu9t0VkbiHtqrsvdq39UDhGJTl1h55VW6CSC4aY4= +github.com/go-git/go-git/v5 v5.4.2/go.mod h1:gQ1kArt6d+n+BGd+/B/I74HwRTLhth2+zti4ihgckDc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= @@ -641,6 +653,7 @@ github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.10/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= @@ -650,6 +663,7 @@ github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbB 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/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= @@ -671,6 +685,7 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= +github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/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/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= @@ -711,6 +726,7 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= +github.com/matryer/is v1.2.0/go.mod h1:2fLPjFQM9rhQ15aVEtbuwhJinnOqrmgXPNdZsdwlWXA= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -942,6 +958,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= +github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -1042,6 +1059,7 @@ github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1 github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= +github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= @@ -1131,6 +1149,7 @@ golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= @@ -1223,6 +1242,7 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= +golang.org/x/net v0.0.0-20210326060303-6b1517762897/go.mod h1:uSPa2vr4CLtc/ILN5odXGNXS6mhrKVzTaCXzk9m6W3k= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= @@ -1365,6 +1385,7 @@ golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210502180810-71e4cd670f79/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/pkg/client/metadata.go b/pkg/client/metadata.go index 20918e379..15180efaf 100644 --- a/pkg/client/metadata.go +++ b/pkg/client/metadata.go @@ -106,6 +106,7 @@ func parseGitDescribe(repo *git.Repository, headRef *plumbing.Reference, commitT if err == nil { if refs, exists := commitTagMap[commitInfo.Hash.String()]; exists { latestTag = refs[0].Name + break } } else { break @@ -126,7 +127,8 @@ func parseGitRefs(repo *git.Repository, headRef *plumbing.Reference, commitTagMa } func getRefName(ref string) string { - if refSplit := strings.Split(ref, "/"); len(refSplit) == 3 { + // refs/tags/v0.1/testing + if refSplit := strings.SplitN(ref, "/", 3); len(refSplit) == 3 { return refSplit[2] } return "" diff --git a/pkg/client/metadata_test.go b/pkg/client/metadata_test.go index 63c486b2a..5c1a79a80 100644 --- a/pkg/client/metadata_test.go +++ b/pkg/client/metadata_test.go @@ -50,7 +50,7 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { when("#generateTagsMap", func() { when("repository has no tags", func() { - it("should return empty map", func() { + it("returns empty map", func() { commitTagsMap := generateTagsMap(repo) h.AssertEq(t, len(commitTagsMap), 0) }) @@ -59,7 +59,7 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { when("repository has only unannotated tags", func() { it("returns correct map if commits only have one tag", func() { for i := 0; i < 4; i++ { - createUnannotatedTag(t, repo, commits[i]) + createUnannotatedTag(t, repo, commits[i], "") } commitTagsMap := generateTagsMap(repo) @@ -78,7 +78,7 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { it("returns map sorted by ascending tag name if commits have multiple tags", func() { for i := 0; i < 4; i++ { for j := 0; j <= rand.Intn(10); j++ { - createUnannotatedTag(t, repo, commits[i]) + createUnannotatedTag(t, repo, commits[i], "") } } @@ -99,7 +99,7 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { when("repository has only annotated tags", func() { it("returns correct map if commits only have one tag", func() { for i := 0; i < 4; i++ { - createAnnotatedTag(t, repo, commits[i]) + createAnnotatedTag(t, repo, commits[i], "") } commitTagsMap := generateTagsMap(repo) @@ -118,7 +118,7 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { it("returns map sorted by descending tag creation time if commits have multiple tags", func() { for i := 0; i < 4; i++ { for j := 0; j <= rand.Intn(10); j++ { - createAnnotatedTag(t, repo, commits[i]) + createAnnotatedTag(t, repo, commits[i], "") } } @@ -139,13 +139,13 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) when("repository has both annotated and unannotated tags", func() { - it("returns map with annotated tags prior to unnanotated if commits have multiple tags", func() { + it("returns map where annotated tags exist prior to unnanotated if commits have multiple tags", func() { for i := 0; i < 4; i++ { for j := 0; j <= rand.Intn(10); j++ { - createAnnotatedTag(t, repo, commits[i]) + createAnnotatedTag(t, repo, commits[i], "") } for j := 0; j <= rand.Intn(10); j++ { - createUnannotatedTag(t, repo, commits[i]) + createUnannotatedTag(t, repo, commits[i], "") } } @@ -166,20 +166,177 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) }) }) + + when("#parseGitDescribe", func() { + when("repository has no tags", func() { + it("returns latest commit hash", func() { + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, commits[len(commits)-1].String()) + }) + }) + + when("repository has only unannotated tags", func() { + it("returns first tag encountered from HEAD", func() { + for i := 0; i < 3; i++ { + tagName := fmt.Sprintf("v0.%d-lw", i+1) + createUnannotatedTag(t, repo, commits[i], tagName) + } + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "v0.3-lw") + }) + + it("returns proper tag name for tags containing `/`", func() { + tagName := "v0.1/testing" + t.Logf("Checking output for tag name: %s", tagName) + createUnannotatedTag(t, repo, commits[0], tagName) + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertContains(t, output, "v0.1/testing") + }) + }) + + when("repository has only annotated tags", func() { + it("returns first tag encountered from HEAD", func() { + for i := 0; i < 3; i++ { + tagName := fmt.Sprintf("v0.%d", i+1) + createAnnotatedTag(t, repo, commits[i], tagName) + } + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "v0.3") + }) + }) + + when("repository has both annotated and unannotated tags", func() { + when("each commit has only one tag", func() { + it("returns the first tag encountered from HEAD if unannotated tag comes first", func() { + createAnnotatedTag(t, repo, commits[0], "ann-tag-at-commit-0") + createUnannotatedTag(t, repo, commits[1], "unann-tag-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-at-commit-2") + createUnannotatedTag(t, repo, commits[3], "unann-tag-at-commit-3") + createUnannotatedTag(t, repo, commits[4], "unann-tag-at-commit-4") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "unann-tag-at-commit-4") + }) + + it("returns the first tag encountered from HEAD if annotated tag comes first", func() { + createAnnotatedTag(t, repo, commits[0], "ann-tag-at-commit-0") + createUnannotatedTag(t, repo, commits[1], "unann-tag-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-at-commit-2") + createAnnotatedTag(t, repo, commits[3], "ann-tag-at-commit-3") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-at-commit-3") + }) + + it("returns the tag at HEAD if annotated tag exists at HEAD", func() { + createAnnotatedTag(t, repo, commits[4], "ann-tag-at-HEAD") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-at-HEAD") + }) + + it("returns the tag at HEAD if unannotated tag exists at HEAD", func() { + createUnannotatedTag(t, repo, commits[4], "unann-tag-at-HEAD") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "unann-tag-at-HEAD") + }) + }) + + when("commits have multiple tags", func() { + it("returns most recently created tag if a commit has multiple annotated tags", func() { + createAnnotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-1-at-commit-2") + createAnnotatedTag(t, repo, commits[2], "ann-tag-2-at-commit-2") + createAnnotatedTag(t, repo, commits[2], "ann-tag-3-at-commit-2") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + + output := parseGitDescribe(repo, headRef, commitTagsMap) + tagsAtCommit := commitTagsMap[commits[2].String()] + h.AssertEq(t, output, tagsAtCommit[0].Name) + for i := 1; i < len(tagsAtCommit); i++ { + h.AssertEq(t, tagsAtCommit[i].TagTime.Before(tagsAtCommit[0].TagTime), true) + } + }) + + it("returns the tag name that comes first when sorted alphabetically if a commit has multiple unannotated tags", func() { + createUnannotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") + createUnannotatedTag(t, repo, commits[2], "v0.000002-lw") + createUnannotatedTag(t, repo, commits[2], "v0.0002-lw") + createUnannotatedTag(t, repo, commits[2], "v1.0002-lw") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "v0.000002-lw") + }) + + it("returns annotated tag is a commit has both annotated and unannotated tags", func() { + createAnnotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-1-at-commit-2") + createUnannotatedTag(t, repo, commits[2], "unann-tag-1-at-commit-2") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-1-at-commit-2") + }) + }) + }) + }) } -func createUnannotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash) { - version := rand.Float32()*10 + float32(rand.Intn(20)) - tagName := fmt.Sprintf("v%f-lw", version) +func createUnannotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash, tagName string) { + if tagName == "" { + version := rand.Float32()*10 + float32(rand.Intn(20)) + tagName = fmt.Sprintf("v%f-lw", version) + } _, err := repo.CreateTag(tagName, commitHash, nil) h.AssertNil(t, err) } -func createAnnotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash) { - version := rand.Float32()*10 + float32(rand.Intn(20)) - tagName := fmt.Sprintf("v%f-%s", version, h.RandString(5)) +func createAnnotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash, tagName string) { + if tagName == "" { + version := rand.Float32()*10 + float32(rand.Intn(20)) + tagName = fmt.Sprintf("v%f-%s", version, h.RandString(5)) + } tagMessage := fmt.Sprintf("This is an annotated tag for version - %s", tagName) - tagOpts := git.CreateTagOptions{ + tagOpts := &git.CreateTagOptions{ Message: tagMessage, Tagger: &object.Signature{ Name: "Test Tagger", @@ -187,7 +344,7 @@ func createAnnotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing. When: time.Now().Add(time.Hour*time.Duration(rand.Intn(100)) + time.Minute*time.Duration(rand.Intn(100))), }, } - _, err := repo.CreateTag(tagName, commitHash, &tagOpts) + _, err := repo.CreateTag(tagName, commitHash, tagOpts) h.AssertNil(t, err) } From e75def31451e99ba2768924b3e343e038ef553e3 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Fri, 20 May 2022 01:50:26 +0530 Subject: [PATCH 04/21] metadata: Add support for `remote` - Add support to fetch and save the origin remote URL of a git repo Signed-off-by: Nitish Gupta --- pkg/client/metadata.go | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/pkg/client/metadata.go b/pkg/client/metadata.go index 15180efaf..bbd0ac7be 100644 --- a/pkg/client/metadata.go +++ b/pkg/client/metadata.go @@ -19,7 +19,6 @@ type TagInfo struct { } func GitMetadata(appPath string) *platform.ProjectSource { - // appPath2 := "/Users/nitish/OSS/pack" repo, err := git.PlainOpen(appPath) if err != nil { print("unable to open git repo") @@ -32,6 +31,7 @@ func GitMetadata(appPath string) *platform.ProjectSource { describe := parseGitDescribe(repo, headRef, commitTagMap) refs := parseGitRefs(repo, headRef, commitTagMap) + remote := parseGitRemote(repo) projectSource := &platform.ProjectSource{ Type: "git", @@ -41,7 +41,7 @@ func GitMetadata(appPath string) *platform.ProjectSource { }, Metadata: map[string]interface{}{ "refs": refs, - "url": "nitis", + "url": remote, }, } return projectSource @@ -90,6 +90,7 @@ func generateTagsMap(repo *git.Repository) map[string][]TagInfo { return commitTagMap } +// `git describe --tags --always` func parseGitDescribe(repo *git.Repository, headRef *plumbing.Reference, commitTagMap map[string][]TagInfo) string { logOpts := &git.LogOptions{ From: headRef.Hash(), @@ -126,8 +127,22 @@ func parseGitRefs(repo *git.Repository, headRef *plumbing.Reference, commitTagMa return parsedRefs } +func parseGitRemote(repo *git.Repository) string { + remotes, err := repo.Remotes() + if err != nil || len(remotes) == 0 { + return "" + } + + for _, remote := range remotes { + if remote.Config().Name == "origin" { + return remote.Config().URLs[0] + } + } + return remotes[0].Config().URLs[0] +} + +// Parse ref name from refs/tags/ func getRefName(ref string) string { - // refs/tags/v0.1/testing if refSplit := strings.SplitN(ref, "/", 3); len(refSplit) == 3 { return refSplit[2] } From 927da530a718f4654b04ba72f1d55d4046ea2e30 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Fri, 20 May 2022 01:52:17 +0530 Subject: [PATCH 05/21] tests: Add tests for parsing refs and remote URL Signed-off-by: Nitish Gupta --- pkg/client/metadata_test.go | 436 +++++++++++++++++++++++++----------- 1 file changed, 305 insertions(+), 131 deletions(-) diff --git a/pkg/client/metadata_test.go b/pkg/client/metadata_test.go index 5c1a79a80..5e7020959 100644 --- a/pkg/client/metadata_test.go +++ b/pkg/client/metadata_test.go @@ -12,6 +12,7 @@ import ( h "github.com/buildpacks/pack/testhelpers" "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" "github.com/go-git/go-git/v5/plumbing/object" "github.com/heroku/color" @@ -168,157 +169,351 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) when("#parseGitDescribe", func() { - when("repository has no tags", func() { - it("returns latest commit hash", func() { - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) - - output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, commits[len(commits)-1].String()) - }) - }) - - when("repository has only unannotated tags", func() { - it("returns first tag encountered from HEAD", func() { - for i := 0; i < 3; i++ { - tagName := fmt.Sprintf("v0.%d-lw", i+1) - createUnannotatedTag(t, repo, commits[i], tagName) - } - - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) - output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "v0.3-lw") - }) - - it("returns proper tag name for tags containing `/`", func() { - tagName := "v0.1/testing" - t.Logf("Checking output for tag name: %s", tagName) - createUnannotatedTag(t, repo, commits[0], tagName) - - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) - output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertContains(t, output, "v0.1/testing") - }) - }) - - when("repository has only annotated tags", func() { - it("returns first tag encountered from HEAD", func() { - for i := 0; i < 3; i++ { - tagName := fmt.Sprintf("v0.%d", i+1) - createAnnotatedTag(t, repo, commits[i], tagName) - } - - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) - output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "v0.3") - }) - }) - - when("repository has both annotated and unannotated tags", func() { - when("each commit has only one tag", func() { - it("returns the first tag encountered from HEAD if unannotated tag comes first", func() { - createAnnotatedTag(t, repo, commits[0], "ann-tag-at-commit-0") - createUnannotatedTag(t, repo, commits[1], "unann-tag-at-commit-1") - createAnnotatedTag(t, repo, commits[2], "ann-tag-at-commit-2") - createUnannotatedTag(t, repo, commits[3], "unann-tag-at-commit-3") - createUnannotatedTag(t, repo, commits[4], "unann-tag-at-commit-4") - + when("tags are defined only in single branch", func() { + when("repository has no tags", func() { + it("returns latest commit hash", func() { commitTagsMap := generateTagsMap(repo) headRef, err := repo.Head() h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "unann-tag-at-commit-4") + h.AssertEq(t, output, commits[len(commits)-1].String()) }) + }) - it("returns the first tag encountered from HEAD if annotated tag comes first", func() { - createAnnotatedTag(t, repo, commits[0], "ann-tag-at-commit-0") - createUnannotatedTag(t, repo, commits[1], "unann-tag-at-commit-1") - createAnnotatedTag(t, repo, commits[2], "ann-tag-at-commit-2") - createAnnotatedTag(t, repo, commits[3], "ann-tag-at-commit-3") + when("repository has only unannotated tags", func() { + it("returns first tag encountered from HEAD", func() { + for i := 0; i < 3; i++ { + tagName := fmt.Sprintf("v0.%d-lw", i+1) + createUnannotatedTag(t, repo, commits[i], tagName) + } commitTagsMap := generateTagsMap(repo) headRef, err := repo.Head() h.AssertNil(t, err) output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "ann-tag-at-commit-3") + h.AssertEq(t, output, "v0.3-lw") }) - it("returns the tag at HEAD if annotated tag exists at HEAD", func() { - createAnnotatedTag(t, repo, commits[4], "ann-tag-at-HEAD") + it("returns proper tag name for tags containing `/`", func() { + tagName := "v0.1/testing" + t.Logf("Checking output for tag name: %s", tagName) + createUnannotatedTag(t, repo, commits[0], tagName) commitTagsMap := generateTagsMap(repo) headRef, err := repo.Head() h.AssertNil(t, err) output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "ann-tag-at-HEAD") + h.AssertContains(t, output, "v0.1/testing") }) + }) - it("returns the tag at HEAD if unannotated tag exists at HEAD", func() { - createUnannotatedTag(t, repo, commits[4], "unann-tag-at-HEAD") + when("repository has only annotated tags", func() { + it("returns first tag encountered from HEAD", func() { + for i := 0; i < 3; i++ { + tagName := fmt.Sprintf("v0.%d", i+1) + createAnnotatedTag(t, repo, commits[i], tagName) + } commitTagsMap := generateTagsMap(repo) headRef, err := repo.Head() h.AssertNil(t, err) output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "unann-tag-at-HEAD") + h.AssertEq(t, output, "v0.3") }) }) - when("commits have multiple tags", func() { - it("returns most recently created tag if a commit has multiple annotated tags", func() { - createAnnotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") - createAnnotatedTag(t, repo, commits[2], "ann-tag-1-at-commit-2") - createAnnotatedTag(t, repo, commits[2], "ann-tag-2-at-commit-2") - createAnnotatedTag(t, repo, commits[2], "ann-tag-3-at-commit-2") + when("repository has both annotated and unannotated tags", func() { + when("each commit has only one tag", func() { + it("returns the first tag encountered from HEAD if unannotated tag comes first", func() { + createAnnotatedTag(t, repo, commits[0], "ann-tag-at-commit-0") + createUnannotatedTag(t, repo, commits[1], "unann-tag-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-at-commit-2") + createUnannotatedTag(t, repo, commits[3], "unann-tag-at-commit-3") + createUnannotatedTag(t, repo, commits[4], "unann-tag-at-commit-4") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "unann-tag-at-commit-4") + }) - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) + it("returns the first tag encountered from HEAD if annotated tag comes first", func() { + createAnnotatedTag(t, repo, commits[0], "ann-tag-at-commit-0") + createUnannotatedTag(t, repo, commits[1], "unann-tag-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-at-commit-2") + createAnnotatedTag(t, repo, commits[3], "ann-tag-at-commit-3") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-at-commit-3") + }) - output := parseGitDescribe(repo, headRef, commitTagsMap) - tagsAtCommit := commitTagsMap[commits[2].String()] - h.AssertEq(t, output, tagsAtCommit[0].Name) - for i := 1; i < len(tagsAtCommit); i++ { - h.AssertEq(t, tagsAtCommit[i].TagTime.Before(tagsAtCommit[0].TagTime), true) - } - }) + it("returns the tag at HEAD if annotated tag exists at HEAD", func() { + createAnnotatedTag(t, repo, commits[4], "ann-tag-at-HEAD") - it("returns the tag name that comes first when sorted alphabetically if a commit has multiple unannotated tags", func() { - createUnannotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") - createUnannotatedTag(t, repo, commits[2], "v0.000002-lw") - createUnannotatedTag(t, repo, commits[2], "v0.0002-lw") - createUnannotatedTag(t, repo, commits[2], "v1.0002-lw") + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-at-HEAD") + }) - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) + it("returns the tag at HEAD if unannotated tag exists at HEAD", func() { + createUnannotatedTag(t, repo, commits[4], "unann-tag-at-HEAD") - output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "v0.000002-lw") + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "unann-tag-at-HEAD") + }) }) - it("returns annotated tag is a commit has both annotated and unannotated tags", func() { - createAnnotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") - createAnnotatedTag(t, repo, commits[2], "ann-tag-1-at-commit-2") - createUnannotatedTag(t, repo, commits[2], "unann-tag-1-at-commit-2") + when("commits have multiple tags", func() { + it("returns most recently created tag if a commit has multiple annotated tags", func() { + createAnnotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-1-at-commit-2") + createAnnotatedTag(t, repo, commits[2], "ann-tag-2-at-commit-2") + createAnnotatedTag(t, repo, commits[2], "ann-tag-3-at-commit-2") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + + output := parseGitDescribe(repo, headRef, commitTagsMap) + tagsAtCommit := commitTagsMap[commits[2].String()] + h.AssertEq(t, output, tagsAtCommit[0].Name) + for i := 1; i < len(tagsAtCommit); i++ { + h.AssertEq(t, tagsAtCommit[i].TagTime.Before(tagsAtCommit[0].TagTime), true) + } + }) + + it("returns the tag name that comes first when sorted alphabetically if a commit has multiple unannotated tags", func() { + createUnannotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") + createUnannotatedTag(t, repo, commits[2], "v0.000002-lw") + createUnannotatedTag(t, repo, commits[2], "v0.0002-lw") + createUnannotatedTag(t, repo, commits[2], "v1.0002-lw") - commitTagsMap := generateTagsMap(repo) - headRef, err := repo.Head() - h.AssertNil(t, err) + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) - output := parseGitDescribe(repo, headRef, commitTagsMap) - h.AssertEq(t, output, "ann-tag-1-at-commit-2") + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "v0.000002-lw") + }) + + it("returns annotated tag is a commit has both annotated and unannotated tags", func() { + createAnnotatedTag(t, repo, commits[1], "ann-tag-1-at-commit-1") + createAnnotatedTag(t, repo, commits[2], "ann-tag-1-at-commit-2") + createUnannotatedTag(t, repo, commits[2], "unann-tag-1-at-commit-2") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-1-at-commit-2") + }) }) }) }) + + // TODO: tests for tags in different branches }) + + when("#parseGitRefs", func() { + when("HEAD is not at a tag", func() { + it("returns branch name if checked out branch is `master`", func() { + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"master"} + h.AssertEq(t, output, expectedOutput) + }) + + it("returns branch name if checked out branch is not `master`", func() { + worktree, err := repo.Worktree() + h.AssertNil(t, err) + checkoutOpts := &git.CheckoutOptions{ + Branch: plumbing.ReferenceName("refs/heads/tests/05-05/test-branch"), + Create: true, + } + err = worktree.Checkout(checkoutOpts) + h.AssertNil(t, err) + createCommits(t, repo, tmpDir, 1) + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"tests/05-05/test-branch"} + h.AssertEq(t, output, expectedOutput) + }) + }) + + when("HEAD is at a commit with single tag", func() { + it("returns annotated tag and branch name", func() { + createAnnotatedTag(t, repo, commits[len(commits)-1], "test-tag") + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"master", "test-tag"} + h.AssertEq(t, output, expectedOutput) + }) + + it("returns unannotated tag and branch name", func() { + createUnannotatedTag(t, repo, commits[len(commits)-1], "test-tag") + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"master", "test-tag"} + h.AssertEq(t, output, expectedOutput) + }) + }) + + when("HEAD is at a commit with multiple tags", func() { + it("returns correct tag names if all tags are unannotated", func() { + createUnannotatedTag(t, repo, commits[len(commits)-2], "v0.01-testtag-lw") + createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-1") + createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-2") + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"master", "v0.02-testtag-lw-1", "v0.02-testtag-lw-2"} + h.AssertEq(t, output, expectedOutput) + }) + + it("returns correct tag names if all tags are annotated", func() { + createAnnotatedTag(t, repo, commits[len(commits)-2], "v0.01-testtag") + createAnnotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag") + createAnnotatedTag(t, repo, commits[len(commits)-1], "v0.03-testtag") + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"master", "v0.02-testtag", "v0.03-testtag"} + sort.Strings(output) + sort.Strings(expectedOutput) + h.AssertEq(t, output, expectedOutput) + }) + + it("returns correct tag names for both tag types", func() { + createUnannotatedTag(t, repo, commits[len(commits)-3], "v0.001-testtag-lw") + createAnnotatedTag(t, repo, commits[len(commits)-2], "v0.01-testtag") + createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-1") + createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-2") + createAnnotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-1") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"master", "v0.02-testtag-1", "v0.02-testtag-lw-1", "v0.02-testtag-lw-2"} + h.AssertEq(t, output, expectedOutput) + }) + + it("returns correct tag names for both tag types when branch is not `master`", func() { + worktree, err := repo.Worktree() + h.AssertNil(t, err) + checkoutOpts := &git.CheckoutOptions{ + Branch: plumbing.ReferenceName("refs/heads/test-branch"), + Create: true, + } + err = worktree.Checkout(checkoutOpts) + h.AssertNil(t, err) + + createUnannotatedTag(t, repo, commits[len(commits)-3], "v0.001-testtag-lw") + createAnnotatedTag(t, repo, commits[len(commits)-2], "v0.01-testtag") + createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-1") + createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-2") + createAnnotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-1") + createAnnotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-2") + + commitTagsMap := generateTagsMap(repo) + headRef, err := repo.Head() + h.AssertNil(t, err) + output := parseGitRefs(repo, headRef, commitTagsMap) + expectedOutput := []string{"test-branch", "v0.02-testtag-1", "v0.02-testtag-2", "v0.02-testtag-lw-1", "v0.02-testtag-lw-2"} + sort.Strings(output) + sort.Strings(expectedOutput) + h.AssertEq(t, output, expectedOutput) + }) + }) + }) + + when("#parseGitRemote", func() { + it("returns fetch url if remote `origin` exists", func() { + remoteOpts := &config.RemoteConfig{ + Name: "origin", + URLs: []string{"git@github.com:testorg/testproj.git", "git@github.com:testorg/testproj.git"}, + } + repo.CreateRemote(remoteOpts) + + output := parseGitRemote(repo) + h.AssertEq(t, output, "git@github.com:testorg/testproj.git") + }) + + it("returns first remote's fetch url if remote `origin` does not exists", func() { + remoteOpts1 := &config.RemoteConfig{ + Name: "not-origin", + URLs: []string{"git@gitlab.com:testorg/testproj.git", "git@gitlab.com:testorg/testproj.git"}, + } + repo.CreateRemote(remoteOpts1) + remoteOpts2 := &config.RemoteConfig{ + Name: "not-at-all-origin", + URLs: []string{"git@github.com:testorg/testproj.git", "git@github.com:testorg/testproj.git"}, + } + repo.CreateRemote(remoteOpts2) + + output := parseGitRemote(repo) + h.AssertEq(t, output, "git@gitlab.com:testorg/testproj.git") + }) + + it("returns empty string if no remote exists", func() { + output := parseGitRemote(repo) + h.AssertEq(t, output, "") + }) + + it("returns fetch url if fetch and push URLs are different", func() { + remoteOpts := &config.RemoteConfig{ + Name: "origin", + URLs: []string{"git@fetch.com:testorg/testproj.git", "git@pushing-p-github.com:testorg/testproj.git"}, + } + repo.CreateRemote(remoteOpts) + + output := parseGitRemote(repo) + h.AssertEq(t, output, "git@fetch.com:testorg/testproj.git") + }) + }) +} + +func createCommits(t *testing.T, repo *git.Repository, repoPath string, numberOfCommits int) []plumbing.Hash { + worktree, err := repo.Worktree() + h.AssertNil(t, err) + + var commitHashes []plumbing.Hash + for i := 0; i < numberOfCommits; i++ { + file, err := ioutil.TempFile(repoPath, h.RandString(10)) + h.AssertNil(t, err) + + _, err = worktree.Add(filepath.Base(file.Name())) + h.AssertNil(t, err) + + commitMsg := fmt.Sprintf("%s %d", "test commit number", i) + commitOpts := git.CommitOptions{} + commitHash, err := worktree.Commit(commitMsg, &commitOpts) + h.AssertNil(t, err) + commitHashes = append(commitHashes, commitHash) + } + return commitHashes } func createUnannotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing.Hash, tagName string) { @@ -347,24 +542,3 @@ func createAnnotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing. _, err := repo.CreateTag(tagName, commitHash, tagOpts) h.AssertNil(t, err) } - -func createCommits(t *testing.T, repo *git.Repository, repoPath string, numberOfCommits int) []plumbing.Hash { - worktree, err := repo.Worktree() - h.AssertNil(t, err) - - var commitHashes []plumbing.Hash - for i := 0; i < numberOfCommits; i++ { - file, err := ioutil.TempFile(repoPath, h.RandString(10)) - h.AssertNil(t, err) - - _, err = worktree.Add(filepath.Base(file.Name())) - h.AssertNil(t, err) - - commitMsg := fmt.Sprintf("%s %d", "test commit number", i) - commitOpts := git.CommitOptions{} - commitHash, err := worktree.Commit(commitMsg, &commitOpts) - h.AssertNil(t, err) - commitHashes = append(commitHashes, commitHash) - } - return commitHashes -} From 073f3ead56eb347d45624626f43d4e1937675038 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Sun, 22 May 2022 17:17:22 +0530 Subject: [PATCH 06/21] metadata: Update git describe logic for multiple branches - Add ability to parse tags if they exist in multiple branches - Add test cases to cover possible branching and tag scenarios - Add new util method and tests Signed-off-by: Nitish Gupta --- pkg/client/metadata.go | 35 ++++++++-- pkg/client/metadata_test.go | 134 ++++++++++++++++++++++++++++-------- 2 files changed, 138 insertions(+), 31 deletions(-) diff --git a/pkg/client/metadata.go b/pkg/client/metadata.go index bbd0ac7be..44ea0c2bd 100644 --- a/pkg/client/metadata.go +++ b/pkg/client/metadata.go @@ -1,6 +1,7 @@ package client import ( + "fmt" "sort" "strings" "time" @@ -90,6 +91,19 @@ func generateTagsMap(repo *git.Repository) map[string][]TagInfo { return commitTagMap } +func generateBranchMap(repo *git.Repository) map[string][]string { + commitBranchMap := make(map[string][]string) + branches, err := repo.Branches() + if err != nil { + return commitBranchMap + } + branches.ForEach(func(ref *plumbing.Reference) error { + commitBranchMap[ref.Hash().String()] = append(commitBranchMap[ref.Hash().String()], getRefName(ref.Name().String())) + return nil + }) + return commitBranchMap +} + // `git describe --tags --always` func parseGitDescribe(repo *git.Repository, headRef *plumbing.Reference, commitTagMap map[string][]TagInfo) string { logOpts := &git.LogOptions{ @@ -102,16 +116,29 @@ func parseGitDescribe(repo *git.Repository, headRef *plumbing.Reference, commitT } latestTag := headRef.Hash().String() + commitsFromHEAD := 0 + commitBranchMap := generateBranchMap(repo) + branchAtHEAD := getRefName(headRef.String()) + currentBranch := branchAtHEAD for { commitInfo, err := commits.Next() - if err == nil { - if refs, exists := commitTagMap[commitInfo.Hash.String()]; exists { + if err != nil { + break + } + + if branchesAtCommit, exists := commitBranchMap[commitInfo.Hash.String()]; exists { + currentBranch = branchesAtCommit[0] + } + if refs, exists := commitTagMap[commitInfo.Hash.String()]; exists { + if branchAtHEAD != currentBranch && commitsFromHEAD != 0 { + // https://git-scm.com/docs/git-describe#_examples + latestTag = fmt.Sprintf("%s-%d-g%s", refs[0].Name, commitsFromHEAD, headRef.Hash().String()) + } else { latestTag = refs[0].Name - break } - } else { break } + commitsFromHEAD += 1 } return latestTag } diff --git a/pkg/client/metadata_test.go b/pkg/client/metadata_test.go index 5e7020959..c1df16b5d 100644 --- a/pkg/client/metadata_test.go +++ b/pkg/client/metadata_test.go @@ -28,25 +28,25 @@ func TestMetadata(t *testing.T) { func testMetadata(t *testing.T, when spec.G, it spec.S) { var ( - tmpDir string - repo *git.Repository - commits []plumbing.Hash + repoPath string + repo *git.Repository + commits []plumbing.Hash ) it.Before(func() { var err error - tmpDir, err = ioutil.TempDir("", "test-repo") + repoPath, err = ioutil.TempDir("", "test-repo") h.AssertNil(t, err) - repo, err = git.PlainInit(tmpDir, false) + repo, err = git.PlainInit(repoPath, false) h.AssertNil(t, err) - commits = createCommits(t, repo, tmpDir, 5) + commits = createCommits(t, repo, repoPath, 5) }) it.After(func() { - h.AssertNil(t, os.RemoveAll(tmpDir)) + h.AssertNil(t, os.RemoveAll(repoPath)) }) when("#generateTagsMap", func() { @@ -168,8 +168,27 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) }) + when("#generateBranchMap", func() { + it("returns map with latest commit of the `master` branch", func() { + branchMap := generateBranchMap(repo) + h.AssertEq(t, branchMap[commits[len(commits)-1].String()][0], "master") + }) + + it("returns map with latest commit all the branches", func() { + checkoutBranch(t, repo, "newbranch-1", true) + newBranchCommits := createCommits(t, repo, repoPath, 3) + checkoutBranch(t, repo, "master", false) + checkoutBranch(t, repo, "newbranch-2", true) + + branchMap := generateBranchMap(repo) + h.AssertEq(t, branchMap[commits[len(commits)-1].String()][0], "master") + h.AssertEq(t, branchMap[commits[len(commits)-1].String()][1], "newbranch-2") + h.AssertEq(t, branchMap[newBranchCommits[len(newBranchCommits)-1].String()][0], "newbranch-1") + }) + }) + when("#parseGitDescribe", func() { - when("tags are defined only in single branch", func() { + when("all tags are defined in a single branch", func() { when("repository has no tags", func() { it("returns latest commit hash", func() { commitTagsMap := generateTagsMap(repo) @@ -322,7 +341,64 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) }) - // TODO: tests for tags in different branches + when("tags are defined in multiple branches", func() { + when("tag is defined in the latest commit of `master` branch and HEAD is at a different branch", func() { + it("returns the tag if HEAD, master and different branch is at tags", func() { + checkoutBranch(t, repo, "new-branch", true) + createAnnotatedTag(t, repo, commits[len(commits)-1], "ann-tag-at-HEAD") + + headRef, err := repo.Head() + h.AssertNil(t, err) + commitTagsMap := generateTagsMap(repo) + output := parseGitDescribe(repo, headRef, commitTagsMap) + h.AssertEq(t, output, "ann-tag-at-HEAD") + }) + + when("branch is multiple commits ahead of master", func() { + it("returns git generated version of annotated tag if branch is 2 commits ahead of `master`", func() { + createAnnotatedTag(t, repo, commits[len(commits)-1], "testTag") + checkoutBranch(t, repo, "new-branch", true) + newCommits := createCommits(t, repo, repoPath, 2) + + headRef, err := repo.Head() + h.AssertNil(t, err) + commitTagsMap := generateTagsMap(repo) + output := parseGitDescribe(repo, headRef, commitTagsMap) + expectedOutput := fmt.Sprintf("testTag-2-g%s", newCommits[len(newCommits)-1].String()) + h.AssertEq(t, output, expectedOutput) + }) + + it("returns git generated version of unannotated tag if branch is 5 commits ahead of `master`", func() { + createUnannotatedTag(t, repo, commits[len(commits)-1], "testTag") + checkoutBranch(t, repo, "new-branch", true) + newCommits := createCommits(t, repo, repoPath, 5) + + headRef, err := repo.Head() + h.AssertNil(t, err) + commitTagsMap := generateTagsMap(repo) + output := parseGitDescribe(repo, headRef, commitTagsMap) + expectedOutput := fmt.Sprintf("testTag-5-g%s", newCommits[len(newCommits)-1].String()) + h.AssertEq(t, output, expectedOutput) + }) + + it("returns the commit hash if only the diverged tree of `master` branch has a tag", func() { + checkoutBranch(t, repo, "new-branch", true) + checkoutBranch(t, repo, "master", false) + newCommits := createCommits(t, repo, repoPath, 3) + createUnannotatedTag(t, repo, newCommits[len(newCommits)-1], "testTagAtMaster") + checkoutBranch(t, repo, "new-branch", false) + + headRef, err := repo.Head() + h.AssertNil(t, err) + commitTagsMap := generateTagsMap(repo) + output := parseGitDescribe(repo, headRef, commitTagsMap) + expectedOutput := commits[len(commits)-1].String() + h.AssertEq(t, output, expectedOutput) + }) + }) + + }) + }) }) when("#parseGitRefs", func() { @@ -337,15 +413,8 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) it("returns branch name if checked out branch is not `master`", func() { - worktree, err := repo.Worktree() - h.AssertNil(t, err) - checkoutOpts := &git.CheckoutOptions{ - Branch: plumbing.ReferenceName("refs/heads/tests/05-05/test-branch"), - Create: true, - } - err = worktree.Checkout(checkoutOpts) - h.AssertNil(t, err) - createCommits(t, repo, tmpDir, 1) + checkoutBranch(t, repo, "tests/05-05/test-branch", true) + createCommits(t, repo, repoPath, 1) commitTagsMap := generateTagsMap(repo) headRef, err := repo.Head() @@ -421,15 +490,7 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { }) it("returns correct tag names for both tag types when branch is not `master`", func() { - worktree, err := repo.Worktree() - h.AssertNil(t, err) - checkoutOpts := &git.CheckoutOptions{ - Branch: plumbing.ReferenceName("refs/heads/test-branch"), - Create: true, - } - err = worktree.Checkout(checkoutOpts) - h.AssertNil(t, err) - + checkoutBranch(t, repo, "test-branch", true) createUnannotatedTag(t, repo, commits[len(commits)-3], "v0.001-testtag-lw") createAnnotatedTag(t, repo, commits[len(commits)-2], "v0.01-testtag") createUnannotatedTag(t, repo, commits[len(commits)-1], "v0.02-testtag-lw-1") @@ -542,3 +603,22 @@ func createAnnotatedTag(t *testing.T, repo *git.Repository, commitHash plumbing. _, err := repo.CreateTag(tagName, commitHash, tagOpts) h.AssertNil(t, err) } + +func checkoutBranch(t *testing.T, repo *git.Repository, branchName string, newBranch bool) { + worktree, err := repo.Worktree() + h.AssertNil(t, err) + + var fullBranchName string + if branchName == "" { + fullBranchName = "refs/heads/" + h.RandString(10) + } else { + fullBranchName = "refs/heads/" + branchName + } + + checkoutOpts := &git.CheckoutOptions{ + Branch: plumbing.ReferenceName(fullBranchName), + Create: newBranch, + } + err = worktree.Checkout(checkoutOpts) + h.AssertNil(t, err) +} From 032e9e782b027f14f03bfc375c0f6466e1018984 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Sun, 22 May 2022 18:06:59 +0530 Subject: [PATCH 07/21] chore: Proper error handling, move files and add few unit tests Signed-off-by: Nitish Gupta --- pkg/client/build.go | 3 +- pkg/{client => project/v02}/metadata.go | 8 +- pkg/{client => project/v02}/metadata_test.go | 78 ++++++++++++++------ 3 files changed, 63 insertions(+), 26 deletions(-) rename pkg/{client => project/v02}/metadata.go (97%) rename pkg/{client => project/v02}/metadata_test.go (93%) diff --git a/pkg/client/build.go b/pkg/client/build.go index a2ad3fe57..5a57a8594 100644 --- a/pkg/client/build.go +++ b/pkg/client/build.go @@ -36,6 +36,7 @@ import ( "github.com/buildpacks/pack/pkg/image" "github.com/buildpacks/pack/pkg/logging" projectTypes "github.com/buildpacks/pack/pkg/project/types" + v02 "github.com/buildpacks/pack/pkg/project/v02" ) const ( @@ -326,7 +327,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { Metadata: map[string]interface{}{"url": sourceURL}, } } else { - projectMetadata.Source = GitMetadata(opts.AppPath) + projectMetadata.Source = v02.GitMetadata(opts.AppPath) } } diff --git a/pkg/client/metadata.go b/pkg/project/v02/metadata.go similarity index 97% rename from pkg/client/metadata.go rename to pkg/project/v02/metadata.go index 44ea0c2bd..071323501 100644 --- a/pkg/client/metadata.go +++ b/pkg/project/v02/metadata.go @@ -1,4 +1,4 @@ -package client +package v02 import ( "fmt" @@ -22,11 +22,11 @@ type TagInfo struct { func GitMetadata(appPath string) *platform.ProjectSource { repo, err := git.PlainOpen(appPath) if err != nil { - print("unable to open git repo") + return nil } headRef, err := repo.Head() if err != nil { - print("unable to parse head") + return nil } commitTagMap := generateTagsMap(repo) @@ -112,7 +112,7 @@ func parseGitDescribe(repo *git.Repository, headRef *plumbing.Reference, commitT } commits, err := repo.Log(logOpts) if err != nil { - print("no commits found") + return "" } latestTag := headRef.Hash().String() diff --git a/pkg/client/metadata_test.go b/pkg/project/v02/metadata_test.go similarity index 93% rename from pkg/client/metadata_test.go rename to pkg/project/v02/metadata_test.go index c1df16b5d..8b048cffb 100644 --- a/pkg/client/metadata_test.go +++ b/pkg/project/v02/metadata_test.go @@ -1,4 +1,4 @@ -package client +package v02 import ( "fmt" @@ -10,7 +10,7 @@ import ( "testing" "time" - h "github.com/buildpacks/pack/testhelpers" + "github.com/buildpacks/lifecycle/platform" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/config" "github.com/go-git/go-git/v5/plumbing" @@ -18,12 +18,14 @@ import ( "github.com/heroku/color" "github.com/sclevine/spec" "github.com/sclevine/spec/report" + + h "github.com/buildpacks/pack/testhelpers" ) func TestMetadata(t *testing.T) { color.Disable(true) defer color.Disable(false) - spec.Run(t, "Metadata", testMetadata, spec.Parallel(), spec.Report(report.Terminal{})) + spec.Run(t, "Metadata", testMetadata, spec.Sequential(), spec.Report(report.Terminal{})) } func testMetadata(t *testing.T, when spec.G, it spec.S) { @@ -49,6 +51,37 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, os.RemoveAll(repoPath)) }) + when("#GitMetadata", func() { + it("returns proper metadata format", func() { + assert := h.NewAssertionManager(t) + remoteOpts := &config.RemoteConfig{ + Name: "origin", + URLs: []string{"git@github.com:testorg/testproj.git", "git@github.com:testorg/testproj.git"}, + } + repo.CreateRemote(remoteOpts) + createUnannotatedTag(t, repo, commits[len(commits)-1], "testTag") + + output := GitMetadata(repoPath) + expectedOutput := &platform.ProjectSource{ + Type: "git", + Version: map[string]interface{}{ + "commit": commits[len(commits)-1].String(), + "describe": "testTag", + }, + Metadata: map[string]interface{}{ + "refs": []string{"master", "testTag"}, + "url": "git@github.com:testorg/testproj.git", + }, + } + assert.Equal(output, expectedOutput) + }) + + it("returns nil if error occurs while fetching metadata", func() { + output := GitMetadata("/git-path-not-found-ok") + h.AssertNil(t, output) + }) + }) + when("#generateTagsMap", func() { when("repository has no tags", func() { it("returns empty map", func() { @@ -396,7 +429,6 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, output, expectedOutput) }) }) - }) }) }) @@ -522,22 +554,6 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, output, "git@github.com:testorg/testproj.git") }) - it("returns first remote's fetch url if remote `origin` does not exists", func() { - remoteOpts1 := &config.RemoteConfig{ - Name: "not-origin", - URLs: []string{"git@gitlab.com:testorg/testproj.git", "git@gitlab.com:testorg/testproj.git"}, - } - repo.CreateRemote(remoteOpts1) - remoteOpts2 := &config.RemoteConfig{ - Name: "not-at-all-origin", - URLs: []string{"git@github.com:testorg/testproj.git", "git@github.com:testorg/testproj.git"}, - } - repo.CreateRemote(remoteOpts2) - - output := parseGitRemote(repo) - h.AssertEq(t, output, "git@gitlab.com:testorg/testproj.git") - }) - it("returns empty string if no remote exists", func() { output := parseGitRemote(repo) h.AssertEq(t, output, "") @@ -554,6 +570,13 @@ func testMetadata(t *testing.T, when spec.G, it spec.S) { h.AssertEq(t, output, "git@fetch.com:testorg/testproj.git") }) }) + + when("#getRefName", func() { + it("return proper ref for refs with `/`", func() { + output := getRefName("refs/tags/this/is/a/tag/with/slashes") + h.AssertEq(t, output, "this/is/a/tag/with/slashes") + }) + }) } func createCommits(t *testing.T, repo *git.Repository, repoPath string, numberOfCommits int) []plumbing.Hash { @@ -564,12 +587,25 @@ func createCommits(t *testing.T, repo *git.Repository, repoPath string, numberOf for i := 0; i < numberOfCommits; i++ { file, err := ioutil.TempFile(repoPath, h.RandString(10)) h.AssertNil(t, err) + defer file.Close() _, err = worktree.Add(filepath.Base(file.Name())) h.AssertNil(t, err) commitMsg := fmt.Sprintf("%s %d", "test commit number", i) - commitOpts := git.CommitOptions{} + commitOpts := git.CommitOptions{ + All: true, + Author: &object.Signature{ + Name: "Test Author", + Email: "testauthor@test.com", + When: time.Now(), + }, + Committer: &object.Signature{ + Name: "Test Committer", + Email: "testcommitter@test.com", + When: time.Now(), + }, + } commitHash, err := worktree.Commit(commitMsg, &commitOpts) h.AssertNil(t, err) commitHashes = append(commitHashes, commitHash) From 6504e8731167ae94f5cb477680bdee3a6a87959b Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Sun, 3 Jul 2022 17:20:47 +0530 Subject: [PATCH 08/21] flags: Add `--cache` flag for build cache as image - Add `flag` definition - Integrate flag options with image cache - Add tests for flag options Signed-off-by: Nitish Gupta --- internal/build/lifecycle_execution.go | 8 ++- internal/build/lifecycle_executor.go | 1 + internal/cache/cache_opts.go | 88 ++++++++++++++++++++++++ internal/cache/cache_opts_test.go | 98 +++++++++++++++++++++++++++ internal/commands/build.go | 12 ++++ pkg/client/build.go | 5 ++ 6 files changed, 210 insertions(+), 2 deletions(-) create mode 100644 internal/cache/cache_opts.go create mode 100644 internal/cache/cache_opts_test.go diff --git a/internal/build/lifecycle_execution.go b/internal/build/lifecycle_execution.go index 37b067908..2a1977673 100644 --- a/internal/build/lifecycle_execution.go +++ b/internal/build/lifecycle_execution.go @@ -124,8 +124,12 @@ func (l *LifecycleExecution) PrevImageName() string { func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseFactoryCreator) error { phaseFactory := phaseFactoryCreator(l) var buildCache Cache - if l.opts.CacheImage != "" { - cacheImage, err := name.ParseReference(l.opts.CacheImage, name.WeakValidation) + if l.opts.CacheImage != "" || l.opts.Cache.CacheType == "image" { + cacheImageName := l.opts.CacheImage + if cacheImageName == "" { + cacheImageName = l.opts.Cache.Source + } + cacheImage, err := name.ParseReference(cacheImageName, name.WeakValidation) if err != nil { return fmt.Errorf("invalid cache image name: %s", err) } diff --git a/internal/build/lifecycle_executor.go b/internal/build/lifecycle_executor.go index 110aec49c..c32d3eaaf 100644 --- a/internal/build/lifecycle_executor.go +++ b/internal/build/lifecycle_executor.go @@ -77,6 +77,7 @@ type LifecycleOptions struct { Interactive bool Termui Termui DockerHost string + Cache cache.CacheOpts CacheImage string HTTPProxy string HTTPSProxy string diff --git a/internal/cache/cache_opts.go b/internal/cache/cache_opts.go new file mode 100644 index 000000000..88af52c58 --- /dev/null +++ b/internal/cache/cache_opts.go @@ -0,0 +1,88 @@ +package cache + +import ( + "encoding/csv" + "fmt" + "strings" + + "github.com/pkg/errors" +) + +type CacheOpts struct { + CacheType string + Format string + Source string +} + +func (c *CacheOpts) Set(value string) error { + csvReader := csv.NewReader(strings.NewReader(value)) + csvReader.Comma = ';' + fields, err := csvReader.Read() + if err != nil { + return err + } + + for _, field := range fields { + parts := strings.SplitN(field, "=", 2) + + if len(parts) == 2 { + key := strings.ToLower(parts[0]) + value := strings.ToLower(parts[1]) + switch key { + case "type": + if value != "build" { + return errors.Errorf("invalid cache type '%s'", value) + } + c.CacheType = value + case "format": + if value != "image" { + return errors.Errorf("invalid cache format '%s'", value) + } + c.Format = value + case "name": + c.Source = value + } + } + + if len(parts) != 2 { + return errors.Errorf("invalid field '%s' must be a key=value pair", field) + } + } + + err = populateMissing(c) + if err != nil { + return err + } + return nil +} + +func (c *CacheOpts) String() string { + var cacheFlag string + if c.CacheType != "" { + cacheFlag += fmt.Sprintf("type=%s;", c.CacheType) + } + if c.Format != "" { + cacheFlag += fmt.Sprintf("format=%s;", c.Format) + } + if c.Source != "" { + cacheFlag += fmt.Sprintf("name=%s", c.Source) + } + return cacheFlag +} + +func (c *CacheOpts) Type() string { + return "cache" +} + +func populateMissing(c *CacheOpts) error { + if c.CacheType == "" { + c.CacheType = "build" + } + if c.Format == "" { + c.Format = "volume" + } + if c.Source == "" { + return errors.Errorf("cache 'name' is required") + } + return nil +} diff --git a/internal/cache/cache_opts_test.go b/internal/cache/cache_opts_test.go new file mode 100644 index 000000000..f9ef964b3 --- /dev/null +++ b/internal/cache/cache_opts_test.go @@ -0,0 +1,98 @@ +package cache + +import ( + "testing" + + "github.com/heroku/color" + "github.com/sclevine/spec" + "github.com/sclevine/spec/report" + + h "github.com/buildpacks/pack/testhelpers" +) + +type CacheOptTestCase struct { + name string + input string + output string + shouldFail bool +} + +func TestMetadata(t *testing.T) { + color.Disable(true) + defer color.Disable(false) + spec.Run(t, "Metadata", testCacheOpts, spec.Sequential(), spec.Report(report.Terminal{})) +} + +func testCacheOpts(t *testing.T, when spec.G, it spec.S) { + when("cache options are passed", func() { + it("image cache format with complete options", func() { + testcases := []CacheOptTestCase{ + { + name: "Build cache as Image", + input: "type=build;format=image;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=image;name=io.test.io/myorg/my-cache:build", + }, + } + + for _, testcase := range testcases { + var cacheFlags CacheOpts + t.Logf("Testing cache type: %s", testcase.name) + err := cacheFlags.Set(testcase.input) + h.AssertNil(t, err) + h.AssertEq(t, testcase.output, cacheFlags.String()) + } + }) + + it("image cache format with missing options", func() { + successTestCases := []CacheOptTestCase{ + { + name: "Build cache as Image missing: type", + input: "format=image;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=image;name=io.test.io/myorg/my-cache:build", + }, + { + name: "Build cache as Image missing: format", + input: "type=build;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build", + }, + { + name: "Build cache as Image missing: type, format", + input: "name=io.test.io/myorg/my-cache:build", + output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build", + }, + { + name: "Build cache as Image missing: name", + input: "type=build;format=image", + output: "cache 'name' is required", + shouldFail: true, + }, + { + name: "Build cache as Image missing: format, name", + input: "type=build", + output: "cache 'name' is required", + shouldFail: true, + }, + { + name: "Build cache as Image missing: type, name", + input: "format=image", + output: "cache 'name' is required", + shouldFail: true, + }, + } + + for _, testcase := range successTestCases { + var cacheFlags CacheOpts + t.Logf("Testing cache type: %s", testcase.name) + err := cacheFlags.Set(testcase.input) + + if testcase.shouldFail { + h.AssertError(t, err, testcase.output) + } else { + h.AssertNil(t, err) + output := cacheFlags.String() + h.AssertEq(t, testcase.output, output) + } + } + }) + }) +} diff --git a/internal/commands/build.go b/internal/commands/build.go index f45de8041..d18f068ef 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -12,6 +12,7 @@ import ( "github.com/pkg/errors" "github.com/spf13/cobra" + "github.com/buildpacks/pack/internal/cache" "github.com/buildpacks/pack/internal/config" "github.com/buildpacks/pack/internal/style" "github.com/buildpacks/pack/pkg/client" @@ -28,6 +29,7 @@ type BuildFlags struct { Interactive bool DockerHost string CacheImage string + Cache cache.CacheOpts AppPath string Builder string Registry string @@ -159,6 +161,7 @@ func Build(logger logging.Logger, cfg config.Config, packClient PackClient) *cob DefaultProcessType: flags.DefaultProcessType, ProjectDescriptorBaseDir: filepath.Dir(actualDescriptorPath), ProjectDescriptor: descriptor, + Cache: flags.Cache, CacheImage: flags.CacheImage, Workspace: flags.Workspace, LifecycleImage: lifecycleImage, @@ -200,6 +203,7 @@ func buildCommandFlags(cmd *cobra.Command, buildFlags *BuildFlags, cfg config.Co cmd.Flags().StringVarP(&buildFlags.AppPath, "path", "p", "", "Path to app dir or zip-formatted file (defaults to current working directory)") cmd.Flags().StringSliceVarP(&buildFlags.Buildpacks, "buildpack", "b", nil, "Buildpack to use. One of:\n a buildpack by id and version in the form of '@',\n path to a buildpack directory (not supported on Windows),\n path/URL to a buildpack .tar or .tgz file, or\n a packaged buildpack image name in the form of '/[:]'"+stringSliceHelp("buildpack")) cmd.Flags().StringVarP(&buildFlags.Builder, "builder", "B", cfg.DefaultBuilder, "Builder image") + cmd.Flags().Var(&buildFlags.Cache, "cache", "Cache used to define different cache options.") cmd.Flags().StringVar(&buildFlags.CacheImage, "cache-image", "", `Cache build layers in remote registry. Requires --publish`) cmd.Flags().BoolVar(&buildFlags.ClearCache, "clear-cache", false, "Clear image's associated cache before building") cmd.Flags().StringVar(&buildFlags.DateTime, "creation-time", "", "Desired create time in the output image config. Accepted values are Unix timestamps (e.g., '1641013200'), or 'now'. Platform API version must be at least 0.9 to use this feature.") @@ -237,6 +241,14 @@ func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackCli return client.NewExperimentError("Support for buildpack registries is currently experimental.") } + if flags.Cache.String() != "" && flags.CacheImage != "" { + return errors.New("'cache' flag cannot be used with 'cache-image' flag.") + } + + if flags.Cache.Format == "image" && !flags.Publish { + return errors.New("image cache format requires the 'publish' flag.") + } + if flags.CacheImage != "" && !flags.Publish { return errors.New("cache-image flag requires the publish flag") } diff --git a/pkg/client/build.go b/pkg/client/build.go index 2b5540b68..5397d3eee 100644 --- a/pkg/client/build.go +++ b/pkg/client/build.go @@ -24,6 +24,7 @@ import ( "github.com/buildpacks/pack/internal/build" "github.com/buildpacks/pack/internal/builder" + "github.com/buildpacks/pack/internal/cache" internalConfig "github.com/buildpacks/pack/internal/config" pname "github.com/buildpacks/pack/internal/name" "github.com/buildpacks/pack/internal/stack" @@ -106,6 +107,9 @@ type BuildOptions struct { // Buildpacks may both read and overwrite these values. Env map[string]string + // Used to configure various cache available options + Cache cache.CacheOpts + // Option only valid if Publish is true // Create an additional image that contains cache=true layers and push it to the registry. CacheImage string @@ -345,6 +349,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error { TrustBuilder: opts.TrustBuilder(opts.Builder), UseCreator: false, DockerHost: opts.DockerHost, + Cache: opts.Cache, CacheImage: opts.CacheImage, HTTPProxy: proxyConfig.HTTPProxy, HTTPSProxy: proxyConfig.HTTPSProxy, From 7d267bcc6911cdefea08f3c1bb799d2fb6b850fd Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Mon, 4 Jul 2022 22:34:06 +0530 Subject: [PATCH 09/21] tests: Add tests for build cache as image using cache flags - Add unit and acceptance tests Signed-off-by: Nitish Gupta --- acceptance/acceptance_test.go | 40 ++++++++++++++++++++++ internal/build/lifecycle_execution.go | 2 +- internal/build/lifecycle_execution_test.go | 31 +++++++++++++++-- internal/cache/cache_opts.go | 2 +- internal/cache/cache_opts_test.go | 11 ++++++ internal/commands/build.go | 8 +++-- internal/commands/build_test.go | 36 +++++++++++++++++++ 7 files changed, 124 insertions(+), 6 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index be56e18b2..3e1dbe329 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -1756,6 +1756,46 @@ func testAcceptance( }) }) + when("--cache with options for build cache as image", func() { + var cacheImageName, cacheFlags string + it.Before(func() { + cacheImageName = fmt.Sprintf("%s-cache", repoName) + cacheFlags = fmt.Sprintf("type=build;format=image;name=%s", cacheImageName) + }) + + it("creates image and cache image on the registry", func() { + buildArgs := []string{ + repoName, + "-p", filepath.Join("testdata", "mock_app"), + "--publish", + "--cache", + cacheFlags, + } + if imageManager.HostOS() != "windows" { + buildArgs = append(buildArgs, "--network", "host") + } + + output := pack.RunSuccessfully("build", buildArgs...) + assertions.NewOutputAssertionManager(t, output).ReportsSuccessfulImageBuild(repoName) + + cacheImageRef, err := name.ParseReference(cacheImageName, name.WeakValidation) + assert.Nil(err) + + t.Log("checking that registry has contents") + assertImage.CanBePulledFromRegistry(repoName) + if imageManager.HostOS() == "windows" { + // Cache images are automatically Linux container images, and therefore can't be pulled + // and inspected correctly on WCOW systems + // https://github.com/buildpacks/lifecycle/issues/529 + imageManager.PullImage(cacheImageRef.Name(), registryConfig.RegistryAuth()) + } else { + assertImage.CanBePulledFromRegistry(cacheImageRef.Name()) + } + + defer imageManager.CleanupImages(cacheImageRef.Name()) + }) + }) + when("ctrl+c", func() { it("stops the execution", func() { var buf = new(bytes.Buffer) diff --git a/internal/build/lifecycle_execution.go b/internal/build/lifecycle_execution.go index 2a1977673..eee61c001 100644 --- a/internal/build/lifecycle_execution.go +++ b/internal/build/lifecycle_execution.go @@ -124,7 +124,7 @@ func (l *LifecycleExecution) PrevImageName() string { func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseFactoryCreator) error { phaseFactory := phaseFactoryCreator(l) var buildCache Cache - if l.opts.CacheImage != "" || l.opts.Cache.CacheType == "image" { + if l.opts.CacheImage != "" || (l.opts.Cache.CacheType == "build" && l.opts.Cache.Format == "image") { cacheImageName := l.opts.CacheImage if cacheImageName == "" { cacheImageName = l.opts.Cache.Source diff --git a/internal/build/lifecycle_execution_test.go b/internal/build/lifecycle_execution_test.go index 7354db5ec..1fea8d31f 100644 --- a/internal/build/lifecycle_execution_test.go +++ b/internal/build/lifecycle_execution_test.go @@ -331,8 +331,8 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { }) when("Error cases", func() { - when("passed invalid cache-image", func() { - it("fails", func() { + when("passed invalid", func() { + it("fails for cache-image", func() { opts := build.LifecycleOptions{ Publish: false, ClearCache: false, @@ -354,6 +354,33 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { h.AssertError(t, err, fmt.Sprintf("invalid cache image name: %s", "could not parse reference: %%!(NOVERB)")) }) + + it("fails for cache flags", func() { + opts := build.LifecycleOptions{ + Publish: false, + ClearCache: false, + RunImage: "test", + Image: imageName, + Builder: fakeBuilder, + TrustBuilder: false, + UseCreator: false, + Cache: cache.CacheOpts{ + CacheType: "build", + Format: "image", + Source: "%%%", + }, + Termui: fakeTermui, + } + + lifecycle, err := build.NewLifecycleExecution(logger, docker, opts) + h.AssertNil(t, err) + + err = lifecycle.Run(context.Background(), func(execution *build.LifecycleExecution) build.PhaseFactory { + return fakePhaseFactory + }) + + h.AssertError(t, err, fmt.Sprintf("invalid cache image name: %s", "could not parse reference: %%!(NOVERB)")) + }) }) }) }) diff --git a/internal/cache/cache_opts.go b/internal/cache/cache_opts.go index 88af52c58..03471c855 100644 --- a/internal/cache/cache_opts.go +++ b/internal/cache/cache_opts.go @@ -30,7 +30,7 @@ func (c *CacheOpts) Set(value string) error { value := strings.ToLower(parts[1]) switch key { case "type": - if value != "build" { + if value != "build" && value != "launch" { return errors.Errorf("invalid cache type '%s'", value) } c.CacheType = value diff --git a/internal/cache/cache_opts_test.go b/internal/cache/cache_opts_test.go index f9ef964b3..6761dcca3 100644 --- a/internal/cache/cache_opts_test.go +++ b/internal/cache/cache_opts_test.go @@ -32,6 +32,11 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { input: "type=build;format=image;name=io.test.io/myorg/my-cache:build", output: "type=build;format=image;name=io.test.io/myorg/my-cache:build", }, + { + name: "Launch cache as Image", + input: "type=launch;format=image;name=io.test.io/myorg/my-cache:build", + output: "type=launch;format=image;name=io.test.io/myorg/my-cache:build", + }, } for _, testcase := range testcases { @@ -78,6 +83,12 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { output: "cache 'name' is required", shouldFail: true, }, + { + name: "Launch cache as Image missing: name", + input: "type=launch;format=image", + output: "cache 'name' is required", + shouldFail: true, + }, } for _, testcase := range successTestCases { diff --git a/internal/commands/build.go b/internal/commands/build.go index d18f068ef..856ccaa93 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -203,7 +203,7 @@ func buildCommandFlags(cmd *cobra.Command, buildFlags *BuildFlags, cfg config.Co cmd.Flags().StringVarP(&buildFlags.AppPath, "path", "p", "", "Path to app dir or zip-formatted file (defaults to current working directory)") cmd.Flags().StringSliceVarP(&buildFlags.Buildpacks, "buildpack", "b", nil, "Buildpack to use. One of:\n a buildpack by id and version in the form of '@',\n path to a buildpack directory (not supported on Windows),\n path/URL to a buildpack .tar or .tgz file, or\n a packaged buildpack image name in the form of '/[:]'"+stringSliceHelp("buildpack")) cmd.Flags().StringVarP(&buildFlags.Builder, "builder", "B", cfg.DefaultBuilder, "Builder image") - cmd.Flags().Var(&buildFlags.Cache, "cache", "Cache used to define different cache options.") + cmd.Flags().Var(&buildFlags.Cache, "cache", "Cache options used to define cache techniques for build process.\n- Cache as image: type=;format=image;name=") cmd.Flags().StringVar(&buildFlags.CacheImage, "cache-image", "", `Cache build layers in remote registry. Requires --publish`) cmd.Flags().BoolVar(&buildFlags.ClearCache, "clear-cache", false, "Clear image's associated cache before building") cmd.Flags().StringVar(&buildFlags.DateTime, "creation-time", "", "Desired create time in the output image config. Accepted values are Unix timestamps (e.g., '1641013200'), or 'now'. Platform API version must be at least 0.9 to use this feature.") @@ -241,12 +241,16 @@ func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackCli return client.NewExperimentError("Support for buildpack registries is currently experimental.") } + if flags.Cache.CacheType == "launch" && flags.Cache.Format == "image" { + logger.Warn("cache definition: 'launch' cache in format 'image' is not supported.") + } + if flags.Cache.String() != "" && flags.CacheImage != "" { return errors.New("'cache' flag cannot be used with 'cache-image' flag.") } if flags.Cache.Format == "image" && !flags.Publish { - return errors.New("image cache format requires the 'publish' flag.") + return errors.New("image cache format requires the 'publish' flag") } if flags.CacheImage != "" && !flags.Publish { diff --git a/internal/commands/build_test.go b/internal/commands/build_test.go index de836e4b6..b4b059e93 100644 --- a/internal/commands/build_test.go +++ b/internal/commands/build_test.go @@ -347,6 +347,33 @@ func testBuildCommand(t *testing.T, when spec.G, it spec.S) { }) }) + when("cache flag with 'format=image' is passed", func() { + when("--publish is not used", func() { + it("errors", func() { + command.SetArgs([]string{"--builder", "my-builder", "image", "--cache", "type=build;format=image;name=myorg/myimage:cache"}) + err := command.Execute() + h.AssertError(t, err, "image cache format requires the 'publish' flag") + }) + }) + when("--publish is used", func() { + it("succeeds", func() { + mockClient.EXPECT(). + Build(gomock.Any(), EqBuildOptionsWithCacheFlags("type=build;format=image;name=myorg/myimage:cache")). + Return(nil) + + command.SetArgs([]string{"--builder", "my-builder", "image", "--cache", "type=build;format=image;name=myorg/myimage:cache", "--publish"}) + h.AssertNil(t, command.Execute()) + }) + }) + when("used together with --cache-image", func() { + it("errors", func() { + command.SetArgs([]string{"--builder", "my-builder", "image", "--cache-image", "some-cache-image", "--cache", "type=build;format=image;name=myorg/myimage:cache"}) + err := command.Execute() + h.AssertError(t, err, "'cache' flag cannot be used with 'cache-image' flag.") + }) + }) + }) + when("a valid lifecycle-image is provided", func() { when("only the image repo is provided", func() { it("uses the provided lifecycle-image and parses it correctly", func() { @@ -860,6 +887,15 @@ func EqBuildOptionsWithCacheImage(cacheImage string) gomock.Matcher { } } +func EqBuildOptionsWithCacheFlags(cacheFlags string) gomock.Matcher { + return buildOptionsMatcher{ + description: fmt.Sprintf("CacheFlags=%s", cacheFlags), + equals: func(o client.BuildOptions) bool { + return o.Cache.String() == cacheFlags + }, + } +} + func EqBuildOptionsWithLifecycleImage(lifecycleImage string) gomock.Matcher { return buildOptionsMatcher{ description: fmt.Sprintf("LifecycleImage=%s", lifecycleImage), From c1deb54451bde9ac4b338785b5a61a8cf9f92f23 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Wed, 6 Jul 2022 13:52:45 +0530 Subject: [PATCH 10/21] flags: Move cache flag constants to enums and update tests - Gate acceptance tests to work only when pack supports `--cache` - string constants for cache type and cache format has been moved to enums - Fix test cases, update acceptance test helper methods - Add new unit tests Signed-off-by: Nitish Gupta --- acceptance/acceptance_test.go | 1 + acceptance/invoke/pack.go | 12 +++- internal/build/lifecycle_execution.go | 2 +- internal/build/lifecycle_execution_test.go | 8 +-- internal/cache/cache_opts.go | 67 ++++++++++++++++------ internal/cache/cache_opts_test.go | 36 ++++++++++++ internal/commands/build.go | 8 +-- internal/commands/build_test.go | 13 ++++- 8 files changed, 117 insertions(+), 30 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index 3e1dbe329..b8f865eb2 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -1759,6 +1759,7 @@ func testAcceptance( when("--cache with options for build cache as image", func() { var cacheImageName, cacheFlags string it.Before(func() { + h.SkipIf(t, !pack.SupportsFeature(invoke.Cache), "") cacheImageName = fmt.Sprintf("%s-cache", repoName) cacheFlags = fmt.Sprintf("type=build;format=image;name=%s", cacheImageName) }) diff --git a/acceptance/invoke/pack.go b/acceptance/invoke/pack.go index c33cafc6e..333dbb054 100644 --- a/acceptance/invoke/pack.go +++ b/acceptance/invoke/pack.go @@ -5,6 +5,7 @@ package invoke import ( "bytes" + "fmt" "io/ioutil" "os" "os/exec" @@ -210,20 +211,27 @@ func (i *PackInvoker) Supports(command string) bool { search = command } + re := regexp.MustCompile(fmt.Sprint(`\b%s\b`, search)) output, err := i.baseCmd(cmdParts...).CombinedOutput() i.assert.Nil(err) - return strings.Contains(string(output), search) && !strings.Contains(string(output), "Unknown help topic") + return re.MatchString(string(output)) && !strings.Contains(string(output), "Unknown help topic") } type Feature int -const CreationTime = iota +const ( + CreationTime = iota + Cache +) var featureTests = map[Feature]func(i *PackInvoker) bool{ CreationTime: func(i *PackInvoker) bool { return i.Supports("build --creation-time") }, + Cache: func(i *PackInvoker) bool { + return i.Supports("build --cache") + }, } func (i *PackInvoker) SupportsFeature(f Feature) bool { diff --git a/internal/build/lifecycle_execution.go b/internal/build/lifecycle_execution.go index eee61c001..c4bd6ba44 100644 --- a/internal/build/lifecycle_execution.go +++ b/internal/build/lifecycle_execution.go @@ -124,7 +124,7 @@ func (l *LifecycleExecution) PrevImageName() string { func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseFactoryCreator) error { phaseFactory := phaseFactoryCreator(l) var buildCache Cache - if l.opts.CacheImage != "" || (l.opts.Cache.CacheType == "build" && l.opts.Cache.Format == "image") { + if l.opts.CacheImage != "" || (l.opts.Cache.CacheType == cache.Build && l.opts.Cache.Format == cache.CacheImage) { cacheImageName := l.opts.CacheImage if cacheImageName == "" { cacheImageName = l.opts.Cache.Source diff --git a/internal/build/lifecycle_execution_test.go b/internal/build/lifecycle_execution_test.go index 1fea8d31f..f1038f65f 100644 --- a/internal/build/lifecycle_execution_test.go +++ b/internal/build/lifecycle_execution_test.go @@ -352,7 +352,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { return fakePhaseFactory }) - h.AssertError(t, err, fmt.Sprintf("invalid cache image name: %s", "could not parse reference: %%!(NOVERB)")) + h.AssertError(t, err, fmt.Sprintf("invalid cache image name: %s", "could not parse reference: %%")) }) it("fails for cache flags", func() { @@ -365,8 +365,8 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { TrustBuilder: false, UseCreator: false, Cache: cache.CacheOpts{ - CacheType: "build", - Format: "image", + CacheType: cache.Build, + Format: cache.CacheImage, Source: "%%%", }, Termui: fakeTermui, @@ -379,7 +379,7 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { return fakePhaseFactory }) - h.AssertError(t, err, fmt.Sprintf("invalid cache image name: %s", "could not parse reference: %%!(NOVERB)")) + h.AssertError(t, err, fmt.Sprintf("invalid cache image name: %s", "could not parse reference: %%")) }) }) }) diff --git a/internal/cache/cache_opts.go b/internal/cache/cache_opts.go index 03471c855..2aaec39b8 100644 --- a/internal/cache/cache_opts.go +++ b/internal/cache/cache_opts.go @@ -8,12 +8,43 @@ import ( "github.com/pkg/errors" ) +type Cache int +type Format int type CacheOpts struct { - CacheType string - Format string + CacheType Cache + Format Format Source string } +const ( + Build Cache = iota + Launch +) +const ( + CacheVolume Format = iota + CacheImage +) + +func (c Cache) String() string { + switch c { + case Build: + return "build" + case Launch: + return "launch" + } + return "" +} + +func (f Format) String() string { + switch f { + case CacheImage: + return "image" + case CacheVolume: + return "volume" + } + return "" +} + func (c *CacheOpts) Set(value string) error { csvReader := csv.NewReader(strings.NewReader(value)) csvReader.Comma = ';' @@ -25,28 +56,34 @@ func (c *CacheOpts) Set(value string) error { for _, field := range fields { parts := strings.SplitN(field, "=", 2) + if len(parts) != 2 { + return errors.Errorf("invalid field '%s' must be a key=value pair", field) + } + if len(parts) == 2 { key := strings.ToLower(parts[0]) value := strings.ToLower(parts[1]) switch key { case "type": - if value != "build" && value != "launch" { + switch value { + case "build": + c.CacheType = Build + case "launch": + c.CacheType = Launch + default: return errors.Errorf("invalid cache type '%s'", value) } - c.CacheType = value case "format": - if value != "image" { + switch value { + case "image": + c.Format = CacheImage + default: return errors.Errorf("invalid cache format '%s'", value) } - c.Format = value case "name": c.Source = value } } - - if len(parts) != 2 { - return errors.Errorf("invalid field '%s' must be a key=value pair", field) - } } err = populateMissing(c) @@ -58,10 +95,10 @@ func (c *CacheOpts) Set(value string) error { func (c *CacheOpts) String() string { var cacheFlag string - if c.CacheType != "" { + if c.CacheType.String() != "" { cacheFlag += fmt.Sprintf("type=%s;", c.CacheType) } - if c.Format != "" { + if c.Format.String() != "" { cacheFlag += fmt.Sprintf("format=%s;", c.Format) } if c.Source != "" { @@ -75,12 +112,6 @@ func (c *CacheOpts) Type() string { } func populateMissing(c *CacheOpts) error { - if c.CacheType == "" { - c.CacheType = "build" - } - if c.Format == "" { - c.Format = "volume" - } if c.Source == "" { return errors.Errorf("cache 'name' is required") } diff --git a/internal/cache/cache_opts_test.go b/internal/cache/cache_opts_test.go index 6761dcca3..c64e53e8d 100644 --- a/internal/cache/cache_opts_test.go +++ b/internal/cache/cache_opts_test.go @@ -105,5 +105,41 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { } } }) + + it("image cache format with invalid options", func() { + testcases := []CacheOptTestCase{ + { + name: "Invalid cache type", + input: "type=invalid_cache;format=image;name=io.test.io/myorg/my-cache:build", + output: "invalid cache type 'invalid_cache'", + shouldFail: true, + }, + { + name: "Invalid cache format", + input: "type=launch;format=invalid_format;name=io.test.io/myorg/my-cache:build", + output: "invalid cache format 'invalid_format'", + shouldFail: true, + }, + { + name: "Not a key=value pair", + input: "launch;format=image;name=io.test.io/myorg/my-cache:build", + output: "invalid field 'launch' must be a key=value pair", + shouldFail: true, + }, + { + name: "Extra semicolon", + input: "type=launch;format=image;name=io.test.io/myorg/my-cache:build;", + output: "invalid field '' must be a key=value pair", + shouldFail: true, + }, + } + + for _, testcase := range testcases { + var cacheFlags CacheOpts + t.Logf("Testing cache type: %s", testcase.name) + err := cacheFlags.Set(testcase.input) + h.AssertError(t, err, testcase.output) + } + }) }) } diff --git a/internal/commands/build.go b/internal/commands/build.go index 856ccaa93..571798718 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -241,15 +241,15 @@ func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackCli return client.NewExperimentError("Support for buildpack registries is currently experimental.") } - if flags.Cache.CacheType == "launch" && flags.Cache.Format == "image" { + if flags.Cache.CacheType == cache.Launch && flags.Cache.Format == cache.CacheImage { logger.Warn("cache definition: 'launch' cache in format 'image' is not supported.") } - if flags.Cache.String() != "" && flags.CacheImage != "" { - return errors.New("'cache' flag cannot be used with 'cache-image' flag.") + if flags.Cache.Format == cache.CacheImage && flags.CacheImage != "" { + return errors.New("'cache' flag with 'image' format cannot be used with 'cache-image' flag.") } - if flags.Cache.Format == "image" && !flags.Publish { + if flags.Cache.Format == cache.CacheImage && !flags.Publish { return errors.New("image cache format requires the 'publish' flag") } diff --git a/internal/commands/build_test.go b/internal/commands/build_test.go index b4b059e93..5f68e40b9 100644 --- a/internal/commands/build_test.go +++ b/internal/commands/build_test.go @@ -369,7 +369,18 @@ func testBuildCommand(t *testing.T, when spec.G, it spec.S) { it("errors", func() { command.SetArgs([]string{"--builder", "my-builder", "image", "--cache-image", "some-cache-image", "--cache", "type=build;format=image;name=myorg/myimage:cache"}) err := command.Execute() - h.AssertError(t, err, "'cache' flag cannot be used with 'cache-image' flag.") + h.AssertError(t, err, "'cache' flag with 'image' format cannot be used with 'cache-image' flag") + }) + }) + when("''type=launch;format=image' is used", func() { + it("warns", func() { + mockClient.EXPECT(). + Build(gomock.Any(), EqBuildOptionsWithCacheFlags("type=launch;format=image;name=myorg/myimage:cache")). + Return(nil) + + command.SetArgs([]string{"--builder", "my-builder", "image", "--cache", "type=launch;format=image;name=myorg/myimage:cache", "--publish"}) + h.AssertNil(t, command.Execute()) + h.AssertContains(t, outBuf.String(), "Warning: cache definition: 'launch' cache in format 'image' is not supported.") }) }) }) From c44d791b670da08d9b08a86562e8f30e413716eb Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Jul 2022 22:13:49 +0000 Subject: [PATCH 11/21] Bump github.com/BurntSushi/toml from 1.1.0 to 1.2.0 Bumps [github.com/BurntSushi/toml](https://github.com/BurntSushi/toml) from 1.1.0 to 1.2.0. - [Release notes](https://github.com/BurntSushi/toml/releases) - [Commits](https://github.com/BurntSushi/toml/compare/v1.1.0...v1.2.0) --- updated-dependencies: - dependency-name: github.com/BurntSushi/toml dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 729db2353..28620c190 100644 --- a/go.mod +++ b/go.mod @@ -1,7 +1,7 @@ module github.com/buildpacks/pack require ( - github.com/BurntSushi/toml v1.1.0 + github.com/BurntSushi/toml v1.2.0 github.com/Masterminds/semver v1.5.0 github.com/apex/log v1.9.0 github.com/buildpacks/imgutil v0.0.0-20220527150729-7a271a852e31 diff --git a/go.sum b/go.sum index 274f70856..94068f01b 100644 --- a/go.sum +++ b/go.sum @@ -107,8 +107,9 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0= +github.com/BurntSushi/toml v1.2.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/Djarvur/go-err113 v0.0.0-20210108212216-aea10b59be24/go.mod h1:4UJr5HIiMZrwgkSPdsjy2uOQExX/WEILpIrO9UPGuXs= github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= From 6e94f6df40e2d0128b879c8775bd8d29b69c4764 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 20 Jul 2022 22:14:10 +0000 Subject: [PATCH 12/21] Bump github.com/google/go-containerregistry from 0.10.0 to 0.11.0 Bumps [github.com/google/go-containerregistry](https://github.com/google/go-containerregistry) from 0.10.0 to 0.11.0. - [Release notes](https://github.com/google/go-containerregistry/releases) - [Changelog](https://github.com/google/go-containerregistry/blob/main/.goreleaser.yml) - [Commits](https://github.com/google/go-containerregistry/compare/v0.10.0...v0.11.0) --- updated-dependencies: - dependency-name: github.com/google/go-containerregistry dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 16 ++++++++-------- go.sum | 59 +++++++++++++++++++++++++++++++++++++++++++++++----------- 2 files changed, 56 insertions(+), 19 deletions(-) diff --git a/go.mod b/go.mod index 729db2353..1b239c7e6 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/ghodss/yaml v1.0.0 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.5.8 - github.com/google/go-containerregistry v0.10.0 + github.com/google/go-containerregistry v0.11.0 github.com/google/go-github/v30 v30.1.0 github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/heroku/color v0.0.6 @@ -29,7 +29,7 @@ require ( github.com/spf13/cobra v1.5.0 golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 - golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 + golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce gopkg.in/src-d/go-git.v4 v4.13.1 @@ -66,7 +66,7 @@ require ( github.com/chrismellard/docker-credential-acr-env v0.0.0-20220327082430-c57b701bfc08 // indirect github.com/containerd/cgroups v1.0.3 // indirect github.com/containerd/containerd v1.6.3 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.11.4 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.12.0 // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/docker/distribution v2.8.1+incompatible // indirect github.com/docker/docker-credential-helpers v0.6.4 // indirect @@ -82,7 +82,7 @@ require ( github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/klauspost/compress v1.15.5 // indirect + github.com/klauspost/compress v1.15.8 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.12 // indirect github.com/mattn/go-isatty v0.0.14 // indirect @@ -97,15 +97,15 @@ require ( github.com/opencontainers/selinux v1.10.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/sirupsen/logrus v1.8.1 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/src-d/gcfg v1.4.0 // indirect github.com/vbatts/tar-split v0.11.2 // indirect github.com/xanzy/ssh-agent v0.3.1 // indirect go.opencensus.io v0.23.0 // indirect - golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect - golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 // indirect - golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect + golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect + golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f // indirect + golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.0 // indirect diff --git a/go.sum b/go.sum index 274f70856..a25b7b592 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,7 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= +cloud.google.com/go v0.102.0/go.mod h1:oWcCzKlqJ5zgHQt9YsaeTY9KzIvjyy0ArmiBUgpQ+nc= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= @@ -43,10 +44,12 @@ cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJW cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M= cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s= cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU= +cloud.google.com/go/compute v1.7.0/go.mod h1:435lt8av5oL9P3fv1OEzSbSUe+ybHXGMPQHHZWZxy9U= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= +cloud.google.com/go/iam v0.3.0/go.mod h1:XzJPvDayI+9zsASAFO68Hk07u3z+f+JrT2xXNdp4bnY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -58,6 +61,7 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= +cloud.google.com/go/storage v1.22.1/go.mod h1:S8N1cAStu7BOeFfE8KAQzmyyLkK8p/vmRq6kuBTW58Y= contrib.go.opencensus.io/exporter/stackdriver v0.13.4/go.mod h1:aXENhDJ1Y4lIg4EUaVTwzvYETVNZk10Pu26tevFKLUc= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20210715213245-6c3934b029d8/go.mod h1:CzsSbkDixRphAF5hS6wbMKq0eI6ccJRb7/A0M6JBnwg= @@ -290,6 +294,7 @@ github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XP github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= +github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo= @@ -371,8 +376,9 @@ github.com/containerd/nri v0.0.0-20201007170849-eb1350a75164/go.mod h1:+2wGSDGFY github.com/containerd/nri v0.0.0-20210316161719-dbaa18c31c14/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/nri v0.1.0/go.mod h1:lmxnXF6oMkbqs39FiCt1s0R2HSMhcLel9vNL3m4AaeY= github.com/containerd/stargz-snapshotter/estargz v0.4.1/go.mod h1:x7Q9dg9QYb4+ELgxmo4gBUeJB0tl5dqH1Sdz0nJU1QM= -github.com/containerd/stargz-snapshotter/estargz v0.11.4 h1:LjrYUZpyOhiSaU7hHrdR82/RBoxfGWSaC0VeSSMXqnk= github.com/containerd/stargz-snapshotter/estargz v0.11.4/go.mod h1:7vRJIcImfY8bpifnMjt+HTJoQxASq7T28MYbP15/Nf0= +github.com/containerd/stargz-snapshotter/estargz v0.12.0 h1:idtwRTLjk2erqiYhPWy2L844By8NRFYEwYHcXhoIWPM= +github.com/containerd/stargz-snapshotter/estargz v0.12.0/go.mod h1:AIQ59TewBFJ4GOPEQXujcrJ/EKxh5xXZegW1rkR1P/M= github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20190828172938-92c8520ef9f8/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o= github.com/containerd/ttrpc v0.0.0-20191028202541-4f1b8fe65a5c/go.mod h1:LPm1u0xBw8r8NOKoOdNMeVHSawSsltak+Ihv+etqsE8= @@ -494,6 +500,7 @@ github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.m github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= +github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE= github.com/envoyproxy/protoc-gen-validate v0.0.14/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/esimonov/ifshort v1.0.3/go.mod h1:yZqNJUrNn20K8Q9n2CrjTKYyVEmX209Hgu+M1LBpeZE= @@ -671,8 +678,8 @@ github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.5.1/go.mod h1:Ct15B4yir3PLOP5jsy0GNeYVaIZs/MK/Jz5any1wFW0= github.com/google/go-containerregistry v0.9.0/go.mod h1:9eq4BnSufyT1kHNffX+vSXVonaJ7yaIOulrKZejMxnQ= -github.com/google/go-containerregistry v0.10.0 h1:qd/fv2nQajGZJenaNcdaghlwSPjQ0NphN9hzArr2WWg= -github.com/google/go-containerregistry v0.10.0/go.mod h1:C7uwbB1QUAtvnknyd3ethxJRd4gtEjU/9WLXzckfI1Y= +github.com/google/go-containerregistry v0.11.0 h1:Xt8x1adcREjFcmDoDK8OdOsjxu90PHkGuwNP8GiHMLM= +github.com/google/go-containerregistry v0.11.0/go.mod h1:BBaYtsHPHA42uEgAvd/NejvAfPSlz281sJWqupjSxfk= github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo= github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8= github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= @@ -708,15 +715,18 @@ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa/go.mod h1:17drOmN3MwGY7t0e+Ei9b45FFGA3fBs3x36SsCg1hq8= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM= github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM= +github.com/googleapis/gax-go/v2 v2.4.0/go.mod h1:XOTVJ59hdnfJLIP/dh8n5CGryZR2LxK9wbMD5+iXC6c= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.5.1/go.mod h1:6U4PtQXGIEt/Z3h5MAT7FNofLnw9vXk2cUuW7uA/OeU= github.com/googleapis/gnostic v0.5.5/go.mod h1:7+EbHbldMins07ALC74bsA81Ovc97DwqyJO1AENw9kA= +github.com/googleapis/go-type-adapters v1.0.0/go.mod h1:zHW75FOG2aur7gAO2B+MLby+cLsWGBF62rFAi7WjWO4= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= @@ -857,8 +867,10 @@ github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8 github.com/klauspost/compress v1.13.5/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.15.4/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= -github.com/klauspost/compress v1.15.5 h1:qyCLMz2JCrKADihKOh9FxnW3houKeNsp2h5OEz0QSEA= github.com/klauspost/compress v1.15.5/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.7/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/klauspost/compress v1.15.8 h1:JahtItbkWjf2jzm/T+qgMxkP9EMHsqEUA6vCMGmXvhA= +github.com/klauspost/compress v1.15.8/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -1202,8 +1214,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sivchari/tenv v1.4.7/go.mod h1:5nF+bITvkebQVanjU6IuMbvIot/7ReNsUV7I5NbprB0= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= @@ -1541,10 +1554,13 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220516155154-20f960328961/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220524220425-1d687d428aca/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8= golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.0.0-20220708220712-1185a9018129 h1:vucSRfWwTsoXro7P+3Cjlr6flUMtzCwzlvkxEQtHHB0= +golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1565,8 +1581,9 @@ golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw= -golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= +golang.org/x/oauth2 v0.0.0-20220608161450-d0670ef3b1eb/go.mod h1:jaDAt6Dkxork7LmZnYtzbRWj0W47D86a3TGe0YHBvmE= +golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 h1:oVlhw3Oe+1reYsE2Nqu19PDJfLzwdU3QUUrG86rLK68= +golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92/go.mod h1:h4gKUeWbJ4rQPri7E0u6Gs4e9Ri2zaLxzw5DI5XGrYg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1579,8 +1596,9 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f h1:Ax0t5p6N38Ga0dThY21weqDEyz2oklo4IvDkpigvkD8= +golang.org/x/sync v0.0.0-20220601150217-0de741cfad7f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -1708,9 +1726,13 @@ golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220610221304-9f5ed59c137d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -1849,12 +1871,14 @@ golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11-0.20220518213611-904e24e9fcf9/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= +golang.org/x/tools v0.1.11/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= +golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1894,6 +1918,9 @@ google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/S google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= +google.golang.org/api v0.78.0/go.mod h1:1Sg78yoMLOhlQTeF+ARBoytAcH1NNyyl390YMy6rKmw= +google.golang.org/api v0.80.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg= +google.golang.org/api v0.84.0/go.mod h1:NTsGnUFJMYROtiquksZHBWtHfeMC7iYthki7Eq3pa8o= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1954,6 +1981,7 @@ google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= +google.golang.org/genproto v0.0.0-20210329143202-679c6ae281ee/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A= google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= @@ -1986,6 +2014,12 @@ google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220429170224-98d788798c3e/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= +google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220518221133-4f43b3371335/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220523171625-347a074981d8/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= +google.golang.org/genproto v0.0.0-20220608133413-ed9918b62aac/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= +google.golang.org/genproto v0.0.0-20220616135557-88e70c0c3a90/go.mod h1:KEWEmljWE5zPzLBa/oHl6DaEt9LmfH6WtH1OHIvleBA= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= @@ -2022,6 +2056,9 @@ google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ5 google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ= +google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= +google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= From 397c959c21e804a46e18e948fedd6009ed56df5e Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Sat, 23 Jul 2022 11:30:48 +0530 Subject: [PATCH 13/21] flags: Add support for 'volume' cache format using `--cache` flag - Extend support for `--cache` flag to volume cache format for both build and launch cache types Signed-off-by: Nitish Gupta --- internal/build/lifecycle_execution.go | 8 +-- internal/cache/cache_opts.go | 93 ++++++++++++--------------- internal/cache/volume_cache.go | 14 ++-- internal/commands/build.go | 6 +- 4 files changed, 59 insertions(+), 62 deletions(-) diff --git a/internal/build/lifecycle_execution.go b/internal/build/lifecycle_execution.go index c4bd6ba44..b04eb22ae 100644 --- a/internal/build/lifecycle_execution.go +++ b/internal/build/lifecycle_execution.go @@ -124,10 +124,10 @@ func (l *LifecycleExecution) PrevImageName() string { func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseFactoryCreator) error { phaseFactory := phaseFactoryCreator(l) var buildCache Cache - if l.opts.CacheImage != "" || (l.opts.Cache.CacheType == cache.Build && l.opts.Cache.Format == cache.CacheImage) { + if l.opts.CacheImage != "" || (l.opts.Cache.Build.Format == cache.CacheImage) { cacheImageName := l.opts.CacheImage if cacheImageName == "" { - cacheImageName = l.opts.Cache.Source + cacheImageName = l.opts.Cache.Build.Source } cacheImage, err := name.ParseReference(cacheImageName, name.WeakValidation) if err != nil { @@ -135,7 +135,7 @@ func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseF } buildCache = cache.NewImageCache(cacheImage, l.docker) } else { - buildCache = cache.NewVolumeCache(l.opts.Image, "build", l.docker) + buildCache = cache.NewVolumeCache(l.opts.Image, l.opts.Cache.Build, "build", l.docker) } l.logger.Debugf("Using build cache volume %s", style.Symbol(buildCache.Name())) @@ -146,7 +146,7 @@ func (l *LifecycleExecution) Run(ctx context.Context, phaseFactoryCreator PhaseF l.logger.Debugf("Build cache %s cleared", style.Symbol(buildCache.Name())) } - launchCache := cache.NewVolumeCache(l.opts.Image, "launch", l.docker) + launchCache := cache.NewVolumeCache(l.opts.Image, l.opts.Cache.Launch, "launch", l.docker) if !l.opts.UseCreator { if l.platformAPI.LessThan("0.7") { diff --git a/internal/cache/cache_opts.go b/internal/cache/cache_opts.go index 2aaec39b8..4f2c7ef99 100644 --- a/internal/cache/cache_opts.go +++ b/internal/cache/cache_opts.go @@ -8,33 +8,21 @@ import ( "github.com/pkg/errors" ) -type Cache int type Format int +type CacheInfo struct { + Format Format + Source string +} type CacheOpts struct { - CacheType Cache - Format Format - Source string + Build CacheInfo + Launch CacheInfo } -const ( - Build Cache = iota - Launch -) const ( CacheVolume Format = iota CacheImage ) -func (c Cache) String() string { - switch c { - case Build: - return "build" - case Launch: - return "launch" - } - return "" -} - func (f Format) String() string { switch f { case CacheImage: @@ -53,36 +41,46 @@ func (c *CacheOpts) Set(value string) error { return err } + cache := &c.Build for _, field := range fields { parts := strings.SplitN(field, "=", 2) - if len(parts) != 2 { return errors.Errorf("invalid field '%s' must be a key=value pair", field) } + key := strings.ToLower(parts[0]) + value := strings.ToLower(parts[1]) + if key == "type" { + switch value { + case "build": + cache = &c.Build + case "launch": + cache = &c.Launch + default: + return errors.Errorf("invalid cache type '%s'", value) + } + break + } + } - if len(parts) == 2 { - key := strings.ToLower(parts[0]) - value := strings.ToLower(parts[1]) - switch key { - case "type": - switch value { - case "build": - c.CacheType = Build - case "launch": - c.CacheType = Launch - default: - return errors.Errorf("invalid cache type '%s'", value) - } - case "format": - switch value { - case "image": - c.Format = CacheImage - default: - return errors.Errorf("invalid cache format '%s'", value) - } - case "name": - c.Source = value + for _, field := range fields { + parts := strings.SplitN(field, "=", 2) + if len(parts) != 2 { + return errors.Errorf("invalid field '%s' must be a key=value pair", field) + } + key := strings.ToLower(parts[0]) + value := strings.ToLower(parts[1]) + switch key { + case "format": + switch value { + case "image": + cache.Format = CacheImage + case "volume": + cache.Format = CacheVolume + default: + return errors.Errorf("invalid cache format '%s'", value) } + case "name": + cache.Source = value } } @@ -95,15 +93,8 @@ func (c *CacheOpts) Set(value string) error { func (c *CacheOpts) String() string { var cacheFlag string - if c.CacheType.String() != "" { - cacheFlag += fmt.Sprintf("type=%s;", c.CacheType) - } - if c.Format.String() != "" { - cacheFlag += fmt.Sprintf("format=%s;", c.Format) - } - if c.Source != "" { - cacheFlag += fmt.Sprintf("name=%s", c.Source) - } + cacheFlag = fmt.Sprintf("type=build;format=%s;name=%s;", c.Build.Format.String(), c.Build.Source) + cacheFlag += fmt.Sprintf("type=launch;format=%s;name=%s;", c.Launch.Format.String(), c.Launch.Source) return cacheFlag } @@ -112,7 +103,7 @@ func (c *CacheOpts) Type() string { } func populateMissing(c *CacheOpts) error { - if c.Source == "" { + if (c.Build.Source == "" && c.Build.Format == CacheImage) || (c.Launch.Source == "" && c.Launch.Format == CacheImage) { return errors.Errorf("cache 'name' is required") } return nil diff --git a/internal/cache/volume_cache.go b/internal/cache/volume_cache.go index fa0124e50..4c009c743 100644 --- a/internal/cache/volume_cache.go +++ b/internal/cache/volume_cache.go @@ -17,12 +17,18 @@ type VolumeCache struct { volume string } -func NewVolumeCache(imageRef name.Reference, suffix string, dockerClient client.CommonAPIClient) *VolumeCache { - sum := sha256.Sum256([]byte(imageRef.Name())) +func NewVolumeCache(imageRef name.Reference, cacheType CacheInfo, suffix string, dockerClient client.CommonAPIClient) *VolumeCache { + var volumeName string + if cacheType.Source == "" { + sum := sha256.Sum256([]byte(imageRef.Name())) + vol := paths.FilterReservedNames(fmt.Sprintf("%s-%x", sanitizedRef(imageRef), sum[:6])) + volumeName = fmt.Sprintf("pack-cache-%s.%s", vol, suffix) + } else { + volumeName = paths.FilterReservedNames(cacheType.Source) + } - vol := paths.FilterReservedNames(fmt.Sprintf("%s-%x", sanitizedRef(imageRef), sum[:6])) return &VolumeCache{ - volume: fmt.Sprintf("pack-cache-%s.%s", vol, suffix), + volume: volumeName, docker: dockerClient, } } diff --git a/internal/commands/build.go b/internal/commands/build.go index 571798718..b07c2f0eb 100644 --- a/internal/commands/build.go +++ b/internal/commands/build.go @@ -241,15 +241,15 @@ func validateBuildFlags(flags *BuildFlags, cfg config.Config, packClient PackCli return client.NewExperimentError("Support for buildpack registries is currently experimental.") } - if flags.Cache.CacheType == cache.Launch && flags.Cache.Format == cache.CacheImage { + if flags.Cache.Launch.Format == cache.CacheImage { logger.Warn("cache definition: 'launch' cache in format 'image' is not supported.") } - if flags.Cache.Format == cache.CacheImage && flags.CacheImage != "" { + if flags.Cache.Build.Format == cache.CacheImage && flags.CacheImage != "" { return errors.New("'cache' flag with 'image' format cannot be used with 'cache-image' flag.") } - if flags.Cache.Format == cache.CacheImage && !flags.Publish { + if flags.Cache.Build.Format == cache.CacheImage && !flags.Publish { return errors.New("image cache format requires the 'publish' flag") } From 1eb52c0bc03cb327f1c2e62b55c23dba33d92776 Mon Sep 17 00:00:00 2001 From: Nitish Gupta Date: Sat, 23 Jul 2022 11:32:50 +0530 Subject: [PATCH 14/21] tests: Add tests for `--cache` flag using volume cache format Signed-off-by: Nitish Gupta --- acceptance/acceptance_test.go | 8 +- internal/build/lifecycle_execution_test.go | 7 +- internal/cache/cache_opts_test.go | 100 ++++++++-- internal/cache/volume_cache_test.go | 209 ++++++++++++++------- internal/commands/build_test.go | 6 +- 5 files changed, 239 insertions(+), 91 deletions(-) diff --git a/acceptance/acceptance_test.go b/acceptance/acceptance_test.go index b8f865eb2..ec32ad2c2 100644 --- a/acceptance/acceptance_test.go +++ b/acceptance/acceptance_test.go @@ -780,8 +780,8 @@ func testAcceptance( ref, err := name.ParseReference(repoName, name.WeakValidation) assert.Nil(err) cacheImage := cache.NewImageCache(ref, dockerCli) - buildCacheVolume := cache.NewVolumeCache(ref, "build", dockerCli) - launchCacheVolume := cache.NewVolumeCache(ref, "launch", dockerCli) + buildCacheVolume := cache.NewVolumeCache(ref, cache.CacheInfo{}, "build", dockerCli) + launchCacheVolume := cache.NewVolumeCache(ref, cache.CacheInfo{}, "launch", dockerCli) cacheImage.Clear(context.TODO()) buildCacheVolume.Clear(context.TODO()) launchCacheVolume.Clear(context.TODO()) @@ -2423,8 +2423,8 @@ include = [ "*.jar", "media/mountain.jpg", "/media/person.png", ] imageManager.CleanupImages(origID, repoName, runBefore) ref, err := name.ParseReference(repoName, name.WeakValidation) assert.Nil(err) - buildCacheVolume := cache.NewVolumeCache(ref, "build", dockerCli) - launchCacheVolume := cache.NewVolumeCache(ref, "launch", dockerCli) + buildCacheVolume := cache.NewVolumeCache(ref, cache.CacheInfo{}, "build", dockerCli) + launchCacheVolume := cache.NewVolumeCache(ref, cache.CacheInfo{}, "launch", dockerCli) assert.Succeeds(buildCacheVolume.Clear(context.TODO())) assert.Succeeds(launchCacheVolume.Clear(context.TODO())) }) diff --git a/internal/build/lifecycle_execution_test.go b/internal/build/lifecycle_execution_test.go index f1038f65f..9fa74edd6 100644 --- a/internal/build/lifecycle_execution_test.go +++ b/internal/build/lifecycle_execution_test.go @@ -365,9 +365,10 @@ func testLifecycleExecution(t *testing.T, when spec.G, it spec.S) { TrustBuilder: false, UseCreator: false, Cache: cache.CacheOpts{ - CacheType: cache.Build, - Format: cache.CacheImage, - Source: "%%%", + Build: cache.CacheInfo{ + Format: cache.CacheImage, + Source: "%%%", + }, }, Termui: fakeTermui, } diff --git a/internal/cache/cache_opts_test.go b/internal/cache/cache_opts_test.go index c64e53e8d..13499eed1 100644 --- a/internal/cache/cache_opts_test.go +++ b/internal/cache/cache_opts_test.go @@ -24,18 +24,18 @@ func TestMetadata(t *testing.T) { } func testCacheOpts(t *testing.T, when spec.G, it spec.S) { - when("cache options are passed", func() { - it("image cache format with complete options", func() { + when("image cache format options are passed", func() { + it("with complete options", func() { testcases := []CacheOptTestCase{ { name: "Build cache as Image", input: "type=build;format=image;name=io.test.io/myorg/my-cache:build", - output: "type=build;format=image;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=image;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;name=;", }, { name: "Launch cache as Image", input: "type=launch;format=image;name=io.test.io/myorg/my-cache:build", - output: "type=launch;format=image;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=volume;name=;type=launch;format=image;name=io.test.io/myorg/my-cache:build;", }, } @@ -48,22 +48,17 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { } }) - it("image cache format with missing options", func() { + it("with missing options", func() { successTestCases := []CacheOptTestCase{ { name: "Build cache as Image missing: type", input: "format=image;name=io.test.io/myorg/my-cache:build", - output: "type=build;format=image;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=image;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;name=;", }, { name: "Build cache as Image missing: format", input: "type=build;name=io.test.io/myorg/my-cache:build", - output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build", - }, - { - name: "Build cache as Image missing: type, format", - input: "name=io.test.io/myorg/my-cache:build", - output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build", + output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;name=;", }, { name: "Build cache as Image missing: name", @@ -72,10 +67,14 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { shouldFail: true, }, { - name: "Build cache as Image missing: format, name", - input: "type=build", - output: "cache 'name' is required", - shouldFail: true, + name: "Build cache as Image missing: type, format", + input: "name=io.test.io/myorg/my-cache:build", + output: "type=build;format=volume;name=io.test.io/myorg/my-cache:build;type=launch;format=volume;name=;", + }, + { + name: "Build cache as Image missing: format, name", + input: "type=build", + output: "type=build;format=volume;name=;type=launch;format=volume;name=;", }, { name: "Build cache as Image missing: type, name", @@ -94,6 +93,9 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { for _, testcase := range successTestCases { var cacheFlags CacheOpts t.Logf("Testing cache type: %s", testcase.name) + if testcase.name == "Everything missing" { + print("i am here") + } err := cacheFlags.Set(testcase.input) if testcase.shouldFail { @@ -106,7 +108,7 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { } }) - it("image cache format with invalid options", func() { + it("with invalid options", func() { testcases := []CacheOptTestCase{ { name: "Invalid cache type", @@ -142,4 +144,68 @@ func testCacheOpts(t *testing.T, when spec.G, it spec.S) { } }) }) + + when("volume cache format options are passed", func() { + it("with complete options", func() { + testcases := []CacheOptTestCase{ + { + name: "Build cache as Volume", + input: "type=build;format=volume;name=test-build-volume-cache", + output: "type=build;format=volume;name=test-build-volume-cache;type=launch;format=volume;name=;", + }, + { + name: "Launch cache as Volume", + input: "type=launch;format=volume;name=test-launch-volume-cache", + output: "type=build;format=volume;name=;type=launch;format=volume;name=test-launch-volume-cache;", + }, + } + + for _, testcase := range testcases { + var cacheFlags CacheOpts + t.Logf("Testing cache type: %s", testcase.name) + err := cacheFlags.Set(testcase.input) + h.AssertNil(t, err) + h.AssertEq(t, testcase.output, cacheFlags.String()) + } + }) + + it("with missing options", func() { + successTestCases := []CacheOptTestCase{ + { + name: "Launch cache as Volume missing: format", + input: "type=launch;name=test-launch-volume", + output: "type=build;format=volume;name=;type=launch;format=volume;name=test-launch-volume;", + }, + { + name: "Launch cache as Volume missing: name", + input: "type=launch;format=volume", + output: "type=build;format=volume;name=;type=launch;format=volume;name=;", + }, + { + name: "Launch cache as Volume missing: format, name", + input: "type=launch", + output: "type=build;format=volume;name=;type=launch;format=volume;name=;", + }, + { + name: "Launch cache as Volume missing: type, name", + input: "format=volume", + output: "type=build;format=volume;name=;type=launch;format=volume;name=;", + }, + } + + for _, testcase := range successTestCases { + var cacheFlags CacheOpts + t.Logf("Testing cache type: %s", testcase.name) + err := cacheFlags.Set(testcase.input) + + if testcase.shouldFail { + h.AssertError(t, err, testcase.output) + } else { + h.AssertNil(t, err) + output := cacheFlags.String() + h.AssertEq(t, testcase.output, output) + } + } + }) + }) } diff --git a/internal/cache/volume_cache_test.go b/internal/cache/volume_cache_test.go index 9a36489ce..ce30c9e5a 100644 --- a/internal/cache/volume_cache_test.go +++ b/internal/cache/volume_cache_test.go @@ -38,86 +38,167 @@ func testCache(t *testing.T, when spec.G, it spec.S) { h.AssertNil(t, err) }) when("#NewVolumeCache", func() { - it("adds suffix to calculated name", func() { - ref, err := name.ParseReference("my/repo", name.WeakValidation) - h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - if !strings.HasSuffix(subject.Name(), ".some-suffix") { - t.Fatalf("Calculated volume name '%s' should end with '.some-suffix'", subject.Name()) - } - }) + when("volume cache name is empty", func() { + it("adds suffix to calculated name", func() { + ref, err := name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + if !strings.HasSuffix(subject.Name(), ".some-suffix") { + t.Fatalf("Calculated volume name '%s' should end with '.some-suffix'", subject.Name()) + } + }) - it("reusing the same cache for the same repo name", func() { - ref, err := name.ParseReference("my/repo", name.WeakValidation) - h.AssertNil(t, err) + it("reusing the same cache for the same repo name", func() { + ref, err := name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - expected := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - if subject.Name() != expected.Name() { - t.Fatalf("The same repo name should result in the same volume") - } - }) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + expected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + if subject.Name() != expected.Name() { + t.Fatalf("The same repo name should result in the same volume") + } + }) - it("supplies different volumes for different tags", func() { - ref, err := name.ParseReference("my/repo:other-tag", name.WeakValidation) - h.AssertNil(t, err) + it("supplies different volumes for different tags", func() { + ref, err := name.ParseReference("my/repo:other-tag", name.WeakValidation) + h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) - ref, err = name.ParseReference("my/repo", name.WeakValidation) - h.AssertNil(t, err) - notExpected := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - if subject.Name() == notExpected.Name() { - t.Fatalf("Different image tags should result in different volumes") - } - }) + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + notExpected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + if subject.Name() == notExpected.Name() { + t.Fatalf("Different image tags should result in different volumes") + } + }) - it("supplies different volumes for different registries", func() { - ref, err := name.ParseReference("registry.com/my/repo:other-tag", name.WeakValidation) - h.AssertNil(t, err) + it("supplies different volumes for different registries", func() { + ref, err := name.ParseReference("registry.com/my/repo:other-tag", name.WeakValidation) + h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) - ref, err = name.ParseReference("my/repo", name.WeakValidation) - h.AssertNil(t, err) - notExpected := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - if subject.Name() == notExpected.Name() { - t.Fatalf("Different image registries should result in different volumes") - } - }) + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + notExpected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + if subject.Name() == notExpected.Name() { + t.Fatalf("Different image registries should result in different volumes") + } + }) - it("resolves implied tag", func() { - ref, err := name.ParseReference("my/repo:latest", name.WeakValidation) - h.AssertNil(t, err) + it("resolves implied tag", func() { + ref, err := name.ParseReference("my/repo:latest", name.WeakValidation) + h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) - ref, err = name.ParseReference("my/repo", name.WeakValidation) - h.AssertNil(t, err) - expected := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - h.AssertEq(t, subject.Name(), expected.Name()) - }) + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + expected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + h.AssertEq(t, subject.Name(), expected.Name()) + }) - it("resolves implied registry", func() { - ref, err := name.ParseReference("index.docker.io/my/repo", name.WeakValidation) - h.AssertNil(t, err) + it("resolves implied registry", func() { + ref, err := name.ParseReference("index.docker.io/my/repo", name.WeakValidation) + h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) - ref, err = name.ParseReference("my/repo", name.WeakValidation) - h.AssertNil(t, err) - expected := cache.NewVolumeCache(ref, "some-suffix", dockerClient) - h.AssertEq(t, subject.Name(), expected.Name()) + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + expected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + h.AssertEq(t, subject.Name(), expected.Name()) + }) + + it("includes human readable information", func() { + ref, err := name.ParseReference("myregistryhost:5000/fedora/httpd:version1.0", name.WeakValidation) + h.AssertNil(t, err) + + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + + h.AssertContains(t, subject.Name(), "fedora_httpd_version1.0") + h.AssertTrue(t, names.RestrictedNamePattern.MatchString(subject.Name())) + }) }) - it("includes human readable information", func() { - ref, err := name.ParseReference("myregistryhost:5000/fedora/httpd:version1.0", name.WeakValidation) - h.AssertNil(t, err) + when("volume cache name is not empty", func() { + volumeName := "test-volume-name" + cacheInfo := cache.CacheInfo{ + Format: cache.CacheVolume, + Source: volumeName, + } + + it("named volume created without suffix", func() { + ref, err := name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject := cache.NewVolumeCache(ref, cacheInfo, "some-suffix", dockerClient) + + if volumeName != subject.Name() { + t.Fatalf("Volume name '%s' should be same as the name specified '%s'", subject.Name(), volumeName) + } + }) - h.AssertContains(t, subject.Name(), "fedora_httpd_version1.0") - h.AssertTrue(t, names.RestrictedNamePattern.MatchString(subject.Name())) + it("reusing the same cache for the same repo name", func() { + ref, err := name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + + subject := cache.NewVolumeCache(ref, cacheInfo, "some-suffix", dockerClient) + + expected := cache.NewVolumeCache(ref, cacheInfo, "some-suffix", dockerClient) + if subject.Name() != expected.Name() { + t.Fatalf("The same repo name should result in the same volume") + } + }) + + it("supplies different volumes for different registries", func() { + ref, err := name.ParseReference("registry.com/my/repo:other-tag", name.WeakValidation) + h.AssertNil(t, err) + + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + notExpected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + if subject.Name() == notExpected.Name() { + t.Fatalf("Different image registries should result in different volumes") + } + }) + + it("resolves implied tag", func() { + ref, err := name.ParseReference("my/repo:latest", name.WeakValidation) + h.AssertNil(t, err) + + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + expected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + h.AssertEq(t, subject.Name(), expected.Name()) + }) + + it("resolves implied registry", func() { + ref, err := name.ParseReference("index.docker.io/my/repo", name.WeakValidation) + h.AssertNil(t, err) + + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + + ref, err = name.ParseReference("my/repo", name.WeakValidation) + h.AssertNil(t, err) + expected := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + h.AssertEq(t, subject.Name(), expected.Name()) + }) + + it("includes human readable information", func() { + ref, err := name.ParseReference("myregistryhost:5000/fedora/httpd:version1.0", name.WeakValidation) + h.AssertNil(t, err) + + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) + + h.AssertContains(t, subject.Name(), "fedora_httpd_version1.0") + h.AssertTrue(t, names.RestrictedNamePattern.MatchString(subject.Name())) + }) }) }) @@ -138,7 +219,7 @@ func testCache(t *testing.T, when spec.G, it spec.S) { ref, err := name.ParseReference(h.RandString(10), name.WeakValidation) h.AssertNil(t, err) - subject = cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject = cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) volumeName = subject.Name() }) @@ -174,7 +255,7 @@ func testCache(t *testing.T, when spec.G, it spec.S) { it("returns the cache type", func() { ref, err := name.ParseReference("my/repo", name.WeakValidation) h.AssertNil(t, err) - subject := cache.NewVolumeCache(ref, "some-suffix", dockerClient) + subject := cache.NewVolumeCache(ref, cache.CacheInfo{}, "some-suffix", dockerClient) expected := cache.Volume h.AssertEq(t, subject.Type(), expected) }) diff --git a/internal/commands/build_test.go b/internal/commands/build_test.go index 5f68e40b9..c647c1711 100644 --- a/internal/commands/build_test.go +++ b/internal/commands/build_test.go @@ -358,7 +358,7 @@ func testBuildCommand(t *testing.T, when spec.G, it spec.S) { when("--publish is used", func() { it("succeeds", func() { mockClient.EXPECT(). - Build(gomock.Any(), EqBuildOptionsWithCacheFlags("type=build;format=image;name=myorg/myimage:cache")). + Build(gomock.Any(), EqBuildOptionsWithCacheFlags("type=build;format=image;name=myorg/myimage:cache;type=launch;format=volume;name=;")). Return(nil) command.SetArgs([]string{"--builder", "my-builder", "image", "--cache", "type=build;format=image;name=myorg/myimage:cache", "--publish"}) @@ -372,10 +372,10 @@ func testBuildCommand(t *testing.T, when spec.G, it spec.S) { h.AssertError(t, err, "'cache' flag with 'image' format cannot be used with 'cache-image' flag") }) }) - when("''type=launch;format=image' is used", func() { + when("'type=launch;format=image' is used", func() { it("warns", func() { mockClient.EXPECT(). - Build(gomock.Any(), EqBuildOptionsWithCacheFlags("type=launch;format=image;name=myorg/myimage:cache")). + Build(gomock.Any(), EqBuildOptionsWithCacheFlags("type=build;format=volume;name=;type=launch;format=image;name=myorg/myimage:cache;")). Return(nil) command.SetArgs([]string{"--builder", "my-builder", "image", "--cache", "type=launch;format=image;name=myorg/myimage:cache", "--publish"}) From 6f37234c863aca9c6f2cd9d99942aa2a42a9de43 Mon Sep 17 00:00:00 2001 From: Natalie Arellano Date: Tue, 26 Jul 2022 12:49:34 -0400 Subject: [PATCH 15/21] Updates windows-wcow runner to be GitHub-hosted vs self-hosted Signed-off-by: Natalie Arellano --- .github/workflows/build.yml | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f8fff7c70..b3f6319b7 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -39,7 +39,7 @@ jobs: pack_bin: pack.exe - config: windows-wcow os: windows - runner: [self-hosted, windows, wcow] + runner: [windows-2019] no_docker: "false" pack_bin: pack.exe runs-on: ${{ matrix.runner }} @@ -89,6 +89,36 @@ jobs: shell: powershell - name: Verify run: make verify + - name: Register runner IP + if: matrix.config == 'windows-wcow' + shell: powershell + run: | + # Get IP from default gateway interface + $IPAddress=(Get-NetIPAddress -InterfaceAlias ((Get-NetRoute "0.0.0.0/0").InterfaceAlias) -AddressFamily IPv4)[0].IPAddress + + # Allow container-to-host registry traffic (from public interface, to the same interface) + New-NetfirewallRule -DisplayName test-registry -LocalAddress $IPAddress -RemoteAddress $IPAddress + + # create or update daemon config to allow host as insecure-registry + $config=@{} + if (Test-Path C:\ProgramData\docker\config\daemon.json) { + $config=(Get-Content C:\ProgramData\docker\config\daemon.json | ConvertFrom-json) + } + $config."insecure-registries" = @("$IPAddress/32") + ConvertTo-json $config | Out-File -Encoding ASCII C:\ProgramData\docker\config\daemon.json + + Restart-Service docker + + # dump docker info for auditing + docker version + docker info + + # Modify etc\hosts to include runner IP + $IPAddress=(Get-NetIPAddress -InterfaceAlias ((Get-NetRoute "0.0.0.0/0").InterfaceAlias) -AddressFamily IPv4)[0].IPAddress + "# Modified by CNB: https://github.com/buildpacks/ci/tree/main/gh-runners/windows + ${IPAddress} host.docker.internal + ${IPAddress} gateway.docker.internal + " | Out-File -Filepath C:\Windows\System32\drivers\etc\hosts -Encoding utf8 - name: Test env: TEST_COVERAGE: 1 From 4fc0140ecfe713f8f744f113ed5acd6aac336387 Mon Sep 17 00:00:00 2001 From: Natalie Arellano Date: Wed, 27 Jul 2022 10:49:41 -0400 Subject: [PATCH 16/21] Fixes for SSH dialer test Signed-off-by: Natalie Arellano --- internal/sshdialer/ssh_dialer_test.go | 10 +--------- internal/sshdialer/windows_test.go | 2 +- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/internal/sshdialer/ssh_dialer_test.go b/internal/sshdialer/ssh_dialer_test.go index 654f12266..209a4d49b 100644 --- a/internal/sshdialer/ssh_dialer_test.go +++ b/internal/sshdialer/ssh_dialer_test.go @@ -920,17 +920,9 @@ func (b badAgent) Signers() ([]ssh.Signer, error) { func withFixedUpSSHCLI(t *testing.T) func() { t.Helper() - which := "which" - if runtime.GOOS == "windows" { - which = "where" - } - - out, err := exec.Command(which, "ssh").CombinedOutput() + sshAbsPath, err := exec.LookPath("ssh") th.AssertNil(t, err) - sshAbsPath := string(out) - sshAbsPath = strings.Trim(sshAbsPath, "\r\n") - sshScript := `#!/bin/sh SSH_BIN -o PasswordAuthentication=no -o ConnectTimeout=3 -o UserKnownHostsFile="$HOME/.ssh/known_hosts" $@ ` diff --git a/internal/sshdialer/windows_test.go b/internal/sshdialer/windows_test.go index 304549d96..4909d0d01 100644 --- a/internal/sshdialer/windows_test.go +++ b/internal/sshdialer/windows_test.go @@ -22,7 +22,7 @@ func fixupPrivateKeyMod(path string) { err = acl.Apply(path, true, false, - acl.GrantName(((mode&0700)<<23)|((mode&0200)<<9), usr.Name)) + acl.GrantName(((mode&0700)<<23)|((mode&0200)<<9), usr.Username)) // See https://github.com/hectane/go-acl/issues/1 if err != nil && err.Error() != "The operation completed successfully." { From f763546c9f34c7bb0a1f839f8dec6a9bf79f040b Mon Sep 17 00:00:00 2001 From: Natalie Arellano Date: Fri, 29 Jul 2022 11:45:27 -0400 Subject: [PATCH 17/21] Use Windows artifact from WCOW worker Signed-off-by: Natalie Arellano --- .github/workflows/build.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index b3f6319b7..4d166c896 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -154,7 +154,7 @@ jobs: PACK_BUILD: ${{ github.run_number }} shell: powershell - uses: actions/upload-artifact@v3 - if: matrix.config != 'windows-wcow' + if: matrix.config != 'windows-lcow' with: name: pack-${{ matrix.os }} path: out/${{ env.PACK_BIN }} From 21140bd97c42b842fe358dcb74fd30fc924c8630 Mon Sep 17 00:00:00 2001 From: Stefan Zabka Date: Mon, 1 Aug 2022 13:19:54 +0200 Subject: [PATCH 18/21] Change Slack link in README to CNCF slack Signed-off-by: Stefan Zabka --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 495172845..478bda902 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ [![GoDoc](https://godoc.org/github.com/buildpacks/pack?status.svg)](https://godoc.org/github.com/buildpacks/pack) [![GitHub license](https://img.shields.io/github/license/buildpacks/pack)](https://github.com/buildpacks/pack/blob/main/LICENSE) [![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/4748/badge)](https://bestpractices.coreinfrastructure.org/projects/4748) -[![Slack](https://img.shields.io/badge/slack-join-ff69b4.svg?logo=slack)](https://slack.buildpacks.io/) +[![Slack](https://img.shields.io/badge/slack-join-ff69b4.svg?logo=slack)](https://slack.cncf.io/) [![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/buildpacks/pack) `pack` makes it easy for... From 1bcf987848ae5ddd1c9aeae949111e80787279b7 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 1 Aug 2022 22:12:58 +0000 Subject: [PATCH 19/21] Bump github.com/gdamore/tcell/v2 from 2.5.1 to 2.5.2 Bumps [github.com/gdamore/tcell/v2](https://github.com/gdamore/tcell) from 2.5.1 to 2.5.2. - [Release notes](https://github.com/gdamore/tcell/releases) - [Changelog](https://github.com/gdamore/tcell/blob/master/CHANGESv2.md) - [Commits](https://github.com/gdamore/tcell/compare/v2.5.1...v2.5.2) --- updated-dependencies: - dependency-name: github.com/gdamore/tcell/v2 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 729db2353..7bd28ffb4 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/docker/docker v20.10.17+incompatible github.com/docker/go-connections v0.4.0 github.com/dustin/go-humanize v1.0.0 - github.com/gdamore/tcell/v2 v2.5.1 + github.com/gdamore/tcell/v2 v2.5.2 github.com/ghodss/yaml v1.0.0 github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.5.8 diff --git a/go.sum b/go.sum index 274f70856..88b158de1 100644 --- a/go.sum +++ b/go.sum @@ -520,8 +520,8 @@ github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYis github.com/gdamore/encoding v1.0.0 h1:+7OoQ1Bc6eTm5niUzBa0Ctsh6JbMW6Ra+YNuAtDBdko= github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= github.com/gdamore/tcell/v2 v2.4.1-0.20210905002822-f057f0a857a1/go.mod h1:Az6Jt+M5idSED2YPGtwnfJV0kXohgdCBPmHGSYc1r04= -github.com/gdamore/tcell/v2 v2.5.1 h1:zc3LPdpK184lBW7syF2a5C6MV827KmErk9jGVnmsl/I= -github.com/gdamore/tcell/v2 v2.5.1/go.mod h1:wSkrPaXoiIWZqW/g7Px4xc79di6FTcpB8tvaKJ6uGBo= +github.com/gdamore/tcell/v2 v2.5.2 h1:tKzG29kO9p2V++3oBY2W9zUjYu7IK1MENFeY/BzJSVY= +github.com/gdamore/tcell/v2 v2.5.2/go.mod h1:wSkrPaXoiIWZqW/g7Px4xc79di6FTcpB8tvaKJ6uGBo= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= From b8adffec78cc6064202c508ce3158d0644f182a0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 3 Aug 2022 20:16:36 +0000 Subject: [PATCH 20/21] Bump github.com/onsi/gomega from 1.19.0 to 1.20.0 Bumps [github.com/onsi/gomega](https://github.com/onsi/gomega) from 1.19.0 to 1.20.0. - [Release notes](https://github.com/onsi/gomega/releases) - [Changelog](https://github.com/onsi/gomega/blob/master/CHANGELOG.md) - [Commits](https://github.com/onsi/gomega/compare/v1.19.0...v1.20.0) --- updated-dependencies: - dependency-name: github.com/onsi/gomega dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- go.mod | 2 +- go.sum | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 092a3fd6e..93a797715 100644 --- a/go.mod +++ b/go.mod @@ -19,7 +19,7 @@ require ( github.com/hectane/go-acl v0.0.0-20190604041725-da78bae5fc95 github.com/heroku/color v0.0.6 github.com/mitchellh/ioprogress v0.0.0-20180201004757-6a23b12fa88e - github.com/onsi/gomega v1.19.0 + github.com/onsi/gomega v1.20.0 github.com/opencontainers/image-spec v1.0.3-0.20220114050600-8b9d41f48198 github.com/pelletier/go-toml v1.9.5 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index 3ab50d355..841bb8d98 100644 --- a/go.sum +++ b/go.sum @@ -1043,8 +1043,9 @@ github.com/onsi/ginkgo v1.13.0/go.mod h1:+REjRxOmWfHCjfv9TTWB1jD1Frx4XydAD3zm1ls github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= -github.com/onsi/ginkgo/v2 v2.1.3 h1:e/3Cwtogj0HA+25nMP1jCMDIf8RtRYbGwGGuBIFztkc= github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4 h1:GNapqRSid3zijZ9H77KrgVG4/8KqiyRsxcSxe+7ApXY= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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= @@ -1056,8 +1057,9 @@ github.com/onsi/gomega v1.10.3/go.mod h1:V9xEwhxec5O8UDM77eCW8vLymOMltsqPVYWrpDs github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= -github.com/onsi/gomega v1.19.0 h1:4ieX6qQjPP/BfC3mpsAtIGGlxTWPeA3Inl/7DtXw1tw= github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.0 h1:8W0cWlwFkflGPLltQvLRB7ZVD5HuP6ng320w2IS245Q= +github.com/onsi/gomega v1.20.0/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -1724,9 +1726,11 @@ golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220318055525-2edf467146b5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220325203850-36772127a21f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220502124256-b6088ccd6cba/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 58c1f5682ce952e076592bd1ba7de348aefe860b Mon Sep 17 00:00:00 2001 From: Javier Romero Date: Fri, 5 Aug 2022 15:44:32 -0500 Subject: [PATCH 21/21] Remove old git library version Signed-off-by: Javier Romero --- go.mod | 3 --- go.sum | 17 ----------------- internal/registry/git_test.go | 2 +- internal/registry/registry_cache.go | 4 ++-- internal/registry/registry_cache_test.go | 4 ++-- testhelpers/registry.go | 4 ++-- testhelpers/testhelpers.go | 2 +- 7 files changed, 8 insertions(+), 28 deletions(-) diff --git a/go.mod b/go.mod index 89bdec8f9..790f06df3 100644 --- a/go.mod +++ b/go.mod @@ -33,7 +33,6 @@ require ( golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce - gopkg.in/src-d/go-git.v4 v4.13.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -105,7 +104,6 @@ require ( github.com/sergi/go-diff v1.2.0 // indirect github.com/sirupsen/logrus v1.9.0 // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/src-d/gcfg v1.4.0 // indirect github.com/vbatts/tar-split v0.11.2 // indirect github.com/xanzy/ssh-agent v0.3.1 // indirect go.opencensus.io v0.23.0 // indirect @@ -115,7 +113,6 @@ require ( golang.org/x/text v0.3.7 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.0 // indirect - gopkg.in/src-d/go-billy.v4 v4.3.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect ) diff --git a/go.sum b/go.sum index 7902706ce..5e582b860 100644 --- a/go.sum +++ b/go.sum @@ -162,8 +162,6 @@ github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:H github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= github.com/acomagu/bufpipe v1.0.3 h1:fxAGrHZTgQ9w5QqVItgzwj235/uYZYgbXitB+dLupOk= github.com/acomagu/bufpipe v1.0.3/go.mod h1:mxdxdup/WdsKVreO5GpW4+M/1CE2sMG4jeGJ2sYmHc4= -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/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -834,7 +832,6 @@ github.com/j-keck/arping v0.0.0-20160618110441-2cf9dc699c56/go.mod h1:ymszkNOg6t github.com/j-keck/arping v1.0.2/go.mod h1:aJbELhR92bSk7tp79AWM/ftfc90EfEi2bQJrbBFOsPw= 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/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= github.com/jgautheron/goconst v1.5.1/go.mod h1:aAosetZ5zaeC/2EfMeRswtxUFBpe2Hr7HzkgX4fanO4= github.com/jhump/protoreflect v1.6.1/go.mod h1:RZQ/lnuN+zqeRVpQigTwO6o0AJUkxbnSnpuG7toUTG4= @@ -869,7 +866,6 @@ github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7V github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/julz/importas v0.0.0-20210419104244-841f0c0fe66d/go.mod h1:oSFU2R4XK/P7kNBrnL/FEQlDGN1/6WoxXEjSSXO0DV0= github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k= -github.com/kevinburke/ssh_config v0.0.0-20190725054713-01f96b0aa0cd/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/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= @@ -899,7 +895,6 @@ github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= @@ -1121,7 +1116,6 @@ github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT9 github.com/otiai10/mint v1.3.1/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= -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/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -1280,8 +1274,6 @@ github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5q github.com/spf13/viper v1.7.1/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= -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/ssgreg/nlreturn/v2 v2.2.1/go.mod h1:E/iiPB78hV7Szg2YfRgyIrk1AD6JVMTRkkxBiELzh2I= github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8= github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8= @@ -1355,7 +1347,6 @@ github.com/vishvananda/netns v0.0.0-20200728191858-db3c7e526aae/go.mod h1:DD4vA1 github.com/vishvananda/netns v0.0.0-20210104183010-2eb08e3e575f/go.mod h1:DD4vA1DwXk04H54A1oHXtwZmA0grkVMdPxx/VGLCah0= github.com/willf/bitset v1.1.11-0.20200630133818-d5bec3311243/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr3+MjI= -github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xanzy/ssh-agent v0.3.0/go.mod h1:3s9xbODqPuuhK9JV1R321M/FlMZSBvE5aY6eAcqrDh0= github.com/xanzy/ssh-agent v0.3.1 h1:AmzO1SSWxw73zxFZPRwaMN1MohDw8UyHnmuxyceTEGo= github.com/xanzy/ssh-agent v0.3.1/go.mod h1:QIE4lCeL7nkC25x+yA3LBIYfwCc1TFziCtG7cBAac6w= @@ -1632,7 +1623,6 @@ golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1812,7 +1802,6 @@ golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgw golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190706070813-72ffa07ba3db/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= -golang.org/x/tools v0.0.0-20190729092621-ff9f1409240a/go.mod h1:jcCCGcm9btYwXyDqrUWc6MKQKKGJCWEQ3AfLSRIbEuI= golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20190910044552-dd2b5c81c578/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -2128,12 +2117,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.3.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -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.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.13.1 h1:SRtFyV8Kxc0UP7aCHcijOMQGPxHSmMOPrzulQWolkYE= -gopkg.in/src-d/go-git.v4 v4.13.1/go.mod h1:nx5NYcxdKxq5fpltdHnPa2Exj4Sx0EclMWZQbYDu2z8= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= diff --git a/internal/registry/git_test.go b/internal/registry/git_test.go index e360f1692..476bf66f5 100644 --- a/internal/registry/git_test.go +++ b/internal/registry/git_test.go @@ -7,9 +7,9 @@ import ( "path/filepath" "testing" + "github.com/go-git/go-git/v5" "github.com/sclevine/spec" "github.com/sclevine/spec/report" - "gopkg.in/src-d/go-git.v4" "github.com/buildpacks/pack/internal/registry" "github.com/buildpacks/pack/pkg/logging" diff --git a/internal/registry/registry_cache.go b/internal/registry/registry_cache.go index 95c9862c6..adc8f666b 100644 --- a/internal/registry/registry_cache.go +++ b/internal/registry/registry_cache.go @@ -13,10 +13,10 @@ import ( "runtime" "time" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" "github.com/pkg/errors" "golang.org/x/mod/semver" - "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing/object" "github.com/buildpacks/pack/internal/style" "github.com/buildpacks/pack/pkg/buildpack" diff --git a/internal/registry/registry_cache_test.go b/internal/registry/registry_cache_test.go index 3bb0e9cc4..de1f3d038 100644 --- a/internal/registry/registry_cache_test.go +++ b/internal/registry/registry_cache_test.go @@ -10,11 +10,11 @@ import ( "testing" "time" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" "github.com/heroku/color" "github.com/sclevine/spec" "github.com/sclevine/spec/report" - "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing/object" "github.com/buildpacks/pack/pkg/logging" h "github.com/buildpacks/pack/testhelpers" diff --git a/testhelpers/registry.go b/testhelpers/registry.go index cd2d3efb8..ec3d6af4b 100644 --- a/testhelpers/registry.go +++ b/testhelpers/registry.go @@ -16,9 +16,9 @@ import ( dockertypes "github.com/docker/docker/api/types" dockercontainer "github.com/docker/docker/api/types/container" "github.com/docker/go-connections/nat" + "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" "golang.org/x/crypto/bcrypt" - "gopkg.in/src-d/go-git.v4" - "gopkg.in/src-d/go-git.v4/plumbing/object" "github.com/buildpacks/pack/pkg/archive" ) diff --git a/testhelpers/testhelpers.go b/testhelpers/testhelpers.go index 12a4d4a70..964274686 100644 --- a/testhelpers/testhelpers.go +++ b/testhelpers/testhelpers.go @@ -27,10 +27,10 @@ import ( "github.com/docker/docker/client" "github.com/docker/docker/pkg/jsonmessage" "github.com/docker/docker/pkg/stdcopy" + "github.com/go-git/go-git/v5" "github.com/google/go-cmp/cmp" "github.com/heroku/color" "github.com/pkg/errors" - "gopkg.in/src-d/go-git.v4" "github.com/buildpacks/pack/internal/stringset" "github.com/buildpacks/pack/internal/style"