diff --git a/README.md b/README.md index 6ebce9f63..17318ab62 100644 --- a/README.md +++ b/README.md @@ -64,21 +64,18 @@ Usage: kiln [options] [] --version, -v bool prints the kiln release version (default: false) Commands: - bake bakes a tile - cache-compiled-releases Cache compiled releases - fetch fetches releases - find-release-version prints a json string of a remote release satisfying the Kilnfile version and stemcell constraints - find-stemcell-version prints the latest stemcell version from Pivnet using the stemcell type listed in the Kilnfile - help prints this usage information - pre-process preprocess yaml files - publish publish tile on Pivnet - release-notes generates release notes from bosh-release release notes - sync-with-local update the Kilnfile.lock based on local releases - update-release bumps a release to a new version - update-stemcell updates stemcell and release information in Kilnfile.lock - upload-release uploads a BOSH release to an s3 release_source - validate validate Kilnfile and Kilnfile.lock - version prints the kiln release version + bake bakes a tile + cache-releases Cache compiled releases + create-release-notes generates release notes from bosh-release release notes + fetch-releases fetches releases + find-release-version prints a json string of a remote release satisfying the Kilnfile version and stemcell constraints + find-stemcell-version prints the latest stemcell version from Pivnet using the stemcell type listed in the Kilnfile + help prints this usage information + publish-release uploads a BOSH release to an s3 release_source + update-release bumps a release to a new version + update-stemcell updates stemcell and release information in Kilnfile.lock + validate validate Kilnfile and Kilnfile.lock + version prints the kiln release version ``` ### `fetch` diff --git a/go.mod b/go.mod index 6b8232bce..bae87db56 100644 --- a/go.mod +++ b/go.mod @@ -18,7 +18,6 @@ require ( github.com/onsi/ginkgo v1.16.4 github.com/onsi/gomega v1.18.1 github.com/pivotal-cf-experimental/gomegamatchers v0.0.0-20180326192815-e36bfcc98c3a - github.com/pivotal-cf/go-pivnet/v2 v2.0.11 github.com/pivotal-cf/jhanda v0.0.0-20200619200912-8de8eb943a43 github.com/pivotal-cf/om v0.0.0-20211027143906-30b10602e528 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 @@ -32,7 +31,6 @@ require ( github.com/Masterminds/goutils v1.1.1 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c // indirect - github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect github.com/VividCortex/ewma v1.1.1 // indirect github.com/acomagu/bufpipe v1.0.3 // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect @@ -47,7 +45,6 @@ require ( github.com/fatih/color v1.10.0 // indirect github.com/fsnotify/fsnotify v1.4.9 // indirect github.com/go-git/gcfg v1.5.0 // indirect - github.com/go-ole/go-ole v1.2.5 // indirect github.com/gofrs/uuid v4.0.0+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/go-querystring v1.1.0 // indirect @@ -74,18 +71,15 @@ require ( github.com/pkg/errors v0.9.1 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/sergi/go-diff v1.2.0 // indirect - github.com/shirou/gopsutil v3.21.1+incompatible // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/xanzy/ssh-agent v0.3.1 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect - golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4 // indirect golang.org/x/sys v0.0.0-20221006211917-84dc82d7e875 // indirect golang.org/x/text v0.3.7 // indirect golang.org/x/tools v0.1.12 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.26.0 // indirect - gopkg.in/cheggaaa/pb.v1 v1.0.28 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect ) diff --git a/go.sum b/go.sum index 0799d6eb2..0169394bf 100644 --- a/go.sum +++ b/go.sum @@ -80,7 +80,6 @@ github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/ github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c h1:FP7mMdsXy0ybzar1sJeIcZtaJka0U/ZmLTW4wRpolYk= github.com/ProtonMail/go-crypto v0.0.0-20210707164159-52430bf6b52c/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= -github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/VividCortex/ewma v1.1.1 h1:MnEK4VOv6n0RSY4vtRe3h11qjxL3+t0B8yOL8iMXdcM= github.com/VividCortex/ewma v1.1.1/go.mod h1:2Tkkvm3sRDVXaiyucHiACn4cqf7DpdyLvmxzcbUokwA= @@ -206,8 +205,6 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-ole/go-ole v0.0.0-20180625085808-7a0fa49edf48/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= -github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -456,8 +453,6 @@ github.com/pierrec/lz4 v2.6.0+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi github.com/pivotal-cf-experimental/gomegamatchers v0.0.0-20180326192815-e36bfcc98c3a h1:K20a2viyp6kZgY41ESLne0eOXyY9DarmwA4q6zQ686w= github.com/pivotal-cf-experimental/gomegamatchers v0.0.0-20180326192815-e36bfcc98c3a/go.mod h1:HdFegZwXOoRNyrqaOX6FC1zMkbA2k1/ktb2anj1E0K8= github.com/pivotal-cf/go-pivnet v1.0.3/go.mod h1:rvEzWli4NJQhX7Z3z0DiEQXsPwC+uE//eIKcpl7S1as= -github.com/pivotal-cf/go-pivnet/v2 v2.0.11 h1:6tzC4zOr7acFPevfP32+8rEU567JlDobqiIejFf8aOc= -github.com/pivotal-cf/go-pivnet/v2 v2.0.11/go.mod h1:Ormn4YO2MooU40LNFwECoLd8XZFwbRcysET+OAn7FLg= github.com/pivotal-cf/go-pivnet/v6 v6.0.2/go.mod h1:ymI4gZvp8lf3GNaf1Re+JRV18zU0w8TLBDQB/t8SaFs= github.com/pivotal-cf/jhanda v0.0.0-20200619200912-8de8eb943a43 h1:SYEUxVbqz3U7pJP/tlaXaD08w0rZVuPvCFRodnw/TLY= github.com/pivotal-cf/jhanda v0.0.0-20200619200912-8de8eb943a43/go.mod h1:UXciri1Yqno0IdXxEzwMF91nnwYMPoN95goHWxVtWq8= @@ -508,8 +503,6 @@ github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX github.com/shirou/gopsutil v0.0.0-20180927124308-a11c78ba2c13/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v2.20.2+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shirou/gopsutil v3.20.12+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= -github.com/shirou/gopsutil v3.21.1+incompatible h1:2LwXWdbjXwyDgq26Yy/OT4xozlpmssQfy/rtfhWb0bY= -github.com/shirou/gopsutil v3.21.1+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= @@ -689,8 +682,6 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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-20220722155255-886fb9371eb4 h1:uVc8UZUe6tr40fFVnUP5Oj+veunVezqYl9z7DYw9xzw= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180709060233-1b2967e3c290/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 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= @@ -918,7 +909,6 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/cheggaaa/pb.v1 v1.0.26/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= -gopkg.in/cheggaaa/pb.v1 v1.0.28 h1:n1tBJnnK2r7g9OW2btFH91V92STTUevLXYFb8gy9EMk= gopkg.in/cheggaaa/pb.v1 v1.0.28/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= diff --git a/internal/acceptance/workflows/baking_a_tile.feature b/internal/acceptance/workflows/baking_a_tile.feature index 5465912db..934e2e10b 100644 --- a/internal/acceptance/workflows/baking_a_tile.feature +++ b/internal/acceptance/workflows/baking_a_tile.feature @@ -3,7 +3,7 @@ Feature: As a developer, I want to bake a tile Given I have a "hello-tile" repository checked out at v0.1.1 And the repository has no fetched releases When I invoke kiln - | fetch | + | fetch-releases | | --no-confirm | | --variable=github_token="${GITHUB_TOKEN}" | And I invoke kiln diff --git a/internal/acceptance/workflows/caching_compiled_releases.feature b/internal/acceptance/workflows/caching_compiled_releases.feature index 606041825..1bbc18cd7 100644 --- a/internal/acceptance/workflows/caching_compiled_releases.feature +++ b/internal/acceptance/workflows/caching_compiled_releases.feature @@ -11,7 +11,7 @@ Feature: As a robot, I want to cache compiled releases And the environment variable "AWS_SECRET_ACCESS_KEY" is set And I remove all the objects in the bucket "hello-tile-releases" And I invoke kiln - | fetch | + | fetch-releases | | --variable=github_token="${GITHUB_TOKEN}" | And I invoke kiln | bake | @@ -20,13 +20,13 @@ Feature: As a robot, I want to cache compiled releases And I add a compiled s3 release-source "hello-tile-releases" to the Kilnfile And I set the stemcell version in the lock to match the one used for the tile When I invoke kiln - | cache-compiled-releases | + | cache-releases | | --upload-target-id=hello-tile-releases | | --name=hello | | --variable=github_token="${GITHUB_TOKEN}" | And the repository has no fetched releases And I invoke kiln - | fetch | + | fetch-releases | | --variable=github_token="${GITHUB_TOKEN}" | And I invoke kiln | bake | diff --git a/internal/acceptance/workflows/generating_release_notes.feature b/internal/acceptance/workflows/generating_release_notes.feature index 20e88bb84..45f36be81 100644 --- a/internal/acceptance/workflows/generating_release_notes.feature +++ b/internal/acceptance/workflows/generating_release_notes.feature @@ -10,7 +10,7 @@ Feature: As a robot, I want to generate release notes | 0.1.3 | When I invoke kiln - | release-notes | + | create-release-notes | | --release-date=2022-07-27 | | --github-issue-milestone=Release-2022-001 | | --update-docs=../scenario/fixtures/release_notes.md.erb | diff --git a/internal/acceptance/workflows/hello-tile b/internal/acceptance/workflows/hello-tile index 2cfa8e267..1a3861bea 160000 --- a/internal/acceptance/workflows/hello-tile +++ b/internal/acceptance/workflows/hello-tile @@ -1 +1 @@ -Subproject commit 2cfa8e26700d2295a9360fc312b8c3ab6a02e240 +Subproject commit 1a3861bea8b89a999cb006221bb22f692cfaa5bd diff --git a/internal/acceptance/workflows/scenario/initialize.go b/internal/acceptance/workflows/scenario/initialize.go index 2a059c0dd..6d622ee5d 100644 --- a/internal/acceptance/workflows/scenario/initialize.go +++ b/internal/acceptance/workflows/scenario/initialize.go @@ -90,6 +90,7 @@ func initializeExec(ctx scenarioContext) { }) ctx.Step(regexp.MustCompile(`^(stdout|stderr|"[^"]*") contains substring: (.*)`), outputContainsSubstring) ctx.Step(regexp.MustCompile(`^the exit code is (\d+)$`), theExitCodeIs) + ctx.Step(regexp.MustCompile(`^(stdout|stderr|"[^"]*") is valid (json|yaml)$`), outputIsValidEncoding) } func InitializeGitHub(ctx *godog.ScenarioContext) { initializeGitHub(ctx) } diff --git a/internal/acceptance/workflows/scenario/step_funcs_aws.go b/internal/acceptance/workflows/scenario/step_funcs_aws.go index 867ac7b03..083f24a39 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_aws.go +++ b/internal/acceptance/workflows/scenario/step_funcs_aws.go @@ -25,6 +25,9 @@ func iRemoveAllTheObjectsInBucket(ctx context.Context, bucket string) error { listErr := s3Session.ListObjectsV2PagesWithContext(ctx, &s3.ListObjectsV2Input{ Bucket: aws.String(bucket), }, func(page *s3.ListObjectsV2Output, b bool) bool { + if len(page.Contents) == 0 { + return false + } var del s3.Delete for _, o := range page.Contents { fmt.Printf(" deleting %s\n", aws.StringValue(o.Key)) diff --git a/internal/acceptance/workflows/scenario/step_funcs_exec.go b/internal/acceptance/workflows/scenario/step_funcs_exec.go index fce675b8a..2ff98555d 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_exec.go +++ b/internal/acceptance/workflows/scenario/step_funcs_exec.go @@ -2,9 +2,12 @@ package scenario import ( "context" + "encoding/json" "fmt" "strconv" "strings" + + "gopkg.in/yaml.v2" ) func outputContainsSubstring(ctx context.Context, outputName, substring string) error { @@ -38,3 +41,20 @@ func theExitCodeIs(ctx context.Context, expectedCode int) error { } return nil } + +func outputIsValidEncoding(ctx context.Context, outputName, encoding string) error { + out, err := output(ctx, outputName) + if err != nil { + return err + } + switch encoding { + case "json": + var raw json.RawMessage + return json.Unmarshal(out.Bytes(), &raw) + case "yaml": + var node interface{} + return yaml.Unmarshal(out.Bytes(), &node) + default: + return fmt.Errorf("unknown encoding: %s", encoding) + } +} diff --git a/internal/acceptance/workflows/scenario/step_funcs_exec_test.go b/internal/acceptance/workflows/scenario/step_funcs_exec_test.go index a44d6de5f..5310090b7 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_exec_test.go +++ b/internal/acceptance/workflows/scenario/step_funcs_exec_test.go @@ -5,40 +5,40 @@ import ( "os/exec" "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" ) func Test_outputContainsSubstring(t *testing.T) { t.Run("stdout contains the string", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) ctx := context.Background() ctx = configureStandardFileDescriptors(ctx) _, err := runAndLogOnError(ctx, exec.Command("echo", "Hello, world!"), true) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) err = outputContainsSubstring(ctx, "stdout", "world") - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }) t.Run("stderr contains the string", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) ctx := context.Background() ctx = configureStandardFileDescriptors(ctx) _, err := runAndLogOnError(ctx, exec.Command("bash", "-c", `echo "Hello, world!" > /dev/stderr`), true) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) err = outputContainsSubstring(ctx, "stderr", "world") - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }) t.Run("stdout does not contain the substring", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) ctx := context.Background() ctx = configureStandardFileDescriptors(ctx) _, err := runAndLogOnError(ctx, exec.Command("echo", "Hello, world!"), true) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) err = outputContainsSubstring(ctx, "stdout", "banana") - please.Expect(err).To(Ω.MatchError(Ω.Equal("expected substring \"banana\" not found in: \"Hello, world!\""))) + please.Expect(err).To(MatchError(Equal("expected substring \"banana\" not found in: \"Hello, world!\""))) }) } diff --git a/internal/acceptance/workflows/scenario/step_funcs_github_test.go b/internal/acceptance/workflows/scenario/step_funcs_github_test.go index 2852e8683..19827c7d4 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_github_test.go +++ b/internal/acceptance/workflows/scenario/step_funcs_github_test.go @@ -4,18 +4,18 @@ import ( "context" "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" ) func Test_githubRepoHasReleaseWithTag(t *testing.T) { if isRunningInCI() { t.Skip("skip this step in CI. GitHub action credentials do not have access to crhntr/hello-release") } - setup := func(t *testing.T) (context.Context, Ω.Gomega) { - please := Ω.NewWithT(t) + setup := func(t *testing.T) (context.Context, Gomega) { + please := NewWithT(t) ctx := context.Background() err := checkoutMain(testTilePath) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) ctx = setTileRepoPath(ctx, testTilePath) ctx, err = loadGithubToken(ctx) if err != nil { @@ -27,12 +27,12 @@ func Test_githubRepoHasReleaseWithTag(t *testing.T) { t.Run("release exists", func(t *testing.T) { ctx, please := setup(t) err := githubRepoHasReleaseWithTag(ctx, "crhntr", "hello-release", "v0.1.5") - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }) t.Run("release does not exist", func(t *testing.T) { ctx, please := setup(t) err := githubRepoHasReleaseWithTag(ctx, "crhntr", "hello-release", "v99.99.99-banana") - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) } diff --git a/internal/acceptance/workflows/scenario/step_funcs_tile.go b/internal/acceptance/workflows/scenario/step_funcs_tile.go index b6fd2ddaa..e1e2d3c2e 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_tile.go +++ b/internal/acceptance/workflows/scenario/step_funcs_tile.go @@ -13,7 +13,7 @@ import ( "gopkg.in/yaml.v2" "github.com/pivotal-cf/kiln/internal/component" - "github.com/pivotal-cf/kiln/pkg/proofing" + "github.com/pivotal-cf/kiln/internal/proofing" "github.com/pivotal-cf/kiln/pkg/tile" ) diff --git a/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go b/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go index fe75397fe..9997c6977 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go +++ b/internal/acceptance/workflows/scenario/step_funcs_tile_source_code.go @@ -3,13 +3,14 @@ package scenario import ( "context" "fmt" + "os" + "os/exec" + "strings" + "github.com/cucumber/godog" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "golang.org/x/exp/slices" - "os" - "os/exec" - "strings" "github.com/pivotal-cf/kiln/internal/component" "github.com/pivotal-cf/kiln/pkg/cargo" diff --git a/internal/acceptance/workflows/scenario/step_funcs_tile_test.go b/internal/acceptance/workflows/scenario/step_funcs_tile_test.go index 28ca0027c..f97e053fe 100644 --- a/internal/acceptance/workflows/scenario/step_funcs_tile_test.go +++ b/internal/acceptance/workflows/scenario/step_funcs_tile_test.go @@ -4,15 +4,15 @@ import ( "context" "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" ) func Test_theLockSpecifiesVersionForRelease(t *testing.T) { - setup := func(t *testing.T) (context.Context, Ω.Gomega) { - please := Ω.NewWithT(t) + setup := func(t *testing.T) (context.Context, Gomega) { + please := NewWithT(t) ctx := context.Background() err := checkoutMain(testTilePath) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) ctx = setTileRepoPath(ctx, testTilePath) return ctx, please } @@ -20,12 +20,12 @@ func Test_theLockSpecifiesVersionForRelease(t *testing.T) { t.Run("it matches the release version", func(t *testing.T) { ctx, please := setup(t) err := theLockSpecifiesVersionForRelease(ctx, "0.1.5", "hello-release") - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }) t.Run("it does not match the release version", func(t *testing.T) { ctx, please := setup(t) err := theLockSpecifiesVersionForRelease(ctx, "9000.0.0", "hello-release") - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) } diff --git a/internal/acceptance/workflows/updating_stemcell.feature b/internal/acceptance/workflows/updating_stemcell.feature index 07c3ae15a..d7f129cfa 100644 --- a/internal/acceptance/workflows/updating_stemcell.feature +++ b/internal/acceptance/workflows/updating_stemcell.feature @@ -6,15 +6,16 @@ Feature: As a dependabot, I want to update a stemcell Scenario: Find the new stemcell Given I have a "hello-tile" repository checked out at v0.1.5 - And TanzuNetwork has product "stemcells-ubuntu-xenial" with version "621.296" + And the environment variable "GITHUB_TOKEN" is set When I invoke kiln | find-stemcell-version | | --variable=github_token="${GITHUB_TOKEN}" | - Then stdout contains substring: "621.296" + Then stdout is valid json Scenario: Update the stemcell Given I have a "hello-tile" repository checked out at v0.1.5 - And TanzuNetwork has product "stemcells-ubuntu-xenial" with version "621.296" + And the environment variable "GITHUB_TOKEN" is set + And TanzuNetwork has product "stemcells-ubuntu-xenial" with version "621.280" And the Kilnfile.lock specifies version "621.0" for the stemcell When I invoke kiln | update-stemcell | diff --git a/internal/acceptance/workflows/using_kiln.feature b/internal/acceptance/workflows/using_kiln.feature index d4417ef4a..6c801c425 100644 --- a/internal/acceptance/workflows/using_kiln.feature +++ b/internal/acceptance/workflows/using_kiln.feature @@ -29,14 +29,12 @@ Feature: As a developer, I want the Kiln CLI to be usable Examples: | command | | bake | - | cache-compiled-releases | - | fetch | + | validate | + | cache-releases | + | fetch-releases | | find-release-version | | find-stemcell-version | - | publish | - | release-notes | - | sync-with-local | + | create-release-notes | | update-release | | update-stemcell | - | upload-release | - | validate | \ No newline at end of file + | publish-release | \ No newline at end of file diff --git a/internal/commands/bake.go b/internal/commands/bake.go index 1a390b0ef..b2467fa6b 100644 --- a/internal/commands/bake.go +++ b/internal/commands/bake.go @@ -64,7 +64,7 @@ type checksummer interface { Sum(path string) error } -func NewBake(fs billy.Filesystem, releasesService baking.ReleasesService, outLogger *log.Logger, errLogger *log.Logger) Bake { +func NewBake(fs billy.Filesystem, releasesService baking.ReleasesService, outLogger *log.Logger, errLogger *log.Logger) *Bake { filesystem := helper.NewFilesystem() zipper := builder.NewZipper() interpolator := builder.NewInterpolator() @@ -80,7 +80,7 @@ func NewBake(fs billy.Filesystem, releasesService baking.ReleasesService, outLog metadataService := baking.NewMetadataService() checksummer := baking.NewChecksummer(errLogger) - return Bake{ + return &Bake{ interpolator: interpolator, tileWriter: tileWriter, checksummer: checksummer, @@ -126,24 +126,24 @@ type Bake struct { Options struct { flags.Standard - Metadata string `short:"m" long:"metadata" default:"base.yml" description:"path to the metadata file"` - ReleaseDirectories []string `short:"rd" long:"releases-directory" default:"releases" description:"path to a directory containing release tarballs"` - FormDirectories []string `short:"f" long:"forms-directory" default:"forms" description:"path to a directory containing forms"` - IconPath string `short:"i" long:"icon" default:"icon.png" description:"path to icon file"` - InstanceGroupDirectories []string `short:"ig" long:"instance-groups-directory" default:"instance_groups" description:"path to a directory containing instance groups"` - JobDirectories []string `short:"j" long:"jobs-directory" default:"jobs" description:"path to a directory containing jobs"` - MigrationDirectories []string `short:"md" long:"migrations-directory" default:"migrations" description:"path to a directory containing migrations"` - PropertyDirectories []string `short:"pd" long:"properties-directory" default:"properties" description:"path to a directory containing property blueprints"` - RuntimeConfigDirectories []string `short:"rcd" long:"runtime-configs-directory" default:"runtime_configs" description:"path to a directory containing runtime configs"` - BOSHVariableDirectories []string `short:"vd" long:"bosh-variables-directory" default:"bosh_variables" description:"path to a directory containing BOSH variables"` - StemcellTarball string `short:"st" long:"stemcell-tarball" description:"deprecated -- path to a stemcell tarball (NOTE: mutually exclusive with --kilnfile)"` - StemcellsDirectories []string `short:"sd" long:"stemcells-directory" description:"path to a directory containing stemcells (NOTE: mutually exclusive with --kilnfile or --stemcell-tarball)"` - EmbedPaths []string `short:"e" long:"embed" description:"path to files to include in the tile /embed directory"` - OutputFile string `short:"o" long:"output-file" description:"path to where the tile will be output"` - MetadataOnly bool `short:"mo" long:"metadata-only" description:"don't build a tile, output the metadata to stdout"` - Sha256 bool ` long:"sha256" description:"calculates a SHA256 checksum of the output file"` - StubReleases bool `short:"sr" long:"stub-releases" description:"skips importing release tarballs into the tile"` - Version string `short:"v" long:"version" description:"version of the tile"` + Metadata string `short:"m" long:"metadata" default-path:"base.yml" description:"path to the metadata file"` + ReleaseDirectories []string `short:"rd" long:"releases-directory" default-path:"releases" description:"path to a directory containing release tarballs"` + FormDirectories []string `short:"f" long:"forms-directory" default-path:"forms" description:"path to a directory containing forms"` + IconPath string `short:"i" long:"icon" default-path:"icon.png" description:"path to icon file"` + InstanceGroupDirectories []string `short:"ig" long:"instance-groups-directory" default-path:"instance_groups" description:"path to a directory containing instance groups"` + JobDirectories []string `short:"j" long:"jobs-directory" default-path:"jobs" description:"path to a directory containing jobs"` + MigrationDirectories []string `short:"md" long:"migrations-directory" default-path:"migrations" description:"path to a directory containing migrations"` + PropertyDirectories []string `short:"pd" long:"properties-directory" default-path:"properties" description:"path to a directory containing property blueprints"` + RuntimeConfigDirectories []string `short:"rcd" long:"runtime-configs-directory" default-path:"runtime_configs" description:"path to a directory containing runtime configs"` + BOSHVariableDirectories []string `short:"vd" long:"bosh-variables-directory" default-path:"bosh_variables" description:"path to a directory containing BOSH variables"` + StemcellTarball string `short:"st" long:"stemcell-tarball" description:"deprecated -- path to a stemcell tarball (NOTE: mutually exclusive with --kilnfile)"` + StemcellsDirectories []string `short:"sd" long:"stemcells-directory" description:"path to a directory containing stemcells (NOTE: mutually exclusive with --kilnfile or --stemcell-tarball)"` + EmbedPaths []string `short:"e" long:"embed" description:"path to files to include in the tile /embed directory"` + OutputFile string `short:"o" long:"output-file" description:"path to where the tile will be output"` + MetadataOnly bool `short:"mo" long:"metadata-only" description:"don't build a tile, output the metadata to stdout"` + Sha256 bool ` long:"sha256" description:"calculates a SHA256 checksum of the output file"` + StubReleases bool `short:"sr" long:"stub-releases" description:"skips importing release tarballs into the tile"` + Version string `short:"v" long:"version" description:"version of the tile"` } } @@ -226,7 +226,7 @@ func (b *Bake) loadFlags(args []string, stat flags.StatFunc, readFile func(strin return nil } -func (b Bake) Execute(args []string) error { +func (b *Bake) Execute(args []string) error { err := b.loadFlags(args, os.Stat, os.ReadFile) if err != nil { return err @@ -371,7 +371,7 @@ func (b Bake) Execute(args []string) error { return nil } -func (b Bake) Usage() jhanda.Usage { +func (b *Bake) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Bakes tile metadata, stemcell, releases, and migrations into a format that can be consumed by OpsManager.", ShortDescription: "bakes a tile", diff --git a/internal/commands/bake_internal_test.go b/internal/commands/bake_internal_test.go index 59246ea4b..1a4656809 100644 --- a/internal/commands/bake_internal_test.go +++ b/internal/commands/bake_internal_test.go @@ -6,13 +6,13 @@ import ( "github.com/pivotal-cf/kiln/internal/builder" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" ) var _ metadataTemplatesParser = (*builder.MetadataPartsDirectoryReader)(nil) func TestBake_loadFlags_sets_reasonable_defaults(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -33,27 +33,27 @@ func TestBake_loadFlags_sets_reasonable_defaults(t *testing.T) { err := bake.loadFlags([]string{}, statNoError, readFile) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(bake.Options.Kilnfile).To(Ω.Equal("Kilnfile")) - please.Expect(bake.Options.Metadata).To(Ω.Equal("base.yml")) - please.Expect(bake.Options.IconPath).To(Ω.Equal("icon.png")) - please.Expect(bake.Options.OutputFile).To(Ω.Equal("tile-4.2.0.pivotal")) + please.Expect(bake.Options.Kilnfile).To(Equal("Kilnfile")) + please.Expect(bake.Options.Metadata).To(Equal("base.yml")) + please.Expect(bake.Options.IconPath).To(Equal("icon.png")) + please.Expect(bake.Options.OutputFile).To(Equal("tile-4.2.0.pivotal")) - please.Expect(bake.Options.ReleaseDirectories).To(Ω.Equal([]string{"releases"})) - please.Expect(bake.Options.FormDirectories).To(Ω.Equal([]string{"forms"})) - please.Expect(bake.Options.InstanceGroupDirectories).To(Ω.Equal([]string{"instance_groups"})) - please.Expect(bake.Options.JobDirectories).To(Ω.Equal([]string{"jobs"})) - please.Expect(bake.Options.MigrationDirectories).To(Ω.Equal([]string{"migrations"})) - please.Expect(bake.Options.PropertyDirectories).To(Ω.Equal([]string{"properties"})) - please.Expect(bake.Options.RuntimeConfigDirectories).To(Ω.Equal([]string{"runtime_configs"})) - please.Expect(bake.Options.BOSHVariableDirectories).To(Ω.Equal([]string{"bosh_variables"})) + please.Expect(bake.Options.ReleaseDirectories).To(Equal([]string{"releases"})) + please.Expect(bake.Options.FormDirectories).To(Equal([]string{"forms"})) + please.Expect(bake.Options.InstanceGroupDirectories).To(Equal([]string{"instance_groups"})) + please.Expect(bake.Options.JobDirectories).To(Equal([]string{"jobs"})) + please.Expect(bake.Options.MigrationDirectories).To(Equal([]string{"migrations"})) + please.Expect(bake.Options.PropertyDirectories).To(Equal([]string{"properties"})) + please.Expect(bake.Options.RuntimeConfigDirectories).To(Equal([]string{"runtime_configs"})) + please.Expect(bake.Options.BOSHVariableDirectories).To(Equal([]string{"bosh_variables"})) - please.Expect(readFileCallCount).To(Ω.Equal(1)) + please.Expect(readFileCallCount).To(Equal(1)) } func TestBake_loadFlags_kilnfile_path_provided(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -77,30 +77,30 @@ func TestBake_loadFlags_kilnfile_path_provided(t *testing.T) { "--forms-directory", "do-not-change", }, statNoError, readFile) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(bake.Options.Kilnfile).To(Ω.Equal("some-dir/Kilnfile")) + please.Expect(bake.Options.Kilnfile).To(Equal("some-dir/Kilnfile")) description := "it should prefix defaults with kiln path" - please.Expect(bake.Options.Metadata).To(Ω.Equal("some-dir/base.yml"), description) - please.Expect(bake.Options.IconPath).To(Ω.Equal("some-dir/icon.png"), description) - please.Expect(bake.Options.OutputFile).To(Ω.Equal("tile-4.2.0.pivotal")) + please.Expect(bake.Options.Metadata).To(Equal("some-dir/base.yml"), description) + please.Expect(bake.Options.IconPath).To(Equal("some-dir/icon.png"), description) + please.Expect(bake.Options.OutputFile).To(Equal("tile-4.2.0.pivotal")) - please.Expect(bake.Options.FormDirectories).To(Ω.Equal([]string{"do-not-change"}), "it should not prefix explicitly passed flags") + please.Expect(bake.Options.FormDirectories).To(Equal([]string{"do-not-change"}), "it should not prefix explicitly passed flags") - please.Expect(bake.Options.ReleaseDirectories).To(Ω.Equal([]string{"some-dir/releases"}), description) - please.Expect(bake.Options.InstanceGroupDirectories).To(Ω.Equal([]string{"some-dir/instance_groups"}), description) - please.Expect(bake.Options.JobDirectories).To(Ω.Equal([]string{"some-dir/jobs"}), description) - please.Expect(bake.Options.MigrationDirectories).To(Ω.Equal([]string{"some-dir/migrations"}), description) - please.Expect(bake.Options.PropertyDirectories).To(Ω.Equal([]string{"some-dir/properties"}), description) - please.Expect(bake.Options.RuntimeConfigDirectories).To(Ω.Equal([]string{"some-dir/runtime_configs"}), description) - please.Expect(bake.Options.BOSHVariableDirectories).To(Ω.Equal([]string{"some-dir/bosh_variables"}), description) + please.Expect(bake.Options.ReleaseDirectories).To(Equal([]string{"some-dir/releases"}), description) + please.Expect(bake.Options.InstanceGroupDirectories).To(Equal([]string{"some-dir/instance_groups"}), description) + please.Expect(bake.Options.JobDirectories).To(Equal([]string{"some-dir/jobs"}), description) + please.Expect(bake.Options.MigrationDirectories).To(Equal([]string{"some-dir/migrations"}), description) + please.Expect(bake.Options.PropertyDirectories).To(Equal([]string{"some-dir/properties"}), description) + please.Expect(bake.Options.RuntimeConfigDirectories).To(Equal([]string{"some-dir/runtime_configs"}), description) + please.Expect(bake.Options.BOSHVariableDirectories).To(Equal([]string{"some-dir/bosh_variables"}), description) - please.Expect(readFileCallCount).To(Ω.Equal(1)) + please.Expect(readFileCallCount).To(Equal(1)) } func TestBake_loadFlags_sets_empty_options_when_default_is_not_applicable(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -111,24 +111,24 @@ func TestBake_loadFlags_sets_empty_options_when_default_is_not_applicable(t *tes err := bake.loadFlags([]string{}, statError, readError) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(bake.Options.Kilnfile).To(Ω.Equal("")) - please.Expect(bake.Options.Metadata).To(Ω.Equal("")) - please.Expect(bake.Options.Version).To(Ω.Equal("")) + please.Expect(bake.Options.Kilnfile).To(Equal("")) + please.Expect(bake.Options.Metadata).To(Equal("")) + please.Expect(bake.Options.Version).To(Equal("")) - please.Expect(bake.Options.ReleaseDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.FormDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.InstanceGroupDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.JobDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.MigrationDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.PropertyDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.RuntimeConfigDirectories).To(Ω.HaveLen(0)) - please.Expect(bake.Options.BOSHVariableDirectories).To(Ω.HaveLen(0)) + please.Expect(bake.Options.ReleaseDirectories).To(HaveLen(0)) + please.Expect(bake.Options.FormDirectories).To(HaveLen(0)) + please.Expect(bake.Options.InstanceGroupDirectories).To(HaveLen(0)) + please.Expect(bake.Options.JobDirectories).To(HaveLen(0)) + please.Expect(bake.Options.MigrationDirectories).To(HaveLen(0)) + please.Expect(bake.Options.PropertyDirectories).To(HaveLen(0)) + please.Expect(bake.Options.RuntimeConfigDirectories).To(HaveLen(0)) + please.Expect(bake.Options.BOSHVariableDirectories).To(HaveLen(0)) } func TestBake_loadFlags_does_not_override_provided_flags(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -175,28 +175,28 @@ func TestBake_loadFlags_does_not_override_provided_flags(t *testing.T) { "--bosh-variables-directory", "bosh-variables-directory-2", }, statError, readNotFound) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(bake.Options.Kilnfile).To(Ω.Equal("kilnfile")) - please.Expect(bake.Options.Metadata).To(Ω.Equal("metadata")) - please.Expect(bake.Options.IconPath).To(Ω.Equal("icon")) - please.Expect(bake.Options.Version).To(Ω.Equal("4.2.0")) - please.Expect(bake.Options.OutputFile).To(Ω.Equal("some-tile.pivotal")) + please.Expect(bake.Options.Kilnfile).To(Equal("kilnfile")) + please.Expect(bake.Options.Metadata).To(Equal("metadata")) + please.Expect(bake.Options.IconPath).To(Equal("icon")) + please.Expect(bake.Options.Version).To(Equal("4.2.0")) + please.Expect(bake.Options.OutputFile).To(Equal("some-tile.pivotal")) - please.Expect(bake.Options.ReleaseDirectories).To(Ω.Equal([]string{"releases-directory-1", "releases-directory-2"})) - please.Expect(bake.Options.FormDirectories).To(Ω.Equal([]string{"forms-directory-1", "forms-directory-2"})) - please.Expect(bake.Options.InstanceGroupDirectories).To(Ω.Equal([]string{"instance-groups-directory-1", "instance-groups-directory-2"})) - please.Expect(bake.Options.JobDirectories).To(Ω.Equal([]string{"jobs-directory-1", "jobs-directory-2"})) - please.Expect(bake.Options.MigrationDirectories).To(Ω.Equal([]string{"migrations-directory-1", "migrations-directory-2"})) - please.Expect(bake.Options.PropertyDirectories).To(Ω.Equal([]string{"properties-directory-1", "properties-directory-2"})) - please.Expect(bake.Options.RuntimeConfigDirectories).To(Ω.Equal([]string{"runtime-configs-directory-1", "runtime-configs-directory-2"})) - please.Expect(bake.Options.BOSHVariableDirectories).To(Ω.Equal([]string{"bosh-variables-directory-1", "bosh-variables-directory-2"})) + please.Expect(bake.Options.ReleaseDirectories).To(Equal([]string{"releases-directory-1", "releases-directory-2"})) + please.Expect(bake.Options.FormDirectories).To(Equal([]string{"forms-directory-1", "forms-directory-2"})) + please.Expect(bake.Options.InstanceGroupDirectories).To(Equal([]string{"instance-groups-directory-1", "instance-groups-directory-2"})) + please.Expect(bake.Options.JobDirectories).To(Equal([]string{"jobs-directory-1", "jobs-directory-2"})) + please.Expect(bake.Options.MigrationDirectories).To(Equal([]string{"migrations-directory-1", "migrations-directory-2"})) + please.Expect(bake.Options.PropertyDirectories).To(Equal([]string{"properties-directory-1", "properties-directory-2"})) + please.Expect(bake.Options.RuntimeConfigDirectories).To(Equal([]string{"runtime-configs-directory-1", "runtime-configs-directory-2"})) + please.Expect(bake.Options.BOSHVariableDirectories).To(Equal([]string{"bosh-variables-directory-1", "bosh-variables-directory-2"})) - please.Expect(readFileCallCount).To(Ω.Equal(0)) + please.Expect(readFileCallCount).To(Equal(0)) } func TestBake_loadFlags_sets_default_output_file_if_not_set(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -217,13 +217,13 @@ func TestBake_loadFlags_sets_default_output_file_if_not_set(t *testing.T) { err := bake.loadFlags([]string{}, statNoError, readFile) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(bake.Options.OutputFile).To(Ω.Equal("tile-1.2.3.pivotal")) - please.Expect(readFileCallCount).To(Ω.Equal(1)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(bake.Options.OutputFile).To(Equal("tile-1.2.3.pivotal")) + please.Expect(readFileCallCount).To(Equal(1)) } func TestBake_loadFlags_does_not_set_outputs_file_when_meta_data_only_is_true(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -236,12 +236,12 @@ func TestBake_loadFlags_does_not_set_outputs_file_when_meta_data_only_is_true(t "--metadata-only", }, statNoError, readFileError) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(bake.Options.OutputFile).To(Ω.Equal("")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(bake.Options.OutputFile).To(Equal("")) } func TestBake_loadFlags_version_file_does_not_exist(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ( bake Bake @@ -256,5 +256,5 @@ func TestBake_loadFlags_version_file_does_not_exist(t *testing.T) { err := bake.loadFlags([]string{}, statError, readFileError) - please.Expect(err).NotTo(Ω.HaveOccurred(), "it should not return an error") + please.Expect(err).NotTo(HaveOccurred(), "it should not return an error") } diff --git a/internal/commands/cache_compiled_releases.go b/internal/commands/cache_releases.go similarity index 88% rename from internal/commands/cache_compiled_releases.go rename to internal/commands/cache_releases.go index 290f1be8e..a91e35121 100644 --- a/internal/commands/cache_compiled_releases.go +++ b/internal/commands/cache_releases.go @@ -39,14 +39,14 @@ type ( } ) -type CacheCompiledReleases struct { +type CacheReleases struct { Options struct { flags.Standard om.ClientConfiguration - UploadTargetID string ` long:"upload-target-id" required:"true" description:"the ID of the release source where the built release will be uploaded"` - ReleasesDir string `short:"rd" long:"releases-directory" default:"releases" description:"path to a directory to download releases into"` - Name string `short:"n" long:"name" default:"cf" description:"name of the tile"` // TODO: parse from base.yml + UploadTargetID string ` long:"upload-target-id" required:"true" description:"the ID of the release source where the built release will be uploaded"` + ReleasesDir string `short:"rd" long:"releases-directory" default-path:"releases" description:"path to a directory to download releases into"` + Name string `short:"n" long:"name" default:"cf" description:"name of the tile"` // TODO: parse from base.yml } Logger *log.Logger @@ -57,8 +57,8 @@ type CacheCompiledReleases struct { Director func(om.ClientConfiguration, om.GetBoshEnvironmentAndSecurityRootCACertificateProvider) (boshdir.Director, error) } -func NewCacheCompiledReleases() *CacheCompiledReleases { - cmd := &CacheCompiledReleases{ +func NewCacheReleases() *CacheReleases { + cmd := &CacheReleases{ FS: osfs.New(""), Logger: log.Default(), } @@ -80,7 +80,7 @@ func NewCacheCompiledReleases() *CacheCompiledReleases { return cmd } -func (cmd *CacheCompiledReleases) WithLogger(logger *log.Logger) *CacheCompiledReleases { +func (cmd *CacheReleases) WithLogger(logger *log.Logger) *CacheReleases { if logger == nil { logger = log.New(io.Discard, "", 0) } @@ -88,7 +88,7 @@ func (cmd *CacheCompiledReleases) WithLogger(logger *log.Logger) *CacheCompiledR return cmd } -func (cmd CacheCompiledReleases) Execute(args []string) error { +func (cmd *CacheReleases) Execute(args []string) error { _, err := flags.LoadFlagsWithDefaults(&cmd.Options, args, cmd.FS.Stat) if err != nil { return err @@ -265,7 +265,7 @@ func hasRequiredCompiledPackages(d boshdir.Director, releaseSlug boshdir.Release return false, nil } -func (cmd CacheCompiledReleases) fetchProductDeploymentData() (_ OpsManagerReleaseCacheSource, deploymentName, stemcellOS, stemcellVersion string, _ error) { +func (cmd *CacheReleases) fetchProductDeploymentData() (_ OpsManagerReleaseCacheSource, deploymentName, stemcellOS, stemcellVersion string, _ error) { omAPI, err := cmd.OpsManager(cmd.Options.ClientConfiguration) if err != nil { return nil, "", "", "", err @@ -301,7 +301,7 @@ func (cmd CacheCompiledReleases) fetchProductDeploymentData() (_ OpsManagerRelea return omAPI, manifest.Name, stagedStemcell.OS, stagedStemcell.Version, nil } -func (cmd CacheCompiledReleases) cacheRelease(bosh boshdir.Director, rc ReleaseStorage, deployment boshdir.Deployment, releaseSlug boshdir.ReleaseSlug, stemcellSlug boshdir.OSVersionSlug) (component.Lock, error) { +func (cmd *CacheReleases) cacheRelease(bosh boshdir.Director, rc ReleaseStorage, deployment boshdir.Deployment, releaseSlug boshdir.ReleaseSlug, stemcellSlug boshdir.OSVersionSlug) (component.Lock, error) { cmd.Logger.Printf("\texporting %s\n", releaseSlug) result, err := deployment.ExportRelease(releaseSlug, stemcellSlug, nil) if err != nil { @@ -353,7 +353,7 @@ func updateLock(lock cargo.KilnfileLock, release component.Lock, targetID string return fmt.Errorf("existing release not found in Kilnfile.lock") } -func (cmd *CacheCompiledReleases) uploadLocalRelease(spec component.Spec, fp string, uploader ReleaseStorage) (component.Lock, error) { +func (cmd *CacheReleases) uploadLocalRelease(spec component.Spec, fp string, uploader ReleaseStorage) (component.Lock, error) { f, err := cmd.FS.Open(fp) if err != nil { return component.Lock{}, err @@ -362,7 +362,7 @@ func (cmd *CacheCompiledReleases) uploadLocalRelease(spec component.Spec, fp str return uploader.UploadRelease(spec, f) } -func (cmd *CacheCompiledReleases) saveReleaseLocally(director boshdir.Director, relDir string, releaseSlug boshdir.ReleaseSlug, stemcellSlug boshdir.OSVersionSlug, res boshdir.ExportReleaseResult) (string, string, string, error) { +func (cmd *CacheReleases) saveReleaseLocally(director boshdir.Director, relDir string, releaseSlug boshdir.ReleaseSlug, stemcellSlug boshdir.OSVersionSlug, res boshdir.ExportReleaseResult) (string, string, string, error) { fileName := fmt.Sprintf("%s-%s-%s-%s.tgz", releaseSlug.Name(), releaseSlug.Version(), stemcellSlug.OS(), stemcellSlug.Version()) filePath := filepath.Join(relDir, fileName) @@ -393,7 +393,7 @@ func (cmd *CacheCompiledReleases) saveReleaseLocally(director boshdir.Director, return filePath, sha256sumString, sha1sumString, nil } -func (cmd CacheCompiledReleases) downloadAndComputeSHA(cache component.ReleaseSource, remote cargo.ComponentLock) (string, error) { +func (cmd *CacheReleases) downloadAndComputeSHA(cache component.ReleaseSource, remote cargo.ComponentLock) (string, error) { if remote.SHA1 != "" { return remote.SHA1, nil } @@ -417,7 +417,7 @@ func (cmd CacheCompiledReleases) downloadAndComputeSHA(cache component.ReleaseSo return comp.SHA1, nil } -func (cmd CacheCompiledReleases) Usage() jhanda.Usage { +func (cmd *CacheReleases) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Downloads compiled bosh releases from an Tanzu Ops Manager bosh director and then uploads them to a bucket", ShortDescription: "Cache compiled releases", diff --git a/internal/commands/cache_compiled_releases_test.go b/internal/commands/cache_releases_test.go similarity index 77% rename from internal/commands/cache_compiled_releases_test.go rename to internal/commands/cache_releases_test.go index dd5627083..c4abe8a26 100644 --- a/internal/commands/cache_compiled_releases_test.go +++ b/internal/commands/cache_releases_test.go @@ -9,9 +9,7 @@ import ( "testing" "github.com/cloudfoundry/bosh-cli/director" - boshdirFakes "github.com/cloudfoundry/bosh-cli/director/directorfakes" "github.com/go-git/go-billy/v5/memfs" - Ω "github.com/onsi/gomega" "github.com/pivotal-cf/jhanda" "github.com/pivotal-cf/kiln/internal/commands" @@ -19,23 +17,26 @@ import ( "github.com/pivotal-cf/kiln/internal/component" "github.com/pivotal-cf/kiln/internal/om" "github.com/pivotal-cf/kiln/pkg/cargo" + + boshdirFakes "github.com/cloudfoundry/bosh-cli/director/directorfakes" + . "github.com/onsi/gomega" ) -var _ jhanda.Command = (*commands.CacheCompiledReleases)(nil) +var _ jhanda.Command = (*commands.CacheReleases)(nil) func TestNewCacheCompiledReleases(t *testing.T) { - please := Ω.NewWithT(t) - cmd := commands.NewCacheCompiledReleases() - please.Expect(cmd).NotTo(Ω.BeNil()) - please.Expect(cmd.Logger).NotTo(Ω.BeNil()) - please.Expect(cmd.FS).NotTo(Ω.BeNil()) - please.Expect(cmd.ReleaseSourceAndCache).NotTo(Ω.BeNil()) - please.Expect(cmd.OpsManager).NotTo(Ω.BeNil()) - please.Expect(cmd.Director).NotTo(Ω.BeNil()) + please := NewWithT(t) + cmd := commands.NewCacheReleases() + please.Expect(cmd).NotTo(BeNil()) + please.Expect(cmd.Logger).NotTo(BeNil()) + please.Expect(cmd.FS).NotTo(BeNil()) + please.Expect(cmd.ReleaseSourceAndCache).NotTo(BeNil()) + please.Expect(cmd.OpsManager).NotTo(BeNil()) + please.Expect(cmd.Director).NotTo(BeNil()) } func TestCacheCompiledReleases_Execute_all_releases_are_already_compiled(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // setup @@ -47,7 +48,7 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_compiled(t *test ID: "compiled-releases", }, }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) please.Expect(fsWriteYAML(fs, "Kilnfile.lock", cargo.KilnfileLock{ Releases: []cargo.ComponentLock{ { @@ -62,7 +63,7 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_compiled(t *test OS: "alpine", Version: "9.0.0", }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) opsManager := new(fakes.OpsManagerReleaseCacheSource) opsManager.GetStagedProductManifestReturns(`{"name": "cf-some-id", "stemcells": [{"os": "alpine", "version": "9.0.0"}]}`, nil) @@ -77,7 +78,7 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_compiled(t *test var output bytes.Buffer logger := log.New(&output, "", 0) - cmd := commands.CacheCompiledReleases{ + cmd := commands.CacheReleases{ FS: fs, Logger: logger, ReleaseSourceAndCache: func(kilnfile cargo.Kilnfile, targetID string) (commands.ReleaseStorage, error) { @@ -99,12 +100,12 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_compiled(t *test // check - please.Expect(output.String()).To(Ω.ContainSubstring("cache already contains releases")) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(output.String()).To(ContainSubstring("cache already contains releases")) + please.Expect(err).NotTo(HaveOccurred()) } func TestCacheCompiledReleases_Execute_all_releases_are_already_cached(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // setup @@ -116,7 +117,7 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_cached(t *testin ID: "compiled-releases", }, }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) please.Expect(fsWriteYAML(fs, "Kilnfile.lock", cargo.KilnfileLock{ Releases: []cargo.ComponentLock{ { @@ -133,7 +134,7 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_cached(t *testin OS: "alpine", Version: "9.0.0", }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) opsManager := new(fakes.OpsManagerReleaseCacheSource) opsManager.GetStagedProductManifestReturns(`{"name": "cf-some-id", "stemcells": [{"os": "alpine", "version": "9.0.0"}]}`, nil) @@ -148,7 +149,7 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_cached(t *testin var output bytes.Buffer logger := log.New(&output, "", 0) - cmd := commands.CacheCompiledReleases{ + cmd := commands.CacheReleases{ FS: fs, Logger: logger, ReleaseSourceAndCache: func(kilnfile cargo.Kilnfile, targetID string) (commands.ReleaseStorage, error) { @@ -170,12 +171,12 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_cached(t *testin // check - please.Expect(output.String()).To(Ω.ContainSubstring("cache already contains releases")) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(output.String()).To(ContainSubstring("cache already contains releases")) + please.Expect(err).NotTo(HaveOccurred()) var updatedKilnfile cargo.KilnfileLock - please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(Ω.HaveOccurred()) - please.Expect(updatedKilnfile.Releases).To(Ω.ContainElement(component.Lock{ + please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(HaveOccurred()) + please.Expect(updatedKilnfile.Releases).To(ContainElement(component.Lock{ Name: "orange", Version: "1.0.0", SHA1: "fake-checksum", RemoteSource: "cached-compiled-releases", @@ -184,13 +185,13 @@ func TestCacheCompiledReleases_Execute_all_releases_are_already_cached(t *testin } // this test covers -// - an export, download, upload, and lock of a non-cached release -// - an update the kilnfile with a non-locked release cached in the database -// (the release is cached on s3 but not set in the lock file) -// - ignoring a locked and cached release -// (the release is cached on the s3 bucket and the lock already has that value in it) +// - an export, download, upload, and lock of a non-cached release +// - an update the kilnfile with a non-locked release cached in the database +// (the release is cached on s3 but not set in the lock file) +// - ignoring a locked and cached release +// (the release is cached on the s3 bucket and the lock already has that value in it) func TestCacheCompiledReleases_Execute_when_one_release_is_cached_another_is_already_compiled_and_another_is_already_locked(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // setup @@ -209,7 +210,7 @@ func TestCacheCompiledReleases_Execute_when_one_release_is_cached_another_is_alr PathTemplate: "{{.Release}}-{{.Version}}.tgz", }, }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) please.Expect(fsWriteYAML(fs, "Kilnfile.lock", cargo.KilnfileLock{ Releases: []cargo.ComponentLock{ { @@ -244,7 +245,7 @@ func TestCacheCompiledReleases_Execute_when_one_release_is_cached_another_is_alr OS: "alpine", Version: "9.0.0", }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) opsManager := new(fakes.OpsManagerReleaseCacheSource) opsManager.GetStagedProductManifestReturns(`{"name": "cf-some-id", "stemcells": [{"os": "alpine", "version": "9.0.0"}]}`, nil) @@ -293,7 +294,7 @@ func TestCacheCompiledReleases_Execute_when_one_release_is_cached_another_is_alr var output bytes.Buffer logger := log.New(&output, "", 0) - cmd := commands.CacheCompiledReleases{ + cmd := commands.CacheReleases{ FS: fs, Logger: logger, ReleaseSourceAndCache: func(kilnfile cargo.Kilnfile, targetID string) (commands.ReleaseStorage, error) { @@ -315,26 +316,26 @@ func TestCacheCompiledReleases_Execute_when_one_release_is_cached_another_is_alr // check - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(releaseStorage.GetMatchedReleaseCallCount()).To(Ω.Equal(3)) - please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Ω.Equal(1)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(releaseStorage.GetMatchedReleaseCallCount()).To(Equal(3)) + please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Equal(1)) requestedID, _ := bosh.DownloadResourceUncheckedArgsForCall(0) - please.Expect(requestedID).To(Ω.Equal("some-blob-id")) + please.Expect(requestedID).To(Equal("some-blob-id")) - please.Expect(output.String()).To(Ω.ContainSubstring("1 release needs to be exported and cached")) - please.Expect(output.String()).To(Ω.ContainSubstring("lemon/3.0.0 compiled with alpine/9.0.0 not found in cache")) - please.Expect(output.String()).To(Ω.ContainSubstring("exporting from bosh deployment cf-some-id")) - please.Expect(output.String()).To(Ω.ContainSubstring("exporting lemon")) - please.Expect(output.String()).To(Ω.ContainSubstring("downloading lemon")) - please.Expect(output.String()).To(Ω.ContainSubstring("uploading lemon")) - please.Expect(output.String()).To(Ω.ContainSubstring("DON'T FORGET TO MAKE A COMMIT AND PR")) + please.Expect(output.String()).To(ContainSubstring("1 release needs to be exported and cached")) + please.Expect(output.String()).To(ContainSubstring("lemon/3.0.0 compiled with alpine/9.0.0 not found in cache")) + please.Expect(output.String()).To(ContainSubstring("exporting from bosh deployment cf-some-id")) + please.Expect(output.String()).To(ContainSubstring("exporting lemon")) + please.Expect(output.String()).To(ContainSubstring("downloading lemon")) + please.Expect(output.String()).To(ContainSubstring("uploading lemon")) + please.Expect(output.String()).To(ContainSubstring("DON'T FORGET TO MAKE A COMMIT AND PR")) - please.Expect(uploadedRelease.String()).To(Ω.Equal(string(releaseInBlobstore))) + please.Expect(uploadedRelease.String()).To(Equal(string(releaseInBlobstore))) var updatedKilnfile cargo.KilnfileLock - please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(Ω.HaveOccurred()) - please.Expect(updatedKilnfile.Releases).To(Ω.ContainElement(component.Lock{ + please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(HaveOccurred()) + please.Expect(updatedKilnfile.Releases).To(ContainElement(component.Lock{ Name: "lemon", Version: "3.0.0", SHA1: "012ed191f1d07c14bbcbbc0423d0de1c56757348", @@ -349,7 +350,7 @@ func TestCacheCompiledReleases_Execute_when_one_release_is_cached_another_is_alr // - export release returns a broken bosh release because we requested the wrong compilation target and the director didn't have the source code necessarily to re-compile against the requested stemcell // - (ideally bosh export-release should return an error but in this case it doesn't so we are just checking for a release with the correct stemcell before downloading a bad one) func TestCacheCompiledReleases_Execute_when_a_release_is_not_compiled_with_the_correct_stemcell(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // setup @@ -368,7 +369,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_is_not_compiled_with_the_c PathTemplate: "{{.Release}}-{{.Version}}.tgz", }, }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) please.Expect(fsWriteYAML(fs, "Kilnfile.lock", cargo.KilnfileLock{ Releases: []cargo.ComponentLock{ { @@ -385,7 +386,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_is_not_compiled_with_the_c OS: "alpine", Version: "8.0.0", }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) opsManager := new(fakes.OpsManagerReleaseCacheSource) opsManager.GetStagedProductManifestReturns(`{"name": "cf-some-id", "stemcells": [{"os": "alpine", "version": "8.0.0"}]}`, nil) @@ -413,7 +414,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_is_not_compiled_with_the_c var output bytes.Buffer logger := log.New(&output, "", 0) - cmd := commands.CacheCompiledReleases{ + cmd := commands.CacheReleases{ FS: fs, Logger: logger, ReleaseSourceAndCache: func(kilnfile cargo.Kilnfile, targetID string) (commands.ReleaseStorage, error) { @@ -435,27 +436,27 @@ func TestCacheCompiledReleases_Execute_when_a_release_is_not_compiled_with_the_c // check - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("not found on bosh director"))) + please.Expect(err).To(MatchError(ContainSubstring("not found on bosh director"))) - please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Ω.Equal(0)) - please.Expect(bosh.HasReleaseCallCount()).To(Ω.Equal(0)) - please.Expect(bosh.FindReleaseCallCount()).To(Ω.Equal(1)) + please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Equal(0)) + please.Expect(bosh.HasReleaseCallCount()).To(Equal(0)) + please.Expect(bosh.FindReleaseCallCount()).To(Equal(1)) { requestedReleaseSlug := bosh.FindReleaseArgsForCall(0) - please.Expect(requestedReleaseSlug.Name()).To(Ω.Equal("banana")) - please.Expect(requestedReleaseSlug.Version()).To(Ω.Equal("2.0.0")) + please.Expect(requestedReleaseSlug.Name()).To(Equal("banana")) + please.Expect(requestedReleaseSlug.Version()).To(Equal("2.0.0")) } - please.Expect(output.String()).To(Ω.ContainSubstring("1 release needs to be exported and cached")) - please.Expect(output.String()).To(Ω.ContainSubstring("banana/2.0.0 compiled with alpine/8.0.0 not found in cache")) - please.Expect(output.String()).To(Ω.ContainSubstring("exporting from bosh deployment cf-some-id")) - please.Expect(output.String()).NotTo(Ω.ContainSubstring("exporting lemon")) - please.Expect(output.String()).NotTo(Ω.ContainSubstring("DON'T FORGET TO MAKE A COMMIT AND PR")) + please.Expect(output.String()).To(ContainSubstring("1 release needs to be exported and cached")) + please.Expect(output.String()).To(ContainSubstring("banana/2.0.0 compiled with alpine/8.0.0 not found in cache")) + please.Expect(output.String()).To(ContainSubstring("exporting from bosh deployment cf-some-id")) + please.Expect(output.String()).NotTo(ContainSubstring("exporting lemon")) + please.Expect(output.String()).NotTo(ContainSubstring("DON'T FORGET TO MAKE A COMMIT AND PR")) var updatedKilnfile cargo.KilnfileLock - please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(Ω.HaveOccurred()) - please.Expect(updatedKilnfile.Releases).To(Ω.ContainElement(component.Lock{ + please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(HaveOccurred()) + please.Expect(updatedKilnfile.Releases).To(ContainElement(component.Lock{ Name: "banana", Version: "2.0.0", @@ -469,7 +470,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_is_not_compiled_with_the_c // this test covers // - when a release does not contain packages func TestCacheCompiledReleases_Execute_when_a_release_has_no_packages(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // setup @@ -493,7 +494,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_has_no_packages(t *testing Name: "banana", }, }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) please.Expect(fsWriteYAML(fs, "Kilnfile.lock", cargo.KilnfileLock{ Releases: []cargo.ComponentLock{ { @@ -510,7 +511,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_has_no_packages(t *testing OS: "alpine", Version: "8.0.0", }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) opsManager := new(fakes.OpsManagerReleaseCacheSource) opsManager.GetStagedProductManifestReturns(`{"name": "cf-some-id", "stemcells": [{"os": "alpine", "version": "8.0.0"}]}`, nil) @@ -548,7 +549,7 @@ func TestCacheCompiledReleases_Execute_when_a_release_has_no_packages(t *testing var output bytes.Buffer logger := log.New(&output, "", 0) - cmd := commands.CacheCompiledReleases{ + cmd := commands.CacheReleases{ FS: fs, Logger: logger, ReleaseSourceAndCache: func(kilnfile cargo.Kilnfile, targetID string) (commands.ReleaseStorage, error) { @@ -570,25 +571,25 @@ func TestCacheCompiledReleases_Execute_when_a_release_has_no_packages(t *testing // check - please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Ω.Equal(1)) - please.Expect(bosh.HasReleaseCallCount()).To(Ω.Equal(0)) - please.Expect(bosh.FindReleaseCallCount()).To(Ω.Equal(1)) + please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Equal(1)) + please.Expect(bosh.HasReleaseCallCount()).To(Equal(0)) + please.Expect(bosh.FindReleaseCallCount()).To(Equal(1)) { requestedReleaseSlug := bosh.FindReleaseArgsForCall(0) - please.Expect(requestedReleaseSlug.Name()).To(Ω.Equal("banana")) - please.Expect(requestedReleaseSlug.Version()).To(Ω.Equal("2.0.0")) + please.Expect(requestedReleaseSlug.Name()).To(Equal("banana")) + please.Expect(requestedReleaseSlug.Version()).To(Equal("2.0.0")) } - please.Expect(output.String()).To(Ω.ContainSubstring("1 release needs to be exported and cached")) - please.Expect(output.String()).To(Ω.ContainSubstring("banana/2.0.0 compiled with alpine/8.0.0 not found in cache")) - please.Expect(output.String()).To(Ω.ContainSubstring("exporting from bosh deployment cf-some-id")) - please.Expect(output.String()).To(Ω.ContainSubstring("oes not have any packages")) - please.Expect(output.String()).To(Ω.ContainSubstring("exporting banana")) + please.Expect(output.String()).To(ContainSubstring("1 release needs to be exported and cached")) + please.Expect(output.String()).To(ContainSubstring("banana/2.0.0 compiled with alpine/8.0.0 not found in cache")) + please.Expect(output.String()).To(ContainSubstring("exporting from bosh deployment cf-some-id")) + please.Expect(output.String()).To(ContainSubstring("oes not have any packages")) + please.Expect(output.String()).To(ContainSubstring("exporting banana")) var updatedKilnfile cargo.KilnfileLock - please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(Ω.HaveOccurred()) - please.Expect(updatedKilnfile.Releases).To(Ω.ContainElement(component.Lock{ + please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedKilnfile)).NotTo(HaveOccurred()) + please.Expect(updatedKilnfile.Releases).To(ContainElement(component.Lock{ Name: "banana", Version: "2.0.0", @@ -598,13 +599,13 @@ func TestCacheCompiledReleases_Execute_when_a_release_has_no_packages(t *testing SHA1: "fake-checksum", }), "it should not override the in-correct element in the Kilnfile.lock") - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(output.String()).To(Ω.ContainSubstring("DON'T FORGET TO MAKE A COMMIT AND PR")) + please.Expect(output.String()).To(ContainSubstring("DON'T FORGET TO MAKE A COMMIT AND PR")) } func TestCacheCompiledReleases_Execute_staged_and_lock_stemcells_are_not_the_same(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // setup @@ -623,7 +624,7 @@ func TestCacheCompiledReleases_Execute_staged_and_lock_stemcells_are_not_the_sam PathTemplate: "{{.Release}}-{{.Version}}.tgz", }, }, - })).NotTo(Ω.HaveOccurred()) + })).NotTo(HaveOccurred()) initialLock := cargo.KilnfileLock{ Releases: []component.Lock{ { @@ -657,7 +658,7 @@ func TestCacheCompiledReleases_Execute_staged_and_lock_stemcells_are_not_the_sam Version: "9.0.0", }, } - please.Expect(fsWriteYAML(fs, "Kilnfile.lock", initialLock)).NotTo(Ω.HaveOccurred()) + please.Expect(fsWriteYAML(fs, "Kilnfile.lock", initialLock)).NotTo(HaveOccurred()) opsManager := new(fakes.OpsManagerReleaseCacheSource) opsManager.GetStagedProductManifestReturns(`{"name": "cf-some-id", "stemcells": [{"os": "alpine", "version": "9.0.1"}]}`, nil) @@ -667,7 +668,7 @@ func TestCacheCompiledReleases_Execute_staged_and_lock_stemcells_are_not_the_sam bosh := new(boshdirFakes.FakeDirector) - cmd := commands.CacheCompiledReleases{ + cmd := commands.CacheReleases{ FS: fs, ReleaseSourceAndCache: func(kilnfile cargo.Kilnfile, targetID string) (commands.ReleaseStorage, error) { return releaseCache, nil @@ -688,13 +689,13 @@ func TestCacheCompiledReleases_Execute_staged_and_lock_stemcells_are_not_the_sam // check - please.Expect(releaseCache.GetMatchedReleaseCallCount()).To(Ω.Equal(0)) - please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Ω.Equal(0)) - please.Expect(err).To(Ω.MatchError(Ω.Equal("staged stemcell (alpine 9.0.1) and lock stemcell (alpine 9.0.0) do not match"))) + please.Expect(releaseCache.GetMatchedReleaseCallCount()).To(Equal(0)) + please.Expect(bosh.DownloadResourceUncheckedCallCount()).To(Equal(0)) + please.Expect(err).To(MatchError(Equal("staged stemcell (alpine 9.0.1) and lock stemcell (alpine 9.0.0) do not match"))) var updatedLock cargo.KilnfileLock - please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedLock)).NotTo(Ω.HaveOccurred()) - please.Expect(updatedLock).To(Ω.Equal(initialLock)) + please.Expect(fsReadYAML(fs, "Kilnfile.lock", &updatedLock)).NotTo(HaveOccurred()) + please.Expect(updatedLock).To(Equal(initialLock)) } func fakeCacheData(spec component.Spec) (component.Lock, error) { diff --git a/internal/commands/release_notes.go b/internal/commands/create_release_notes.go similarity index 85% rename from internal/commands/release_notes.go rename to internal/commands/create_release_notes.go index 5b61afd24..0197fd6b7 100644 --- a/internal/commands/release_notes.go +++ b/internal/commands/create_release_notes.go @@ -15,13 +15,13 @@ import ( "text/template" "time" - "github.com/pivotal-cf/kiln/internal/gh" - "github.com/go-git/go-git/v5" "github.com/google/go-github/v40/github" "github.com/pivotal-cf/jhanda" + "github.com/pivotal-cf/kiln/internal/component" - "github.com/pivotal-cf/kiln/internal/release" + "github.com/pivotal-cf/kiln/internal/gh" + "github.com/pivotal-cf/kiln/pkg/notes" ) const releaseDateFormat = "2006-01-02" @@ -33,7 +33,7 @@ type ReleaseNotes struct { GithubToken string `long:"github-token" short:"g" description:"auth token for fetching issues merged between releases" env:"GITHUB_TOKEN"` Kilnfile string `long:"kilnfile" short:"k" description:"path to Kilnfile"` DocsFile string `long:"update-docs" short:"u" description:"path to docs file to update"` - release.IssuesQuery + notes.IssuesQuery } repository *git.Repository @@ -46,18 +46,18 @@ type ReleaseNotes struct { repoOwner, repoName string } -type FetchNotesData func(ctx context.Context, repo *git.Repository, client *github.Client, tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision string, issuesQuery release.IssuesQuery) (release.NotesData, error) +type FetchNotesData func(ctx context.Context, repo *git.Repository, client *github.Client, tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision string, issuesQuery notes.IssuesQuery) (notes.Data, error) -func NewReleaseNotesCommand() (ReleaseNotes, error) { - return ReleaseNotes{ - fetchNotesData: release.FetchNotesData, +func NewReleaseNotesCommand() *ReleaseNotes { + return &ReleaseNotes{ + fetchNotesData: notes.FetchNotesData, readFile: os.ReadFile, Writer: os.Stdout, stat: os.Stat, - }, nil + } } -func (r ReleaseNotes) Usage() jhanda.Usage { +func (r *ReleaseNotes) Usage() jhanda.Usage { return jhanda.Usage{ Description: "generates release notes from bosh-release release notes on GitHub between two tile repo git references", ShortDescription: "generates release notes from bosh-release release notes", @@ -65,7 +65,7 @@ func (r ReleaseNotes) Usage() jhanda.Usage { } } -func (r ReleaseNotes) Execute(args []string) error { +func (r *ReleaseNotes) Execute(args []string) error { ctx := context.Background() if err := r.initRepo(); err != nil { @@ -87,7 +87,7 @@ func (r ReleaseNotes) Execute(args []string) error { client = gh.Client(ctx, r.Options.GithubToken) } - _ = release.FetchNotesData // fetchNotesData is FetchNotesData + _ = notes.FetchNotesData // fetchNotesData is FetchNotesData data, err := r.fetchNotesData(ctx, r.repository, client, r.repoOwner, r.repoName, r.Options.Kilnfile, @@ -112,13 +112,13 @@ func (r ReleaseNotes) Execute(args []string) error { return r.updateDocsFile(data) } -func (r *ReleaseNotes) updateDocsFile(data release.NotesData) error { +func (r *ReleaseNotes) updateDocsFile(data notes.Data) error { // TODO: add helpful logging docsFileContent, err := r.readFile(r.Options.DocsFile) if err != nil { return err } - page, err := release.ParseNotesPage(string(docsFileContent)) + page, err := notes.ParseNotesPage(string(docsFileContent)) if err != nil { return err } @@ -184,8 +184,8 @@ func (r *ReleaseNotes) initRepo() error { return nil } -func (r ReleaseNotes) writeNotes(w io.Writer, info release.NotesData) error { - releaseNotesTemplate := release.DefaultNotesTemplate() +func (r *ReleaseNotes) writeNotes(w io.Writer, info notes.Data) error { + releaseNotesTemplate := notes.DefaultNotesTemplate() if r.Options.TemplateName != "" { templateBuf, err := r.readFile(r.Options.TemplateName) if err != nil { @@ -194,7 +194,7 @@ func (r ReleaseNotes) writeNotes(w io.Writer, info release.NotesData) error { releaseNotesTemplate = string(templateBuf) } - t, err := release.DefaultTemplateFuncs(template.New(r.Options.TemplateName)).Parse(releaseNotesTemplate) + t, err := notes.DefaultTemplateFunctions(template.New(r.Options.TemplateName)).Parse(releaseNotesTemplate) if err != nil { return fmt.Errorf("failed to parse template: %w", err) } @@ -207,7 +207,7 @@ func (r ReleaseNotes) writeNotes(w io.Writer, info release.NotesData) error { return nil } -func (r ReleaseNotes) checkInputs(nonFlagArgs []string) error { +func (r *ReleaseNotes) checkInputs(nonFlagArgs []string) error { if len(nonFlagArgs) != 2 { return errors.New("expected two arguments: ") } @@ -241,7 +241,7 @@ func (r ReleaseNotes) checkInputs(nonFlagArgs []string) error { return nil } -func (r ReleaseNotes) parseReleaseDate() (time.Time, error) { +func (r *ReleaseNotes) parseReleaseDate() (time.Time, error) { var releaseDate time.Time if r.Options.ReleaseDate != "" { diff --git a/internal/commands/release_notes_test.go b/internal/commands/create_release_notes_test.go similarity index 66% rename from internal/commands/release_notes_test.go rename to internal/commands/create_release_notes_test.go index 956d8c60d..990a56a1c 100644 --- a/internal/commands/release_notes_test.go +++ b/internal/commands/create_release_notes_test.go @@ -7,10 +7,7 @@ import ( "testing" "time" - "github.com/pivotal-cf/kiln/internal/component" - "github.com/pivotal-cf/kiln/pkg/cargo" - - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" "github.com/Masterminds/semver" "github.com/go-git/go-billy/v5/memfs" @@ -20,19 +17,21 @@ import ( "github.com/google/go-github/v40/github" "github.com/pivotal-cf/jhanda" - "github.com/pivotal-cf/kiln/internal/release" + "github.com/pivotal-cf/kiln/internal/component" + "github.com/pivotal-cf/kiln/pkg/cargo" + "github.com/pivotal-cf/kiln/pkg/notes" ) -var _ jhanda.Command = ReleaseNotes{} +var _ jhanda.Command = (*ReleaseNotes)(nil) func TestReleaseNotes_Usage(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} - please.Expect(rn.Usage().Description).NotTo(Ω.BeEmpty()) - please.Expect(rn.Usage().ShortDescription).NotTo(Ω.BeEmpty()) - please.Expect(rn.Usage().Flags).NotTo(Ω.BeNil()) + please.Expect(rn.Usage().Description).NotTo(BeEmpty()) + please.Expect(rn.Usage().ShortDescription).NotTo(BeEmpty()) + please.Expect(rn.Usage().Flags).NotTo(BeNil()) } //go:embed testdata/release_notes_output.md @@ -47,10 +46,10 @@ func TestReleaseNotes_Execute(t *testing.T) { return tm } - please := Ω.NewWithT(t) + please := NewWithT(t) nonNilRepo, _ := git.Init(memory.NewStorage(), memfs.New()) - please.Expect(nonNilRepo).NotTo(Ω.BeNil()) + please.Expect(nonNilRepo).NotTo(BeNil()) readFileCount := 0 readFileFunc := func(string) ([]byte, error) { @@ -61,7 +60,7 @@ func TestReleaseNotes_Execute(t *testing.T) { var ( tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision string - issuesQuery release.IssuesQuery + issuesQuery notes.IssuesQuery repository *git.Repository client *github.Client ctx context.Context @@ -74,11 +73,11 @@ func TestReleaseNotes_Execute(t *testing.T) { repoOwner: "bunch", repoName: "banana", readFile: readFileFunc, - fetchNotesData: func(c context.Context, repo *git.Repository, ghc *github.Client, tro, trn, kfp, ir, fr string, iq release.IssuesQuery) (release.NotesData, error) { + fetchNotesData: func(c context.Context, repo *git.Repository, ghc *github.Client, tro, trn, kfp, ir, fr string, iq notes.IssuesQuery) (notes.Data, error) { ctx, repository, client = c, repo, ghc tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision = tro, trn, kfp, ir, fr issuesQuery = iq - return release.NotesData{ + return notes.Data{ ReleaseDate: mustParseTime(time.Parse(releaseDateFormat, "2021-11-04")), Version: semver.MustParse("0.1.0-build.50000"), Issues: []*github.Issue{ @@ -88,7 +87,7 @@ func TestReleaseNotes_Execute(t *testing.T) { Stemcell: cargo.Stemcell{ OS: "fruit-tree", Version: "40000.2", }, - Components: []release.ComponentData{ + Components: []notes.ComponentData{ {Lock: cargo.ComponentLock{Name: "banana", Version: "1.2.0"}, Releases: []*github.RepositoryRelease{ {TagName: strPtr("1.2.0"), Body: strPtr("peal\nis\nyellow")}, {TagName: strPtr("1.1.1"), Body: strPtr("remove from bunch")}, @@ -116,24 +115,24 @@ func TestReleaseNotes_Execute(t *testing.T) { "tile/1.1.0", "tile/1.2.0", }) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(ctx).NotTo(Ω.BeNil()) - please.Expect(repository).NotTo(Ω.BeNil()) - please.Expect(client).NotTo(Ω.BeNil()) + please.Expect(ctx).NotTo(BeNil()) + please.Expect(repository).NotTo(BeNil()) + please.Expect(client).NotTo(BeNil()) - please.Expect(tileRepoOwner).To(Ω.Equal("bunch")) - please.Expect(tileRepoName).To(Ω.Equal("banana")) - please.Expect(kilnfilePath).To(Ω.Equal("tile/Kilnfile")) - please.Expect(initialRevision).To(Ω.Equal("tile/1.1.0")) - please.Expect(finalRevision).To(Ω.Equal("tile/1.2.0")) + please.Expect(tileRepoOwner).To(Equal("bunch")) + please.Expect(tileRepoName).To(Equal("banana")) + please.Expect(kilnfilePath).To(Equal("tile/Kilnfile")) + please.Expect(initialRevision).To(Equal("tile/1.1.0")) + please.Expect(finalRevision).To(Equal("tile/1.2.0")) - please.Expect(issuesQuery.IssueMilestone).To(Ω.Equal("smoothie")) - please.Expect(issuesQuery.IssueIDs).To(Ω.Equal([]string{"54000", "54321"})) - please.Expect(issuesQuery.IssueLabels).To(Ω.Equal([]string{"tropical", "20000"})) + please.Expect(issuesQuery.IssueMilestone).To(Equal("smoothie")) + please.Expect(issuesQuery.IssueIDs).To(Equal([]string{"54000", "54321"})) + please.Expect(issuesQuery.IssueLabels).To(Equal([]string{"tropical", "20000"})) t.Log(out.String()) - please.Expect(out.String()).To(Ω.Equal(releaseNotesExpectedOutput)) + please.Expect(out.String()).To(Equal(releaseNotesExpectedOutput)) }) t.Run("when updating a docs file", func(t *testing.T) { @@ -144,90 +143,90 @@ func TestReleaseNotes_checkInputs(t *testing.T) { t.Parallel() t.Run("missing args", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} err := rn.checkInputs(nil) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("expected two arguments"))) + please.Expect(err).To(MatchError(ContainSubstring("expected two arguments"))) }) t.Run("missing arg", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} err := rn.checkInputs([]string{"some-hash"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("expected two arguments"))) + please.Expect(err).To(MatchError(ContainSubstring("expected two arguments"))) }) t.Run("too many args", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} err := rn.checkInputs([]string{"a", "b", "c"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("expected two arguments"))) + please.Expect(err).To(MatchError(ContainSubstring("expected two arguments"))) }) t.Run("too many args", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} err := rn.checkInputs([]string{"a", "b", "c"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("expected two arguments"))) + please.Expect(err).To(MatchError(ContainSubstring("expected two arguments"))) }) t.Run("bad issue title expression", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} rn.Options.IssueTitleExp = `\` err := rn.checkInputs([]string{"a", "b"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("expression"))) + please.Expect(err).To(MatchError(ContainSubstring("expression"))) }) t.Run("malformed release date", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} rn.Options.ReleaseDate = `some-date` err := rn.checkInputs([]string{"a", "b"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("cannot parse"))) + please.Expect(err).To(MatchError(ContainSubstring("cannot parse"))) }) t.Run("issue flag without auth", func(t *testing.T) { t.Run("milestone", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} rn.Options.IssueMilestone = "s" err := rn.checkInputs([]string{"a", "b"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("github-token"))) + please.Expect(err).To(MatchError(ContainSubstring("github-token"))) }) t.Run("ids", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} rn.Options.IssueIDs = []string{"s"} err := rn.checkInputs([]string{"a", "b"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("github-token"))) + please.Expect(err).To(MatchError(ContainSubstring("github-token"))) }) t.Run("labels", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} rn.Options.IssueLabels = []string{"s"} err := rn.checkInputs([]string{"a", "b"}) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("github-token"))) + please.Expect(err).To(MatchError(ContainSubstring("github-token"))) }) t.Run("exp", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) rn := ReleaseNotes{} rn.Options.IssueTitleExp = "s" err := rn.checkInputs([]string{"a", "b"}) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }) }) } @@ -235,7 +234,7 @@ func TestReleaseNotes_checkInputs(t *testing.T) { func Test_getGithubRemoteRepoOwnerAndName(t *testing.T) { t.Parallel() t.Run("when there is a github http remote", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) repo, _ := git.Init(memory.NewStorage(), memfs.New()) _, _ = repo.CreateRemote(&config.RemoteConfig{ @@ -245,13 +244,13 @@ func Test_getGithubRemoteRepoOwnerAndName(t *testing.T) { }, }) o, r, err := getGithubRemoteRepoOwnerAndName(repo) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(o).To(Ω.Equal("pivotal-cf")) - please.Expect(r).To(Ω.Equal("kiln")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(o).To(Equal("pivotal-cf")) + please.Expect(r).To(Equal("kiln")) }) t.Run("when there is a github ssh remote", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) repo, _ := git.Init(memory.NewStorage(), memfs.New()) _, _ = repo.CreateRemote(&config.RemoteConfig{ @@ -261,21 +260,21 @@ func Test_getGithubRemoteRepoOwnerAndName(t *testing.T) { }, }) o, r, err := getGithubRemoteRepoOwnerAndName(repo) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(o).To(Ω.Equal("pivotal-cf")) - please.Expect(r).To(Ω.Equal("kiln")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(o).To(Equal("pivotal-cf")) + please.Expect(r).To(Equal("kiln")) }) t.Run("when there are no remotes", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) repo, _ := git.Init(memory.NewStorage(), memfs.New()) _, _, err := getGithubRemoteRepoOwnerAndName(repo) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("not found"))) + please.Expect(err).To(MatchError(ContainSubstring("not found"))) }) t.Run("when there are many remotes", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) repo, _ := git.Init(memory.NewStorage(), memfs.New()) _, _ = repo.CreateRemote(&config.RemoteConfig{ @@ -291,8 +290,8 @@ func Test_getGithubRemoteRepoOwnerAndName(t *testing.T) { }, }) o, _, err := getGithubRemoteRepoOwnerAndName(repo) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(o).To(Ω.Equal("pivotal-cf"), "it uses the remote with name 'origin'") + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(o).To(Equal("pivotal-cf"), "it uses the remote with name 'origin'") }) } diff --git a/internal/commands/fakes/pivnet_product_files_service.go b/internal/commands/fakes/pivnet_product_files_service.go deleted file mode 100644 index dd7484452..000000000 --- a/internal/commands/fakes/pivnet_product_files_service.go +++ /dev/null @@ -1,195 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "sync" - - pivnet "github.com/pivotal-cf/go-pivnet/v2" - "github.com/pivotal-cf/kiln/internal/commands" -) - -type PivnetProductFilesService struct { - AddToReleaseStub func(string, int, int) error - addToReleaseMutex sync.RWMutex - addToReleaseArgsForCall []struct { - arg1 string - arg2 int - arg3 int - } - addToReleaseReturns struct { - result1 error - } - addToReleaseReturnsOnCall map[int]struct { - result1 error - } - ListStub func(string) ([]pivnet.ProductFile, error) - listMutex sync.RWMutex - listArgsForCall []struct { - arg1 string - } - listReturns struct { - result1 []pivnet.ProductFile - result2 error - } - listReturnsOnCall map[int]struct { - result1 []pivnet.ProductFile - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *PivnetProductFilesService) AddToRelease(arg1 string, arg2 int, arg3 int) error { - fake.addToReleaseMutex.Lock() - ret, specificReturn := fake.addToReleaseReturnsOnCall[len(fake.addToReleaseArgsForCall)] - fake.addToReleaseArgsForCall = append(fake.addToReleaseArgsForCall, struct { - arg1 string - arg2 int - arg3 int - }{arg1, arg2, arg3}) - stub := fake.AddToReleaseStub - fakeReturns := fake.addToReleaseReturns - fake.recordInvocation("AddToRelease", []interface{}{arg1, arg2, arg3}) - fake.addToReleaseMutex.Unlock() - if stub != nil { - return stub(arg1, arg2, arg3) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *PivnetProductFilesService) AddToReleaseCallCount() int { - fake.addToReleaseMutex.RLock() - defer fake.addToReleaseMutex.RUnlock() - return len(fake.addToReleaseArgsForCall) -} - -func (fake *PivnetProductFilesService) AddToReleaseCalls(stub func(string, int, int) error) { - fake.addToReleaseMutex.Lock() - defer fake.addToReleaseMutex.Unlock() - fake.AddToReleaseStub = stub -} - -func (fake *PivnetProductFilesService) AddToReleaseArgsForCall(i int) (string, int, int) { - fake.addToReleaseMutex.RLock() - defer fake.addToReleaseMutex.RUnlock() - argsForCall := fake.addToReleaseArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 -} - -func (fake *PivnetProductFilesService) AddToReleaseReturns(result1 error) { - fake.addToReleaseMutex.Lock() - defer fake.addToReleaseMutex.Unlock() - fake.AddToReleaseStub = nil - fake.addToReleaseReturns = struct { - result1 error - }{result1} -} - -func (fake *PivnetProductFilesService) AddToReleaseReturnsOnCall(i int, result1 error) { - fake.addToReleaseMutex.Lock() - defer fake.addToReleaseMutex.Unlock() - fake.AddToReleaseStub = nil - if fake.addToReleaseReturnsOnCall == nil { - fake.addToReleaseReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.addToReleaseReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *PivnetProductFilesService) List(arg1 string) ([]pivnet.ProductFile, error) { - fake.listMutex.Lock() - ret, specificReturn := fake.listReturnsOnCall[len(fake.listArgsForCall)] - fake.listArgsForCall = append(fake.listArgsForCall, struct { - arg1 string - }{arg1}) - stub := fake.ListStub - fakeReturns := fake.listReturns - fake.recordInvocation("List", []interface{}{arg1}) - fake.listMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PivnetProductFilesService) ListCallCount() int { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - return len(fake.listArgsForCall) -} - -func (fake *PivnetProductFilesService) ListCalls(stub func(string) ([]pivnet.ProductFile, error)) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = stub -} - -func (fake *PivnetProductFilesService) ListArgsForCall(i int) string { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - argsForCall := fake.listArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *PivnetProductFilesService) ListReturns(result1 []pivnet.ProductFile, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - fake.listReturns = struct { - result1 []pivnet.ProductFile - result2 error - }{result1, result2} -} - -func (fake *PivnetProductFilesService) ListReturnsOnCall(i int, result1 []pivnet.ProductFile, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - if fake.listReturnsOnCall == nil { - fake.listReturnsOnCall = make(map[int]struct { - result1 []pivnet.ProductFile - result2 error - }) - } - fake.listReturnsOnCall[i] = struct { - result1 []pivnet.ProductFile - result2 error - }{result1, result2} -} - -func (fake *PivnetProductFilesService) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.addToReleaseMutex.RLock() - defer fake.addToReleaseMutex.RUnlock() - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *PivnetProductFilesService) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ commands.PivnetProductFilesService = new(PivnetProductFilesService) diff --git a/internal/commands/fakes/pivnet_release_dependencies_service.go b/internal/commands/fakes/pivnet_release_dependencies_service.go deleted file mode 100644 index 43840debe..000000000 --- a/internal/commands/fakes/pivnet_release_dependencies_service.go +++ /dev/null @@ -1,119 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "sync" - - pivnet "github.com/pivotal-cf/go-pivnet/v2" - "github.com/pivotal-cf/kiln/internal/commands" -) - -type PivnetReleaseDependenciesService struct { - ListStub func(string, int) ([]pivnet.ReleaseDependency, error) - listMutex sync.RWMutex - listArgsForCall []struct { - arg1 string - arg2 int - } - listReturns struct { - result1 []pivnet.ReleaseDependency - result2 error - } - listReturnsOnCall map[int]struct { - result1 []pivnet.ReleaseDependency - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *PivnetReleaseDependenciesService) List(arg1 string, arg2 int) ([]pivnet.ReleaseDependency, error) { - fake.listMutex.Lock() - ret, specificReturn := fake.listReturnsOnCall[len(fake.listArgsForCall)] - fake.listArgsForCall = append(fake.listArgsForCall, struct { - arg1 string - arg2 int - }{arg1, arg2}) - stub := fake.ListStub - fakeReturns := fake.listReturns - fake.recordInvocation("List", []interface{}{arg1, arg2}) - fake.listMutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PivnetReleaseDependenciesService) ListCallCount() int { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - return len(fake.listArgsForCall) -} - -func (fake *PivnetReleaseDependenciesService) ListCalls(stub func(string, int) ([]pivnet.ReleaseDependency, error)) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = stub -} - -func (fake *PivnetReleaseDependenciesService) ListArgsForCall(i int) (string, int) { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - argsForCall := fake.listArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *PivnetReleaseDependenciesService) ListReturns(result1 []pivnet.ReleaseDependency, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - fake.listReturns = struct { - result1 []pivnet.ReleaseDependency - result2 error - }{result1, result2} -} - -func (fake *PivnetReleaseDependenciesService) ListReturnsOnCall(i int, result1 []pivnet.ReleaseDependency, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - if fake.listReturnsOnCall == nil { - fake.listReturnsOnCall = make(map[int]struct { - result1 []pivnet.ReleaseDependency - result2 error - }) - } - fake.listReturnsOnCall[i] = struct { - result1 []pivnet.ReleaseDependency - result2 error - }{result1, result2} -} - -func (fake *PivnetReleaseDependenciesService) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *PivnetReleaseDependenciesService) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ commands.PivnetReleaseDependenciesService = new(PivnetReleaseDependenciesService) diff --git a/internal/commands/fakes/pivnet_release_upgrade_paths_service.go b/internal/commands/fakes/pivnet_release_upgrade_paths_service.go deleted file mode 100644 index 0670c2d1f..000000000 --- a/internal/commands/fakes/pivnet_release_upgrade_paths_service.go +++ /dev/null @@ -1,119 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "sync" - - pivnet "github.com/pivotal-cf/go-pivnet/v2" - "github.com/pivotal-cf/kiln/internal/commands" -) - -type PivnetReleaseUpgradePathsService struct { - GetStub func(string, int) ([]pivnet.ReleaseUpgradePath, error) - getMutex sync.RWMutex - getArgsForCall []struct { - arg1 string - arg2 int - } - getReturns struct { - result1 []pivnet.ReleaseUpgradePath - result2 error - } - getReturnsOnCall map[int]struct { - result1 []pivnet.ReleaseUpgradePath - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *PivnetReleaseUpgradePathsService) Get(arg1 string, arg2 int) ([]pivnet.ReleaseUpgradePath, error) { - fake.getMutex.Lock() - ret, specificReturn := fake.getReturnsOnCall[len(fake.getArgsForCall)] - fake.getArgsForCall = append(fake.getArgsForCall, struct { - arg1 string - arg2 int - }{arg1, arg2}) - stub := fake.GetStub - fakeReturns := fake.getReturns - fake.recordInvocation("Get", []interface{}{arg1, arg2}) - fake.getMutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PivnetReleaseUpgradePathsService) GetCallCount() int { - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() - return len(fake.getArgsForCall) -} - -func (fake *PivnetReleaseUpgradePathsService) GetCalls(stub func(string, int) ([]pivnet.ReleaseUpgradePath, error)) { - fake.getMutex.Lock() - defer fake.getMutex.Unlock() - fake.GetStub = stub -} - -func (fake *PivnetReleaseUpgradePathsService) GetArgsForCall(i int) (string, int) { - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() - argsForCall := fake.getArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *PivnetReleaseUpgradePathsService) GetReturns(result1 []pivnet.ReleaseUpgradePath, result2 error) { - fake.getMutex.Lock() - defer fake.getMutex.Unlock() - fake.GetStub = nil - fake.getReturns = struct { - result1 []pivnet.ReleaseUpgradePath - result2 error - }{result1, result2} -} - -func (fake *PivnetReleaseUpgradePathsService) GetReturnsOnCall(i int, result1 []pivnet.ReleaseUpgradePath, result2 error) { - fake.getMutex.Lock() - defer fake.getMutex.Unlock() - fake.GetStub = nil - if fake.getReturnsOnCall == nil { - fake.getReturnsOnCall = make(map[int]struct { - result1 []pivnet.ReleaseUpgradePath - result2 error - }) - } - fake.getReturnsOnCall[i] = struct { - result1 []pivnet.ReleaseUpgradePath - result2 error - }{result1, result2} -} - -func (fake *PivnetReleaseUpgradePathsService) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *PivnetReleaseUpgradePathsService) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ commands.PivnetReleaseUpgradePathsService = new(PivnetReleaseUpgradePathsService) diff --git a/internal/commands/fakes/pivnet_releases_service.go b/internal/commands/fakes/pivnet_releases_service.go deleted file mode 100644 index 563562a5a..000000000 --- a/internal/commands/fakes/pivnet_releases_service.go +++ /dev/null @@ -1,198 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "sync" - - pivnet "github.com/pivotal-cf/go-pivnet/v2" - "github.com/pivotal-cf/kiln/internal/commands" -) - -type PivnetReleasesService struct { - ListStub func(string) ([]pivnet.Release, error) - listMutex sync.RWMutex - listArgsForCall []struct { - arg1 string - } - listReturns struct { - result1 []pivnet.Release - result2 error - } - listReturnsOnCall map[int]struct { - result1 []pivnet.Release - result2 error - } - UpdateStub func(string, pivnet.Release) (pivnet.Release, error) - updateMutex sync.RWMutex - updateArgsForCall []struct { - arg1 string - arg2 pivnet.Release - } - updateReturns struct { - result1 pivnet.Release - result2 error - } - updateReturnsOnCall map[int]struct { - result1 pivnet.Release - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *PivnetReleasesService) List(arg1 string) ([]pivnet.Release, error) { - fake.listMutex.Lock() - ret, specificReturn := fake.listReturnsOnCall[len(fake.listArgsForCall)] - fake.listArgsForCall = append(fake.listArgsForCall, struct { - arg1 string - }{arg1}) - stub := fake.ListStub - fakeReturns := fake.listReturns - fake.recordInvocation("List", []interface{}{arg1}) - fake.listMutex.Unlock() - if stub != nil { - return stub(arg1) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PivnetReleasesService) ListCallCount() int { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - return len(fake.listArgsForCall) -} - -func (fake *PivnetReleasesService) ListCalls(stub func(string) ([]pivnet.Release, error)) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = stub -} - -func (fake *PivnetReleasesService) ListArgsForCall(i int) string { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - argsForCall := fake.listArgsForCall[i] - return argsForCall.arg1 -} - -func (fake *PivnetReleasesService) ListReturns(result1 []pivnet.Release, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - fake.listReturns = struct { - result1 []pivnet.Release - result2 error - }{result1, result2} -} - -func (fake *PivnetReleasesService) ListReturnsOnCall(i int, result1 []pivnet.Release, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - if fake.listReturnsOnCall == nil { - fake.listReturnsOnCall = make(map[int]struct { - result1 []pivnet.Release - result2 error - }) - } - fake.listReturnsOnCall[i] = struct { - result1 []pivnet.Release - result2 error - }{result1, result2} -} - -func (fake *PivnetReleasesService) Update(arg1 string, arg2 pivnet.Release) (pivnet.Release, error) { - fake.updateMutex.Lock() - ret, specificReturn := fake.updateReturnsOnCall[len(fake.updateArgsForCall)] - fake.updateArgsForCall = append(fake.updateArgsForCall, struct { - arg1 string - arg2 pivnet.Release - }{arg1, arg2}) - stub := fake.UpdateStub - fakeReturns := fake.updateReturns - fake.recordInvocation("Update", []interface{}{arg1, arg2}) - fake.updateMutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PivnetReleasesService) UpdateCallCount() int { - fake.updateMutex.RLock() - defer fake.updateMutex.RUnlock() - return len(fake.updateArgsForCall) -} - -func (fake *PivnetReleasesService) UpdateCalls(stub func(string, pivnet.Release) (pivnet.Release, error)) { - fake.updateMutex.Lock() - defer fake.updateMutex.Unlock() - fake.UpdateStub = stub -} - -func (fake *PivnetReleasesService) UpdateArgsForCall(i int) (string, pivnet.Release) { - fake.updateMutex.RLock() - defer fake.updateMutex.RUnlock() - argsForCall := fake.updateArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 -} - -func (fake *PivnetReleasesService) UpdateReturns(result1 pivnet.Release, result2 error) { - fake.updateMutex.Lock() - defer fake.updateMutex.Unlock() - fake.UpdateStub = nil - fake.updateReturns = struct { - result1 pivnet.Release - result2 error - }{result1, result2} -} - -func (fake *PivnetReleasesService) UpdateReturnsOnCall(i int, result1 pivnet.Release, result2 error) { - fake.updateMutex.Lock() - defer fake.updateMutex.Unlock() - fake.UpdateStub = nil - if fake.updateReturnsOnCall == nil { - fake.updateReturnsOnCall = make(map[int]struct { - result1 pivnet.Release - result2 error - }) - } - fake.updateReturnsOnCall[i] = struct { - result1 pivnet.Release - result2 error - }{result1, result2} -} - -func (fake *PivnetReleasesService) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - fake.updateMutex.RLock() - defer fake.updateMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *PivnetReleasesService) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ commands.PivnetReleasesService = new(PivnetReleasesService) diff --git a/internal/commands/fakes/pivnet_user_groups_service.go b/internal/commands/fakes/pivnet_user_groups_service.go deleted file mode 100644 index f2995946e..000000000 --- a/internal/commands/fakes/pivnet_user_groups_service.go +++ /dev/null @@ -1,186 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "sync" - - pivnet "github.com/pivotal-cf/go-pivnet/v2" - "github.com/pivotal-cf/kiln/internal/commands" -) - -type PivnetUserGroupsService struct { - AddToReleaseStub func(string, int, int) error - addToReleaseMutex sync.RWMutex - addToReleaseArgsForCall []struct { - arg1 string - arg2 int - arg3 int - } - addToReleaseReturns struct { - result1 error - } - addToReleaseReturnsOnCall map[int]struct { - result1 error - } - ListStub func() ([]pivnet.UserGroup, error) - listMutex sync.RWMutex - listArgsForCall []struct { - } - listReturns struct { - result1 []pivnet.UserGroup - result2 error - } - listReturnsOnCall map[int]struct { - result1 []pivnet.UserGroup - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *PivnetUserGroupsService) AddToRelease(arg1 string, arg2 int, arg3 int) error { - fake.addToReleaseMutex.Lock() - ret, specificReturn := fake.addToReleaseReturnsOnCall[len(fake.addToReleaseArgsForCall)] - fake.addToReleaseArgsForCall = append(fake.addToReleaseArgsForCall, struct { - arg1 string - arg2 int - arg3 int - }{arg1, arg2, arg3}) - stub := fake.AddToReleaseStub - fakeReturns := fake.addToReleaseReturns - fake.recordInvocation("AddToRelease", []interface{}{arg1, arg2, arg3}) - fake.addToReleaseMutex.Unlock() - if stub != nil { - return stub(arg1, arg2, arg3) - } - if specificReturn { - return ret.result1 - } - return fakeReturns.result1 -} - -func (fake *PivnetUserGroupsService) AddToReleaseCallCount() int { - fake.addToReleaseMutex.RLock() - defer fake.addToReleaseMutex.RUnlock() - return len(fake.addToReleaseArgsForCall) -} - -func (fake *PivnetUserGroupsService) AddToReleaseCalls(stub func(string, int, int) error) { - fake.addToReleaseMutex.Lock() - defer fake.addToReleaseMutex.Unlock() - fake.AddToReleaseStub = stub -} - -func (fake *PivnetUserGroupsService) AddToReleaseArgsForCall(i int) (string, int, int) { - fake.addToReleaseMutex.RLock() - defer fake.addToReleaseMutex.RUnlock() - argsForCall := fake.addToReleaseArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 -} - -func (fake *PivnetUserGroupsService) AddToReleaseReturns(result1 error) { - fake.addToReleaseMutex.Lock() - defer fake.addToReleaseMutex.Unlock() - fake.AddToReleaseStub = nil - fake.addToReleaseReturns = struct { - result1 error - }{result1} -} - -func (fake *PivnetUserGroupsService) AddToReleaseReturnsOnCall(i int, result1 error) { - fake.addToReleaseMutex.Lock() - defer fake.addToReleaseMutex.Unlock() - fake.AddToReleaseStub = nil - if fake.addToReleaseReturnsOnCall == nil { - fake.addToReleaseReturnsOnCall = make(map[int]struct { - result1 error - }) - } - fake.addToReleaseReturnsOnCall[i] = struct { - result1 error - }{result1} -} - -func (fake *PivnetUserGroupsService) List() ([]pivnet.UserGroup, error) { - fake.listMutex.Lock() - ret, specificReturn := fake.listReturnsOnCall[len(fake.listArgsForCall)] - fake.listArgsForCall = append(fake.listArgsForCall, struct { - }{}) - stub := fake.ListStub - fakeReturns := fake.listReturns - fake.recordInvocation("List", []interface{}{}) - fake.listMutex.Unlock() - if stub != nil { - return stub() - } - if specificReturn { - return ret.result1, ret.result2 - } - return fakeReturns.result1, fakeReturns.result2 -} - -func (fake *PivnetUserGroupsService) ListCallCount() int { - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - return len(fake.listArgsForCall) -} - -func (fake *PivnetUserGroupsService) ListCalls(stub func() ([]pivnet.UserGroup, error)) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = stub -} - -func (fake *PivnetUserGroupsService) ListReturns(result1 []pivnet.UserGroup, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - fake.listReturns = struct { - result1 []pivnet.UserGroup - result2 error - }{result1, result2} -} - -func (fake *PivnetUserGroupsService) ListReturnsOnCall(i int, result1 []pivnet.UserGroup, result2 error) { - fake.listMutex.Lock() - defer fake.listMutex.Unlock() - fake.ListStub = nil - if fake.listReturnsOnCall == nil { - fake.listReturnsOnCall = make(map[int]struct { - result1 []pivnet.UserGroup - result2 error - }) - } - fake.listReturnsOnCall[i] = struct { - result1 []pivnet.UserGroup - result2 error - }{result1, result2} -} - -func (fake *PivnetUserGroupsService) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.addToReleaseMutex.RLock() - defer fake.addToReleaseMutex.RUnlock() - fake.listMutex.RLock() - defer fake.listMutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *PivnetUserGroupsService) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ commands.PivnetUserGroupsService = new(PivnetUserGroupsService) diff --git a/internal/commands/fakes/remote_pather_finder.go b/internal/commands/fakes/remote_pather_finder.go deleted file mode 100644 index 097977487..000000000 --- a/internal/commands/fakes/remote_pather_finder.go +++ /dev/null @@ -1,119 +0,0 @@ -// Code generated by counterfeiter. DO NOT EDIT. -package fakes - -import ( - "sync" - - "github.com/pivotal-cf/kiln/internal/commands" - "github.com/pivotal-cf/kiln/internal/component" - "github.com/pivotal-cf/kiln/pkg/cargo" -) - -type RemotePatherFinder struct { - Stub func(cargo.Kilnfile, string) (component.RemotePather, error) - mutex sync.RWMutex - argsForCall []struct { - arg1 cargo.Kilnfile - arg2 string - } - returns struct { - result1 component.RemotePather - result2 error - } - returnsOnCall map[int]struct { - result1 component.RemotePather - result2 error - } - invocations map[string][][]interface{} - invocationsMutex sync.RWMutex -} - -func (fake *RemotePatherFinder) Spy(arg1 cargo.Kilnfile, arg2 string) (component.RemotePather, error) { - fake.mutex.Lock() - ret, specificReturn := fake.returnsOnCall[len(fake.argsForCall)] - fake.argsForCall = append(fake.argsForCall, struct { - arg1 cargo.Kilnfile - arg2 string - }{arg1, arg2}) - stub := fake.Stub - returns := fake.returns - fake.recordInvocation("RemotePatherFinder", []interface{}{arg1, arg2}) - fake.mutex.Unlock() - if stub != nil { - return stub(arg1, arg2) - } - if specificReturn { - return ret.result1, ret.result2 - } - return returns.result1, returns.result2 -} - -func (fake *RemotePatherFinder) CallCount() int { - fake.mutex.RLock() - defer fake.mutex.RUnlock() - return len(fake.argsForCall) -} - -func (fake *RemotePatherFinder) Calls(stub func(cargo.Kilnfile, string) (component.RemotePather, error)) { - fake.mutex.Lock() - defer fake.mutex.Unlock() - fake.Stub = stub -} - -func (fake *RemotePatherFinder) ArgsForCall(i int) (cargo.Kilnfile, string) { - fake.mutex.RLock() - defer fake.mutex.RUnlock() - return fake.argsForCall[i].arg1, fake.argsForCall[i].arg2 -} - -func (fake *RemotePatherFinder) Returns(result1 component.RemotePather, result2 error) { - fake.mutex.Lock() - defer fake.mutex.Unlock() - fake.Stub = nil - fake.returns = struct { - result1 component.RemotePather - result2 error - }{result1, result2} -} - -func (fake *RemotePatherFinder) ReturnsOnCall(i int, result1 component.RemotePather, result2 error) { - fake.mutex.Lock() - defer fake.mutex.Unlock() - fake.Stub = nil - if fake.returnsOnCall == nil { - fake.returnsOnCall = make(map[int]struct { - result1 component.RemotePather - result2 error - }) - } - fake.returnsOnCall[i] = struct { - result1 component.RemotePather - result2 error - }{result1, result2} -} - -func (fake *RemotePatherFinder) Invocations() map[string][][]interface{} { - fake.invocationsMutex.RLock() - defer fake.invocationsMutex.RUnlock() - fake.mutex.RLock() - defer fake.mutex.RUnlock() - copiedInvocations := map[string][][]interface{}{} - for key, value := range fake.invocations { - copiedInvocations[key] = value - } - return copiedInvocations -} - -func (fake *RemotePatherFinder) recordInvocation(key string, args []interface{}) { - fake.invocationsMutex.Lock() - defer fake.invocationsMutex.Unlock() - if fake.invocations == nil { - fake.invocations = map[string][][]interface{}{} - } - if fake.invocations[key] == nil { - fake.invocations[key] = [][]interface{}{} - } - fake.invocations[key] = append(fake.invocations[key], args) -} - -var _ commands.RemotePatherFinder = new(RemotePatherFinder).Spy diff --git a/internal/commands/fetch.go b/internal/commands/fetch_releases.go similarity index 81% rename from internal/commands/fetch.go rename to internal/commands/fetch_releases.go index 369737e44..4b58cecf8 100644 --- a/internal/commands/fetch.go +++ b/internal/commands/fetch_releases.go @@ -12,7 +12,7 @@ import ( "github.com/pivotal-cf/kiln/pkg/cargo" ) -type Fetch struct { +type FetchReleases struct { logger *log.Logger multiReleaseSourceProvider MultiReleaseSourceProvider @@ -21,19 +21,19 @@ type Fetch struct { Options struct { flags.Standard - ReleasesDir string `short:"rd" long:"releases-directory" default:"releases" description:"path to a directory to download releases into"` + ReleasesDir string `short:"rd" long:"releases-directory" default-path:"releases" description:"path to a directory to download releases into"` - DownloadThreads int `short:"dt" long:"download-threads" description:"number of parallel threads to download parts from S3"` - NoConfirm bool `short:"n" long:"no-confirm" description:"non-interactive mode, will delete extra releases in releases dir without prompting"` - AllowOnlyPublishableReleases bool `long:"allow-only-publishable-releases" description:"include releases that would not be shipped with the tile (development builds)"` + DownloadThreads int `short:"dt" long:"download-threads" description:"number of parallel threads to download parts from S3"` + NoConfirm bool `short:"n" long:"no-confirm" description:"non-interactive mode, will delete extra releases in releases dir without prompting"` + AllowOnlyPublishableReleases bool ` long:"allow-only-publishable-releases" description:"include releases that would not be shipped with the tile (development builds)"` } } //counterfeiter:generate -o ./fakes/multi_release_source_provider.go --fake-name MultiReleaseSourceProvider . MultiReleaseSourceProvider type MultiReleaseSourceProvider func(cargo.Kilnfile, bool) component.MultiReleaseSource -func NewFetch(logger *log.Logger, multiReleaseSourceProvider MultiReleaseSourceProvider, localReleaseDirectory LocalReleaseDirectory) Fetch { - return Fetch{ +func NewFetchReleases(logger *log.Logger, multiReleaseSourceProvider MultiReleaseSourceProvider, localReleaseDirectory LocalReleaseDirectory) *FetchReleases { + return &FetchReleases{ logger: logger, localReleaseDirectory: localReleaseDirectory, multiReleaseSourceProvider: multiReleaseSourceProvider, @@ -46,7 +46,7 @@ type LocalReleaseDirectory interface { DeleteExtraReleases(extraReleases []component.Local, noConfirm bool) error } -func (f Fetch) Execute(args []string) error { +func (f *FetchReleases) Execute(args []string) error { kilnfile, kilnfileLock, availableLocalReleaseSet, err := f.setup(args) if err != nil { return err @@ -71,7 +71,7 @@ func (f Fetch) Execute(args []string) error { return nil } -func (f *Fetch) setup(args []string) (cargo.Kilnfile, cargo.KilnfileLock, []component.Local, error) { +func (f *FetchReleases) setup(args []string) (cargo.Kilnfile, cargo.KilnfileLock, []component.Local, error) { _, err := flags.LoadFlagsWithDefaults(&f.Options, args, nil) if err != nil { return cargo.Kilnfile{}, cargo.KilnfileLock{}, nil, err @@ -103,7 +103,7 @@ func (f *Fetch) setup(args []string) (cargo.Kilnfile, cargo.KilnfileLock, []comp return kilnfile, kilnfileLock, availableLocalReleaseSet, nil } -func (f Fetch) downloadMissingReleases(kilnfile cargo.Kilnfile, releaseLocks []cargo.ComponentLock) ([]component.Local, error) { +func (f *FetchReleases) downloadMissingReleases(kilnfile cargo.Kilnfile, releaseLocks []cargo.ComponentLock) ([]component.Local, error) { releaseSource := f.multiReleaseSourceProvider(kilnfile, f.Options.AllowOnlyPublishableReleases) // f.Options.DownloadThreads @@ -138,7 +138,7 @@ func (f Fetch) downloadMissingReleases(kilnfile cargo.Kilnfile, releaseLocks []c return downloaded, nil } -func (f Fetch) Usage() jhanda.Usage { +func (f *FetchReleases) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Fetches releases listed in Kilnfile.lock from S3 and downloads it locally", ShortDescription: "fetches releases", diff --git a/internal/commands/fetch_test.go b/internal/commands/fetch_releases_test.go similarity index 97% rename from internal/commands/fetch_test.go rename to internal/commands/fetch_releases_test.go index 5eef1e33a..33dbe446b 100644 --- a/internal/commands/fetch_test.go +++ b/internal/commands/fetch_releases_test.go @@ -20,9 +20,9 @@ import ( "github.com/pivotal-cf/kiln/pkg/cargo" ) -var _ = Describe("Fetch", func() { +var _ = Describe("FetchReleases", func() { var ( - fetch commands.Fetch + fetchReleasesCommand *commands.FetchReleases logger *log.Logger tmpDir string someKilnfilePath string @@ -53,7 +53,7 @@ var _ = Describe("Fetch", func() { logger = log.New(GinkgoWriter, "", 0) var err error - tmpDir, err = os.MkdirTemp("", "fetch-test") + tmpDir, err = os.MkdirTemp("", "fetchReleasesCommand-test") Expect(err).NotTo(HaveOccurred()) someReleasesDirectory, err = os.MkdirTemp(tmpDir, "") @@ -117,9 +117,9 @@ stemcell_criteria: err := os.WriteFile(someKilnfileLockPath, []byte(lockContents), 0o644) Expect(err).NotTo(HaveOccurred()) - fetch = commands.NewFetch(logger, multiReleaseSourceProvider, fakeLocalReleaseDirectory) + fetchReleasesCommand = commands.NewFetchReleases(logger, multiReleaseSourceProvider, fakeLocalReleaseDirectory) - fetchExecuteErr = fetch.Execute(fetchExecuteArgs) + fetchExecuteErr = fetchReleasesCommand.Execute(fetchExecuteArgs) }) When("a local compiled release exists", func() { @@ -584,7 +584,7 @@ release_sources: Context("kilnfile is missing", func() { It("returns an error", func() { badKilnfilePath := filepath.Join(tmpDir, "non-existent-Kilnfile") - err := fetch.Execute([]string{ + err := fetchReleasesCommand.Execute([]string{ "--releases-directory", someReleasesDirectory, "--kilnfile", badKilnfilePath, }) @@ -593,7 +593,7 @@ release_sources: }) Context("# of download threads is not a number", func() { It("returns an error", func() { - err := fetch.Execute([]string{ + err := fetchReleasesCommand.Execute([]string{ "--releases-directory", someReleasesDirectory, "--kilnfile", someKilnfilePath, "--download-threads", "not-a-number", @@ -607,7 +607,7 @@ release_sources: fakeLocalReleaseDirectory.GetLocalReleasesReturns(nil, errors.New("some-error")) }) It("returns an error", func() { - err := fetch.Execute([]string{ + err := fetchReleasesCommand.Execute([]string{ "--releases-directory", someReleasesDirectory, "--kilnfile", someKilnfilePath, }) @@ -621,10 +621,10 @@ release_sources: Describe("Usage", func() { It("returns usage information for the command", func() { - Expect(fetch.Usage()).To(Equal(jhanda.Usage{ + Expect(fetchReleasesCommand.Usage()).To(Equal(jhanda.Usage{ Description: "Fetches releases listed in Kilnfile.lock from S3 and downloads it locally", ShortDescription: "fetches releases", - Flags: fetch.Options, + Flags: fetchReleasesCommand.Options, })) }) }) diff --git a/internal/commands/find_release_version.go b/internal/commands/find_release_version.go index 93ee99edd..410616f4a 100644 --- a/internal/commands/find_release_version.go +++ b/internal/commands/find_release_version.go @@ -30,14 +30,14 @@ type releaseVersionOutput struct { SHA string `json:"sha"` } -func NewFindReleaseVersion(outLogger *log.Logger, multiReleaseSourceProvider MultiReleaseSourceProvider) FindReleaseVersion { - return FindReleaseVersion{ +func NewFindReleaseVersion(outLogger *log.Logger, multiReleaseSourceProvider MultiReleaseSourceProvider) *FindReleaseVersion { + return &FindReleaseVersion{ outLogger: outLogger, mrsProvider: multiReleaseSourceProvider, } } -func (cmd FindReleaseVersion) Execute(args []string) error { +func (cmd *FindReleaseVersion) Execute(args []string) error { kilnfile, kilnfileLock, err := cmd.setup(args) if err != nil { return err @@ -90,7 +90,7 @@ func (cmd *FindReleaseVersion) setup(args []string) (cargo.Kilnfile, cargo.Kilnf return kilnfile, kilnfileLock, nil } -func (cmd FindReleaseVersion) Usage() jhanda.Usage { +func (cmd *FindReleaseVersion) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Prints a json string of a remote release satisfying the Kilnfile version and stemcell constraints.", ShortDescription: "prints a json string of a remote release satisfying the Kilnfile version and stemcell constraints", diff --git a/internal/commands/find_release_version_test.go b/internal/commands/find_release_version_test.go index ed79d407b..039b907e0 100644 --- a/internal/commands/find_release_version_test.go +++ b/internal/commands/find_release_version_test.go @@ -17,7 +17,7 @@ import ( var _ = Describe("Find the release version", func() { var ( - findReleaseVersion commands.FindReleaseVersion + findReleaseVersion *commands.FindReleaseVersion logger *log.Logger fakeReleasesSource *fakes.MultiReleaseSource diff --git a/internal/commands/find_stemcell_version.go b/internal/commands/find_stemcell_version.go index 3249814c1..6542b1004 100644 --- a/internal/commands/find_stemcell_version.go +++ b/internal/commands/find_stemcell_version.go @@ -20,7 +20,6 @@ import ( const ( ErrStemcellOSInfoMustBeValid = "stemcell os information is missing or invalid" ErrStemcellMajorVersionMustBeValid = "stemcell major Version is missing or invalid" - TanzuNetRemotePath = "network.pivotal.io" ) type FindStemcellVersion struct { @@ -40,15 +39,15 @@ type stemcellVersionOutput struct { RemotePath string `json:"remote_path"` } -func NewFindStemcellVersion(outLogger *log.Logger, pivnetService *pivnet.Service) FindStemcellVersion { - return FindStemcellVersion{ +func NewFindStemcellVersion(outLogger *log.Logger, pivnetService *pivnet.Service) *FindStemcellVersion { + return &FindStemcellVersion{ outLogger: outLogger, pivnetService: pivnetService, FS: osfs.New(""), } } -func (cmd FindStemcellVersion) Execute(args []string) error { +func (cmd *FindStemcellVersion) Execute(args []string) error { kilnfile, err := cmd.setup(args) if err != nil { return err @@ -69,11 +68,7 @@ func (cmd FindStemcellVersion) Execute(args []string) error { return fmt.Errorf(ErrStemcellOSInfoMustBeValid) } - if kilnfile.Stemcell.Version == "" { - return fmt.Errorf(ErrStemcellMajorVersionMustBeValid) - } - - majorVersion, err := ExtractMajorVersion(kilnfile.Stemcell.Version) + majorVersion, err := extractMajorVersion(kilnfile.Stemcell.Version) if err != nil { return err } @@ -87,7 +82,7 @@ func (cmd FindStemcellVersion) Execute(args []string) error { stemcellVersionJson, err := json.Marshal(stemcellVersionOutput{ Version: stemcellVersion, Source: "Tanzunet", - RemotePath: TanzuNetRemotePath, + RemotePath: pivnet.ProductionHost, }) if err != nil { return err @@ -98,28 +93,6 @@ func (cmd FindStemcellVersion) Execute(args []string) error { return nil } -func ExtractMajorVersion(version string) (string, error) { - _, err := semver.NewConstraint(version) - if err != nil { - return "", fmt.Errorf("invalid stemcell constraint in kilnfile: %w", err) - } - - semVer := strings.Split(version, ".") - - reg, err := regexp.Compile(`[^0-9]+`) - if err != nil { - return "", err - } - - majorVersion := reg.ReplaceAllString(semVer[0], "") - - if majorVersion == "" { - return "", fmt.Errorf(ErrStemcellMajorVersionMustBeValid) - } - - return majorVersion, nil -} - func (cmd *FindStemcellVersion) setup(args []string) (cargo.Kilnfile, error) { _, err := jhanda.Parse(&cmd.Options, args) if err != nil { @@ -139,10 +112,36 @@ func (cmd *FindStemcellVersion) setup(args []string) (cargo.Kilnfile, error) { return kilnfile, nil } -func (cmd FindStemcellVersion) Usage() jhanda.Usage { +func (cmd *FindStemcellVersion) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Prints the latest stemcell version from Pivnet using the stemcell type listed in the Kilnfile", ShortDescription: "prints the latest stemcell version from Pivnet using the stemcell type listed in the Kilnfile", Flags: cmd.Options, } } + +func extractMajorVersion(version string) (string, error) { + if version == "" { + return "", fmt.Errorf(ErrStemcellMajorVersionMustBeValid) + } + + _, err := semver.NewConstraint(version) + if err != nil { + return "", fmt.Errorf("invalid stemcell constraint in kilnfile: %w", err) + } + + semVer := strings.Split(version, ".") + + reg, err := regexp.Compile(`[^0-9]+`) + if err != nil { + return "", err + } + + majorVersion := reg.ReplaceAllString(semVer[0], "") + + if majorVersion == "" { + return "", fmt.Errorf(ErrStemcellMajorVersionMustBeValid) + } + + return majorVersion, nil +} diff --git a/internal/commands/find_stemcell_version_internal_test.go b/internal/commands/find_stemcell_version_internal_test.go new file mode 100644 index 000000000..5821a220c --- /dev/null +++ b/internal/commands/find_stemcell_version_internal_test.go @@ -0,0 +1,75 @@ +package commands + +import ( + "testing" + + . "github.com/onsi/gomega" +) + +func Test_extractMajorVersion(t *testing.T) { + tests := []struct { + name string + input string + expectedResult string + expectErrTo OmegaMatcher + }{ + { + name: "with tilde ~", + input: "~456", + expectedResult: "456", + expectErrTo: Not(HaveOccurred()), + }, + { + name: "with hypens -", + input: "777.1-621", + expectedResult: "777", + expectErrTo: Not(HaveOccurred()), + }, + { + name: "with wildcards *", + input: "1234.*", + expectedResult: "1234", + expectErrTo: Not(HaveOccurred()), + }, + { + name: "with caret ^", + input: "^456", + expectedResult: "456", + expectErrTo: Not(HaveOccurred()), + }, + + { + name: "with absolute value", + input: "333.334", + expectedResult: "333", + expectErrTo: Not(HaveOccurred()), + }, + { + name: "specifier does not have major version", + input: "*", + expectedResult: "", + expectErrTo: And( + HaveOccurred(), + MatchError(ContainSubstring(ErrStemcellMajorVersionMustBeValid)), + ), + }, + { + name: "specifier is an empty string", + input: "", + expectedResult: "", + expectErrTo: And( + HaveOccurred(), + MatchError(ContainSubstring(ErrStemcellMajorVersionMustBeValid)), + ), + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + please := NewWithT(t) + + got, err := extractMajorVersion(tt.input) + please.Expect(err).To(tt.expectErrTo) + please.Expect(got).To(Equal(tt.expectedResult)) + }) + } +} diff --git a/internal/commands/find_stemcell_version_test.go b/internal/commands/find_stemcell_version_test.go index 4400bc8a4..bdf04d7f6 100644 --- a/internal/commands/find_stemcell_version_test.go +++ b/internal/commands/find_stemcell_version_test.go @@ -17,7 +17,7 @@ import ( var _ = Describe("Find the stemcell version", func() { var ( - findStemcellVersion commands.FindStemcellVersion + findStemcellVersion *commands.FindStemcellVersion logger *log.Logger writer strings.Builder @@ -155,89 +155,4 @@ stemcell_criteria: }) }) }) - - Describe("ExtractMajorVersion", func() { - var ( - stemcellVersionSpecifier string - majorVersion string - returnedErr error - ) - - BeforeEach(func() { - stemcellVersionSpecifier = "~456" - }) - - JustBeforeEach(func() { - majorVersion, returnedErr = commands.ExtractMajorVersion(stemcellVersionSpecifier) - }) - - When("Invalid Stemcell Version Specifier is provided", func() { - When("with just *", func() { - BeforeEach(func() { - stemcellVersionSpecifier = "*" - }) - - It("returns the latest stemcell version", func() { - Expect(returnedErr).To(HaveOccurred()) - Expect(returnedErr.Error()).To(Equal(commands.ErrStemcellMajorVersionMustBeValid)) - }) - }) - }) - - When("Valid Stemcell Version Specifier is provided", func() { - When("with tilde ~ ", func() { - BeforeEach(func() { - stemcellVersionSpecifier = "~456" - }) - - It("returns the latest stemcell version", func() { - Expect(returnedErr).NotTo(HaveOccurred()) - Expect(majorVersion).To(Equal("456")) - }) - }) - When("with hypens -", func() { - BeforeEach(func() { - stemcellVersionSpecifier = "777.1-621" - }) - - It("returns the latest stemcell version", func() { - Expect(returnedErr).NotTo(HaveOccurred()) - Expect(majorVersion).To(Equal("777")) - }) - }) - - When("with wildcards *", func() { - BeforeEach(func() { - stemcellVersionSpecifier = "1234.*" - }) - - It("returns the latest stemcell version", func() { - Expect(returnedErr).NotTo(HaveOccurred()) - Expect(majorVersion).To(Equal("1234")) - }) - }) - - When("with caret ^", func() { - BeforeEach(func() { - stemcellVersionSpecifier = "^456" - }) - - It("returns the latest stemcell version", func() { - Expect(returnedErr).NotTo(HaveOccurred()) - Expect(majorVersion).To(Equal("456")) - }) - }) - - When("with absolute value", func() { - BeforeEach(func() { - stemcellVersionSpecifier = "333.334" - }) - - It("returns the latest stemcell version", func() { - Expect(returnedErr).NotTo(HaveOccurred()) - Expect(majorVersion).To(Equal("333")) - }) - }) - }) - }) }) diff --git a/internal/commands/flags/parse.go b/internal/commands/flags/parse.go index b9454cdc7..47aad8e56 100644 --- a/internal/commands/flags/parse.go +++ b/internal/commands/flags/parse.go @@ -2,12 +2,8 @@ package flags import ( "fmt" - "go/ast" "io" - "os" "path/filepath" - "reflect" - "strings" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/osfs" @@ -15,11 +11,12 @@ import ( "gopkg.in/yaml.v2" "github.com/pivotal-cf/kiln/internal/baking" + "github.com/pivotal-cf/kiln/internal/defaultpath" "github.com/pivotal-cf/kiln/pkg/cargo" ) type ( - StatFunc func(string) (os.FileInfo, error) + StatFunc = defaultpath.StatFunc KilnfileOptions interface { KilnfilePathPrefix() string @@ -31,9 +28,9 @@ type ( ) type Standard struct { - Kilnfile string `short:"kf" long:"kilnfile" default:"Kilnfile" description:"path to Kilnfile"` - VariableFiles []string `short:"vf" long:"variables-file" description:"path to a file containing variables to interpolate"` - Variables []string `short:"vr" long:"variable" description:"key value pairs of variables to interpolate"` + Kilnfile string `short:"kf" long:"kilnfile" default-path:"Kilnfile" description:"path to Kilnfile"` + VariableFiles []string `short:"vf" long:"variables-file" description:"path to a file containing variables to interpolate"` + Variables []string `short:"vr" long:"variable" description:"key value pairs of variables to interpolate"` } // LoadKilnfiles parses and interpolates the Kilnfile and parsed the Kilnfile.lock. @@ -108,7 +105,7 @@ func (options *Standard) SaveKilnfileLock(fsOverride billy.Basic, kilnfileLock c return nil } -func (options Standard) KilnfilePathPrefix() string { +func (options *Standard) KilnfilePathPrefix() string { pathPrefix := filepath.Dir(options.Kilnfile) if pathPrefix == "." { pathPrefix = "" @@ -116,162 +113,29 @@ func (options Standard) KilnfilePathPrefix() string { return pathPrefix } -func (options Standard) KilnfileLockPath() string { +func (options *Standard) KilnfileLockPath() string { return options.Kilnfile + ".lock" } // LoadFlagsWithDefaults only sets default values if the flag is not set // this permits explicitly setting "zero values" for in arguments without them being // overwritten. -func LoadFlagsWithDefaults(options KilnfileOptions, args []string, statOverride StatFunc) ([]string, error) { - if statOverride == nil { - statOverride = os.Stat - } +func LoadFlagsWithDefaults(options KilnfileOptions, args []string, statOverride defaultpath.StatFunc) ([]string, error) { argsAfterFlags, err := jhanda.Parse(options, args) if err != nil { return nil, err } - v := reflect.ValueOf(options).Elem() - - pathPrefix := options.KilnfilePathPrefix() - - // handle simple case first - configureArrayDefaults(v, pathPrefix, args, statOverride) - configurePathDefaults(v, pathPrefix, args, statOverride) + defaultpath.SetFields(options, options.KilnfilePathPrefix(), args, statOverride) return argsAfterFlags, nil } -func configureArrayDefaults(v reflect.Value, pathPrefix string, args []string, stat StatFunc) { - t := v.Type() - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - - switch field.Type.Kind() { - default: - continue - case reflect.Struct: - embeddedValue := v.Field(i) - if field.Anonymous && ast.IsExported(embeddedValue.Type().Name()) { - configurePathDefaults(embeddedValue, pathPrefix, args, stat) - } - continue - case reflect.Slice: - } - - defaultValueStr, ok := field.Tag.Lookup("default") - if !ok { - continue - } - defaultValues := strings.Split(defaultValueStr, ",") - - flagValues, ok := v.Field(i).Interface().([]string) - if !ok { - // this might occur if we add non string slice params - // notice the field Kind check above was not super specific - continue - } - - if IsSet(field.Tag.Get("short"), field.Tag.Get("long"), args) { - v.Field(i).Set(reflect.ValueOf(flagValues[len(defaultValues):])) - continue - } - - filteredDefaults := defaultValues[:0] - for _, p := range defaultValues { - if pathPrefix != "" { - p = filepath.Join(pathPrefix, p) - } - _, err := stat(p) - if err != nil { - continue - } - filteredDefaults = append(filteredDefaults, p) - } - - // if default values were found, use them, - // else filteredDefaults will be an empty slice - // and the Bake command will continue as if they were not set - v.Field(i).Set(reflect.ValueOf(filteredDefaults)) - } -} - -func configurePathDefaults(v reflect.Value, pathPrefix string, args []string, stat StatFunc) { - t := v.Type() - - for i := 0; i < t.NumField(); i++ { - field := t.Field(i) - - switch field.Type.Kind() { - default: - continue - case reflect.Struct: - embeddedValue := v.Field(i) - if field.Anonymous && ast.IsExported(embeddedValue.Type().Name()) { - configurePathDefaults(embeddedValue, pathPrefix, args, stat) - } - continue - case reflect.String: - } - - if IsSet(field.Tag.Get("short"), field.Tag.Get("long"), args) { - continue - } - - defaultValue, ok := field.Tag.Lookup("default") - if !ok { - continue - } - - value, ok := v.Field(i).Interface().(string) - if !ok { - continue // this should not occur - } - - isDefaultValue := defaultValue == value - - if !isDefaultValue { - continue - } - - if pathPrefix != "" { - value = filepath.Join(pathPrefix, value) - } - - _, err := stat(value) - if err != nil { - // set to zero value - v.Field(i).Set(reflect.Zero(v.Field(i).Type())) - continue - } - - v.Field(i).Set(reflect.ValueOf(value)) - } -} - // IsSet can be used to check if a flag is set in a set // of arguments. Both "long" and "short" flag names must // be passed. func IsSet(short, long string, args []string) bool { - check := func(name string, arg string) bool { - if name == "" { - return false - } - - return arg == "--"+name || arg == "-"+name || - strings.HasPrefix(arg, "--"+name+"=") || - strings.HasPrefix(arg, "-"+name+"=") - } - - for _, a := range args { - if check(short, a) || check(long, a) { - return true - } - } - - return false + return defaultpath.IsSet(short, long, args) } func closeAndIgnoreError(c io.Closer) { _ = c.Close() } diff --git a/internal/commands/help.go b/internal/commands/help.go index 7c0f5dfdc..aaaff2a4d 100644 --- a/internal/commands/help.go +++ b/internal/commands/help.go @@ -3,69 +3,106 @@ package commands import ( "fmt" "io" + "reflect" "sort" "strings" - "text/template" + + "golang.org/x/exp/maps" "github.com/pivotal-cf/jhanda" ) -var usageTemplate = template.Must(template.New("usage").Parse( /* language=gotemplate */ `{{.Title}} -{{.Description}} - -Usage: {{.Usage}} -{{range .GlobalFlags}} {{.}} -{{end}} -{{if .Arguments}}{{.ArgumentsName}}: -{{range .Arguments}} {{.}} -{{end}}{{end}} -`)) - -type TemplateContext struct { +type helpData struct { + // input Title string Description string Usage string GlobalFlags []string ArgumentsName string - Arguments []string + ArgumentLines []string +} + +func (tc helpData) String() string { + var sb strings.Builder + + if tc.Title != "kiln" { + sb.WriteString("\n") + sb.WriteString(tc.Title) + sb.WriteString("\n\n") + } + if tc.Description != "" { + sb.WriteString(tc.Description) + sb.WriteString("\n\n") + } + if tc.Usage != "" { + sb.WriteString("Usage: ") + sb.WriteString(tc.Usage) + sb.WriteString("\n") + } + if len(tc.GlobalFlags) > 0 { + for _, flag := range tc.GlobalFlags { + sb.WriteString(" ") + sb.WriteString(flag) + sb.WriteString("\n") + } + sb.WriteString("\n") + } + + if tc.ArgumentsName != "" { + sb.WriteString(tc.ArgumentsName) + sb.WriteString("\n") + } + + for _, line := range tc.ArgumentLines { + sb.WriteString(line) + sb.WriteString("\n") + } + + sb.WriteString("\n") + + return sb.String() } type Help struct { - output io.Writer - flags string - commands jhanda.CommandSet + output io.Writer + flags string + commands jhanda.CommandSet + groupOrder []string + groups map[string][]string } -func NewHelp(output io.Writer, flags string, commands jhanda.CommandSet) Help { +func NewHelp(output io.Writer, flags string, commands jhanda.CommandSet, groupOrder []string, groups map[string][]string) Help { + if len(groupOrder) == 0 { + groupNames := maps.Keys(groups) + sort.Strings(groupNames) + groupOrder = groupNames + } return Help{ - output: output, - flags: flags, - commands: commands, + output: output, + flags: flags, + commands: commands, + groupOrder: groupOrder, + groups: groups, } } func (h Help) Execute(args []string) error { globalFlags := strings.Split(h.flags, "\n") - var context TemplateContext + var data helpData if len(args) == 0 { - context = h.buildGlobalContext() + data = h.buildGlobalContext() } else { var err error - context, err = h.buildCommandContext(args[0]) + data, err = h.buildCommandContext(args[0]) if err != nil { return err } } + data.GlobalFlags = globalFlags - context.GlobalFlags = globalFlags - - err := usageTemplate.Execute(h.output, context) - if err != nil { - return err - } - - return nil + _, err := fmt.Fprintf(h.output, "%s", data) + return err } func (h Help) Usage() jhanda.Usage { @@ -75,41 +112,44 @@ func (h Help) Usage() jhanda.Usage { } } -func (h Help) buildGlobalContext() TemplateContext { - var ( - length int - names []string - ) +func (h Help) buildGlobalContext() helpData { + var commands []string - for name := range h.commands { - names = append(names, name) - if len(name) > length { - length = len(name) + for _, groupName := range h.groupOrder { + groupCommandNames := h.groups[groupName] + if len(groupCommandNames) == 0 { + continue } - } + names := groupCommandNames + maxLength := maxLen(names) + sort.Strings(names) + commands = append(commands, fmt.Sprintf("%s:", groupName)) - sort.Strings(names) + for _, name := range names { + command := h.commands[name] + name = padCommand(name, " ", maxLength) + commands = append(commands, fmt.Sprintf(" %s %s", name, command.Usage().ShortDescription)) + } - var commands []string - for _, name := range names { - command := h.commands[name] - name = h.pad(name, " ", length) - commands = append(commands, fmt.Sprintf("%s %s", name, command.Usage().ShortDescription)) + commands = append(commands, "") } - return TemplateContext{ + commands = commands[:len(commands)-1] + + result := helpData{ Title: "kiln", Description: "kiln helps you build ops manager compatible tiles", Usage: "kiln [options] []", - ArgumentsName: "Commands", - Arguments: commands, + ArgumentLines: commands, } + + return result } -func (h Help) buildCommandContext(command string) (TemplateContext, error) { +func (h Help) buildCommandContext(command string) (helpData, error) { usage, err := h.commands.Usage(command) if err != nil { - return TemplateContext{}, err + return helpData{}, err } var ( @@ -117,15 +157,16 @@ func (h Help) buildCommandContext(command string) (TemplateContext, error) { argsPlaceholder string ) if usage.Flags != nil { - flagUsage, err := jhanda.PrintUsage(usage.Flags) + flagUsage, err := printUsage(usage.Flags) if err != nil { - return TemplateContext{}, err + return helpData{}, err } for _, flag := range strings.Split(flagUsage, "\n") { - if flag != "" { - flagList = append(flagList, flag) + if flag == "" { + continue } + flagList = append(flagList, " "+flag) } if len(flagList) != 0 { @@ -133,16 +174,160 @@ func (h Help) buildCommandContext(command string) (TemplateContext, error) { } } - return TemplateContext{ + return helpData{ Title: fmt.Sprintf("kiln %s", command), Description: usage.Description, Usage: fmt.Sprintf("kiln [options] %s%s", command, argsPlaceholder), - ArgumentsName: "Command Arguments", - Arguments: flagList, + ArgumentsName: "Flags", + ArgumentLines: flagList, }, nil } -func (h Help) pad(str, pad string, length int) string { +func padCommand(str, pad string, length int) string { + return str + strings.Repeat(pad, length-len(str)) +} + +func maxLen(slice []string) int { + var max int + for _, e := range slice { + if len(e) > max { + max = len(e) + } + } + return max +} + +func printUsage(receiver interface{}) (string, error) { + v := reflect.ValueOf(receiver) + t := v.Type() + if t.Kind() != reflect.Struct { + return "", fmt.Errorf("unexpected pointer to non-struct type %s", t.Kind()) + } + + fields := getFields(t) + + var usage []string + var length int + for _, field := range fields { + var arguments []string + long, ok := field.Tag.Lookup("long") + if ok { + arguments = append(arguments, fmt.Sprintf("--%s", long)) + } + + short, ok := field.Tag.Lookup("short") + if ok { + arguments = append(arguments, fmt.Sprintf("-%s", short)) + } + + envs, ok := field.Tag.Lookup("env") + if ok { + arguments = append(arguments, strings.Split(envs, ",")...) + } + + field := strings.Join(arguments, ", ") + + if len(field) > length { + length = len(field) + } + + usage = append(usage, field) + } + + for i, line := range usage { + usage[i] = pad(line, " ", length) + } + + for i, field := range fields { + var kindParts []string + if _, ok := field.Tag.Lookup("required"); ok { + kindParts = append(kindParts, "required") + } + + kind := field.Type.Kind().String() + if kind == reflect.Slice.String() { + kind = field.Type.Elem().Kind().String() + kindParts = append(kindParts, "variadic") + } + + if len(kindParts) > 0 { + kind = fmt.Sprintf("%s (%s)", kind, strings.Join(kindParts, ", ")) + } + + line := fmt.Sprintf("%s %s", usage[i], kind) + + if len(line) > length { + length = len(line) + } + + usage[i] = line + } + + for i, line := range usage { + usage[i] = pad(line, " ", length) + } + + for i, field := range fields { + description, ok := field.Tag.Lookup("description") + if ok { + if _, ok := field.Tag.Lookup("deprecated"); ok { + description = fmt.Sprintf("**DEPRECATED** %s", description) + } + + if _, ok := field.Tag.Lookup("experimental"); ok { + description = fmt.Sprintf("**EXPERIMENTAL** %s", description) + } + + usage[i] += fmt.Sprintf(" %s", description) + } + } + + for i, field := range fields { + defaultValue, ok := field.Tag.Lookup("default") + if ok { + usage[i] += fmt.Sprintf(" (default: %s)", defaultValue) + } + } + + for i, field := range fields { + defaultValue, ok := field.Tag.Lookup("default-path") + if ok { + usage[i] += fmt.Sprintf(" (default-path: %s)", strings.Join(strings.Split(defaultValue, ","), ", ")) + } + } + + for i, field := range fields { + aliases, ok := field.Tag.Lookup("alias") + if ok { + var arguments []string + for _, alias := range strings.Split(aliases, ",") { + arguments = append(arguments, fmt.Sprintf("--%s", alias)) + } + usage[i] += fmt.Sprintf("\n (aliases: %s)", strings.Join(arguments, ", ")) + } + } + + sort.Strings(usage) + + return strings.Join(usage, "\n"), nil +} + +func getFields(t reflect.Type) []reflect.StructField { + var fields []reflect.StructField + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + if field.Type.Kind() == reflect.Struct { + fields = append(fields, getFields(field.Type)...) + continue + } + + fields = append(fields, field) + } + return fields +} + +func pad(str, pad string, length int) string { for { str += pad if len(str) > length { diff --git a/internal/commands/help_test.go b/internal/commands/help_test.go index 80296e78c..5ecf14e28 100644 --- a/internal/commands/help_test.go +++ b/internal/commands/help_test.go @@ -14,37 +14,40 @@ import ( ) const ( - GLOBAL_USAGE = `kiln -kiln helps you build ops manager compatible tiles + GLOBAL_USAGE = `kiln helps you build ops manager compatible tiles Usage: kiln [options] [] --query, -? asks a question --surprise, -! gives you a present -Commands: +House: clean cleans the pot you used cook cooks you a stew ` COMMAND_USAGE = `kiln cook + This command will help you cook a stew. Usage: kiln [options] cook [] --query, -? asks a question --surprise, -! gives you a present -Command Arguments: +Flags --lemon, -l int teaspoons of lemon juice --stock, -s int teaspoons of vegan stock --water, -w int cups of water ` FLAGLESS_USAGE = `kiln cook + This command will help you cook a stew. Usage: kiln [options] cook --query, -? asks a question --surprise, -! gives you a present + +Flags ` ) @@ -74,6 +77,8 @@ var _ = Describe("Help", func() { help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{ "cook": cook, "clean": clean, + }, nil, map[string][]string{ + "House": {"cook", "clean"}, }) err := help.Execute([]string{}) Expect(err).NotTo(HaveOccurred()) @@ -95,7 +100,9 @@ var _ = Describe("Help", func() { }{}, }) - help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{"cook": cook}) + help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{"cook": cook}, nil, map[string][]string{ + "House": {"cook", "clean"}, + }) err := help.Execute([]string{"cook"}) Expect(err).NotTo(HaveOccurred()) @@ -104,7 +111,9 @@ var _ = Describe("Help", func() { Context("when the command does not exist", func() { It("returns an error", func() { - help := commands.NewHelp(output, flags, jhanda.CommandSet{}) + help := commands.NewHelp(output, flags, jhanda.CommandSet{}, nil, map[string][]string{ + "House": {"cook", "clean"}, + }) err := help.Execute([]string{"missing-command"}) Expect(err).To(MatchError("unknown command: missing-command")) }) @@ -119,7 +128,9 @@ var _ = Describe("Help", func() { Flags: func() {}, }) - help := commands.NewHelp(output, flags, jhanda.CommandSet{"cook": cook}) + help := commands.NewHelp(output, flags, jhanda.CommandSet{"cook": cook}, nil, map[string][]string{ + "House": {"cook", "clean"}, + }) err := help.Execute([]string{"cook"}) Expect(err).To(MatchError("unexpected pointer to non-struct type func")) }) @@ -133,7 +144,9 @@ var _ = Describe("Help", func() { ShortDescription: "cooks you a stew", }) - help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{"cook": cook}) + help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{"cook": cook}, nil, map[string][]string{ + "House": {"cook", "clean"}, + }) err := help.Execute([]string{"cook"}) Expect(err).NotTo(HaveOccurred()) @@ -151,7 +164,9 @@ var _ = Describe("Help", func() { Flags: struct{}{}, }) - help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{"cook": cook}) + help := commands.NewHelp(output, strings.TrimSpace(flags), jhanda.CommandSet{"cook": cook}, nil, map[string][]string{ + "House": {"cook", "clean"}, + }) err := help.Execute([]string{"cook"}) Expect(err).NotTo(HaveOccurred()) @@ -164,7 +179,9 @@ var _ = Describe("Help", func() { Describe("Usage", func() { It("returns usage information for the command", func() { - help := commands.NewHelp(nil, "", jhanda.CommandSet{}) + help := commands.NewHelp(nil, "", jhanda.CommandSet{}, nil, map[string][]string{ + "House": {"cook", "clean"}, + }) Expect(help.Usage()).To(Equal(jhanda.Usage{ Description: "This command prints helpful usage information.", ShortDescription: "prints this usage information", diff --git a/internal/commands/publish.go b/internal/commands/publish.go deleted file mode 100644 index 8fe344cbd..000000000 --- a/internal/commands/publish.go +++ /dev/null @@ -1,611 +0,0 @@ -package commands - -import ( - "errors" - "fmt" - "io" - "log" - "os" - "sort" - "strconv" - "strings" - "time" - - "github.com/Masterminds/semver" - "github.com/go-git/go-billy/v5" - "github.com/pivotal-cf/go-pivnet/v2" - "github.com/pivotal-cf/go-pivnet/v2/logshim" - "github.com/pivotal-cf/jhanda" - "gopkg.in/yaml.v2" - - "github.com/pivotal-cf/kiln/pkg/cargo" -) - -const ( - publishDateFormat = "2006-01-02" - oslFileType = "Open Source License" -) - -//counterfeiter:generate -o ./fakes/pivnet_releases_service.go --fake-name PivnetReleasesService . PivnetReleasesService -type PivnetReleasesService interface { - List(productSlug string) ([]pivnet.Release, error) - Update(productSlug string, release pivnet.Release) (pivnet.Release, error) -} - -//counterfeiter:generate -o ./fakes/pivnet_product_files_service.go --fake-name PivnetProductFilesService . PivnetProductFilesService -type PivnetProductFilesService interface { - List(productSlug string) ([]pivnet.ProductFile, error) - AddToRelease(productSlug string, releaseID int, productFileID int) error -} - -//counterfeiter:generate -o ./fakes/pivnet_user_groups_service.go --fake-name PivnetUserGroupsService . PivnetUserGroupsService -type PivnetUserGroupsService interface { - List() ([]pivnet.UserGroup, error) - AddToRelease(productSlug string, releaseID int, userGroupID int) error -} - -//counterfeiter:generate -o ./fakes/pivnet_release_upgrade_paths_service.go --fake-name PivnetReleaseUpgradePathsService . PivnetReleaseUpgradePathsService -type PivnetReleaseUpgradePathsService interface { - Get(productSlug string, releaseID int) ([]pivnet.ReleaseUpgradePath, error) -} - -//counterfeiter:generate -o ./fakes/pivnet_release_dependencies_service.go --fake-name PivnetReleaseDependenciesService . PivnetReleaseDependenciesService -type PivnetReleaseDependenciesService interface { - List(productSlug string, releaseID int) ([]pivnet.ReleaseDependency, error) -} - -type Publish struct { - Options struct { - Kilnfile string `short:"kf" long:"kilnfile" default:"Kilnfile" description:"path to Kilnfile"` - Version string `short:"v" long:"version-file" default:"version" description:"path to version file"` - PivnetToken string `short:"t" long:"pivnet-token" description:"pivnet refresh token" required:"true"` - PivnetHost string `long:"pivnet-host" default:"https://network.pivotal.io" description:"pivnet host"` - IncludesSecurityFix bool `long:"security-fix" description:"the release includes security fixes"` - Window string `long:"window" required:"true"` - } - - PivnetReleaseService PivnetReleasesService - PivnetProductFilesService PivnetProductFilesService - PivnetUserGroupsService PivnetUserGroupsService - PivnetReleaseUpgradePathsService PivnetReleaseUpgradePathsService - PivnetReleaseDependenciesService PivnetReleaseDependenciesService - - FS billy.Filesystem - Now func() time.Time - - OutLogger, ErrLogger *log.Logger -} - -func NewPublish(outLogger, errLogger *log.Logger, fs billy.Filesystem) Publish { - return Publish{ - OutLogger: outLogger, - ErrLogger: errLogger, - FS: fs, - } -} - -func (p Publish) Execute(args []string) error { - defer p.recoverFromPanic() - - kilnfile, buildVersion, err := p.parseArgsAndSetup(args) - if err != nil { - return err - } - - err = p.updateReleaseOnPivnet(kilnfile, buildVersion) - if err != nil { - return fmt.Errorf("failed to publish tile: %s", err) - } else { - p.OutLogger.Println("Successfully published tile.") - } - return nil -} - -func (p Publish) recoverFromPanic() func() { - return func() { - if r := recover(); r != nil { - p.ErrLogger.Println(r) - os.Exit(1) - } - } -} - -func (p *Publish) parseArgsAndSetup(args []string) (cargo.Kilnfile, *semver.Version, error) { - _, err := jhanda.Parse(&p.Options, args) - if err != nil { - return cargo.Kilnfile{}, nil, err - } - - if p.Now == nil { - p.Now = time.Now - } - - if p.PivnetReleaseService == nil || p.PivnetProductFilesService == nil || p.PivnetUserGroupsService == nil || p.PivnetReleaseUpgradePathsService == nil || p.PivnetReleaseDependenciesService == nil { - config := pivnet.ClientConfig{ - Host: p.Options.PivnetHost, - UserAgent: "kiln", - } - - tokenService := pivnet.NewAccessTokenOrLegacyToken(p.Options.PivnetToken, p.Options.PivnetHost, false) - - logger := logshim.NewLogShim(p.OutLogger, p.ErrLogger, false) - client := pivnet.NewClient(tokenService, config, logger) - client.HTTP.Timeout = 60 * 5 * time.Second - - if p.PivnetReleaseService == nil { - p.PivnetReleaseService = client.Releases - } - - if p.PivnetProductFilesService == nil { - p.PivnetProductFilesService = client.ProductFiles - } - - if p.PivnetUserGroupsService == nil { - p.PivnetUserGroupsService = client.UserGroups - } - - if p.PivnetReleaseUpgradePathsService == nil { - p.PivnetReleaseUpgradePathsService = client.ReleaseUpgradePaths - } - - if p.PivnetReleaseDependenciesService == nil { - p.PivnetReleaseDependenciesService = client.ReleaseDependencies - } - } - - versionFile, err := p.FS.Open(p.Options.Version) - if err != nil { - return cargo.Kilnfile{}, nil, err - } - defer closeAndIgnoreError(versionFile) - - versionBuf, err := io.ReadAll(versionFile) - if err != nil { - return cargo.Kilnfile{}, nil, err - } - - version, err := semver.NewVersion(strings.TrimSpace(string(versionBuf))) - if err != nil { - return cargo.Kilnfile{}, nil, err - } - - file, err := p.FS.Open(p.Options.Kilnfile) - if err != nil { - return cargo.Kilnfile{}, nil, err - } - defer closeAndIgnoreError(file) - - var kilnfile cargo.Kilnfile - if err := yaml.NewDecoder(file).Decode(&kilnfile); err != nil { - return cargo.Kilnfile{}, nil, fmt.Errorf("could not parse Kilnfile: %s", err) - } - - window := p.Options.Window - if window != "ga" && window != "rc" && window != "beta" && window != "alpha" { - return cargo.Kilnfile{}, nil, fmt.Errorf("unknown window: %q", window) - } - - return kilnfile, version, nil -} - -func (p Publish) updateReleaseOnPivnet(kilnfile cargo.Kilnfile, buildVersion *semver.Version) error { - p.OutLogger.Printf("Requesting list of releases for %s", kilnfile.Slug) - - window := p.Options.Window - - rv, err := ReleaseVersionFromBuildVersion(buildVersion, window) - if err != nil { - return err - } - - releaseType := releaseType(window, p.Options.IncludesSecurityFix, rv) - - var releases releaseSet - releases, err = p.PivnetReleaseService.List(kilnfile.Slug) - if err != nil { - return err - } - - versionToPublish, err := p.determineVersion(releases, rv) - if err != nil { - return err - } - - _, err = releases.Find(versionToPublish.String()) - if err == nil { - return fmt.Errorf("release %s already exists", versionToPublish.String()) - } - - release, err := releases.Find(buildVersion.String()) - if err != nil { - return err - } - - licenseFileName, err := p.attachLicenseFile(kilnfile.Slug, release.ID, versionToPublish) - if err != nil { - return err - } - - upgradePaths, err := p.PivnetReleaseUpgradePathsService.Get(kilnfile.Slug, release.ID) - if err != nil { - return err - } - - if len(upgradePaths) == 0 { - return fmt.Errorf("no upgrade paths set for %s", release.Version) - } - - dependencies, err := p.PivnetReleaseDependenciesService.List(kilnfile.Slug, release.ID) - if err != nil { - return err - } - - if len(dependencies) == 0 { - return fmt.Errorf("no dependencies set for %s", release.Version) - } - - endOfSupportDate, err := p.eogsDate(rv, releases) - if err != nil { - return err - } - - var availability string - if rv.IsGA() { - availability = "All Users" - } else { - availability = "Selected User Groups Only" - } - - releaseDate := p.Now().Format(publishDateFormat) - updatedRelease, err := p.updateRelease(release, kilnfile.Slug, versionToPublish.String(), releaseType, releaseDate, endOfSupportDate, availability, licenseFileName) - if err != nil { - return err - } - - err = p.addUserGroups(rv, updatedRelease, kilnfile) - if err != nil { - return err - } - - return nil -} - -func (p Publish) eogsDate(rv *releaseVersion, releases releaseSet) (string, error) { - if rv.IsGA() { - sameMajorAndMinor, err := rv.MajorMinorConstraint() - if err != nil { - return "", err - } - - lastPatchRelease, matchExists, err := releases.FindLatest(sameMajorAndMinor) - if err != nil { - return "", err - } - - if !matchExists { - return endOfSupportFor(p.Now()), nil - } else if lastPatchRelease.EndOfSupportDate != "" { - return lastPatchRelease.EndOfSupportDate, nil - } else { - return "", fmt.Errorf("previously published release %q does not have an End of General Support date", lastPatchRelease.Version) - } - } - return "", nil -} - -func (p Publish) updateRelease(release pivnet.Release, slug, version string, releaseType pivnet.ReleaseType, releaseDate, endOfSupportDate, availability, licenseFileName string) (pivnet.Release, error) { - p.OutLogger.Println("Updating product record on PivNet...") - p.OutLogger.Printf(" Version: %s\n", version) - p.OutLogger.Printf(" Release date: %s\n", releaseDate) - p.OutLogger.Printf(" Release type: %s\n", releaseType) - if endOfSupportDate != "" { - p.OutLogger.Printf(" EOGS date: %s\n", endOfSupportDate) - } - p.OutLogger.Printf(" Availability: %s\n", availability) - if licenseFileName != "" { - p.OutLogger.Printf(" License file: %s\n", licenseFileName) - } else { - p.OutLogger.Printf(" License file: None, pre-GA release") - } - release.Version = version - release.ReleaseType = releaseType - release.ReleaseDate = releaseDate - release.EndOfSupportDate = endOfSupportDate - release.Availability = availability - updatedRelease, err := p.PivnetReleaseService.Update(slug, release) - if err != nil { - return pivnet.Release{}, err - } - return updatedRelease, nil -} - -func (p Publish) addUserGroups(rv *releaseVersion, release pivnet.Release, kilnfile cargo.Kilnfile) error { - if rv.IsGA() { - return nil - } - - var ( - err error - allUserGroups []pivnet.UserGroup - errorCount int - ) -listUserGroupsRetryLoop: - for { - allUserGroups, err = p.PivnetUserGroupsService.List() - if err != nil && errorCount < 5 { - if !strings.HasSuffix(err.Error(), "net/http: request canceled (Client.Timeout exceeded while awaiting headers)") { - return err - } - errorCount++ - p.ErrLogger.Printf("failed list user groups with error: %s", err) - p.OutLogger.Printf("retrying list command (%d retries so far)", errorCount) - continue listUserGroupsRetryLoop - } - break listUserGroupsRetryLoop - } - - p.OutLogger.Println("Granting access to groups...") - for _, userGroupName := range kilnfile.PreGaUserGroups { - p.OutLogger.Printf(" - %s\n", userGroupName) - groupFound := false - for _, userGroup := range allUserGroups { - if userGroup.Name == userGroupName { - err := p.PivnetUserGroupsService.AddToRelease(kilnfile.Slug, release.ID, userGroup.ID) - if err != nil { - return err - } - groupFound = true - break - } - } - if !groupFound { - return fmt.Errorf("no matching user group %q on Pivnet", userGroupName) - } - } - return nil -} - -func endOfSupportFor(publishDate time.Time) string { - monthWithOverflow := publishDate.Month() + 10 - month := ((monthWithOverflow - 1) % 12) + 1 - yearDelta := int((monthWithOverflow - 1) / 12) - startOfTenthMonth := time.Date(publishDate.Year()+yearDelta, month, 1, 0, 0, 0, 0, publishDate.Location()) - endOfNinthMonth := startOfTenthMonth.Add(-24 * time.Hour) - return endOfNinthMonth.Format(publishDateFormat) -} - -func (p Publish) attachLicenseFile(slug string, releaseID int, version *releaseVersion) (string, error) { - if version.IsGA() { - productFiles, err := p.PivnetProductFilesService.List(slug) - if err != nil { - return "", err - } - - productFile, found := findMatchingOSL(productFiles, version) - if !found { - return "", errors.New("required license file doesn't exist on Pivnet") - } - - err = p.PivnetProductFilesService.AddToRelease(slug, releaseID, productFile.ID) - if err == nil { - return productFile.Name, nil - } else { - return "", err - } - } - return "", nil -} - -func findMatchingOSL(productFiles []pivnet.ProductFile, version *releaseVersion) (pivnet.ProductFile, bool) { - for _, file := range productFiles { - if file.FileType == oslFileType && file.FileVersion == version.MajorAndMinor() { - return file, true - } - } - return pivnet.ProductFile{}, false -} - -func (p Publish) determineVersion(releases releaseSet, version *releaseVersion) (*releaseVersion, error) { - if version.IsGA() { - return version, nil - } - - constraint, err := version.PrereleaseVersionsConstraint() - if err != nil { - return nil, fmt.Errorf("determineVersion: error building prerelease version constraint: %w", err) - } - - latestRelease, previousReleaseExists, err := releases.FindLatest(constraint) - if err != nil { - return nil, fmt.Errorf("determineVersion: error finding the latest release: %w", err) - } - if !previousReleaseExists { - return version, nil - } - - maxPublishedVersion, err := ReleaseVersionFromPublishedVersion(latestRelease.Version) - if err != nil { - return nil, fmt.Errorf("determineVersion: error parsing release version: %w", err) - } - - version, err = version.SetPrereleaseVersion(maxPublishedVersion.PrereleaseVersion() + 1) - if err != nil { - return nil, err - } - - return version, nil -} - -func releaseType(window string, includesSecurityFix bool, v *releaseVersion) pivnet.ReleaseType { - switch window { - case "rc": - return "Release Candidate" - case "beta": - return "Beta Release" - case "alpha": - return "Alpha Release" - case "ga": - switch { - case v.IsMajor(): - return "Major Release" - case v.IsMinor(): - return "Minor Release" - default: - if includesSecurityFix { - return "Security Release" - } else { - return "Maintenance Release" - } - } - default: - return "Developer Release" - } -} - -// Usage writes helpful information. -func (p Publish) Usage() jhanda.Usage { - return jhanda.Usage{ - Description: "UpdateStemcell release date, end of general support date, and license files for a tile on Pivnet.", - ShortDescription: "publish tile on Pivnet", - Flags: p.Options, - } -} - -type releaseSet []pivnet.Release - -func (rs releaseSet) Find(version string) (pivnet.Release, error) { - for _, r := range rs { - if r.Version == version { - return r, nil - } - } - - return pivnet.Release{}, fmt.Errorf("release with version %s not found", version) -} - -func (rs releaseSet) FindLatest(constraint *semver.Constraints) (pivnet.Release, bool, error) { - var matches []pivnet.Release - for _, release := range rs { - v, err := semver.NewVersion(release.Version) - if err != nil { - continue - } - - if constraint.Check(v) { - matches = append(matches, release) - } - } - - if len(matches) == 0 { - return pivnet.Release{}, false, nil - } - - sort.Slice(matches, func(i, j int) bool { - v1 := semver.MustParse(matches[i].Version) - v2 := semver.MustParse(matches[j].Version) - return v1.LessThan(v2) - }) - - return matches[len(matches)-1], true, nil -} - -type releaseVersion struct { - semver semver.Version - window string - prereleaseVersion int -} - -func ReleaseVersionFromBuildVersion(baseVersion *semver.Version, window string) (*releaseVersion, error) { - v2, err := baseVersion.SetPrerelease("") - if err != nil { - return nil, fmt.Errorf("ReleaseVersionFromBuildVersion: error clearing prerelease of %q: %w", v2, err) - } - - rv := &releaseVersion{semver: v2, window: window, prereleaseVersion: 0} - - if window != "ga" { - rv, err = rv.SetPrereleaseVersion(1) - if err != nil { - return nil, fmt.Errorf("ReleaseVersionFromBuildVersion: error setting prerelease of %q to 1: %w", rv, err) - } - } - return rv, nil -} - -func ReleaseVersionFromPublishedVersion(versionString string) (*releaseVersion, error) { - version, err := semver.NewVersion(versionString) - if err != nil { - return nil, fmt.Errorf("ReleaseVersionFromPublishedVersion: unable to parse version %q: %w", versionString, err) - } - segments := strings.Split(version.Prerelease(), ".") - if len(segments) != 2 { - return nil, fmt.Errorf("ReleaseVersionFromPublishedVersion: expected prerelease to have a dot (%q)", version) - } - - window := segments[0] - prereleaseVersion, err := strconv.Atoi(segments[len(segments)-1]) - if err != nil { - return nil, fmt.Errorf("ReleaseVersionFromPublishedVersion: release has malformed prelease version (%s): %w", version, err) - } - - return &releaseVersion{ - semver: *version, - window: window, - prereleaseVersion: prereleaseVersion, - }, nil -} - -func (rv releaseVersion) MajorMinorConstraint() (*semver.Constraints, error) { - return semver.NewConstraint(fmt.Sprintf("~%d.%d.0", rv.semver.Major(), rv.semver.Minor())) -} - -func (rv releaseVersion) PrereleaseVersionsConstraint() (*semver.Constraints, error) { - if rv.IsGA() { - return nil, fmt.Errorf("can't determine PrereleaseVersionsConstraint for %q, which is GA", rv.semver) - } - coreVersion := fmt.Sprintf("%d.%d.%d-%s", rv.semver.Major(), rv.semver.Minor(), rv.semver.Patch(), rv.window) - constraintStr := fmt.Sprintf(">= %s.0, <= %s.9999", coreVersion, coreVersion) - return semver.NewConstraint(constraintStr) -} - -func (rv releaseVersion) SetPrereleaseVersion(prereleaseVersion int) (*releaseVersion, error) { - if rv.IsGA() { - return nil, fmt.Errorf("SetPrereleaseVersion: can't set the prerelease version on a GA version (%q)", rv.String()) - } - v, err := rv.semver.SetPrerelease(fmt.Sprintf("%s.%d", rv.window, prereleaseVersion)) - if err != nil { - return nil, fmt.Errorf("SetPrereleaseVersion: couldn't set prerelease: %w", err) - } - rv.semver = v - rv.prereleaseVersion = prereleaseVersion - - return &rv, nil -} - -func (rv releaseVersion) IsGA() bool { - return rv.window == "ga" -} - -func (rv releaseVersion) IsMajor() bool { - return rv.semver.Minor() == 0 && rv.semver.Patch() == 0 -} - -func (rv releaseVersion) IsMinor() bool { - return rv.semver.Minor() != 0 && rv.semver.Patch() == 0 -} - -func (rv releaseVersion) String() string { - return rv.semver.String() -} - -func (rv releaseVersion) MajorAndMinor() string { - return fmt.Sprintf("%d.%d", rv.semver.Major(), rv.semver.Minor()) -} - -func (rv releaseVersion) Semver() *semver.Version { - return &rv.semver -} - -func (rv releaseVersion) PrereleaseVersion() int { - return rv.prereleaseVersion -} diff --git a/internal/commands/upload_release.go b/internal/commands/publish_release.go similarity index 95% rename from internal/commands/upload_release.go rename to internal/commands/publish_release.go index 820430734..ea93facf1 100644 --- a/internal/commands/upload_release.go +++ b/internal/commands/publish_release.go @@ -14,7 +14,7 @@ import ( "github.com/pivotal-cf/kiln/pkg/cargo" ) -type UploadRelease struct { +type PublishRelease struct { FS billy.Filesystem ReleaseUploaderFinder ReleaseUploaderFinder Logger *log.Logger @@ -30,7 +30,7 @@ type UploadRelease struct { //counterfeiter:generate -o ./fakes/release_uploader_finder.go --fake-name ReleaseUploaderFinder . ReleaseUploaderFinder type ReleaseUploaderFinder func(cargo.Kilnfile, string) (component.ReleaseUploader, error) -func (command UploadRelease) Execute(args []string) error { +func (command *PublishRelease) Execute(args []string) error { _, err := flags.LoadFlagsWithDefaults(&command.Options, args, command.FS.Stat) if err != nil { return err @@ -95,7 +95,7 @@ func (command UploadRelease) Execute(args []string) error { return nil } -func (command UploadRelease) Usage() jhanda.Usage { +func (command *PublishRelease) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Uploads a BOSH Release to an S3 release source for use in kiln fetch", ShortDescription: "uploads a BOSH release to an s3 release_source", diff --git a/internal/commands/upload_release_test.go b/internal/commands/publish_release_test.go similarity index 80% rename from internal/commands/upload_release_test.go rename to internal/commands/publish_release_test.go index 9b960efa0..af6bee2be 100644 --- a/internal/commands/upload_release_test.go +++ b/internal/commands/publish_release_test.go @@ -1,11 +1,16 @@ package commands_test import ( + "archive/tar" + "compress/gzip" "crypto/sha1" "errors" "fmt" "io" "log" + "os" + "strings" + "time" "github.com/go-git/go-billy/v5" "github.com/go-git/go-billy/v5/memfs" @@ -17,18 +22,17 @@ import ( commandsFakes "github.com/pivotal-cf/kiln/internal/commands/fakes" "github.com/pivotal-cf/kiln/internal/component" "github.com/pivotal-cf/kiln/internal/component/fakes" - testHelpers "github.com/pivotal-cf/kiln/internal/test-helpers" "github.com/pivotal-cf/kiln/pkg/cargo" ) -var _ = Describe("UploadRelease", func() { +var _ = Describe("PublishRelease", func() { Context("Execute", func() { var ( fs billy.Filesystem releaseUploaderFinder *commandsFakes.ReleaseUploaderFinder releaseUploader *fakes.ReleaseUploader - uploadRelease commands.UploadRelease + uploadRelease commands.PublishRelease expectedReleaseSHA string ) @@ -41,7 +45,7 @@ var _ = Describe("UploadRelease", func() { releaseUploaderFinder = new(commandsFakes.ReleaseUploaderFinder) releaseUploaderFinder.Returns(releaseUploader, nil) - uploadRelease = commands.UploadRelease{ + uploadRelease = commands.PublishRelease{ FS: fs, Logger: log.New(GinkgoWriter, "", 0), ReleaseUploaderFinder: releaseUploaderFinder.Spy, @@ -51,7 +55,7 @@ var _ = Describe("UploadRelease", func() { Expect(fsWriteYAML(fs, "Kilnfile.lock", cargo.KilnfileLock{})).NotTo(HaveOccurred()) var err error - expectedReleaseSHA, err = testHelpers.WriteReleaseTarball("banana-release.tgz", "banana", "1.2.3", fs) + expectedReleaseSHA, err = writeReleaseTarball("banana-release.tgz", "banana", "1.2.3", fs) Expect(err).NotTo(HaveOccurred()) }) @@ -105,7 +109,7 @@ var _ = Describe("UploadRelease", func() { When("the release tarball is compiled", func() { BeforeEach(func() { - _, err := testHelpers.WriteTarballWithFile("banana-release.tgz", "release.MF", ` + _, err := writeTarballWithFile("banana-release.tgz", "release.MF", ` name: banana version: 1.2.3 compiled_packages: @@ -138,7 +142,7 @@ compiled_packages: BeforeEach(func() { for _, rel := range devReleases { - _, err = testHelpers.WriteReleaseTarball(rel.tarballName, "banana", rel.version, fs) + _, err = writeReleaseTarball(rel.tarballName, "banana", rel.version, fs) Expect(err).NotTo(HaveOccurred()) } }) @@ -158,7 +162,7 @@ compiled_packages: When("the release version is malformed", func() { BeforeEach(func() { - _, err := testHelpers.WriteReleaseTarball("banana-malformed.tgz", "banana", "v1_2_garbage", fs) + _, err := writeReleaseTarball("banana-malformed.tgz", "banana", "v1_2_garbage", fs) Expect(err).NotTo(HaveOccurred()) }) @@ -248,3 +252,68 @@ compiled_packages: }) }) }) + +func writeReleaseTarball(path, name, version string, fs billy.Filesystem) (string, error) { + releaseManifest := ` +name: ` + name + ` +version: ` + version + ` +` + return writeTarballWithFile(path, "release.MF", releaseManifest, fs) +} + +func writeTarballWithFile(tarballPath, internalFilePath, fileContents string, fs billy.Filesystem) (string, error) { + f, err := fs.Create(tarballPath) + if err != nil { + return "", err + } + + gw := gzip.NewWriter(f) + tw := tar.NewWriter(gw) + + contentsReader := strings.NewReader(fileContents) + + header := &tar.Header{ + Name: internalFilePath, + Size: contentsReader.Size(), + Mode: int64(os.O_RDONLY), + ModTime: time.Now(), + } + err = tw.WriteHeader(header) + if err != nil { + return "", err + } + + _, err = io.Copy(tw, contentsReader) + if err != nil { + return "", err + } + + err = tw.Close() + if err != nil { + return "", err + } + + err = gw.Close() + if err != nil { + return "", err + } + + err = f.Close() + if err != nil { + return "", err + } + + tarball, err := fs.Open(tarballPath) + if err != nil { + return "", err + } + defer closeAndIgnoreError(tarball) + + hash := sha1.New() + _, err = io.Copy(hash, tarball) + if err != nil { + return "", err + } + + return fmt.Sprintf("%x", hash.Sum(nil)), nil +} diff --git a/internal/commands/publish_test.go b/internal/commands/publish_test.go deleted file mode 100644 index 4ba19e66a..000000000 --- a/internal/commands/publish_test.go +++ /dev/null @@ -1,1023 +0,0 @@ -package commands_test - -import ( - "errors" - "io" - "log" - "strings" - "time" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/Masterminds/semver" - "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/memfs" - "github.com/pivotal-cf/go-pivnet/v2" - - "github.com/pivotal-cf/kiln/internal/commands" - commandsFakes "github.com/pivotal-cf/kiln/internal/commands/fakes" -) - -var _ = Describe("Publish", func() { - const ( - slug = "elastic-runtime" - userGroup1Name = "Dell/EMC Early Access Group" - userGroup1ID = 123 - userGroup2Name = "PCF R&D" - userGroup2ID = 456 - - defaultKilnFileBody = `--- -slug: ` + slug + ` -pre_ga_user_groups: - - ` + userGroup1Name + ` - - ` + userGroup2Name + ` -` - ) - - var someVersion *semver.Version - BeforeEach(func() { - someVersion = semver.MustParse("2.8.0-build.111") - }) - - Describe("Execute", func() { - When("on the happy-path", func() { - var ( - publish commands.Publish - rs *commandsFakes.PivnetReleasesService - pfs *commandsFakes.PivnetProductFilesService - ugs *commandsFakes.PivnetUserGroupsService - releaseUpgradePathsService *commandsFakes.PivnetReleaseUpgradePathsService - releaseDependenciesService *commandsFakes.PivnetReleaseDependenciesService - now time.Time - versionStr string - releasesOnPivnet []pivnet.Release - outLoggerBuffer strings.Builder - ) - const releaseID = 123 - - BeforeEach(func() { - versionStr = "2.0.0-build.45" - rs = new(commandsFakes.PivnetReleasesService) - pfs = new(commandsFakes.PivnetProductFilesService) - ugs = new(commandsFakes.PivnetUserGroupsService) - releaseUpgradePathsService = new(commandsFakes.PivnetReleaseUpgradePathsService) - releaseUpgradePathsService.GetReturns([]pivnet.ReleaseUpgradePath{{}}, nil) - releaseDependenciesService = new(commandsFakes.PivnetReleaseDependenciesService) - releaseDependenciesService.ListReturns([]pivnet.ReleaseDependency{{}}, nil) - releasesOnPivnet = []pivnet.Release{} - now = time.Now() - outLoggerBuffer = strings.Builder{} - }) - - JustBeforeEach(func() { - if len(releasesOnPivnet) == 0 { - releasesOnPivnet = []pivnet.Release{{Version: versionStr, ID: releaseID}} - } - rs.ListReturns(releasesOnPivnet, nil) - - rs.UpdateReturns(pivnet.Release{ID: releaseID}, nil) - - ugs.ListReturns([]pivnet.UserGroup{ - {ID: userGroup1ID, Name: userGroup1Name}, - {ID: 123, Name: "Ignore me!"}, - {ID: userGroup2ID, Name: userGroup2Name}, - }, nil) - - fs := memfs.New() - vf, _ := fs.Create("version") - _, _ = vf.Write([]byte(versionStr)) - defer closeAndIgnoreError(vf) - - kf, _ := fs.Create("Kilnfile") - _, _ = kf.Write([]byte(defaultKilnFileBody)) - defer closeAndIgnoreError(kf) - - publish = commands.Publish{ - FS: fs, - PivnetReleaseService: rs, - PivnetProductFilesService: pfs, - PivnetUserGroupsService: ugs, - PivnetReleaseUpgradePathsService: releaseUpgradePathsService, - PivnetReleaseDependenciesService: releaseDependenciesService, - Now: func() time.Time { - return now - }, - OutLogger: log.New(&outLoggerBuffer, "", 0), - ErrLogger: log.New(io.Discard, "", 0), - } - }) - - Context("during the alpha window", func() { - var args []string - - BeforeEach(func() { - args = []string{"--window", "alpha", "--pivnet-token", "SOME_TOKEN"} - }) - - It("updates Pivnet release with the determined version and release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.ListCallCount()).To(Equal(1)) - Expect(rs.ListArgsForCall(0)).To(Equal(slug)) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0-alpha.1")) - Expect(r.ReleaseType).To(BeEquivalentTo("Alpha Release")) - Expect(r.EndOfSupportDate).To(Equal("")) - Expect(r.ReleaseDate).To(Equal(now.Format("2006-01-02"))) - Expect(r.Availability).To(Equal("Selected User Groups Only")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.0.0-alpha.1")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Alpha Release")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release date: %s", now.Format("2006-01-02"))) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Availability: Selected User Groups Only")) - }) - - It("does not add a file to the release", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(pfs.AddToReleaseCallCount()).To(Equal(0)) - Expect(outLoggerBuffer.String()).To(ContainSubstring(" License file: None, pre-GA release")) - }) - - It("adds the pre-GA user groups to the release", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(ugs.ListCallCount()).To(Equal(1)) - - Expect(ugs.AddToReleaseCallCount()).To(Equal(2)) - - s, rid, ugid := ugs.AddToReleaseArgsForCall(0) - Expect(s).To(Equal(s)) - Expect(rid).To(Equal(releaseID)) - Expect(ugid).To(Equal(userGroup1ID)) - - s, rid, ugid = ugs.AddToReleaseArgsForCall(1) - Expect(s).To(Equal(s)) - Expect(rid).To(Equal(releaseID)) - Expect(ugid).To(Equal(userGroup2ID)) - - Expect(outLoggerBuffer.String()).To(ContainSubstring("Granting access to groups...")) - Expect(outLoggerBuffer.String()).To(ContainSubstring(userGroup1Name)) - Expect(outLoggerBuffer.String()).To(ContainSubstring(userGroup2Name)) - - Expect(outLoggerBuffer.String()).To(ContainSubstring("Successfully published tile.")) - }) - - Context("when previous alphas have been published", func() { - BeforeEach(func() { - releasesOnPivnet = []pivnet.Release{ - {Version: versionStr, ID: releaseID}, - {Version: "2.0.0-alpha.456"}, - } - }) - - It("publishes with a version that increments the alpha number", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0-alpha.457")) - }) - }) - - Context("when the --security-fix flag is given", func() { - BeforeEach(func() { - args = append(args, "--security-fix") - }) - - It("sets the correct release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - _, r := rs.UpdateArgsForCall(0) - Expect(r.ReleaseType).To(BeEquivalentTo("Alpha Release")) - }) - }) - }) - - Context("during the beta window", func() { - var args []string - - BeforeEach(func() { - args = []string{"--window", "beta", "--pivnet-token", "SOME_TOKEN"} - }) - - It("updates Pivnet release with the determined version and release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.ListCallCount()).To(Equal(1)) - Expect(rs.ListArgsForCall(0)).To(Equal(slug)) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0-beta.1")) - Expect(r.ReleaseType).To(BeEquivalentTo("Beta Release")) - Expect(r.EndOfSupportDate).To(Equal("")) - Expect(r.ReleaseDate).To(Equal(now.Format("2006-01-02"))) - Expect(r.Availability).To(Equal("Selected User Groups Only")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.0.0-beta.1")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Beta Release")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release date: %s", now.Format("2006-01-02"))) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Availability: Selected User Groups Only")) - }) - - It("does not add a file to the release", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(pfs.AddToReleaseCallCount()).To(Equal(0)) - Expect(outLoggerBuffer.String()).To(ContainSubstring(" License file: None, pre-GA release")) - }) - - It("adds the pre-GA user groups to the release", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(ugs.ListCallCount()).To(Equal(1)) - - Expect(ugs.AddToReleaseCallCount()).To(Equal(2)) - - s, rid, ugid := ugs.AddToReleaseArgsForCall(0) - Expect(s).To(Equal(s)) - Expect(rid).To(Equal(releaseID)) - Expect(ugid).To(Equal(userGroup1ID)) - - s, rid, ugid = ugs.AddToReleaseArgsForCall(1) - Expect(s).To(Equal(s)) - Expect(rid).To(Equal(releaseID)) - Expect(ugid).To(Equal(userGroup2ID)) - }) - - Context("when previous betas have been published", func() { - BeforeEach(func() { - releasesOnPivnet = []pivnet.Release{ - {Version: versionStr, ID: releaseID}, - {Version: "2.0.0-beta.123"}, - } - }) - - It("publishes with a version that increments the alpha number", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0-beta.124")) - }) - }) - - Context("when the --security-fix flag is given", func() { - BeforeEach(func() { - args = append(args, "--security-fix") - }) - - It("sets the correct release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - _, r := rs.UpdateArgsForCall(0) - Expect(r.ReleaseType).To(BeEquivalentTo("Beta Release")) - }) - }) - }) - - Context("during the rc window", func() { - var args []string - - BeforeEach(func() { - args = []string{"--window", "rc", "--pivnet-token", "SOME_TOKEN"} - }) - - It("updates Pivnet release with the determined version and release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.ListCallCount()).To(Equal(1)) - Expect(rs.ListArgsForCall(0)).To(Equal(slug)) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0-rc.1")) - Expect(r.ReleaseType).To(BeEquivalentTo("Release Candidate")) - Expect(r.EndOfSupportDate).To(Equal("")) - Expect(r.ReleaseDate).To(Equal(now.Format("2006-01-02"))) - Expect(r.Availability).To(Equal("Selected User Groups Only")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.0.0-rc.1")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Release Candidate")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release date: %s", now.Format("2006-01-02"))) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Availability: Selected User Groups Only")) - }) - - It("does not add a file to the release", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(pfs.AddToReleaseCallCount()).To(Equal(0)) - Expect(outLoggerBuffer.String()).To(ContainSubstring(" License file: None, pre-GA release")) - }) - - It("adds the pre-GA user groups to the release", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(ugs.ListCallCount()).To(Equal(1)) - - Expect(ugs.AddToReleaseCallCount()).To(Equal(2)) - - s, rid, ugid := ugs.AddToReleaseArgsForCall(0) - Expect(s).To(Equal(s)) - Expect(rid).To(Equal(releaseID)) - Expect(ugid).To(Equal(userGroup1ID)) - - s, rid, ugid = ugs.AddToReleaseArgsForCall(1) - Expect(s).To(Equal(s)) - Expect(rid).To(Equal(releaseID)) - Expect(ugid).To(Equal(userGroup2ID)) - - Expect(outLoggerBuffer.String()).To(ContainSubstring("Granting access to groups...")) - Expect(outLoggerBuffer.String()).To(ContainSubstring(userGroup1Name)) - Expect(outLoggerBuffer.String()).To(ContainSubstring(userGroup2Name)) - }) - - Context("when previous release candidates have been published", func() { - BeforeEach(func() { - releasesOnPivnet = []pivnet.Release{ - {Version: versionStr, ID: releaseID}, - {Version: "2.0.0-rc.2"}, - {Version: "2.0.0-rc.1"}, - } - }) - - It("publishes with a version that increments the alpha number", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0-rc.3")) - }) - }) - - Context("when the --security-fix flag is given", func() { - BeforeEach(func() { - args = append(args, "--security-fix") - }) - - It("sets the correct release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - _, r := rs.UpdateArgsForCall(0) - Expect(r.ReleaseType).To(BeEquivalentTo("Release Candidate")) - }) - }) - }) - - Context("during the ga window", func() { - const ( - version20FileID = 42 - version21FileID = 43 - ) - var ( - args []string - endOfSupportDate string - ) - - BeforeEach(func() { - args = []string{"--window", "ga", "--pivnet-token", "SOME_TOKEN"} - - now = time.Date(2016, 5, 4, 3, 2, 1, 0, time.Local) - endOfSupportDate = "2017-02-28" // by default, PivNet does not have EOGS: now + 300 days - - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 40, - Name: "Uncle Bob's Magic Elixir", - FileVersion: "2.0", - FileType: "Snake Oil", - }, - { - ID: 41, - Name: "Uncle Bob's Magic Elixir", - FileVersion: "2.1", - FileType: "Snake Oil", - }, - { - ID: version21FileID, - Name: "PCF Pivotal Application Service v2.1 OSL", - FileVersion: "2.1", - FileType: "Open Source License", - }, - { - ID: version20FileID, - Name: "PCF Pivotal Application Service v2.0 OSL", - FileVersion: "2.0", - FileType: "Open Source License", - }, - }, - nil, - ) - }) - - Context("for a major release", func() { - BeforeEach(func() { - versionStr = "2.0.0-build.45" - }) - - It("updates Pivnet release with the determined version and release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.ListCallCount()).To(Equal(1)) - Expect(rs.ListArgsForCall(0)).To(Equal(slug)) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.0.0")) - Expect(r.ReleaseType).To(BeEquivalentTo("Major Release")) - Expect(r.EndOfSupportDate).To(Equal(endOfSupportDate)) - Expect(r.ReleaseDate).To(Equal("2016-05-04")) - Expect(r.Availability).To(Equal("All Users")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.0.0")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Major Release")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release date: %s", now.Format("2006-01-02"))) - Expect(outLoggerBuffer.String()).To(ContainSubstring("EOGS date: %s", endOfSupportDate)) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Availability: All Users")) - }) - - It("adds the appropriate OSL file", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(pfs.AddToReleaseCallCount()).To(Equal(1)) - productSlug, productReleaseID, fileID := pfs.AddToReleaseArgsForCall(0) - Expect(productSlug).To(Equal(slug)) - Expect(productReleaseID).To(Equal(releaseID)) - Expect(fileID).To(Equal(version20FileID)) - - Expect(outLoggerBuffer.String()).To(ContainSubstring("License file: PCF Pivotal Application Service v2.0 OSL")) - }) - - Context("when the --security-fix flag is given", func() { - BeforeEach(func() { - args = append(args, "--security-fix") - }) - - It("sets the correct release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - _, r := rs.UpdateArgsForCall(0) - Expect(r.ReleaseType).To(BeEquivalentTo("Major Release")) - }) - }) - }) - - Context("for a minor release", func() { - BeforeEach(func() { - versionStr = "2.1.0-build.45" - }) - - It("updates Pivnet release with the determined version and release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.ListCallCount()).To(Equal(1)) - Expect(rs.ListArgsForCall(0)).To(Equal(slug)) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.1.0")) - Expect(r.ReleaseType).To(BeEquivalentTo("Minor Release")) - Expect(r.EndOfSupportDate).To(Equal(endOfSupportDate)) - Expect(r.ReleaseDate).To(Equal("2016-05-04")) - Expect(r.Availability).To(Equal("All Users")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.1.0")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Minor Release")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release date: %s", now.Format("2006-01-02"))) - Expect(outLoggerBuffer.String()).To(ContainSubstring("EOGS date: %s", endOfSupportDate)) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Availability: All Users")) - }) - - It("adds the appropriate OSL file", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(pfs.AddToReleaseCallCount()).To(Equal(1)) - productSlug, productReleaseID, fileID := pfs.AddToReleaseArgsForCall(0) - Expect(productSlug).To(Equal(slug)) - Expect(productReleaseID).To(Equal(releaseID)) - Expect(fileID).To(Equal(version21FileID)) - - Expect(outLoggerBuffer.String()).To(ContainSubstring("License file: PCF Pivotal Application Service v2.1 OSL")) - }) - - Context("when the --security-fix flag is given", func() { - BeforeEach(func() { - args = append(args, "--security-fix") - }) - - It("sets the correct release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - _, r := rs.UpdateArgsForCall(0) - Expect(r.ReleaseType).To(BeEquivalentTo("Minor Release")) - }) - }) - }) - - Context("for a patch release", func() { - BeforeEach(func() { - versionStr = "2.1.1-build.45" - endOfSupportDate = "2019-07-31" - - releasesOnPivnet = []pivnet.Release{ - {Version: versionStr, ID: releaseID}, - {Version: "2.1.0", EndOfSupportDate: endOfSupportDate}, - {Version: "2.1.1-build.1234"}, - {Version: "2.0.0", EndOfSupportDate: "2010-01-05"}, - } - }) - - It("updates Pivnet release with the determined version and release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.ListCallCount()).To(Equal(1)) - Expect(rs.ListArgsForCall(0)).To(Equal(slug)) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.1.1")) - Expect(r.ReleaseType).To(BeEquivalentTo("Maintenance Release")) - Expect(r.EndOfSupportDate).To(Equal(endOfSupportDate)) - Expect(r.ReleaseDate).To(Equal("2016-05-04")) - Expect(r.Availability).To(Equal("All Users")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.1.1")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Maintenance Release")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release date: %s", now.Format("2006-01-02"))) - Expect(outLoggerBuffer.String()).To(ContainSubstring("EOGS date: %s", endOfSupportDate)) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Availability: All Users")) - }) - - It("adds the appropriate OSL file", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(pfs.AddToReleaseCallCount()).To(Equal(1)) - productSlug, productReleaseID, fileID := pfs.AddToReleaseArgsForCall(0) - Expect(productSlug).To(Equal(slug)) - Expect(productReleaseID).To(Equal(releaseID)) - Expect(fileID).To(Equal(version21FileID)) - - Expect(outLoggerBuffer.String()).To(ContainSubstring("License file: PCF Pivotal Application Service v2.1 OSL")) - }) - - Context("when the --security-fix flag is given", func() { - BeforeEach(func() { - args = append(args, "--security-fix") - }) - - It("sets the correct release type", func() { - err := publish.Execute(args) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - _, r := rs.UpdateArgsForCall(0) - Expect(r.ReleaseType).To(BeEquivalentTo("Security Release")) - }) - }) - }) - }) - }) - - When("the sad/unhappy case", func() { - var ( - publish commands.Publish - now time.Time - fs billy.Filesystem - - noVersionFile, noKilnFile bool - versionFileBody, kilnFileBody string - rs *commandsFakes.PivnetReleasesService - pfs *commandsFakes.PivnetProductFilesService - ugs *commandsFakes.PivnetUserGroupsService - releaseUpgradePathsService *commandsFakes.PivnetReleaseUpgradePathsService - releaseDependenciesService *commandsFakes.PivnetReleaseDependenciesService - - executeArgs []string - outLoggerBuffer strings.Builder - ) - - BeforeEach(func() { - publish = commands.Publish{} - publish.Options.Kilnfile = "Kilnfile" - outLoggerBuffer = strings.Builder{} - publish.OutLogger = log.New(&outLoggerBuffer, "", 0) - publish.ErrLogger = log.New(io.Discard, "", 0) - - rs = new(commandsFakes.PivnetReleasesService) - pfs = new(commandsFakes.PivnetProductFilesService) - ugs = new(commandsFakes.PivnetUserGroupsService) - releaseUpgradePathsService = new(commandsFakes.PivnetReleaseUpgradePathsService) - releaseUpgradePathsService.GetReturns([]pivnet.ReleaseUpgradePath{{}}, nil) - - releaseDependenciesService = new(commandsFakes.PivnetReleaseDependenciesService) - releaseDependenciesService.ListReturns([]pivnet.ReleaseDependency{{}}, nil) - - noVersionFile, noKilnFile = false, false - fs = memfs.New() - kilnFileBody = defaultKilnFileBody - - executeArgs = []string{"--pivnet-token", "SOME_TOKEN", "--window", "ga"} - }) - - JustBeforeEach(func() { - versionFileBody = someVersion.String() - - if !noVersionFile { - version, _ := fs.Create("version") - _, _ = version.Write([]byte(versionFileBody)) - defer closeAndIgnoreError(version) - } - - if !noKilnFile { - kilnFile, _ := fs.Create("Kilnfile") - _, _ = kilnFile.Write([]byte(kilnFileBody)) - defer closeAndIgnoreError(kilnFile) - } - - publish.FS = fs - publish.PivnetReleaseService = rs - publish.PivnetProductFilesService = pfs - publish.PivnetUserGroupsService = ugs - publish.PivnetReleaseUpgradePathsService = releaseUpgradePathsService - publish.PivnetReleaseDependenciesService = releaseDependenciesService - publish.Now = func() time.Time { - return now - } - }) - - When("the window flag is not provided", func() { - BeforeEach(func() { - executeArgs = []string{"--pivnet-token", "SOME_TOKEN"} - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("missing required flag \"--window\""))) - }) - }) - - When("the an unknown window is provided", func() { - BeforeEach(func() { - executeArgs = []string{"--window", "nosuchwindow", "--pivnet-token", "SOME_TOKEN"} - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("unknown window: \"nosuchwindow\""))) - }) - }) - - When("the release is already published", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: "2.8.0"}}, nil) - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("release 2.8.0 already exists"))) - }) - }) - - When("the release to be updated is not found", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: "1.2.3-build.1"}}, nil) - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("release with version " + someVersion.String() + " not found"))) - }) - }) - - When("the version file contains an invalid semver", func() { - BeforeEach(func() { - versionFileBody = "not a banana" - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - }) - }) - - When("the Kilnfile does not exist", func() { - BeforeEach(func() { - noVersionFile = true - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("file does not exist"))) - }) - }) - - When("the Kilnfile does not exist", func() { - BeforeEach(func() { - noKilnFile = true - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("file does not exist"))) - }) - }) - - When("there is bad yaml in the file", func() { - BeforeEach(func() { - kilnFileBody = `}` - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("yaml:"))) - }) - }) - - When("there is an error fetching product files from Pivnet", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - pfs.ListReturns(nil, errors.New("bad stuff happened")) - }) - - It("returns an error and makes no changes", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(0)) - Expect(pfs.ListCallCount()).To(Equal(1)) - Expect(pfs.AddToReleaseCallCount()).To(Equal(0)) - Expect(err).To(MatchError(ContainSubstring("bad stuff happened"))) - }) - }) - - When("there the necessary license file doesn't exist on Pivnet", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 42, - Name: "PCF Pivotal Application Service v2.1 OSL", - FileVersion: "2.1", - FileType: "Open Source License", - }, - }, - nil, - ) - }) - - It("returns an error and makes no changes", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("file doesn't exist"))) - - Expect(rs.UpdateCallCount()).To(Equal(0)) - Expect(pfs.ListCallCount()).To(Equal(1)) - Expect(pfs.AddToReleaseCallCount()).To(Equal(0)) - }) - }) - - When("there is an error adding the license file to the release on Pivnet", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 42, - Name: "PCF Pivotal Application Service v2.8 OSL", - FileVersion: "2.8", - FileType: "Open Source License", - }, - }, - nil, - ) - pfs.AddToReleaseReturns(errors.New("more bad stuff happened")) - }) - - It("returns an error and makes no changes", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(0)) - Expect(pfs.ListCallCount()).To(Equal(1)) - Expect(pfs.AddToReleaseCallCount()).To(Equal(1)) - Expect(err).To(MatchError(ContainSubstring("failed to publish tile: more bad stuff happened"))) - }) - }) - - When("a release on PivNet has an invalid version", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{ - {Version: someVersion.String()}, - {Version: "invalid version"}, - }, nil) - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 42, - Name: "PCF Pivotal Application Service v2.8 OSL", - FileVersion: "2.8", - FileType: "Open Source License", - }, - }, - nil, - ) - }) - - It("ignores that release and updates the correct release", func() { - err := publish.Execute(executeArgs) - Expect(err).NotTo(HaveOccurred()) - - Expect(rs.UpdateCallCount()).To(Equal(1)) - { - s, r := rs.UpdateArgsForCall(0) - Expect(s).To(Equal(slug)) - Expect(r.Version).To(Equal("2.8.0")) - Expect(r.ReleaseType).To(BeEquivalentTo("Minor Release")) - } - Expect(outLoggerBuffer.String()).To(ContainSubstring("Version: 2.8.0")) - Expect(outLoggerBuffer.String()).To(ContainSubstring("Release type: Minor Release")) - }) - }) - - When("the previous release on PivNet does not have an EOGS date", func() { - BeforeEach(func() { - someVersion = semver.MustParse("2.9.1-build.111") - - rs.ListReturns([]pivnet.Release{ - {Version: someVersion.String(), ID: 99}, - {Version: "2.9.0", EndOfSupportDate: ""}, - }, nil) - - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 42, - Name: "PCF Pivotal Application Service v2.9 OSL", - FileVersion: "2.9", - FileType: "Open Source License", - }, - }, - nil, - ) - }) - - It("returns an error instead of publishing the release", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("does not have an End of General Support date"))) - - Expect(rs.UpdateCallCount()).To(Equal(0)) - }) - }) - - When("there is an error fetching user groups from PivNet", func() { - BeforeEach(func() { - executeArgs = []string{"--pivnet-token", "SOME_TOKEN", "--window", "rc"} - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - ugs.ListReturns(nil, errors.New("error returning user groups")) - }) - - It("returns an error ", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("error returning user groups"))) - }) - }) - - When("there is an error adding a user group to release", func() { - BeforeEach(func() { - executeArgs = []string{"--pivnet-token", "SOME_TOKEN", "--window", "rc"} - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - ugs.ListReturns([]pivnet.UserGroup{ - {ID: userGroup1ID, Name: userGroup1Name}, - {ID: userGroup2ID, Name: userGroup2Name}, - }, nil) - ugs.AddToReleaseReturns(errors.New("error adding user group to release")) - }) - - It("returns an error ", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("error adding user group to release"))) - }) - }) - - When("one of the required user groups doesn't exist", func() { - BeforeEach(func() { - executeArgs = []string{"--pivnet-token", "SOME_TOKEN", "--window", "rc"} - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - ugs.ListReturns([]pivnet.UserGroup{ - {ID: userGroup2ID, Name: userGroup2Name}, - }, nil) - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring(userGroup1Name))) - }) - }) - - When("upgrade path is empty", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 42, - Name: "PCF Pivotal Application Service v2.8 OSL", - FileVersion: "2.8", - FileType: "Open Source License", - }, - }, - nil, - ) - releaseUpgradePathsService.GetReturns([]pivnet.ReleaseUpgradePath{}, nil) - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("no upgrade paths set for 2.8"))) - }) - }) - - When("dependencies is empty", func() { - BeforeEach(func() { - rs.ListReturns([]pivnet.Release{{Version: someVersion.String()}}, nil) - pfs.ListReturns( - []pivnet.ProductFile{ - { - ID: 42, - Name: "PCF Pivotal Application Service v2.8 OSL", - FileVersion: "2.8", - FileType: "Open Source License", - }, - }, - nil, - ) - releaseDependenciesService.ListReturns([]pivnet.ReleaseDependency{}, nil) - }) - - It("returns an error", func() { - err := publish.Execute(executeArgs) - Expect(err).To(HaveOccurred()) - Expect(err).To(MatchError(ContainSubstring("no dependencies set for 2.8"))) - }) - }) - }) - }) -}) diff --git a/internal/commands/sync_with_local.go b/internal/commands/sync_with_local.go deleted file mode 100644 index c02f4bd85..000000000 --- a/internal/commands/sync_with_local.go +++ /dev/null @@ -1,115 +0,0 @@ -package commands - -import ( - "fmt" - "log" - - "github.com/pivotal-cf/kiln/internal/commands/flags" - - "github.com/go-git/go-billy/v5" - "github.com/pivotal-cf/jhanda" - - "github.com/pivotal-cf/kiln/internal/component" - "github.com/pivotal-cf/kiln/pkg/cargo" -) - -type SyncWithLocal struct { - Options struct { - flags.Standard - - ReleasesDir string `short:"rd" long:"releases-directory" default:"releases" description:"path to a directory to download releases into"` - ReleaseSourceID string ` long:"assume-release-source" required:"true" description:"the release source to put in updated records"` - SkipSameVersion bool ` long:"skip-same-version" description:"only update the Kilnfile.lock when the release version has changed'"` - } - fs billy.Filesystem - localReleaseDirectory LocalReleaseDirectory - logger *log.Logger - remotePatherFinder RemotePatherFinder -} - -func NewSyncWithLocal(fs billy.Filesystem, localReleaseDirectory LocalReleaseDirectory, remotePatherFinder RemotePatherFinder, logger *log.Logger) SyncWithLocal { - return SyncWithLocal{ - fs: fs, - localReleaseDirectory: localReleaseDirectory, - logger: logger, - remotePatherFinder: remotePatherFinder, - } -} - -//counterfeiter:generate -o ./fakes/remote_pather_finder.go --fake-name RemotePatherFinder . RemotePatherFinder -type RemotePatherFinder func(cargo.Kilnfile, string) (component.RemotePather, error) - -func (command SyncWithLocal) Execute(args []string) error { - _, err := flags.LoadFlagsWithDefaults(&command.Options, args, command.fs.Stat) - if err != nil { - return err - } - - kilnfile, kilnfileLock, err := command.Options.Standard.LoadKilnfiles(command.fs, nil) - if err != nil { - return fmt.Errorf("error loading Kilnfiles: %w", err) - } - - remotePather, err := command.remotePatherFinder(kilnfile, command.Options.ReleaseSourceID) - if err != nil { - return fmt.Errorf("couldn't load the release source: %w", err) // untested - } - - command.logger.Printf("Finding releases in %s...\n", command.Options.ReleasesDir) - releases, err := command.localReleaseDirectory.GetLocalReleases(command.Options.ReleasesDir) - if err != nil { - return fmt.Errorf("couldn't process releases in releases directory: %w", err) // untested - } - - command.logger.Printf("Found %d releases on disk\n", len(releases)) - - for _, rel := range releases { - remotePath, err := remotePather.RemotePath(component.Spec{ - Name: rel.Name, - Version: rel.Version, - StemcellOS: kilnfileLock.Stemcell.OS, - StemcellVersion: kilnfileLock.Stemcell.Version, - }) - if err != nil { - return fmt.Errorf("couldn't generate a remote path for release %q: %w", rel.Name, err) - } - - var matchingRelease *cargo.ComponentLock - for i := range kilnfileLock.Releases { - if kilnfileLock.Releases[i].Name == rel.Name { - matchingRelease = &kilnfileLock.Releases[i] - break - } - } - if matchingRelease == nil { - return fmt.Errorf("the local release %q does not exist in the Kilnfile.lock", rel.Name) - } - - if command.Options.SkipSameVersion && matchingRelease.Version == rel.Version { - command.logger.Printf("Skipping %s. Release version hasn't changed\n", rel.Name) - continue - } - - matchingRelease.Version = rel.Version - matchingRelease.SHA1 = rel.SHA1 - matchingRelease.RemoteSource = command.Options.ReleaseSourceID - matchingRelease.RemotePath = remotePath - - command.logger.Printf("Updated %s to %s\n", rel.Name, rel.Version) - } - - err = command.Options.SaveKilnfileLock(command.fs, kilnfileLock) - if err != nil { - return err - } - - return nil -} - -func (command SyncWithLocal) Usage() jhanda.Usage { - return jhanda.Usage{ - Description: "Update the Kilnfile.lock based on the local releases directory. Assume the given release source", - ShortDescription: "update the Kilnfile.lock based on local releases", - Flags: command.Options, - } -} diff --git a/internal/commands/sync_with_local_test.go b/internal/commands/sync_with_local_test.go deleted file mode 100644 index 56b37b425..000000000 --- a/internal/commands/sync_with_local_test.go +++ /dev/null @@ -1,257 +0,0 @@ -package commands_test - -import ( - "errors" - "log" - - "github.com/go-git/go-billy/v5" - "github.com/go-git/go-billy/v5/memfs" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/internal/commands" - commandsFakes "github.com/pivotal-cf/kiln/internal/commands/fakes" - "github.com/pivotal-cf/kiln/internal/component" - fetcherFakes "github.com/pivotal-cf/kiln/internal/component/fakes" - "github.com/pivotal-cf/kiln/pkg/cargo" -) - -var _ = Describe("sync-with-local", func() { - Describe("Execute", func() { - const ( - releaseSourceID = "some-source" - stemcellOS = "linux-os" - stemcellVersion = "2.2" - release1Name = "some-release" - release1OldVersion = "1" - release1NewVersion = "2" - release1OldSha = "old-sha" - release1NewSha = "new-sha" - release1OldSourceID = "old-source" - release1OldRemotePath = "old-path" - release1NewRemotePath = "new-path" - releaseName = "some-release-2" - releaseOldVersion = "42" - releaseNewVersion = "43" - releaseOldSha = "old-sha-2" - releaseNewSha = "new-sha-2" - releaseOldSourceID = "old-source-2" - releaseOldRemotePath = "old-path-2" - releaseNewRemotePath = "new-path-2" - - kilnfilePath = "Kilnfile" - kilnfileLockPath = kilnfilePath + ".lock" - ) - - var ( - syncWithLocal commands.SyncWithLocal - localReleaseDirectory *commandsFakes.LocalReleaseDirectory - remotePatherFinder *commandsFakes.RemotePatherFinder - remotePather *fetcherFakes.RemotePather - fs billy.Filesystem - kilnfileLock cargo.KilnfileLock - ) - - BeforeEach(func() { - kilnfileLock = cargo.KilnfileLock{ - Releases: []cargo.ComponentLock{ - { - Name: release1Name, - Version: release1OldVersion, - RemoteSource: release1OldSourceID, - RemotePath: release1OldRemotePath, - SHA1: release1OldSha, - }, - { - Name: releaseName, - Version: releaseOldVersion, - RemoteSource: releaseOldSourceID, - RemotePath: releaseOldRemotePath, - SHA1: releaseOldSha, - }, - }, - Stemcell: cargo.Stemcell{OS: stemcellOS, Version: stemcellVersion}, - } - - localReleaseDirectory = new(commandsFakes.LocalReleaseDirectory) - localReleaseDirectory.GetLocalReleasesReturns([]component.Local{ - { - Lock: component.Lock{Name: release1Name, Version: release1NewVersion, SHA1: release1NewSha}, - LocalPath: "local-path", - }, - { - Lock: component.Lock{Name: releaseName, Version: releaseNewVersion, SHA1: releaseNewSha}, - LocalPath: "local-path-2", - }, - }, nil) - - remotePatherFinder = new(commandsFakes.RemotePatherFinder) - remotePather = new(fetcherFakes.RemotePather) - - remotePatherFinder.Returns(remotePather, nil) - remotePather.RemotePathCalls(func(requirement component.Spec) (path string, err error) { - switch requirement.Name { - case release1Name: - return release1NewRemotePath, nil - case releaseName: - return releaseNewRemotePath, nil - default: - panic("unexpected release name") - } - }) - - fs = memfs.New() - logger := log.New(GinkgoWriter, "", 0) - - syncWithLocal = commands.NewSyncWithLocal(fs, localReleaseDirectory, remotePatherFinder.Spy, logger) - }) - - JustBeforeEach(func() { - Expect(fsWriteYAML(fs, kilnfileLockPath, kilnfileLock)).NotTo(HaveOccurred()) - Expect(fsWriteYAML(fs, kilnfilePath, cargo.Kilnfile{})).NotTo(HaveOccurred()) - }) - - It("updates the Kilnfile.lock to have the same version as the local releases", func() { - err := syncWithLocal.Execute([]string{ - "--kilnfile", kilnfilePath, - "--assume-release-source", releaseSourceID, - }) - Expect(err).NotTo(HaveOccurred()) - - var updatedLockfile cargo.KilnfileLock - Expect(fsReadYAML(fs, kilnfileLockPath, &updatedLockfile)).NotTo(HaveOccurred()) - Expect(updatedLockfile.Releases).To(Equal([]cargo.ComponentLock{ - { - Name: release1Name, - Version: release1NewVersion, - RemoteSource: releaseSourceID, - RemotePath: release1NewRemotePath, - SHA1: release1NewSha, - }, - { - Name: releaseName, - Version: releaseNewVersion, - RemoteSource: releaseSourceID, - RemotePath: releaseNewRemotePath, - SHA1: releaseNewSha, - }, - })) - }) - - When("one of the releases on disk is the same version as in the Kilnfile.lock", func() { - BeforeEach(func() { - localReleaseDirectory.GetLocalReleasesReturns([]component.Local{ - { - Lock: component.Lock{Name: release1Name, Version: release1OldVersion, SHA1: release1NewSha}, - LocalPath: "local-path", - }, - { - Lock: component.Lock{Name: releaseName, Version: releaseNewVersion, SHA1: releaseNewSha}, - LocalPath: "local-path-2", - }, - }, nil) - }) - - It("updates the Kilnfile.lock to have the correct remote info and SHA1", func() { - err := syncWithLocal.Execute([]string{ - "--kilnfile", kilnfilePath, - "--assume-release-source", releaseSourceID, - }) - Expect(err).NotTo(HaveOccurred()) - - var updatedLockfile cargo.KilnfileLock - Expect(fsReadYAML(fs, kilnfileLockPath, &updatedLockfile)).NotTo(HaveOccurred()) - Expect(updatedLockfile.Releases).To(Equal([]cargo.ComponentLock{ - { - Name: release1Name, - Version: release1OldVersion, - RemoteSource: releaseSourceID, - RemotePath: release1NewRemotePath, - SHA1: release1NewSha, - }, - { - Name: releaseName, - Version: releaseNewVersion, - RemoteSource: releaseSourceID, - RemotePath: releaseNewRemotePath, - SHA1: releaseNewSha, - }, - })) - }) - - When("--skip-same-version is passed", func() { - It("doesn't modify that entry", func() { - err := syncWithLocal.Execute([]string{ - "--kilnfile", kilnfilePath, - "--assume-release-source", releaseSourceID, - "--skip-same-version", - }) - Expect(err).NotTo(HaveOccurred()) - - var updatedLockfile cargo.KilnfileLock - Expect(fsReadYAML(fs, kilnfileLockPath, &updatedLockfile)).NotTo(HaveOccurred()) - Expect(updatedLockfile.Releases).To(Equal([]cargo.ComponentLock{ - { - Name: release1Name, - Version: release1OldVersion, - RemoteSource: release1OldSourceID, - RemotePath: release1OldRemotePath, - SHA1: release1OldSha, - }, - { - Name: releaseName, - Version: releaseNewVersion, - RemoteSource: releaseSourceID, - RemotePath: releaseNewRemotePath, - SHA1: releaseNewSha, - }, - })) - }) - }) - }) - - When("a release on disk doesn't exist in the Kilnfile.lock", func() { - BeforeEach(func() { - kilnfileLock = cargo.KilnfileLock{ - Releases: []cargo.ComponentLock{ - { - Name: release1Name, - Version: release1OldVersion, - RemoteSource: release1OldSourceID, - RemotePath: release1OldRemotePath, - SHA1: release1OldSha, - }, - }, - Stemcell: cargo.Stemcell{}, - } - }) - - It("returns an error", func() { - err := syncWithLocal.Execute([]string{ - "--kilnfile", kilnfilePath, - "--assume-release-source", releaseSourceID, - }) - - Expect(err).To(MatchError(ContainSubstring("does not exist"))) - Expect(err).To(MatchError(ContainSubstring(releaseName))) - }) - }) - - When("there's an error generating the remote path for a release", func() { - BeforeEach(func() { - remotePather.RemotePathReturns("", errors.New("bad bad stuff")) - }) - - It("returns an error", func() { - err := syncWithLocal.Execute([]string{ - "--kilnfile", kilnfilePath, - "--assume-release-source", releaseSourceID, - }) - - Expect(err).To(MatchError(ContainSubstring("bad bad stuff"))) - Expect(err).To(MatchError(ContainSubstring(release1Name))) - }) - }) - }) -}) diff --git a/internal/commands/update_release.go b/internal/commands/update_release.go index 17dc2cf3a..b170b0b5b 100644 --- a/internal/commands/update_release.go +++ b/internal/commands/update_release.go @@ -16,11 +16,11 @@ type UpdateRelease struct { Options struct { flags.Standard - Name string `short:"n" long:"name" required:"true" description:"name of release to update"` - Version string `short:"v" long:"version" required:"true" description:"desired version of release"` - ReleasesDir string `short:"rd" long:"releases-directory" default:"releases" description:"path to a directory to download releases into"` - AllowOnlyPublishableReleases bool `long:"allow-only-publishable-releases" description:"include releases that would not be shipped with the tile (development builds)"` - WithoutDownload bool `long:"without-download" description:"updates releases without downloading them"` + Name string `short:"n" long:"name" required:"true" description:"name of release to update"` + Version string `short:"v" long:"version" required:"true" description:"desired version of release"` + ReleasesDir string `short:"rd" long:"releases-directory" default-path:"releases" description:"path to a directory to download releases into"` + AllowOnlyPublishableReleases bool ` long:"allow-only-publishable-releases" description:"include releases that would not be shipped with the tile (development builds)"` + WithoutDownload bool ` long:"without-download" description:"updates releases without downloading them"` } multiReleaseSourceProvider MultiReleaseSourceProvider filesystem billy.Filesystem diff --git a/internal/commands/update_stemcell.go b/internal/commands/update_stemcell.go index 21cd5d4aa..6c7c3d8a0 100644 --- a/internal/commands/update_stemcell.go +++ b/internal/commands/update_stemcell.go @@ -19,15 +19,15 @@ type UpdateStemcell struct { Options struct { flags.Standard - Version string `short:"v" long:"version" required:"true" description:"desired version of stemcell"` - ReleasesDir string `short:"rd" long:"releases-directory" default:"releases" description:"path to a directory to download releases into"` + Version string `short:"v" long:"version" required:"true" description:"desired version of stemcell"` + ReleasesDir string `short:"rd" long:"releases-directory" default-path:"releases" description:"path to a directory to download releases into"` } FS billy.Filesystem MultiReleaseSourceProvider MultiReleaseSourceProvider Logger *log.Logger } -func (update UpdateStemcell) Execute(args []string) error { +func (update *UpdateStemcell) Execute(args []string) error { _, err := flags.LoadFlagsWithDefaults(&update.Options, args, update.FS.Stat) if err != nil { return err @@ -114,7 +114,7 @@ func (update UpdateStemcell) Execute(args []string) error { return nil } -func (update UpdateStemcell) Usage() jhanda.Usage { +func (update *UpdateStemcell) Usage() jhanda.Usage { return jhanda.Usage{ Description: "Updates stemcell and release information in Kilnfile.lock", ShortDescription: "updates stemcell and release information in Kilnfile.lock", diff --git a/internal/commands/update_stemcell_test.go b/internal/commands/update_stemcell_test.go index 3f5138148..ad8ecc725 100644 --- a/internal/commands/update_stemcell_test.go +++ b/internal/commands/update_stemcell_test.go @@ -24,7 +24,7 @@ import ( ) var _ = Describe("UpdateStemcell", func() { - var _ jhanda.Command = commands.UpdateStemcell{} + var _ jhanda.Command = &commands.UpdateStemcell{} const ( newStemcellOS = "old-os" diff --git a/internal/commands/validate_test.go b/internal/commands/validate_test.go index 6fd1f7a9d..9e8ce2e5c 100644 --- a/internal/commands/validate_test.go +++ b/internal/commands/validate_test.go @@ -3,76 +3,77 @@ package commands import ( "testing" + "github.com/go-git/go-billy/v5/osfs" + "github.com/pivotal-cf/kiln/pkg/cargo" - "github.com/go-git/go-billy/v5/osfs" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" ) func TestValidate_FloatingRelease(t *testing.T) { t.Parallel() - please := Ω.NewWithT(t) + please := NewWithT(t) validate := Validate{ FS: osfs.New("testdata/validate/floating-release"), } err := validate.Execute(nil) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) } func TestValidate_MissingLock(t *testing.T) { t.Parallel() - please := Ω.NewWithT(t) + please := NewWithT(t) validate := Validate{ FS: osfs.New("testdata/validate/missing-lock"), } err := validate.Execute(nil) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) } func TestValidate_WrongVersionType(t *testing.T) { t.Parallel() - please := Ω.NewWithT(t) + please := NewWithT(t) validate := Validate{ FS: osfs.New("testdata/validate/wrong-version-type"), } err := validate.Execute(nil) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) } func TestValidate_InvalidConstraint(t *testing.T) { t.Parallel() - please := Ω.NewWithT(t) + please := NewWithT(t) validate := Validate{ FS: osfs.New("testdata/validate/invalid-constraint"), } err := validate.Execute(nil) - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("bpm"))) + please.Expect(err).To(MatchError(ContainSubstring("bpm"))) } func TestValidate_PinnedRelease(t *testing.T) { t.Parallel() - please := Ω.NewWithT(t) + please := NewWithT(t) validate := Validate{ FS: osfs.New("testdata/validate/pinned-release"), } err := validate.Execute(nil) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) } func TestValidate_validateRelease(t *testing.T) { t.Run("missing name", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) r := cargo.ComponentSpec{} l := cargo.ComponentLock{} err := validateRelease(r, l, 0) - please.Expect(err).To(Ω.And( - Ω.HaveOccurred(), - Ω.MatchError(Ω.ContainSubstring("missing name")), + please.Expect(err).To(And( + HaveOccurred(), + MatchError(ContainSubstring("missing name")), )) }) t.Run("no version", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) r := cargo.ComponentSpec{ Name: "capi", } @@ -81,11 +82,11 @@ func TestValidate_validateRelease(t *testing.T) { Version: "2.3.4", } err := validateRelease(r, l, 0) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }) t.Run("invalid version constraint", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) r := cargo.ComponentSpec{ Name: "capi", Version: "meh", @@ -95,14 +96,14 @@ func TestValidate_validateRelease(t *testing.T) { Version: "2.3.4", } err := validateRelease(r, l, 0) - please.Expect(err).To(Ω.And( - Ω.HaveOccurred(), - Ω.MatchError(Ω.ContainSubstring("invalid version constraint")), + please.Expect(err).To(And( + HaveOccurred(), + MatchError(ContainSubstring("invalid version constraint")), )) }) t.Run("version does not match constraint", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) r := cargo.ComponentSpec{ Name: "capi", Version: "~2", @@ -112,14 +113,14 @@ func TestValidate_validateRelease(t *testing.T) { Version: "3.0.5", } err := validateRelease(r, l, 0) - please.Expect(err).To(Ω.And( - Ω.HaveOccurred(), - Ω.MatchError(Ω.ContainSubstring("match constraint")), + please.Expect(err).To(And( + HaveOccurred(), + MatchError(ContainSubstring("match constraint")), )) }) t.Run("invalid lock version", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) r := cargo.ComponentSpec{ Name: "capi", Version: "~2", @@ -129,9 +130,9 @@ func TestValidate_validateRelease(t *testing.T) { Version: "BAD", } err := validateRelease(r, l, 0) - please.Expect(err).To(Ω.And( - Ω.HaveOccurred(), - Ω.MatchError(Ω.ContainSubstring("invalid lock version")), + please.Expect(err).To(And( + HaveOccurred(), + MatchError(ContainSubstring("invalid lock version")), )) }) } diff --git a/internal/component/bump.go b/internal/component/bump.go index 7568962e7..5631a35c3 100644 --- a/internal/component/bump.go +++ b/internal/component/bump.go @@ -18,7 +18,7 @@ type Bump struct { Releases []*github.RepositoryRelease } -func (bump Bump) ReleaseNotes() string { +func (bump *Bump) ReleaseNotes() string { var s strings.Builder for _, r := range bump.Releases { @@ -49,7 +49,22 @@ func (bump *Bump) deduplicateReleasesWithTheSameTagName() { } } -func CalculateBumps(current, previous []Lock) []Bump { +func (bump *Bump) toFrom() (to, from *semver.Version, _ error) { + var err error + from, err = semver.NewVersion(bump.FromVersion) + if err != nil { + return nil, nil, err + } + to, err = semver.NewVersion(bump.ToVersion) + if err != nil { + return nil, nil, err + } + return to, from, err +} + +type BumpList []Bump + +func CalculateBumps(current, previous []Lock) BumpList { var ( bumps []Bump previousSpecs = make(map[string]Lock, len(previous)) @@ -71,21 +86,6 @@ func CalculateBumps(current, previous []Lock) []Bump { return bumps } -func (bump Bump) toFrom() (to, from *semver.Version, _ error) { - var err error - from, err = semver.NewVersion(bump.FromVersion) - if err != nil { - return nil, nil, err - } - to, err = semver.NewVersion(bump.ToVersion) - if err != nil { - return nil, nil, err - } - return to, from, err -} - -type BumpList []Bump - func (list BumpList) ForLock(lock Lock) Bump { for _, b := range list { if b.Name == lock.Name { diff --git a/internal/component/bump_internal_test.go b/internal/component/bump_internal_test.go index 89d52c8ad..78dcbfbd1 100644 --- a/internal/component/bump_internal_test.go +++ b/internal/component/bump_internal_test.go @@ -1,9 +1,10 @@ package component import ( + "testing" + "github.com/google/go-github/v40/github" Ω "github.com/onsi/gomega" - "testing" ) func TestInternal_deduplicateReleasesWithTheSameTagName(t *testing.T) { diff --git a/internal/component/bump_test.go b/internal/component/bump_test.go index b8fab78b7..eaada4f17 100644 --- a/internal/component/bump_test.go +++ b/internal/component/bump_test.go @@ -8,8 +8,7 @@ import ( "github.com/google/go-github/v40/github" - Ω "github.com/onsi/gomega" - + . "github.com/onsi/gomega" fakes "github.com/pivotal-cf/kiln/internal/component/fakes_internal" "github.com/pivotal-cf/kiln/pkg/cargo" @@ -17,14 +16,14 @@ import ( func TestCalculateBumps(t *testing.T) { t.Parallel() - please := Ω.NewWithT(t) + please := NewWithT(t) t.Run("when the components stay the same", func(t *testing.T) { please.Expect(CalculateBumps([]Lock{ {Name: "a", Version: "1"}, }, []Lock{ {Name: "a", Version: "1"}, - })).To(Ω.HaveLen(0)) + })).To(HaveLen(0)) }) t.Run("when a component is bumped", func(t *testing.T) { @@ -34,7 +33,7 @@ func TestCalculateBumps(t *testing.T) { }, []Lock{ {Name: "a", Version: "1"}, {Name: "b", Version: "1"}, - })).To(Ω.Equal([]Bump{ + })).To(Equal(BumpList{ {Name: "b", FromVersion: "1", ToVersion: "2"}, }), "it returns the changed lock", @@ -50,7 +49,7 @@ func TestCalculateBumps(t *testing.T) { {Name: "a", Version: "1"}, {Name: "b", Version: "1"}, {Name: "c", Version: "1"}, - })).To(Ω.Equal([]Bump{ + })).To(Equal(BumpList{ {Name: "a", FromVersion: "1", ToVersion: "2"}, {Name: "c", FromVersion: "1", ToVersion: "2"}, }), @@ -64,7 +63,7 @@ func TestCalculateBumps(t *testing.T) { }, []Lock{ {Name: "a", Version: "1"}, {Name: "b", Version: "1"}, - })).To(Ω.HaveLen(0), + })).To(HaveLen(0), "it does not return a bump", ) }) @@ -78,7 +77,7 @@ func TestCalculateBumps(t *testing.T) { {Name: "b", Version: "1"}, }, []Lock{ {Name: "a", Version: "1"}, - })).To(Ω.Equal([]Bump{ + })).To(Equal(BumpList{ {Name: "b", FromVersion: "", ToVersion: "1"}, }), "it returns the component as a bump", @@ -87,7 +86,7 @@ func TestCalculateBumps(t *testing.T) { } func TestInternal_addReleaseNotes(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) var ltsCallCount int @@ -150,12 +149,12 @@ func TestInternal_addReleaseNotes(t *testing.T) { FromVersion: "9", }, }) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(result).To(Ω.HaveLen(2)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(result).To(HaveLen(2)) - please.Expect(ltsCallCount).To(Ω.Equal(3)) + please.Expect(ltsCallCount).To(Equal(3)) - please.Expect(result[0].ReleaseNotes()).To(Ω.Equal("served\nplated\nstored\nlabeled\npreserved\nchopped\ncleaned")) + please.Expect(result[0].ReleaseNotes()).To(Equal("served\nplated\nstored\nlabeled\npreserved\nchopped\ncleaned")) } func githubResponse(t *testing.T, status int) *github.Response { diff --git a/internal/component/github_release_source_internal_test.go b/internal/component/github_release_source_internal_test.go index 0f47a0fc3..67f3faf7a 100644 --- a/internal/component/github_release_source_internal_test.go +++ b/internal/component/github_release_source_internal_test.go @@ -11,9 +11,9 @@ import ( "github.com/google/go-github/v40/github" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" - "github.com/pivotal-cf/kiln/internal/component/fakes_internal" + fakes "github.com/pivotal-cf/kiln/internal/component/fakes_internal" ) func TestGithubReleaseSource_downloadRelease(t *testing.T) { @@ -23,7 +23,7 @@ func TestGithubReleaseSource_downloadRelease(t *testing.T) { RemotePath: "https://github.com/cloudfoundry/routing-release/releases/download/v0.239.0/routing-0.239.0.tgz", } - please := Ω.NewWithT(t) + please := NewWithT(t) tempDir := t.TempDir() t.Cleanup(func() { _ = os.RemoveAll(tempDir) @@ -31,7 +31,7 @@ func TestGithubReleaseSource_downloadRelease(t *testing.T) { asset := bytes.NewBufferString("some contents\n") - downloader := new(fakes_internal.ReleaseByTagGetterAssetDownloader) + downloader := new(fakes.ReleaseByTagGetterAssetDownloader) downloader.GetReleaseByTagReturnsOnCall(0, nil, nil, errors.New("banana")) downloader.GetReleaseByTagReturnsOnCall(1, &github.RepositoryRelease{ Assets: []*github.ReleaseAsset{ @@ -44,21 +44,21 @@ func TestGithubReleaseSource_downloadRelease(t *testing.T) { logger := log.New(io.Discard, "", 0) local, err := downloadRelease(context.Background(), tempDir, lock, downloader, logger) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) { _, org, repo, tag := downloader.GetReleaseByTagArgsForCall(0) - please.Expect(org).To(Ω.Equal("cloudfoundry")) - please.Expect(repo).To(Ω.Equal("routing-release")) - please.Expect(tag).To(Ω.Equal("0.239.0")) + please.Expect(org).To(Equal("cloudfoundry")) + please.Expect(repo).To(Equal("routing-release")) + please.Expect(tag).To(Equal("0.239.0")) } { _, org, repo, tag := downloader.GetReleaseByTagArgsForCall(1) - please.Expect(org).To(Ω.Equal("cloudfoundry")) - please.Expect(repo).To(Ω.Equal("routing-release")) - please.Expect(tag).To(Ω.Equal("v0.239.0")) + please.Expect(org).To(Equal("cloudfoundry")) + please.Expect(repo).To(Equal("routing-release")) + please.Expect(tag).To(Equal("v0.239.0")) } - please.Expect(local.LocalPath).To(Ω.BeAnExistingFile(), "it finds the created asset file") - please.Expect(local.SHA1).To(Ω.Equal("3a2be7b07a1a19072bf54c95a8c4a3fe0cdb35d4")) + please.Expect(local.LocalPath).To(BeAnExistingFile(), "it finds the created asset file") + please.Expect(local.SHA1).To(Equal("3a2be7b07a1a19072bf54c95a8c4a3fe0cdb35d4")) } diff --git a/internal/component/github_release_source_test.go b/internal/component/github_release_source_test.go index db405266b..8cfc8e4cd 100644 --- a/internal/component/github_release_source_test.go +++ b/internal/component/github_release_source_test.go @@ -12,11 +12,12 @@ import ( "testing" "github.com/google/go-github/v40/github" - Ω "github.com/onsi/gomega" "github.com/pivotal-cf/kiln/internal/component" "github.com/pivotal-cf/kiln/internal/component/fakes" "github.com/pivotal-cf/kiln/pkg/cargo" + + . "github.com/onsi/gomega" ) func TestListAllOfTheCrap(t *testing.T) { @@ -105,45 +106,45 @@ func TestGithubReleaseSource_ComponentLockFromGithubRelease(t *testing.T) { }) t.Run("it returns success stuff", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(err).NotTo(Ω.HaveOccurred()) + damnIt.Expect(err).NotTo(HaveOccurred()) }) t.Run("it sets the lock fields properly", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(lock.Name).To(Ω.Equal("routing")) - damnIt.Expect(lock.Version).To(Ω.Equal("0.226.0")) - damnIt.Expect(lock.RemoteSource).To(Ω.Equal(owner)) - damnIt.Expect(lock.RemotePath).To(Ω.Equal("https://github.com/cloudfoundry/routing-release/releases/download/0.226.0/routing-0.226.0.tgz")) + damnIt.Expect(lock.Name).To(Equal("routing")) + damnIt.Expect(lock.Version).To(Equal("0.226.0")) + damnIt.Expect(lock.RemoteSource).To(Equal(owner)) + damnIt.Expect(lock.RemotePath).To(Equal("https://github.com/cloudfoundry/routing-release/releases/download/0.226.0/routing-0.226.0.tgz")) }) t.Run("it downloads the file", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(downloader.DownloadReleaseAssetCallCount()).To(Ω.Equal(1)) + damnIt.Expect(downloader.DownloadReleaseAssetCallCount()).To(Equal(1)) _, org, repo, build, client := downloader.DownloadReleaseAssetArgsForCall(0) - damnIt.Expect(org).To(Ω.Equal("cloudfoundry")) - damnIt.Expect(repo).To(Ω.Equal("routing-release")) - damnIt.Expect(build).To(Ω.Equal(int64(420))) - damnIt.Expect(client).NotTo(Ω.BeNil()) + damnIt.Expect(org).To(Equal("cloudfoundry")) + damnIt.Expect(repo).To(Equal("routing-release")) + damnIt.Expect(build).To(Equal(int64(420))) + damnIt.Expect(client).NotTo(BeNil()) t.Run("it sets the tarball hash", func(t *testing.T) { - doubleDamnIt := Ω.NewWithT(t) - doubleDamnIt.Expect(lock.SHA1).To(Ω.Equal("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")) - doubleDamnIt.Expect(file.CloseCalled).To(Ω.BeTrue()) + doubleDamnIt := NewWithT(t) + doubleDamnIt.Expect(lock.SHA1).To(Equal("aaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d")) + doubleDamnIt.Expect(file.CloseCalled).To(BeTrue()) }) }) t.Run("it makes the right request", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(releaseGetter.GetReleaseByTagCallCount()).To(Ω.Equal(1)) + damnIt.Expect(releaseGetter.GetReleaseByTagCallCount()).To(Equal(1)) _, org, repo, tag := releaseGetter.GetReleaseByTagArgsForCall(0) - damnIt.Expect(org).To(Ω.Equal("cloudfoundry")) - damnIt.Expect(repo).To(Ω.Equal("routing-release")) - damnIt.Expect(tag).To(Ω.Equal("v0.226.0")) + damnIt.Expect(org).To(Equal("cloudfoundry")) + damnIt.Expect(repo).To(Equal("routing-release")) + damnIt.Expect(tag).To(Equal("v0.226.0")) }) }) @@ -196,30 +197,30 @@ func TestGithubReleaseSource_ComponentLockFromGithubRelease(t *testing.T) { // Then... t.Run("it returns success stuff", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(err).NotTo(Ω.HaveOccurred()) + damnIt.Expect(err).NotTo(HaveOccurred()) }) t.Run("it sets the lock fields properly", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(lock.Name).To(Ω.Equal("routing")) - damnIt.Expect(lock.Version).To(Ω.Equal("0.226.0")) - damnIt.Expect(lock.RemoteSource).To(Ω.Equal(owner)) - damnIt.Expect(lock.RemotePath).To(Ω.Equal("https://github.com/cloudfoundry/routing-release/releases/download/v0.226.0/routing-0.226.0.tgz")) + damnIt.Expect(lock.Name).To(Equal("routing")) + damnIt.Expect(lock.Version).To(Equal("0.226.0")) + damnIt.Expect(lock.RemoteSource).To(Equal(owner)) + damnIt.Expect(lock.RemotePath).To(Equal("https://github.com/cloudfoundry/routing-release/releases/download/v0.226.0/routing-0.226.0.tgz")) }) t.Run("it makes the right request", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) - damnIt.Expect(releaseGetter.GetReleaseByTagCallCount()).To(Ω.Equal(2)) + damnIt.Expect(releaseGetter.GetReleaseByTagCallCount()).To(Equal(2)) _, _, _, tag := releaseGetter.GetReleaseByTagArgsForCall(0) - damnIt.Expect(tag).To(Ω.Equal("v0.226.0")) + damnIt.Expect(tag).To(Equal("v0.226.0")) _, _, _, tag = releaseGetter.GetReleaseByTagArgsForCall(1) - damnIt.Expect(tag).To(Ω.Equal("0.226.0")) + damnIt.Expect(tag).To(Equal("0.226.0")) }) }) } @@ -233,14 +234,14 @@ func TestGithubReleaseSource_FindReleaseVersion(t *testing.T) { _, err := grs.FindReleaseVersion(s, false) t.Run("it returns an error about version not being specific", func(t *testing.T) { - damnIt := Ω.NewWithT(t) - damnIt.Expect(err).To(Ω.HaveOccurred()) - damnIt.Expect(err.Error()).To(Ω.ContainSubstring("expected version to be a constraint")) + damnIt := NewWithT(t) + damnIt.Expect(err).To(HaveOccurred()) + damnIt.Expect(err.Error()).To(ContainSubstring("expected version to be a constraint")) }) }) t.Run("noDownload is true", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) downloader := new(fakes.ReleaseAssetDownloader) downloader.DownloadReleaseAssetReturns(nil, "", fmt.Errorf("this is a mistake! I'm not supposed to be here!")) @@ -287,10 +288,10 @@ func TestGithubReleaseSource_FindReleaseVersion(t *testing.T) { } lock, err := grsMock.FindReleaseVersion(s, true) - please.Expect(err).ToNot(Ω.HaveOccurred()) + please.Expect(err).ToNot(HaveOccurred()) - please.Expect(lock.SHA1).To(Ω.Equal("not-calculated")) - please.Expect(downloader.Invocations()).To(Ω.BeEmpty()) + please.Expect(lock.SHA1).To(Equal("not-calculated")) + please.Expect(downloader.Invocations()).To(BeEmpty()) }) } @@ -303,16 +304,16 @@ func TestGithubReleaseSource_GetMatchedRelease(t *testing.T) { _, err := grs.GetMatchedRelease(s) t.Run("it returns an error about version not being specific", func(t *testing.T) { - damnIt := Ω.NewWithT(t) - damnIt.Expect(err).To(Ω.HaveOccurred()) - damnIt.Expect(err.Error()).To(Ω.ContainSubstring("expected version to be an exact version")) + damnIt := NewWithT(t) + damnIt.Expect(err).To(HaveOccurred()) + damnIt.Expect(err.Error()).To(ContainSubstring("expected version to be an exact version")) }) }) } func TestGetGithubReleaseWithTag(t *testing.T) { t.Run("when get release with tag api request fails", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) releaseGetter := new(fakes.ReleaseByTagGetter) @@ -341,12 +342,12 @@ func TestGetGithubReleaseWithTag(t *testing.T) { } _, err := grsMock.GetGithubReleaseWithTag(ctx, s) - damnIt.Expect(err).To(Ω.HaveOccurred()) + damnIt.Expect(err).To(HaveOccurred()) }) t.Run("when the status code is unauthorized and the error is nil", func(t *testing.T) { // yes this happened... how is this not an error? - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) defer func() { r := recover() @@ -382,7 +383,7 @@ func TestGetGithubReleaseWithTag(t *testing.T) { } _, err := grsMock.GetGithubReleaseWithTag(ctx, s) - damnIt.Expect(err).To(Ω.HaveOccurred()) + damnIt.Expect(err).To(HaveOccurred()) }) } @@ -390,7 +391,7 @@ func TestGetLatestMatchingRelease(t *testing.T) { strPtr := func(s string) *string { return &s } t.Run("when get release with tag api request fails", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) releaseGetter := new(fakes.ReleasesLister) @@ -446,13 +447,13 @@ func TestGetLatestMatchingRelease(t *testing.T) { } rel, err := grsMock.GetLatestMatchingRelease(context.TODO(), s) - damnIt.Expect(err).NotTo(Ω.HaveOccurred()) - damnIt.Expect(rel.GetTagName()).To(Ω.Equal("2.0.4")) - damnIt.Expect(releaseGetter.ListReleasesCallCount()).To(Ω.Equal(3)) + damnIt.Expect(err).NotTo(HaveOccurred()) + damnIt.Expect(rel.GetTagName()).To(Equal("2.0.4")) + damnIt.Expect(releaseGetter.ListReleasesCallCount()).To(Equal(3)) }) t.Run("when some of the github releases tags have a v prefix", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) releaseGetter := new(fakes.ReleasesLister) @@ -496,9 +497,9 @@ func TestGetLatestMatchingRelease(t *testing.T) { } rel, err := grsMock.GetLatestMatchingRelease(context.TODO(), s) - damnIt.Expect(err).NotTo(Ω.HaveOccurred()) - damnIt.Expect(rel.GetTagName()).To(Ω.Equal("v2.0.4")) - damnIt.Expect(releaseGetter.ListReleasesCallCount()).To(Ω.Equal(3)) + damnIt.Expect(err).NotTo(HaveOccurred()) + damnIt.Expect(rel.GetTagName()).To(Equal("v2.0.4")) + damnIt.Expect(releaseGetter.ListReleasesCallCount()).To(Equal(3)) }) t.Run("component repo does not match release source org", func(t *testing.T) { @@ -525,8 +526,8 @@ func TestGetLatestMatchingRelease(t *testing.T) { _, err := grsMock.GetLatestMatchingRelease(ctx, spec) // then - please := Ω.NewWithT(t) - please.Expect(component.IsErrNotFound(err)).To(Ω.BeTrue()) + please := NewWithT(t) + please.Expect(component.IsErrNotFound(err)).To(BeTrue()) }) } @@ -544,15 +545,39 @@ func TestDownloadReleaseAsset(t *testing.T) { } t.Run("when the release is downloaded", func(t *testing.T) { - damnIt := Ω.NewWithT(t) + damnIt := NewWithT(t) tempDir := t.TempDir() t.Cleanup(func() { _ = os.RemoveAll(tempDir) }) local, err := grs.DownloadRelease(tempDir, testLock) - damnIt.Expect(err).NotTo(Ω.HaveOccurred()) + damnIt.Expect(err).NotTo(HaveOccurred()) - damnIt.Expect(local.LocalPath).NotTo(Ω.BeAnExistingFile(), "it creates the expected asset") + damnIt.Expect(local.LocalPath).NotTo(BeAnExistingFile(), "it creates the expected asset") }) } + +//func TestLockFromGithubRelease_componet_repo_does_not_match_release_source_org(t *testing.T) { +// // given +// var ( +// githubOrg = "banana" +// otherGitHubOrg = "orange" +// +// ctx = context.Background() +// downloader = new(fakes.ReleaseAssetDownloader) +// spec = cargo.ComponentSpec{ +// GitHubRepository: "https://github.com/" + otherGitHubOrg + "/muffin", +// } +// getRelease = func(ctx context.Context, org, repo string) (*github.RepositoryRelease, error) { +// return nil, fmt.Errorf("get release does not need to be called for this test") +// } +// ) +// +// // when +// _, err := component.LockFromGithubRelease(ctx, downloader, githubOrg, spec, getRelease) +// +// // then +// please := NewWithT(t) +// please.Expect(component.IsErrNotFound(err)).To(BeTrue()) +//} diff --git a/internal/defaultpath/fields.go b/internal/defaultpath/fields.go new file mode 100644 index 000000000..fe0f00429 --- /dev/null +++ b/internal/defaultpath/fields.go @@ -0,0 +1,169 @@ +package defaultpath + +import ( + "go/ast" + "os" + "path/filepath" + "reflect" + "strings" +) + +const TagName = "default-path" + +type StatFunc func(string) (os.FileInfo, error) + +func SetFields(config interface{}, pathPrefix string, args []string, stat StatFunc) { + if stat == nil { + stat = os.Stat + } + v := reflect.ValueOf(config).Elem() + + configureArrayDefaults(v, pathPrefix, args, stat) + configurePathDefaults(v, pathPrefix, args, stat) +} + +func configureArrayDefaults(v reflect.Value, pathPrefix string, args []string, stat StatFunc) { + t := v.Type() + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + switch field.Type.Kind() { + default: + continue + case reflect.Struct: + embeddedValue := v.Field(i) + if field.Anonymous && ast.IsExported(embeddedValue.Type().Name()) { + configureArrayDefaults(embeddedValue, pathPrefix, args, stat) + } + continue + case reflect.Slice: + } + + defaultValueStr, ok := field.Tag.Lookup(TagName) + if !ok { + continue + } + defaultValues := filter(strings.Split(defaultValueStr, ","), "", -1) + + passedValues, ok := v.Field(i).Interface().([]string) + if !ok { + // this might occur if we add non string slice params + // notice the field Kind check above was not super specific + continue + } + passedValues = filter(passedValues, "", -1) + + if IsSet(field.Tag.Get("long"), field.Tag.Get("short"), args) { + v.Field(i).Set(reflect.ValueOf(passedValues)) + continue + } + + filteredDefaults := defaultValues[:0] + for _, p := range defaultValues { + if pathPrefix != "" { + p = filepath.Join(pathPrefix, p) + } + _, err := stat(p) + if err != nil { + continue + } + filteredDefaults = append(filteredDefaults, p) + } + + // if default values were found, use them, + // else filteredDefaults will be an empty slice + // and the Bake command will continue as if they were not set + v.Field(i).Set(reflect.ValueOf(filteredDefaults)) + } +} + +func configurePathDefaults(v reflect.Value, pathPrefix string, args []string, stat StatFunc) { + t := v.Type() + + for i := 0; i < t.NumField(); i++ { + field := t.Field(i) + + switch field.Type.Kind() { + default: + continue + case reflect.Struct: + embeddedValue := v.Field(i) + if field.Anonymous && ast.IsExported(embeddedValue.Type().Name()) { + configurePathDefaults(embeddedValue, pathPrefix, args, stat) + } + continue + case reflect.String: + } + + if IsSet(field.Tag.Get("short"), field.Tag.Get("long"), args) { + continue + } + + defaultValue, ok := field.Tag.Lookup(TagName) + if !ok { + continue + } + + value, ok := v.Field(i).Interface().(string) + if !ok { + continue // this should not occur + } + + isDefaultValue := defaultValue == value + + if isDefaultValue { + continue + } + value = defaultValue + + if pathPrefix != "" { + value = filepath.Join(pathPrefix, value) + } + + _, err := stat(value) + if err != nil { + // set to zero value + v.Field(i).Set(reflect.Zero(v.Field(i).Type())) + continue + } + + v.Field(i).Set(reflect.ValueOf(value)) + } +} + +func IsSet(short, long string, args []string) bool { + check := func(name string, arg string) bool { + if name == "" { + return false + } + + return arg == "--"+name || arg == "-"+name || + strings.HasPrefix(arg, "--"+name+"=") || + strings.HasPrefix(arg, "-"+name+"=") + } + + for _, a := range args { + if check(short, a) || check(long, a) { + return true + } + } + + return false +} + +func filter[T comparable](in []T, valueToRemove T, limit int) []T { + filtered := in[:0] + removed := 0 + for _, v := range in { + if v == valueToRemove { + continue + } + filtered = append(filtered, v) + removed++ + if limit > 0 && removed < limit { + break + } + } + return filtered +} diff --git a/internal/defaultpath/fields_test.go b/internal/defaultpath/fields_test.go new file mode 100644 index 000000000..6f28fdb64 --- /dev/null +++ b/internal/defaultpath/fields_test.go @@ -0,0 +1,164 @@ +package defaultpath + +import ( + "os" + "testing" + + "github.com/pivotal-cf/jhanda" + + . "github.com/onsi/gomega" +) + +type Embedded struct { + SharedConfig string `short:"s" long:"shared-config" default-path:"shared.yml"` + SharedScripts []string `short:"i" long:"shared-script" default-path:"a.sh,b.sh"` +} + +type options struct { + Embedded + + Config string `short:"c" long:"config" default-path:"config.yml"` + AdditionalConfigs []string `short:"a" long:"additional-config" default-path:"f1.yml,f2.yml,f3.yml"` + SomeBool bool `short:"e" long:"ensure" default-path:"true"` +} + +func TestSetFields_sets_defaults(t *testing.T) { + please := NewWithT(t) + + var ( + ops options + args = []string(nil) + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "", args, statNoError) + + please.Expect(ops.Config).To(Equal("config.yml")) + please.Expect(ops.AdditionalConfigs).To(Equal([]string{"f1.yml", "f2.yml", "f3.yml"})) + please.Expect(ops.SharedConfig).To(Equal("shared.yml")) + please.Expect(ops.SharedScripts).To(Equal([]string{"a.sh", "b.sh"})) +} + +func TestSetFields_adds_path_prefix_to_defaults(t *testing.T) { + please := NewWithT(t) + + var ( + ops options + args = []string(nil) + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "some-dir", args, statNoError) + + please.Expect(ops.Config).To(Equal("some-dir/config.yml")) + please.Expect(ops.AdditionalConfigs).To(Equal([]string{"some-dir/f1.yml", "some-dir/f2.yml", "some-dir/f3.yml"})) + please.Expect(ops.SharedConfig).To(Equal("some-dir/shared.yml")) +} + +func TestSetFields_sets_empty_options_when_filepath_does_not_exist(t *testing.T) { + please := NewWithT(t) + + var ( + ops options + args = []string(nil) + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "some-dir", args, statErrNotExistsAll) + + please.Expect(ops.Config).To(Equal("")) + please.Expect(ops.AdditionalConfigs).To(HaveLen(0)) + please.Expect(ops.SharedConfig).To(Equal("")) +} + +func TestSetFields_does_not_override_provided_flags(t *testing.T) { + t.Run("long", func(t *testing.T) { + please := NewWithT(t) + + var ( + ops options + args = []string{ + "--shared-config", "s.yml", + "--config", "c.yml", + "--additional-config", "a1.yml", + "--additional-config", "a2.yml", + } + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "some-dir", args, statErrNotExistsAll) + + please.Expect(ops.Config).To(Equal("c.yml")) + please.Expect(ops.AdditionalConfigs).To(Equal([]string{"a1.yml", "a2.yml"})) + please.Expect(ops.SharedConfig).To(Equal("s.yml")) + }) + + t.Run("short", func(t *testing.T) { + please := NewWithT(t) + + var ( + ops options + args = []string{ + "-s", "s.yml", + "-c", "c.yml", + "-a", "a1.yml", + "-a", "a2.yml", + } + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "some-dir", args, statErrNotExistsAll) + + please.Expect(ops.Config).To(Equal("c.yml")) + please.Expect(ops.AdditionalConfigs).To(Equal([]string{"a1.yml", "a2.yml"})) + please.Expect(ops.SharedConfig).To(Equal("s.yml")) + }) +} + +func TestSetFields_does_not_add_defaults_if_flag_exists(t *testing.T) { + please := NewWithT(t) + + var ( + ops options + args = []string{ + "--additional-config", "a2.yml", + } + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "some-dir", args, statErrNotExistsAll) + + please.Expect(ops.AdditionalConfigs).To(Equal([]string{"a2.yml"})) +} + +func TestSetFields_does_not_override_existing_array(t *testing.T) { + t.Skip(`This unexpected behavior reproduced in this test not in any actual command usage. +We don't generally add flags to slice fields before jhanda.Parse or SetFields. +This is some strange behavior but a quick fix is not clear.`) + please := NewWithT(t) + + var ( + ops = options{ + AdditionalConfigs: []string{"addition.yml"}, + } + args = []string{ + "--additional-config", "a2.yml", + } + ) + + _, err := jhanda.Parse(&ops, args) + please.Expect(err).NotTo(HaveOccurred()) + SetFields(&ops, "some-dir", args, statErrNotExistsAll) + + please.Expect(ops.AdditionalConfigs).To(Equal([]string{"addition.yml", "a2.yml"})) +} + +func statNoError(string) (os.FileInfo, error) { return nil, nil } + +func statErrNotExistsAll(string) (os.FileInfo, error) { return nil, os.ErrNotExist } diff --git a/pkg/cargo/fixtures/manifest.yml b/internal/manifest/fixtures/manifest.yml similarity index 100% rename from pkg/cargo/fixtures/manifest.yml rename to internal/manifest/fixtures/manifest.yml diff --git a/pkg/cargo/fixtures/metadata.yml b/internal/manifest/fixtures/metadata.yml similarity index 100% rename from pkg/cargo/fixtures/metadata.yml rename to internal/manifest/fixtures/metadata.yml diff --git a/pkg/cargo/generator.go b/internal/manifest/generate.go similarity index 78% rename from pkg/cargo/generator.go rename to internal/manifest/generate.go index b5a0e56ac..4aeb9cc70 100644 --- a/pkg/cargo/generator.go +++ b/internal/manifest/generate.go @@ -1,26 +1,22 @@ -package cargo +package manifest import ( - "gopkg.in/yaml.v2" + "io" + + opsman2 "github.com/pivotal-cf/kiln/internal/manifest/opsman" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" - "github.com/pivotal-cf/kiln/pkg/cargo/opsman" - "github.com/pivotal-cf/kiln/pkg/proofing" + "gopkg.in/yaml.v2" ) type OpsManagerConfig struct { DeploymentName string AvailabilityZones []string - Stemcells []opsman.Stemcell - ResourceConfigs []opsman.ResourceConfig -} - -type Generator struct{} - -func NewGenerator() Generator { - return Generator{} + Stemcells []opsman2.Stemcell + ResourceConfigs []opsman2.ResourceConfig } -func (g Generator) Execute(template proofing.ProductTemplate, config OpsManagerConfig) Manifest { +func Generate(template proofing2.ProductTemplate, config OpsManagerConfig) Manifest { releases := generateReleases(template.Releases) stemcell := findStemcell(template.StemcellCriteria, config.Stemcells) update := generateUpdate(template.Serial) @@ -37,7 +33,7 @@ func (g Generator) Execute(template proofing.ProductTemplate, config OpsManagerC } } -func generateReleases(templateReleases []proofing.Release) []Release { +func generateReleases(templateReleases []proofing2.Release) []Release { var releases []Release for _, release := range templateReleases { @@ -51,7 +47,7 @@ func generateReleases(templateReleases []proofing.Release) []Release { return releases } -func findStemcell(criteria proofing.StemcellCriteria, stemcells []opsman.Stemcell) Stemcell { +func findStemcell(criteria proofing2.StemcellCriteria, stemcells []opsman2.Stemcell) Stemcell { var stemcell Stemcell for _, s := range stemcells { @@ -80,7 +76,7 @@ func generateUpdate(serial bool) Update { } } -func generateInstanceGroups(jobTypes []proofing.JobType, resourceConfigs []opsman.ResourceConfig, availabilityZones []string, stemcellAlias string) []InstanceGroup { +func generateInstanceGroups(jobTypes []proofing2.JobType, resourceConfigs []opsman2.ResourceConfig, availabilityZones []string, stemcellAlias string) []InstanceGroup { var instanceGroups []InstanceGroup for _, jobType := range jobTypes { @@ -115,7 +111,7 @@ func generateInstanceGroups(jobTypes []proofing.JobType, resourceConfigs []opsma return instanceGroups } -func generateInstanceGroupJobs(templates []proofing.Template) []InstanceGroupJob { +func generateInstanceGroupJobs(templates []proofing2.Template) []InstanceGroupJob { var jobs []InstanceGroupJob for _, template := range templates { @@ -150,7 +146,7 @@ func evaluateManifestSnippet(snippet string) interface{} { return result } -func generateVariables(templateVariables []proofing.Variable) []Variable { +func generateVariables(templateVariables []proofing2.Variable) []Variable { var variables []Variable for _, variable := range templateVariables { @@ -163,3 +159,7 @@ func generateVariables(templateVariables []proofing.Variable) []Variable { return variables } + +func closeAndIgnoreError(c io.Closer) { + _ = c.Close() +} diff --git a/internal/manifest/generate_test.go b/internal/manifest/generate_test.go new file mode 100644 index 000000000..6f5f73242 --- /dev/null +++ b/internal/manifest/generate_test.go @@ -0,0 +1,65 @@ +package manifest + +import ( + "os" + "testing" + + opsman2 "github.com/pivotal-cf/kiln/internal/manifest/opsman" + "github.com/pivotal-cf/kiln/internal/proofing" + + "gopkg.in/yaml.v2" + + . "github.com/onsi/gomega" + gomegaMatchers "github.com/pivotal-cf-experimental/gomegamatchers" +) + +func TestGenerate(t *testing.T) { + t.Run("generates a well-formed manifest", func(t *testing.T) { + please := NewWithT(t) + + f, err := os.Open("fixtures/metadata.yml") + defer closeAndIgnoreError(f) + please.Expect(err).NotTo(HaveOccurred()) + + template, err := proofing.Parse(f) + please.Expect(err).NotTo(HaveOccurred()) + + manifest := Generate(template, OpsManagerConfig{ + DeploymentName: "some-product-name", + AvailabilityZones: []string{ + "some-az-1", + "some-az-2", + }, + Stemcells: []opsman2.Stemcell{ + { + Name: "some-stemcell-name", + Version: "some-stemcell-version", + OS: "some-stemcell-os", + }, + { + Name: "other-stemcell-name", + Version: "other-stemcell-version", + OS: "other-stemcell-os", + }, + }, + ResourceConfigs: []opsman2.ResourceConfig{ + { + Name: "some-job-type-name", + Instances: opsman2.ResourceConfigInstances{Value: 1}, + }, + { + Name: "other-job-type-name", + Instances: opsman2.ResourceConfigInstances{Value: -1}, // NOTE: negative value indicates "automatic" + }, + }, + }) + + actualManifest, err := yaml.Marshal(manifest) + please.Expect(err).NotTo(HaveOccurred()) + + expectedManifest, err := os.ReadFile("fixtures/manifest.yml") + please.Expect(err).NotTo(HaveOccurred()) + + please.Expect(actualManifest).To(gomegaMatchers.HelpfullyMatchYAML(string(expectedManifest))) + }) +} diff --git a/pkg/cargo/manifest.go b/internal/manifest/manifest.go similarity index 99% rename from pkg/cargo/manifest.go rename to internal/manifest/manifest.go index 3619c8858..074a0a244 100644 --- a/pkg/cargo/manifest.go +++ b/internal/manifest/manifest.go @@ -1,4 +1,4 @@ -package cargo +package manifest type Manifest struct { Name string `yaml:"name"` diff --git a/pkg/cargo/opsman/resource_config.go b/internal/manifest/opsman/resource_config.go similarity index 100% rename from pkg/cargo/opsman/resource_config.go rename to internal/manifest/opsman/resource_config.go diff --git a/pkg/cargo/opsman/stemcell.go b/internal/manifest/opsman/stemcell.go similarity index 100% rename from pkg/cargo/opsman/stemcell.go rename to internal/manifest/opsman/stemcell.go diff --git a/internal/pivnet/service.go b/internal/pivnet/service.go index 148249656..278dd8ade 100644 --- a/internal/pivnet/service.go +++ b/internal/pivnet/service.go @@ -10,6 +10,10 @@ import ( "strings" ) +const ( + ProductionHost = "network.pivotal.io" +) + type stringError string func (str stringError) Error() string { return string(str) } @@ -43,9 +47,9 @@ func (service *Service) SetToken(token string) { // Do sets required headers for requests to network.pivotal.io. // If service.Client is nil, it uses http.DefaultClient. -func (service Service) Do(req *http.Request) (*http.Response, error) { +func (service *Service) Do(req *http.Request) (*http.Response, error) { if service.Target == "" { - service.Target = "network.pivotal.io" + service.Target = ProductionHost } if service.Client == nil { service.Client = http.DefaultClient @@ -81,7 +85,7 @@ type Release struct { ID int `json:"id"` } -func (service Service) Releases(productSlug string) ([]Release, error) { +func (service *Service) Releases(productSlug string) ([]Release, error) { req, _ := http.NewRequest(http.MethodGet, "/api/v2/products/"+productSlug+"/releases", nil) var body struct { @@ -120,7 +124,6 @@ func (service *Service) StemcellVersion(slug string, majorStemcellVersion string locator := url.URL{ Scheme: "https", - Host: "network.pivotal.io", Path: path.Join("/api/v2/products", slug, "releases/latest"), RawQuery: fmt.Sprintf("major=%s", majorStemcellVersion), } diff --git a/pkg/proofing/collection_property_blueprint.go b/internal/proofing/collection_property_blueprint.go similarity index 100% rename from pkg/proofing/collection_property_blueprint.go rename to internal/proofing/collection_property_blueprint.go diff --git a/pkg/proofing/collection_property_blueprint_test.go b/internal/proofing/collection_property_blueprint_test.go similarity index 85% rename from pkg/proofing/collection_property_blueprint_test.go rename to internal/proofing/collection_property_blueprint_test.go index 9a59c0f54..18e8fcb52 100644 --- a/pkg/proofing/collection_property_blueprint_test.go +++ b/internal/proofing/collection_property_blueprint_test.go @@ -3,25 +3,25 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("CollectionPropertyBlueprint", func() { - var collectionPropertyBlueprint proofing.CollectionPropertyBlueprint + var collectionPropertyBlueprint proofing2.CollectionPropertyBlueprint BeforeEach(func() { f, err := os.Open("fixtures/property_blueprints.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) var ok bool - collectionPropertyBlueprint, ok = productTemplate.PropertyBlueprints[2].(proofing.CollectionPropertyBlueprint) + collectionPropertyBlueprint, ok = productTemplate.PropertyBlueprints[2].(proofing2.CollectionPropertyBlueprint) Expect(ok).To(BeTrue()) }) @@ -41,7 +41,7 @@ var _ = Describe("CollectionPropertyBlueprint", func() { It("returns a list of normalized property blueprints", func() { normalized := collectionPropertyBlueprint.Normalize("some-prefix") - Expect(normalized).To(ConsistOf([]proofing.NormalizedPropertyBlueprint{ + Expect(normalized).To(ConsistOf([]proofing2.NormalizedPropertyBlueprint{ { Property: "some-prefix.some-collection-name", Configurable: true, diff --git a/pkg/proofing/collection_property_input.go b/internal/proofing/collection_property_input.go similarity index 100% rename from pkg/proofing/collection_property_input.go rename to internal/proofing/collection_property_input.go diff --git a/pkg/proofing/collection_property_input_test.go b/internal/proofing/collection_property_input_test.go similarity index 85% rename from pkg/proofing/collection_property_input_test.go rename to internal/proofing/collection_property_input_test.go index fdb812ef7..5e68ab72c 100644 --- a/pkg/proofing/collection_property_input_test.go +++ b/internal/proofing/collection_property_input_test.go @@ -3,25 +3,25 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("CollectionPropertyInput", func() { - var collectionPropertyInput proofing.CollectionPropertyInput + var collectionPropertyInput proofing2.CollectionPropertyInput BeforeEach(func() { f, err := os.Open("fixtures/form_types.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) var ok bool - collectionPropertyInput, ok = productTemplate.FormTypes[0].PropertyInputs[1].(proofing.CollectionPropertyInput) + collectionPropertyInput, ok = productTemplate.FormTypes[0].PropertyInputs[1].(proofing2.CollectionPropertyInput) Expect(ok).To(BeTrue()) }) diff --git a/pkg/proofing/collection_subfield_property_input.go b/internal/proofing/collection_subfield_property_input.go similarity index 100% rename from pkg/proofing/collection_subfield_property_input.go rename to internal/proofing/collection_subfield_property_input.go diff --git a/pkg/proofing/errand_template.go b/internal/proofing/errand_template.go similarity index 100% rename from pkg/proofing/errand_template.go rename to internal/proofing/errand_template.go diff --git a/pkg/proofing/errand_template_test.go b/internal/proofing/errand_template_test.go similarity index 83% rename from pkg/proofing/errand_template_test.go rename to internal/proofing/errand_template_test.go index aaea87b18..213f53d35 100644 --- a/pkg/proofing/errand_template_test.go +++ b/internal/proofing/errand_template_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("ErrandTemplate", func() { - var errandTemplate proofing.ErrandTemplate + var errandTemplate proofing2.ErrandTemplate BeforeEach(func() { f, err := os.Open("fixtures/errands.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) errandTemplate = productTemplate.PostDeployErrands[0] diff --git a/pkg/proofing/fixtures/errands.yml b/internal/proofing/fixtures/errands.yml similarity index 100% rename from pkg/proofing/fixtures/errands.yml rename to internal/proofing/fixtures/errands.yml diff --git a/pkg/proofing/fixtures/form_types.yml b/internal/proofing/fixtures/form_types.yml similarity index 100% rename from pkg/proofing/fixtures/form_types.yml rename to internal/proofing/fixtures/form_types.yml diff --git a/pkg/proofing/fixtures/job_types.yml b/internal/proofing/fixtures/job_types.yml similarity index 100% rename from pkg/proofing/fixtures/job_types.yml rename to internal/proofing/fixtures/job_types.yml diff --git a/pkg/proofing/fixtures/malformed.yml b/internal/proofing/fixtures/malformed.yml similarity index 100% rename from pkg/proofing/fixtures/malformed.yml rename to internal/proofing/fixtures/malformed.yml diff --git a/pkg/proofing/fixtures/metadata.yml b/internal/proofing/fixtures/metadata.yml similarity index 100% rename from pkg/proofing/fixtures/metadata.yml rename to internal/proofing/fixtures/metadata.yml diff --git a/pkg/proofing/fixtures/property_blueprints.yml b/internal/proofing/fixtures/property_blueprints.yml similarity index 100% rename from pkg/proofing/fixtures/property_blueprints.yml rename to internal/proofing/fixtures/property_blueprints.yml diff --git a/pkg/proofing/form_type.go b/internal/proofing/form_type.go similarity index 100% rename from pkg/proofing/form_type.go rename to internal/proofing/form_type.go diff --git a/pkg/proofing/form_type_test.go b/internal/proofing/form_type_test.go similarity index 83% rename from pkg/proofing/form_type_test.go rename to internal/proofing/form_type_test.go index e18f4601e..1917b427c 100644 --- a/pkg/proofing/form_type_test.go +++ b/internal/proofing/form_type_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("FormType", func() { - var formType proofing.FormType + var formType proofing2.FormType BeforeEach(func() { f, err := os.Open("fixtures/form_types.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) formType = productTemplate.FormTypes[0] diff --git a/pkg/proofing/init_test.go b/internal/proofing/init_test.go similarity index 100% rename from pkg/proofing/init_test.go rename to internal/proofing/init_test.go diff --git a/pkg/proofing/install_time_verifier.go b/internal/proofing/install_time_verifier.go similarity index 100% rename from pkg/proofing/install_time_verifier.go rename to internal/proofing/install_time_verifier.go diff --git a/pkg/proofing/install_time_verifier_test.go b/internal/proofing/install_time_verifier_test.go similarity index 79% rename from pkg/proofing/install_time_verifier_test.go rename to internal/proofing/install_time_verifier_test.go index c27a3a559..3e29652dd 100644 --- a/pkg/proofing/install_time_verifier_test.go +++ b/internal/proofing/install_time_verifier_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("InstallTimeVerifier", func() { - var installTimeVerifier proofing.InstallTimeVerifier + var installTimeVerifier proofing2.InstallTimeVerifier BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) installTimeVerifier = productTemplate.InstallTimeVerifiers[0] diff --git a/pkg/proofing/instance_definition.go b/internal/proofing/instance_definition.go similarity index 100% rename from pkg/proofing/instance_definition.go rename to internal/proofing/instance_definition.go diff --git a/pkg/proofing/instance_definition_test.go b/internal/proofing/instance_definition_test.go similarity index 81% rename from pkg/proofing/instance_definition_test.go rename to internal/proofing/instance_definition_test.go index 0d1a0c1ff..2308ea52f 100644 --- a/pkg/proofing/instance_definition_test.go +++ b/internal/proofing/instance_definition_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("InstanceDefinition", func() { - var instanceDefinition proofing.InstanceDefinition + var instanceDefinition proofing2.InstanceDefinition BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) instanceDefinition = productTemplate.JobTypes[0].InstanceDefinition diff --git a/pkg/proofing/job_type.go b/internal/proofing/job_type.go similarity index 100% rename from pkg/proofing/job_type.go rename to internal/proofing/job_type.go diff --git a/pkg/proofing/job_type_test.go b/internal/proofing/job_type_test.go similarity index 90% rename from pkg/proofing/job_type_test.go rename to internal/proofing/job_type_test.go index 3573c45eb..1a3d69101 100644 --- a/pkg/proofing/job_type_test.go +++ b/internal/proofing/job_type_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("JobType", func() { - var jobType proofing.JobType + var jobType proofing2.JobType BeforeEach(func() { f, err := os.Open("fixtures/job_types.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) jobType = productTemplate.JobTypes[0] @@ -36,7 +36,7 @@ var _ = Describe("JobType", func() { Expect(jobType.Serial).To(BeTrue()) Expect(jobType.SingleAZOnly).To(BeTrue()) - Expect(jobType.InstanceDefinition).To(BeAssignableToTypeOf(proofing.InstanceDefinition{})) + Expect(jobType.InstanceDefinition).To(BeAssignableToTypeOf(proofing2.InstanceDefinition{})) Expect(jobType.PropertyBlueprints).To(HaveLen(1)) Expect(jobType.ResourceDefinitions).To(HaveLen(1)) Expect(jobType.Templates).To(HaveLen(1)) @@ -45,7 +45,7 @@ var _ = Describe("JobType", func() { Context("property_blueprints", func() { It("parses their structure", func() { - propertyBlueprint, ok := jobType.PropertyBlueprints[0].(proofing.SimplePropertyBlueprint) + propertyBlueprint, ok := jobType.PropertyBlueprints[0].(proofing2.SimplePropertyBlueprint) Expect(ok).To(BeTrue()) Expect(propertyBlueprint.Configurable).To(BeTrue()) diff --git a/pkg/proofing/named_manifest.go b/internal/proofing/named_manifest.go similarity index 100% rename from pkg/proofing/named_manifest.go rename to internal/proofing/named_manifest.go diff --git a/pkg/proofing/parse.go b/internal/proofing/parse.go similarity index 100% rename from pkg/proofing/parse.go rename to internal/proofing/parse.go diff --git a/pkg/proofing/parse_test.go b/internal/proofing/parse_test.go similarity index 78% rename from pkg/proofing/parse_test.go rename to internal/proofing/parse_test.go index 4e4109c45..780e030f7 100644 --- a/pkg/proofing/parse_test.go +++ b/internal/proofing/parse_test.go @@ -4,10 +4,10 @@ import ( "errors" "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("Parse", func() { @@ -16,15 +16,15 @@ var _ = Describe("Parse", func() { defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) - Expect(productTemplate).To(BeAssignableToTypeOf(proofing.ProductTemplate{})) + Expect(productTemplate).To(BeAssignableToTypeOf(proofing2.ProductTemplate{})) }) Context("failure cases", func() { Context("when the metadata file cannot be read", func() { It("returns an error", func() { - _, err := proofing.Parse(erroringReader{}) + _, err := proofing2.Parse(erroringReader{}) Expect(err).To(MatchError("failed to read")) }) }) @@ -35,7 +35,7 @@ var _ = Describe("Parse", func() { defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - _, err = proofing.Parse(f) + _, err = proofing2.Parse(f) Expect(err).To(MatchError(ContainSubstring("cannot unmarshal"))) }) }) diff --git a/pkg/proofing/product_template.go b/internal/proofing/product_template.go similarity index 100% rename from pkg/proofing/product_template.go rename to internal/proofing/product_template.go diff --git a/pkg/proofing/product_template_test.go b/internal/proofing/product_template_test.go similarity index 95% rename from pkg/proofing/product_template_test.go rename to internal/proofing/product_template_test.go index 27c1f5e12..309480bf4 100644 --- a/pkg/proofing/product_template_test.go +++ b/internal/proofing/product_template_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("ProductTemplate", func() { - var productTemplate proofing.ProductTemplate + var productTemplate proofing2.ProductTemplate BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err = proofing.Parse(f) + productTemplate, err = proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) }) @@ -46,7 +46,7 @@ var _ = Describe("ProductTemplate", func() { Expect(productTemplate.RequiresProductVersions).To(HaveLen(1)) Expect(productTemplate.Releases).To(HaveLen(1)) Expect(productTemplate.RuntimeConfigs).To(HaveLen(1)) - Expect(productTemplate.StemcellCriteria).To(BeAssignableToTypeOf(proofing.StemcellCriteria{})) + Expect(productTemplate.StemcellCriteria).To(BeAssignableToTypeOf(proofing2.StemcellCriteria{})) Expect(productTemplate.Variables).To(HaveLen(1)) }) @@ -56,7 +56,7 @@ var _ = Describe("ProductTemplate", func() { defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err = proofing.Parse(f) + productTemplate, err = proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) }) diff --git a/pkg/proofing/product_version.go b/internal/proofing/product_version.go similarity index 100% rename from pkg/proofing/product_version.go rename to internal/proofing/product_version.go diff --git a/pkg/proofing/property_blueprints.go b/internal/proofing/property_blueprints.go similarity index 100% rename from pkg/proofing/property_blueprints.go rename to internal/proofing/property_blueprints.go diff --git a/pkg/proofing/property_blueprints_test.go b/internal/proofing/property_blueprints_test.go similarity index 70% rename from pkg/proofing/property_blueprints_test.go rename to internal/proofing/property_blueprints_test.go index cd4e24574..801f49838 100644 --- a/pkg/proofing/property_blueprints_test.go +++ b/internal/proofing/property_blueprints_test.go @@ -4,34 +4,34 @@ import ( "errors" "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("PropertyBlueprints", func() { - var productTemplate proofing.ProductTemplate + var productTemplate proofing2.ProductTemplate BeforeEach(func() { f, err := os.Open("fixtures/property_blueprints.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err = proofing.Parse(f) + productTemplate, err = proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) }) It("parses the different types", func() { - Expect(productTemplate.PropertyBlueprints[0]).To(BeAssignableToTypeOf(proofing.SimplePropertyBlueprint{})) - Expect(productTemplate.PropertyBlueprints[1]).To(BeAssignableToTypeOf(proofing.SelectorPropertyBlueprint{})) - Expect(productTemplate.PropertyBlueprints[2]).To(BeAssignableToTypeOf(proofing.CollectionPropertyBlueprint{})) + Expect(productTemplate.PropertyBlueprints[0]).To(BeAssignableToTypeOf(proofing2.SimplePropertyBlueprint{})) + Expect(productTemplate.PropertyBlueprints[1]).To(BeAssignableToTypeOf(proofing2.SelectorPropertyBlueprint{})) + Expect(productTemplate.PropertyBlueprints[2]).To(BeAssignableToTypeOf(proofing2.CollectionPropertyBlueprint{})) }) Context("failure cases", func() { Context("when the YAML cannot be unmarshalled", func() { It("returns an error", func() { - propertyBlueprints := proofing.PropertyBlueprints([]proofing.PropertyBlueprint{}) + propertyBlueprints := proofing2.PropertyBlueprints([]proofing2.PropertyBlueprint{}) err := propertyBlueprints.UnmarshalYAML(func(v interface{}) error { return errors.New("unmarshal failed") diff --git a/pkg/proofing/property_inputs.go b/internal/proofing/property_inputs.go similarity index 100% rename from pkg/proofing/property_inputs.go rename to internal/proofing/property_inputs.go diff --git a/pkg/proofing/property_inputs_test.go b/internal/proofing/property_inputs_test.go similarity index 74% rename from pkg/proofing/property_inputs_test.go rename to internal/proofing/property_inputs_test.go index 26d98a1f7..16c52114b 100644 --- a/pkg/proofing/property_inputs_test.go +++ b/internal/proofing/property_inputs_test.go @@ -4,36 +4,36 @@ import ( "errors" "os" - "github.com/pivotal-cf/kiln/pkg/proofing" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" ) var _ = Describe("PropertyInputs", func() { - var formType proofing.FormType + var formType proofing2.FormType BeforeEach(func() { f, err := os.Open("fixtures/form_types.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) formType = productTemplate.FormTypes[0] }) It("parses the different types", func() { - Expect(formType.PropertyInputs[0]).To(BeAssignableToTypeOf(proofing.SimplePropertyInput{})) - Expect(formType.PropertyInputs[1]).To(BeAssignableToTypeOf(proofing.CollectionPropertyInput{})) - Expect(formType.PropertyInputs[2]).To(BeAssignableToTypeOf(proofing.SelectorPropertyInput{})) + Expect(formType.PropertyInputs[0]).To(BeAssignableToTypeOf(proofing2.SimplePropertyInput{})) + Expect(formType.PropertyInputs[1]).To(BeAssignableToTypeOf(proofing2.CollectionPropertyInput{})) + Expect(formType.PropertyInputs[2]).To(BeAssignableToTypeOf(proofing2.SelectorPropertyInput{})) }) Context("failure cases", func() { Context("when the YAML cannot be unmarshalled", func() { It("returns an error", func() { - propertyInputs := proofing.PropertyInputs([]proofing.PropertyInput{}) + propertyInputs := proofing2.PropertyInputs([]proofing2.PropertyInput{}) err := propertyInputs.UnmarshalYAML(func(v interface{}) error { return errors.New("unmarshal failed") diff --git a/pkg/proofing/release.go b/internal/proofing/release.go similarity index 100% rename from pkg/proofing/release.go rename to internal/proofing/release.go diff --git a/pkg/proofing/release_test.go b/internal/proofing/release_test.go similarity index 88% rename from pkg/proofing/release_test.go rename to internal/proofing/release_test.go index 1b2732bb1..fb1f8307e 100644 --- a/pkg/proofing/release_test.go +++ b/internal/proofing/release_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("Release", func() { - var release proofing.Release + var release proofing2.Release BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) release = productTemplate.Releases[0] @@ -36,7 +36,7 @@ var _ = Describe("Release", func() { Context("validations", func() { BeforeEach(func() { - release = proofing.Release{ + release = proofing2.Release{ Name: "some-name", Version: "some-version", File: "some-file", @@ -60,7 +60,7 @@ var _ = Describe("Release", func() { }) It("combines validations", func() { - release = proofing.Release{} + release = proofing2.Release{} Expect(release.Validate()).To(MatchError(`- release name must be present - release file must be present - release version must be present`)) diff --git a/pkg/proofing/resource_definition.go b/internal/proofing/resource_definition.go similarity index 100% rename from pkg/proofing/resource_definition.go rename to internal/proofing/resource_definition.go diff --git a/pkg/proofing/resource_definitions.go b/internal/proofing/resource_definitions.go similarity index 100% rename from pkg/proofing/resource_definitions.go rename to internal/proofing/resource_definitions.go diff --git a/pkg/proofing/resource_definitions_test.go b/internal/proofing/resource_definitions_test.go similarity index 81% rename from pkg/proofing/resource_definitions_test.go rename to internal/proofing/resource_definitions_test.go index f93a58c9a..542608a2b 100644 --- a/pkg/proofing/resource_definitions_test.go +++ b/internal/proofing/resource_definitions_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("ResourceDefinitions", func() { - var resourceDefinition proofing.ResourceDefinition + var resourceDefinition proofing2.ResourceDefinition BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) resourceDefinition = productTemplate.JobTypes[0].ResourceDefinitions[0] diff --git a/pkg/proofing/runtime_config_template.go b/internal/proofing/runtime_config_template.go similarity index 100% rename from pkg/proofing/runtime_config_template.go rename to internal/proofing/runtime_config_template.go diff --git a/pkg/proofing/runtime_config_template_test.go b/internal/proofing/runtime_config_template_test.go similarity index 77% rename from pkg/proofing/runtime_config_template_test.go rename to internal/proofing/runtime_config_template_test.go index 10f6b2a1b..468245691 100644 --- a/pkg/proofing/runtime_config_template_test.go +++ b/internal/proofing/runtime_config_template_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("RuntimeConfigTemplate", func() { - var runtimeConfigTemplate proofing.RuntimeConfigTemplate + var runtimeConfigTemplate proofing2.RuntimeConfigTemplate BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) runtimeConfigTemplate = productTemplate.RuntimeConfigs[0] diff --git a/pkg/proofing/selector_option_property_input.go b/internal/proofing/selector_option_property_input.go similarity index 100% rename from pkg/proofing/selector_option_property_input.go rename to internal/proofing/selector_option_property_input.go diff --git a/pkg/proofing/selector_property_blueprint.go b/internal/proofing/selector_property_blueprint.go similarity index 100% rename from pkg/proofing/selector_property_blueprint.go rename to internal/proofing/selector_property_blueprint.go diff --git a/pkg/proofing/selector_property_blueprint_test.go b/internal/proofing/selector_property_blueprint_test.go similarity index 87% rename from pkg/proofing/selector_property_blueprint_test.go rename to internal/proofing/selector_property_blueprint_test.go index f44beb56e..8bf40389c 100644 --- a/pkg/proofing/selector_property_blueprint_test.go +++ b/internal/proofing/selector_property_blueprint_test.go @@ -3,25 +3,25 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("SelectorPropertyBlueprint", func() { - var selectorPropertyBlueprint proofing.SelectorPropertyBlueprint + var selectorPropertyBlueprint proofing2.SelectorPropertyBlueprint BeforeEach(func() { f, err := os.Open("fixtures/property_blueprints.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) var ok bool - selectorPropertyBlueprint, ok = productTemplate.PropertyBlueprints[1].(proofing.SelectorPropertyBlueprint) + selectorPropertyBlueprint, ok = productTemplate.PropertyBlueprints[1].(proofing2.SelectorPropertyBlueprint) Expect(ok).To(BeTrue()) }) @@ -42,7 +42,7 @@ var _ = Describe("SelectorPropertyBlueprint", func() { It("returns a list of normalized property blueprints", func() { normalized := selectorPropertyBlueprint.Normalize("some-prefix") - Expect(normalized).To(ConsistOf([]proofing.NormalizedPropertyBlueprint{ + Expect(normalized).To(ConsistOf([]proofing2.NormalizedPropertyBlueprint{ { Property: "some-prefix.some-selector-name", Configurable: true, diff --git a/pkg/proofing/selector_property_input.go b/internal/proofing/selector_property_input.go similarity index 100% rename from pkg/proofing/selector_property_input.go rename to internal/proofing/selector_property_input.go diff --git a/pkg/proofing/selector_property_input_test.go b/internal/proofing/selector_property_input_test.go similarity index 85% rename from pkg/proofing/selector_property_input_test.go rename to internal/proofing/selector_property_input_test.go index 149f180e5..dcf6d8455 100644 --- a/pkg/proofing/selector_property_input_test.go +++ b/internal/proofing/selector_property_input_test.go @@ -3,25 +3,25 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("SelectorPropertyInput", func() { - var selectorPropertyInput proofing.SelectorPropertyInput + var selectorPropertyInput proofing2.SelectorPropertyInput BeforeEach(func() { f, err := os.Open("fixtures/form_types.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) var ok bool - selectorPropertyInput, ok = productTemplate.FormTypes[0].PropertyInputs[2].(proofing.SelectorPropertyInput) + selectorPropertyInput, ok = productTemplate.FormTypes[0].PropertyInputs[2].(proofing2.SelectorPropertyInput) Expect(ok).To(BeTrue()) }) @@ -35,7 +35,7 @@ var _ = Describe("SelectorPropertyInput", func() { }) Context("selector_property_inputs", func() { - var selectorOptionPropertyInput proofing.SelectorOptionPropertyInput + var selectorOptionPropertyInput proofing2.SelectorOptionPropertyInput BeforeEach(func() { selectorOptionPropertyInput = selectorPropertyInput.SelectorPropertyInputs[0] diff --git a/pkg/proofing/selector_property_option_template.go b/internal/proofing/selector_property_option_template.go similarity index 100% rename from pkg/proofing/selector_property_option_template.go rename to internal/proofing/selector_property_option_template.go diff --git a/pkg/proofing/simple_property_blueprint.go b/internal/proofing/simple_property_blueprint.go similarity index 100% rename from pkg/proofing/simple_property_blueprint.go rename to internal/proofing/simple_property_blueprint.go diff --git a/pkg/proofing/simple_property_blueprint_test.go b/internal/proofing/simple_property_blueprint_test.go similarity index 87% rename from pkg/proofing/simple_property_blueprint_test.go rename to internal/proofing/simple_property_blueprint_test.go index 47121010b..4eecf0ee1 100644 --- a/pkg/proofing/simple_property_blueprint_test.go +++ b/internal/proofing/simple_property_blueprint_test.go @@ -3,25 +3,25 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("SimplePropertyBlueprint", func() { - var simplePropertyBlueprint proofing.SimplePropertyBlueprint + var simplePropertyBlueprint proofing2.SimplePropertyBlueprint BeforeEach(func() { f, err := os.Open("fixtures/property_blueprints.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) var ok bool - simplePropertyBlueprint, ok = productTemplate.PropertyBlueprints[0].(proofing.SimplePropertyBlueprint) + simplePropertyBlueprint, ok = productTemplate.PropertyBlueprints[0].(proofing2.SimplePropertyBlueprint) Expect(ok).To(BeTrue()) }) @@ -42,7 +42,7 @@ var _ = Describe("SimplePropertyBlueprint", func() { It("returns a list of normalized property blueprints", func() { normalized := simplePropertyBlueprint.Normalize("some-prefix") - Expect(normalized).To(ConsistOf([]proofing.NormalizedPropertyBlueprint{ + Expect(normalized).To(ConsistOf([]proofing2.NormalizedPropertyBlueprint{ { Property: "some-prefix.some-simple-name", Configurable: true, diff --git a/pkg/proofing/simple_property_input.go b/internal/proofing/simple_property_input.go similarity index 100% rename from pkg/proofing/simple_property_input.go rename to internal/proofing/simple_property_input.go diff --git a/pkg/proofing/simple_property_input_test.go b/internal/proofing/simple_property_input_test.go similarity index 78% rename from pkg/proofing/simple_property_input_test.go rename to internal/proofing/simple_property_input_test.go index 39c4018d2..a3821d6b2 100644 --- a/pkg/proofing/simple_property_input_test.go +++ b/internal/proofing/simple_property_input_test.go @@ -3,25 +3,25 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("SimplePropertyInput", func() { - var simplePropertyInput proofing.SimplePropertyInput + var simplePropertyInput proofing2.SimplePropertyInput BeforeEach(func() { f, err := os.Open("fixtures/form_types.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) var ok bool - simplePropertyInput, ok = productTemplate.FormTypes[0].PropertyInputs[0].(proofing.SimplePropertyInput) + simplePropertyInput, ok = productTemplate.FormTypes[0].PropertyInputs[0].(proofing2.SimplePropertyInput) Expect(ok).To(BeTrue()) }) diff --git a/pkg/proofing/stemcell_criteria.go b/internal/proofing/stemcell_criteria.go similarity index 100% rename from pkg/proofing/stemcell_criteria.go rename to internal/proofing/stemcell_criteria.go diff --git a/pkg/proofing/stemcell_criteria_test.go b/internal/proofing/stemcell_criteria_test.go similarity index 79% rename from pkg/proofing/stemcell_criteria_test.go rename to internal/proofing/stemcell_criteria_test.go index 5e06c9807..aa5b2e4d6 100644 --- a/pkg/proofing/stemcell_criteria_test.go +++ b/internal/proofing/stemcell_criteria_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("StemcellCriteria", func() { - var stemcellCriteria proofing.StemcellCriteria + var stemcellCriteria proofing2.StemcellCriteria BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) stemcellCriteria = productTemplate.StemcellCriteria diff --git a/pkg/proofing/template.go b/internal/proofing/template.go similarity index 100% rename from pkg/proofing/template.go rename to internal/proofing/template.go diff --git a/pkg/proofing/template_test.go b/internal/proofing/template_test.go similarity index 83% rename from pkg/proofing/template_test.go rename to internal/proofing/template_test.go index 68b94076f..907e28657 100644 --- a/pkg/proofing/template_test.go +++ b/internal/proofing/template_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("Template", func() { - var template proofing.Template + var template proofing2.Template BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) template = productTemplate.JobTypes[0].Templates[0] diff --git a/pkg/proofing/validation_error.go b/internal/proofing/validation_error.go similarity index 100% rename from pkg/proofing/validation_error.go rename to internal/proofing/validation_error.go diff --git a/pkg/proofing/variable.go b/internal/proofing/variable.go similarity index 100% rename from pkg/proofing/variable.go rename to internal/proofing/variable.go diff --git a/pkg/proofing/variable_test.go b/internal/proofing/variable_test.go similarity index 80% rename from pkg/proofing/variable_test.go rename to internal/proofing/variable_test.go index add65822c..ceca87450 100644 --- a/pkg/proofing/variable_test.go +++ b/internal/proofing/variable_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("Variable", func() { - var variable proofing.Variable + var variable proofing2.Variable BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) variable = productTemplate.Variables[0] diff --git a/pkg/proofing/verifier_blueprint.go b/internal/proofing/verifier_blueprint.go similarity index 100% rename from pkg/proofing/verifier_blueprint.go rename to internal/proofing/verifier_blueprint.go diff --git a/pkg/proofing/verifier_blueprint_test.go b/internal/proofing/verifier_blueprint_test.go similarity index 78% rename from pkg/proofing/verifier_blueprint_test.go rename to internal/proofing/verifier_blueprint_test.go index 6d4458af6..8b859a886 100644 --- a/pkg/proofing/verifier_blueprint_test.go +++ b/internal/proofing/verifier_blueprint_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("VerifierBlueprint", func() { - var verifierBlueprint proofing.VerifierBlueprint + var verifierBlueprint proofing2.VerifierBlueprint BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) verifierBlueprint = productTemplate.FormTypes[0].Verifiers[0] diff --git a/pkg/proofing/zero_if_binding.go b/internal/proofing/zero_if_binding.go similarity index 100% rename from pkg/proofing/zero_if_binding.go rename to internal/proofing/zero_if_binding.go diff --git a/pkg/proofing/zero_if_binding_test.go b/internal/proofing/zero_if_binding_test.go similarity index 79% rename from pkg/proofing/zero_if_binding_test.go rename to internal/proofing/zero_if_binding_test.go index afebc50c1..df7ba2be8 100644 --- a/pkg/proofing/zero_if_binding_test.go +++ b/internal/proofing/zero_if_binding_test.go @@ -3,21 +3,21 @@ package proofing_test import ( "os" + proofing2 "github.com/pivotal-cf/kiln/internal/proofing" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) var _ = Describe("ZeroIf", func() { - var zeroIfBinding proofing.ZeroIfBinding + var zeroIfBinding proofing2.ZeroIfBinding BeforeEach(func() { f, err := os.Open("fixtures/metadata.yml") defer closeAndIgnoreError(f) Expect(err).NotTo(HaveOccurred()) - productTemplate, err := proofing.Parse(f) + productTemplate, err := proofing2.Parse(f) Expect(err).NotTo(HaveOccurred()) zeroIfBinding = productTemplate.JobTypes[0].InstanceDefinition.ZeroIf diff --git a/internal/test-helpers/tgz_helpers.go b/internal/test-helpers/tgz_helpers.go deleted file mode 100644 index 257e54d3a..000000000 --- a/internal/test-helpers/tgz_helpers.go +++ /dev/null @@ -1,81 +0,0 @@ -package test_helpers - -import ( - "archive/tar" - "compress/gzip" - "crypto/sha1" - "fmt" - "io" - "os" - "strings" - "time" - - "github.com/go-git/go-billy/v5" -) - -func WriteReleaseTarball(path, name, version string, fs billy.Filesystem) (string, error) { - releaseManifest := ` -name: ` + name + ` -version: ` + version + ` -` - return WriteTarballWithFile(path, "release.MF", releaseManifest, fs) -} - -func WriteTarballWithFile(tarballPath, internalFilePath, fileContents string, fs billy.Filesystem) (string, error) { - f, err := fs.Create(tarballPath) - if err != nil { - return "", err - } - - gw := gzip.NewWriter(f) - tw := tar.NewWriter(gw) - - contentsReader := strings.NewReader(fileContents) - - header := &tar.Header{ - Name: internalFilePath, - Size: contentsReader.Size(), - Mode: int64(os.O_RDONLY), - ModTime: time.Now(), - } - err = tw.WriteHeader(header) - if err != nil { - return "", err - } - - _, err = io.Copy(tw, contentsReader) - if err != nil { - return "", err - } - - err = tw.Close() - if err != nil { - return "", err - } - - err = gw.Close() - if err != nil { - return "", err - } - - err = f.Close() - if err != nil { - return "", err - } - - tarball, err := fs.Open(tarballPath) - if err != nil { - return "", err - } - defer closeAndIgnoreError(tarball) - - hash := sha1.New() - _, err = io.Copy(hash, tarball) - if err != nil { - return "", err - } - - return fmt.Sprintf("%x", hash.Sum(nil)), nil -} - -func closeAndIgnoreError(c io.Closer) { _ = c.Close() } diff --git a/internal/tools/import.go b/internal/tools/import.go index 96e1b9b12..3912c07ad 100644 --- a/internal/tools/import.go +++ b/internal/tools/import.go @@ -1,6 +1,8 @@ //go:build tools // +build tools +// Package tools is a convention in Go codebases to trick the dependency manager to include development CLIs into +// the codebase. It is often used for generators. package tools import ( diff --git a/main.go b/main.go index c924b224e..525d21083 100644 --- a/main.go +++ b/main.go @@ -18,43 +18,41 @@ import ( var version = "unknown" func main() { - errLogger := log.New(os.Stderr, "", 0) - outLogger := log.New(os.Stdout, "", 0) - + // ------------------- + // parse global flags var global struct { Help bool `short:"h" long:"help" description:"prints this usage information" default:"false"` Version bool `short:"v" long:"version" description:"prints the kiln release version" default:"false"` } - args, err := jhanda.Parse(&global, os.Args[1:]) if err != nil { log.Fatal(err) } - globalFlagsUsage, err := jhanda.PrintUsage(global) if err != nil { log.Fatal(err) } + // ------------------------------------- + // Set root command and shift arguments var command string if len(args) > 0 { command, args = args[0], args[1:] } - - if global.Version { + switch { + case global.Version: command = "version" - } - - if global.Help { + case global.Help: command = "help" - } - - if command == "" { + case command == "": command = "help" } + // -------------------- + // Setup collaborators fs := osfs.New("") - + errLogger := log.New(os.Stderr, "", 0) + outLogger := log.New(os.Stdout, "", 0) releaseManifestReader := builder.NewReleaseManifestReader(fs) releasesService := baking.NewReleasesService(errLogger, releaseManifestReader) pivnetService := new(pivnet.Service) @@ -67,43 +65,61 @@ func main() { repo := component.NewReleaseSourceRepo(kilnfile, outLogger) return repo.FindReleaseUploader(sourceID) }) - rpFinder := commands.RemotePatherFinder(func(kilnfile cargo.Kilnfile, sourceID string) (component.RemotePather, error) { - repo := component.NewReleaseSourceRepo(kilnfile, outLogger) - return repo.FindRemotePather(sourceID) - }) + + // ------------------ + // Register commands + const ( + bakeCommandName = "bake" + cacheReleasesCommandName = "cache-releases" + createReleaseNotesCommandName = "create-release-notes" + fetchReleasesCommandName = "fetch-releases" + findReleaseVersionCommandName = "find-release-version" + findStemcellVersionCommandName = "find-stemcell-version" + publishReleaseCommandName = "publish-release" + updateReleaseCommandName = "update-release" + updateStemcellCommandName = "update-stemcell" + validateCommandName = "validate" + ) commandSet := jhanda.CommandSet{} - commandSet["help"] = commands.NewHelp(os.Stdout, globalFlagsUsage, commandSet) + + // Global Commands + commandSet["help"] = commands.NewHelp(os.Stdout, globalFlagsUsage, commandSet, + []string{"Tile Commands", "Component Commands", "Component Team Commands"}, + map[string][]string{ + "Component Team Commands": {publishReleaseCommandName, updateReleaseCommandName}, + "Tile Commands": {bakeCommandName, validateCommandName, createReleaseNotesCommandName}, + "Component Commands": {fetchReleasesCommandName, cacheReleasesCommandName, findReleaseVersionCommandName, findStemcellVersionCommandName, updateStemcellCommandName}, + }, + ) commandSet["version"] = commands.NewVersion(outLogger, version) - commandSet["bake"] = commands.NewBake(fs, releasesService, outLogger, errLogger) - commandSet["update-release"] = commands.NewUpdateRelease(outLogger, fs, mrsProvider) - commandSet["fetch"] = commands.NewFetch(outLogger, mrsProvider, localReleaseDirectory) - commandSet["upload-release"] = commands.UploadRelease{ + + // Component Team Commands + commandSet[updateReleaseCommandName] = commands.NewUpdateRelease(outLogger, fs, mrsProvider) + commandSet[publishReleaseCommandName] = &commands.PublishRelease{ FS: fs, Logger: outLogger, ReleaseUploaderFinder: ruFinder, } - commandSet["sync-with-local"] = commands.NewSyncWithLocal(fs, localReleaseDirectory, rpFinder, outLogger) - commandSet["publish"] = commands.NewPublish(outLogger, errLogger, osfs.New("")) - commandSet["update-stemcell"] = commands.UpdateStemcell{ + // Tile Commands + commandSet[bakeCommandName] = commands.NewBake(fs, releasesService, outLogger, errLogger) + commandSet[validateCommandName] = commands.NewValidate(osfs.New("")) + commandSet[createReleaseNotesCommandName] = commands.NewReleaseNotesCommand() + + // Component Commands + commandSet[fetchReleasesCommandName] = commands.NewFetchReleases(outLogger, mrsProvider, localReleaseDirectory) + commandSet[cacheReleasesCommandName] = commands.NewCacheReleases().WithLogger(outLogger) + commandSet[findReleaseVersionCommandName] = commands.NewFindReleaseVersion(outLogger, mrsProvider) + commandSet[findStemcellVersionCommandName] = commands.NewFindStemcellVersion(outLogger, pivnetService) + commandSet[updateStemcellCommandName] = &commands.UpdateStemcell{ Logger: outLogger, MultiReleaseSourceProvider: mrsProvider, FS: osfs.New(""), } - commandSet["find-release-version"] = commands.NewFindReleaseVersion(outLogger, mrsProvider) - - commandSet["find-stemcell-version"] = commands.NewFindStemcellVersion(outLogger, pivnetService) - - commandSet["cache-compiled-releases"] = commands.NewCacheCompiledReleases().WithLogger(outLogger) - - commandSet["validate"] = commands.NewValidate(osfs.New("")) - commandSet["release-notes"], err = commands.NewReleaseNotesCommand() - if err != nil { - log.Fatal(err) - } - + // ------------ + // Run command err = commandSet.Execute(command, args) if err != nil { log.Fatal(err) diff --git a/pkg/cargo/generator_test.go b/pkg/cargo/generator_test.go deleted file mode 100644 index f568cf80b..000000000 --- a/pkg/cargo/generator_test.go +++ /dev/null @@ -1,72 +0,0 @@ -package cargo_test - -import ( - "os" - - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" - . "github.com/pivotal-cf-experimental/gomegamatchers" - - "gopkg.in/yaml.v2" - - "github.com/pivotal-cf/kiln/pkg/cargo" - "github.com/pivotal-cf/kiln/pkg/cargo/opsman" - "github.com/pivotal-cf/kiln/pkg/proofing" -) - -var _ = Describe("Generator", func() { - var generator cargo.Generator - - BeforeEach(func() { - generator = cargo.NewGenerator() - }) - - Describe("Execute", func() { - It("generates a well-formed manifest", func() { - f, err := os.Open("fixtures/metadata.yml") - defer closeAndIgnoreError(f) - Expect(err).NotTo(HaveOccurred()) - - template, err := proofing.Parse(f) - Expect(err).NotTo(HaveOccurred()) - - manifest := generator.Execute(template, cargo.OpsManagerConfig{ - DeploymentName: "some-product-name", - AvailabilityZones: []string{ - "some-az-1", - "some-az-2", - }, - Stemcells: []opsman.Stemcell{ - { - Name: "some-stemcell-name", - Version: "some-stemcell-version", - OS: "some-stemcell-os", - }, - { - Name: "other-stemcell-name", - Version: "other-stemcell-version", - OS: "other-stemcell-os", - }, - }, - ResourceConfigs: []opsman.ResourceConfig{ - { - Name: "some-job-type-name", - Instances: opsman.ResourceConfigInstances{Value: 1}, - }, - { - Name: "other-job-type-name", - Instances: opsman.ResourceConfigInstances{Value: -1}, // NOTE: negative value indicates "automatic" - }, - }, - }) - - actualManifest, err := yaml.Marshal(manifest) - Expect(err).NotTo(HaveOccurred()) - - expectedManifest, err := os.ReadFile("fixtures/manifest.yml") - Expect(err).NotTo(HaveOccurred()) - - Expect(actualManifest).To(HelpfullyMatchYAML(string(expectedManifest))) - }) - }) -}) diff --git a/pkg/cargo/kilnfile.go b/pkg/cargo/kilnfile.go index 4f376f0f5..3858fcb10 100644 --- a/pkg/cargo/kilnfile.go +++ b/pkg/cargo/kilnfile.go @@ -5,6 +5,8 @@ import ( "fmt" "strings" + "github.com/pivotal-cf/kiln/internal/manifest" + "github.com/Masterminds/semver" boshdir "github.com/cloudfoundry/bosh-cli/director" ) @@ -217,3 +219,5 @@ func (k KilnfileLock) UpdateReleaseLockWithName(name string, lock ComponentLock) } return errors.New("not found") } + +type Stemcell = manifest.Stemcell diff --git a/pkg/cargo/kilnfile_helpers_test.go b/pkg/cargo/kilnfile_helpers_test.go index 5e2cb58c3..389cf0738 100644 --- a/pkg/cargo/kilnfile_helpers_test.go +++ b/pkg/cargo/kilnfile_helpers_test.go @@ -4,13 +4,13 @@ import ( "strings" "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" "github.com/pivotal-cf/kiln/pkg/cargo" ) func TestInterpolateAndParseKilnfile(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) variables := map[string]interface{}{ "bucket": "my-bucket", @@ -25,9 +25,9 @@ func TestInterpolateAndParseKilnfile(t *testing.T) { strings.NewReader(validKilnfile), variables, ) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(kilnfile).To(Ω.Equal(cargo.Kilnfile{ + please.Expect(kilnfile).To(Equal(cargo.Kilnfile{ ReleaseSources: []cargo.ReleaseSourceConfig{ { Type: "s3", @@ -42,7 +42,7 @@ func TestInterpolateAndParseKilnfile(t *testing.T) { } func TestInterpolateAndParseKilnfile_input_is_not_valid_yaml(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) variables := map[string]interface{}{ "bucket": "my-bucket", @@ -57,11 +57,11 @@ func TestInterpolateAndParseKilnfile_input_is_not_valid_yaml(t *testing.T) { strings.NewReader("invalid : bad : yaml"), variables, ) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) } func TestInterpolateAndParseKilnfile_interpolation_variable_not_found(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) variables := map[string]interface{}{ "bucket": "my-bucket", @@ -76,7 +76,7 @@ func TestInterpolateAndParseKilnfile_interpolation_variable_not_found(t *testing strings.NewReader(validKilnfile), variables, ) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) } const validKilnfile = `--- diff --git a/pkg/cargo/kilnfile_test.go b/pkg/cargo/kilnfile_test.go index efcf7184e..9db891779 100644 --- a/pkg/cargo/kilnfile_test.go +++ b/pkg/cargo/kilnfile_test.go @@ -3,7 +3,8 @@ package cargo import ( "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" + "gopkg.in/yaml.v2" ) @@ -14,7 +15,7 @@ version: fake-version remote_source: fake-source remote_path: fake/path/to/fake-component-name ` - damnit := Ω.NewWithT(t) + damnit := NewWithT(t) cl, err := yaml.Marshal(ComponentLock{ Name: "fake-component-name", @@ -24,6 +25,6 @@ remote_path: fake/path/to/fake-component-name RemotePath: "fake/path/to/fake-component-name", }) - damnit.Expect(err).NotTo(Ω.HaveOccurred()) - damnit.Expect(string(cl)).To(Ω.Equal(validComponentLockYaml)) + damnit.Expect(err).NotTo(HaveOccurred()) + damnit.Expect(string(cl)).To(Equal(validComponentLockYaml)) } diff --git a/pkg/cargo/load_kilnfiles.go b/pkg/cargo/load_kilnfiles.go index 508d4d27d..d1f4c4dfc 100644 --- a/pkg/cargo/load_kilnfiles.go +++ b/pkg/cargo/load_kilnfiles.go @@ -30,7 +30,7 @@ func (k KilnfileLoader) LoadKilnfiles(fs billy.Filesystem, kilnfilePath string, templateVariablesService := baking.NewTemplateVariablesService(fs) templateVariables, err := templateVariablesService.FromPathsAndPairs(variablesFiles, variables) if err != nil { - return Kilnfile{}, KilnfileLock{}, fmt.Errorf("error processing --variable or --variables-file arguments - are you logged into lpass? (error: %w)", err) + return Kilnfile{}, KilnfileLock{}, fmt.Errorf("loading variables failed: %w", err) } kf, err := fs.Open(kilnfilePath) diff --git a/pkg/history/historic_test.go b/pkg/history/historic_test.go index 8bf55e01b..2d5eeae94 100644 --- a/pkg/history/historic_test.go +++ b/pkg/history/historic_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" @@ -17,7 +17,7 @@ import ( ) func TestVersion(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) // START setup tileDir := "tile" @@ -51,15 +51,15 @@ func TestVersion(t *testing.T) { t.Run("alpha", func(t *testing.T) { version, err := Version(repo.Storer, initialHash, "tile") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(version).To(Ω.Equal("1.0.0-alpha.1")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(version).To(Equal("1.0.0-alpha.1")) }) t.Run("ga release", func(t *testing.T) { version, err := Version(repo.Storer, finalHash, "tile") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(version).To(Ω.Equal("1.0.0")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(version).To(Equal("1.0.0")) }) } @@ -120,24 +120,24 @@ func TestKilnfile(t *testing.T) { // END setup t.Run("legacy bill of materials", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) _, kl, err := Kilnfile(repo.Storer, initialHash, "tile") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(kl.Releases).To(Ω.Equal([]cargo.ComponentLock{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(kl.Releases).To(Equal([]cargo.ComponentLock{ {Name: "banana", Version: "0.1.0"}, {Name: "lemon", Version: "1.1.0"}, })) }) t.Run("Kilnfile.lock", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) _, finalKF, err := Kilnfile(repo.Storer, finalHash, "tile/Kilnfile") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(finalKF.Releases).To(Ω.Equal([]cargo.ComponentLock{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(finalKF.Releases).To(Equal([]cargo.ComponentLock{ {Name: "banana", Version: "0.9.0"}, {Name: "lemon", Version: "1.9.0"}, {Name: "apple", Version: "0.0.1"}, @@ -145,23 +145,23 @@ func TestKilnfile(t *testing.T) { }) t.Run("Kilnfile", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) kf, _, err := Kilnfile(repo.Storer, finalHash, "tile") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(kf.Releases).To(Ω.Equal([]cargo.ComponentSpec{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(kf.Releases).To(Equal([]cargo.ComponentSpec{ {Name: "banana"}, {Name: "lemon"}, })) }) t.Run("bad yaml", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) _, _, err := Kilnfile(repo.Storer, badYAML, "tile") - please.Expect(err).To(Ω.MatchError(Ω.ContainSubstring("cannot unmarshal"))) + please.Expect(err).To(MatchError(ContainSubstring("cannot unmarshal"))) }) } @@ -217,15 +217,15 @@ func TestWalk(t *testing.T) { }, h1) // END setup - please := Ω.NewWithT(t) + please := NewWithT(t) callCount := 0 err := Walk(repo.Storer, hf, func(*object.Commit) error { callCount++ return nil }) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(callCount).To(Ω.Equal(3)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(callCount).To(Equal(3)) }) t.Run("with branch", func(t *testing.T) { @@ -277,15 +277,15 @@ func TestWalk(t *testing.T) { }, h1, b2) // END setup - please := Ω.NewWithT(t) + please := NewWithT(t) callCount := 0 err := Walk(repo.Storer, hf, func(*object.Commit) error { callCount++ return nil }) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(callCount).To(Ω.Equal(5)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(callCount).To(Equal(5)) }) } diff --git a/internal/release/fakes/historic_kilnfile.go b/pkg/notes/fakes/historic_kilnfile.go similarity index 100% rename from internal/release/fakes/historic_kilnfile.go rename to pkg/notes/fakes/historic_kilnfile.go diff --git a/internal/release/fakes/historic_version.go b/pkg/notes/fakes/historic_version.go similarity index 100% rename from internal/release/fakes/historic_version.go rename to pkg/notes/fakes/historic_version.go diff --git a/internal/release/fakes/issue_getter.go b/pkg/notes/fakes/issue_getter.go similarity index 100% rename from internal/release/fakes/issue_getter.go rename to pkg/notes/fakes/issue_getter.go diff --git a/internal/release/fakes/issues_by_repo_lister.go b/pkg/notes/fakes/issues_by_repo_lister.go similarity index 100% rename from internal/release/fakes/issues_by_repo_lister.go rename to pkg/notes/fakes/issues_by_repo_lister.go diff --git a/internal/release/fakes/issues_service.go b/pkg/notes/fakes/issues_service.go similarity index 100% rename from internal/release/fakes/issues_service.go rename to pkg/notes/fakes/issues_service.go diff --git a/internal/release/fakes/milestone_lister.go b/pkg/notes/fakes/milestone_lister.go similarity index 100% rename from internal/release/fakes/milestone_lister.go rename to pkg/notes/fakes/milestone_lister.go diff --git a/internal/release/fakes/releases_service.go b/pkg/notes/fakes/releases_service.go similarity index 100% rename from internal/release/fakes/releases_service.go rename to pkg/notes/fakes/releases_service.go diff --git a/internal/release/fakes/revision_resolver.go b/pkg/notes/fakes/revision_resolver.go similarity index 100% rename from internal/release/fakes/revision_resolver.go rename to pkg/notes/fakes/revision_resolver.go diff --git a/internal/release/notes.md.template b/pkg/notes/notes.md.template similarity index 100% rename from internal/release/notes.md.template rename to pkg/notes/notes.md.template diff --git a/internal/release/notes_data.go b/pkg/notes/notes_data.go similarity index 96% rename from internal/release/notes_data.go rename to pkg/notes/notes_data.go index 414e662cb..7e8158407 100644 --- a/internal/release/notes_data.go +++ b/pkg/notes/notes_data.go @@ -1,4 +1,4 @@ -package release +package notes import ( "bytes" @@ -42,7 +42,7 @@ func (cd ComponentData) HasReleaseNotes() bool { return false } -type NotesData struct { +type Data struct { Version *semver.Version ReleaseDate time.Time @@ -53,28 +53,28 @@ type NotesData struct { Stemcell cargo.Stemcell } -//func (notes NotesData) String() string { +//func (notes Data) String() string { // note, _ := notes.WriteVersionNotes() // return note.Notes //} -func (notes NotesData) WriteVersionNotes() (VersionNote, error) { - noteTemplate, err := DefaultTemplateFuncs(template.New("")).Parse(DefaultNotesTemplate()) +func (notes Data) WriteVersionNotes() (TileVersionNote, error) { + noteTemplate, err := DefaultTemplateFunctions(template.New("")).Parse(DefaultNotesTemplate()) if err != nil { - return VersionNote{}, err + return TileVersionNote{}, err } var buf bytes.Buffer err = noteTemplate.Execute(&buf, notes) if err != nil { - return VersionNote{}, err + return TileVersionNote{}, err } - return VersionNote{ + return TileVersionNote{ Version: notes.Version.String(), Notes: buf.String(), }, nil } -func (notes NotesData) HasComponentReleases() bool { +func (notes Data) HasComponentReleases() bool { for _, r := range notes.Components { if len(r.Releases) > 0 { return true @@ -102,10 +102,10 @@ func (q IssuesQuery) Exp() (*regexp.Regexp, error) { return regexp.Compile(str) } -func FetchNotesData(ctx context.Context, repo *git.Repository, client *github.Client, tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision string, issuesQuery IssuesQuery) (NotesData, error) { +func FetchNotesData(ctx context.Context, repo *git.Repository, client *github.Client, tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision string, issuesQuery IssuesQuery) (Data, error) { f, err := newFetchNotesData(repo, tileRepoOwner, tileRepoName, kilnfilePath, initialRevision, finalRevision, client, issuesQuery) if err != nil { - return NotesData{}, err + return Data{}, err } return f.fetch(ctx) } @@ -155,13 +155,13 @@ type fetchNotesData struct { issuesQuery IssuesQuery } -func (r fetchNotesData) fetch(ctx context.Context) (NotesData, error) { +func (r fetchNotesData) fetch(ctx context.Context) (Data, error) { initialKilnfileLock, finalKilnfileLock, finalKilnfile, finalVersion, err := r.fetchHistoricFiles(r.kilnfilePath, r.initialRevision, r.finalRevision) if err != nil { - return NotesData{}, err + return Data{}, err } - data := NotesData{ + data := Data{ Version: finalVersion, Bumps: component.CalculateBumps(finalKilnfileLock.Releases, initialKilnfileLock.Releases), Stemcell: finalKilnfileLock.Stemcell, @@ -169,12 +169,12 @@ func (r fetchNotesData) fetch(ctx context.Context) (NotesData, error) { wtKilnfile, err := r.kilnfileFromWorktree(r.kilnfilePath) if err != nil { - return NotesData{}, err + return Data{}, err } data.Issues, data.Bumps, err = r.fetchIssuesAndReleaseNotes(ctx, finalKilnfile, wtKilnfile, data.Bumps, r.issuesQuery) if err != nil { - return NotesData{}, err + return Data{}, err } for _, c := range finalKilnfileLock.Releases { diff --git a/internal/release/notes_data_test.go b/pkg/notes/notes_data_test.go similarity index 76% rename from internal/release/notes_data_test.go rename to pkg/notes/notes_data_test.go index 797aa131e..ae49b84cc 100644 --- a/internal/release/notes_data_test.go +++ b/pkg/notes/notes_data_test.go @@ -1,4 +1,4 @@ -package release +package notes import ( "context" @@ -8,7 +8,8 @@ import ( "sort" "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" + "github.com/pivotal-cf/kiln/pkg/notes/fakes" "github.com/go-git/go-billy/v5/memfs" "github.com/go-git/go-git/v5" @@ -16,12 +17,11 @@ import ( "github.com/go-git/go-git/v5/storage/memory" "github.com/google/go-github/v40/github" - "github.com/pivotal-cf/kiln/internal/release/fakes" "github.com/pivotal-cf/kiln/pkg/cargo" ) func Test_fetch(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) t.Setenv("GITHUB_TOKEN", "") @@ -110,85 +110,85 @@ func Test_fetch(t *testing.T) { } _, err := rn.fetch(context.Background()) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(revisionResolver.ResolveRevisionCallCount()).To(Ω.Equal(2)) - please.Expect(revisionResolver.ResolveRevisionArgsForCall(0)).To(Ω.Equal(plumbing.Revision("tile/1.1.0"))) - please.Expect(revisionResolver.ResolveRevisionArgsForCall(1)).To(Ω.Equal(plumbing.Revision("tile/1.2.0"))) + please.Expect(revisionResolver.ResolveRevisionCallCount()).To(Equal(2)) + please.Expect(revisionResolver.ResolveRevisionArgsForCall(0)).To(Equal(plumbing.Revision("tile/1.1.0"))) + please.Expect(revisionResolver.ResolveRevisionArgsForCall(1)).To(Equal(plumbing.Revision("tile/1.2.0"))) - please.Expect(historicVersion.CallCount()).To(Ω.Equal(1)) + please.Expect(historicVersion.CallCount()).To(Equal(1)) _, historicVersionHashArg, _ := historicVersion.ArgsForCall(0) - please.Expect(historicVersionHashArg).To(Ω.Equal(finalHash)) - please.Expect(fakeReleaseService.ListReleasesCallCount()).To(Ω.Equal(2)) - please.Expect(fakeIssuesService.GetCallCount()).To(Ω.Equal(2)) + please.Expect(historicVersionHashArg).To(Equal(finalHash)) + please.Expect(fakeReleaseService.ListReleasesCallCount()).To(Equal(2)) + please.Expect(fakeIssuesService.GetCallCount()).To(Equal(2)) _, orgName, repoName, n := fakeIssuesService.GetArgsForCall(0) - please.Expect(orgName).To(Ω.Equal("pivotal-cf")) - please.Expect(repoName).To(Ω.Equal("fake-tile-repo")) - please.Expect(n).To(Ω.Equal(54000)) + please.Expect(orgName).To(Equal("pivotal-cf")) + please.Expect(repoName).To(Equal("fake-tile-repo")) + please.Expect(n).To(Equal(54000)) _, orgName, repoName, n = fakeIssuesService.GetArgsForCall(1) - please.Expect(orgName).To(Ω.Equal("pivotal-cf")) - please.Expect(repoName).To(Ω.Equal("fake-tile-repo")) - please.Expect(n).To(Ω.Equal(54321)) + please.Expect(orgName).To(Equal("pivotal-cf")) + please.Expect(repoName).To(Equal("fake-tile-repo")) + please.Expect(n).To(Equal(54321)) } func Test_issuesFromIssueIDs(t *testing.T) { t.Parallel() t.Run("no ids", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssueGetter) result, err := issuesFromIssueIDs(context.Background(), issuesService, "o", "n", nil) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(result).To(Ω.HaveLen(0)) - please.Expect(issuesService.GetCallCount()).To(Ω.Equal(0)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(result).To(HaveLen(0)) + please.Expect(issuesService.GetCallCount()).To(Equal(0)) }) t.Run("some ids", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssueGetter) issuesService.GetReturnsOnCall(0, &github.Issue{Number: intPtr(1)}, githubResponse(t, 200), nil) issuesService.GetReturnsOnCall(1, &github.Issue{Number: intPtr(2)}, githubResponse(t, 200), nil) result, err := issuesFromIssueIDs(context.Background(), issuesService, "o", "n", []string{"1", "2"}) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(result).To(Ω.HaveLen(2)) - please.Expect(result[0].GetNumber()).To(Ω.Equal(1)) - please.Expect(result[1].GetNumber()).To(Ω.Equal(2)) + please.Expect(result).To(HaveLen(2)) + please.Expect(result[0].GetNumber()).To(Equal(1)) + please.Expect(result[1].GetNumber()).To(Equal(2)) - please.Expect(issuesService.GetCallCount()).To(Ω.Equal(2)) + please.Expect(issuesService.GetCallCount()).To(Equal(2)) ctx, ro, rn, number := issuesService.GetArgsForCall(0) - please.Expect(ctx).NotTo(Ω.BeNil()) - please.Expect(ro).To(Ω.Equal("o")) - please.Expect(rn).To(Ω.Equal("n")) - please.Expect(number).To(Ω.Equal(1)) + please.Expect(ctx).NotTo(BeNil()) + please.Expect(ro).To(Equal("o")) + please.Expect(rn).To(Equal("n")) + please.Expect(number).To(Equal(1)) _, _, _, number = issuesService.GetArgsForCall(1) - please.Expect(number).To(Ω.Equal(2)) + please.Expect(number).To(Equal(2)) }) t.Run("the issues service returns an error", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssueGetter) issuesService.GetReturnsOnCall(0, &github.Issue{Number: intPtr(1)}, nil, errors.New("banana")) _, err := issuesFromIssueIDs(context.Background(), issuesService, "o", "n", []string{"1"}) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) t.Run("the issues service returns a not okay status", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssueGetter) issuesService.GetReturnsOnCall(0, &github.Issue{Number: intPtr(1)}, githubResponse(t, http.StatusUnauthorized), nil) _, err := issuesFromIssueIDs(context.Background(), issuesService, "o", "n", []string{"1"}) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) } @@ -196,26 +196,26 @@ func Test_resolveMilestoneNumber(t *testing.T) { t.Parallel() t.Run("empty milestone option", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.MilestoneLister) result, err := resolveMilestoneNumber(context.Background(), issuesService, "o", "n", "") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(result).To(Ω.Equal("")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(result).To(Equal("")) }) t.Run("when passed a number", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.MilestoneLister) result, err := resolveMilestoneNumber(context.Background(), issuesService, "o", "n", "42") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(result).To(Ω.Equal("42"), "it returns that number") - please.Expect(issuesService.ListMilestonesCallCount()).To(Ω.Equal(0), "it does not reach out o") + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(result).To(Equal("42"), "it returns that number") + please.Expect(issuesService.ListMilestonesCallCount()).To(Equal(0), "it does not reach out o") }) t.Run("when the milestone is found on the second page", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.MilestoneLister) issuesService.ListMilestonesReturnsOnCall(0, @@ -237,31 +237,31 @@ func Test_resolveMilestoneNumber(t *testing.T) { result, err := resolveMilestoneNumber(context.Background(), issuesService, "o", "n", "banana") - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(issuesService.ListMilestonesCallCount()).To(Ω.Equal(2)) - please.Expect(result).To(Ω.Equal("42")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(issuesService.ListMilestonesCallCount()).To(Equal(2)) + please.Expect(result).To(Equal("42")) }) // TODO: test pagination t.Run("the issues service returns an error", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.MilestoneLister) issuesService.ListMilestonesReturns(nil, nil, errors.New("banana")) _, err := resolveMilestoneNumber(context.Background(), issuesService, "o", "n", "m") - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) t.Run("the issues service returns a not okay status", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.MilestoneLister) issuesService.ListMilestonesReturns(nil, githubResponse(t, http.StatusUnauthorized), nil) _, err := resolveMilestoneNumber(context.Background(), issuesService, "o", "n", "m") - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) } @@ -269,39 +269,39 @@ func Test_fetchIssuesWithLabelAndMilestone(t *testing.T) { t.Parallel() t.Run("empty milestone and labels", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssuesByRepoLister) result, err := fetchIssuesWithLabelAndMilestone(context.Background(), issuesService, "o", "n", "", nil) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(result).To(Ω.HaveLen(0)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(result).To(HaveLen(0)) }) // TODO: issue service call params t.Run("the issues service returns an error", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssuesByRepoLister) issuesService.ListByRepoReturns(nil, nil, errors.New("banana")) _, err := fetchIssuesWithLabelAndMilestone(context.Background(), issuesService, "o", "n", "1", nil) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) t.Run("the issues service returns a not okay status", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issuesService := new(fakes.IssuesByRepoLister) issuesService.ListByRepoReturns(nil, githubResponse(t, http.StatusUnauthorized), nil) _, err := fetchIssuesWithLabelAndMilestone(context.Background(), issuesService, "o", "n", "1", nil) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) } func Test_issuesBySemanticTitlePrefix(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) issues := []*github.Issue{ {Title: strPtr("**[NONE]** lorem ipsum")}, @@ -318,7 +318,7 @@ func Test_issuesBySemanticTitlePrefix(t *testing.T) { titles = append(titles, issue.GetTitle()) } - please.Expect(titles).To(Ω.Equal([]string{ + please.Expect(titles).To(Equal([]string{ "**[security Fix]** 111 lorem ipsum", "**[security fix]** 222 lorem ipsum", "**[Feature]** lorem ipsum", @@ -329,7 +329,7 @@ func Test_issuesBySemanticTitlePrefix(t *testing.T) { } func Test_appendFilterAndSortIssues(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) getID := func() func() int64 { var n int64 return func() int64 { @@ -358,7 +358,7 @@ func Test_appendFilterAndSortIssues(t *testing.T) { titles = append(titles, issue.GetTitle()) } - please.Expect(titles).To(Ω.Equal([]string{ + please.Expect(titles).To(Equal([]string{ "**[security Fix]** 111 lorem ipsum", "**[security fix]** 222 lorem ipsum", "**[Feature]** lorem ipsum", @@ -369,24 +369,24 @@ func Test_appendFilterAndSortIssues(t *testing.T) { } func TestReleaseNotes_Options_IssueTitleExp(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) exp, err := IssuesQuery{}.Exp() - please.Expect(err).NotTo(Ω.HaveOccurred()) - - please.Expect(exp.MatchString("**[Bug Fix]** Lorem Ipsum")).To(Ω.BeTrue()) - please.Expect(exp.MatchString("**[bug fix]** Lorem Ipsum")).To(Ω.BeTrue()) - please.Expect(exp.MatchString("**[Feature]** Lorem Ipsum")).To(Ω.BeTrue()) - please.Expect(exp.MatchString("**[feature improvement]** Lorem Ipsum")).To(Ω.BeTrue()) - please.Expect(exp.MatchString("**[security fix]** Lorem Ipsum")).To(Ω.BeTrue()) - - please.Expect(exp.MatchString("**[none]** Lorem Ipsum")).To(Ω.BeFalse()) - please.Expect(exp.MatchString("**[none]** feature bug fix security")).To(Ω.BeFalse()) - please.Expect(exp.MatchString("Lorem Ipsum")).To(Ω.BeFalse()) - please.Expect(exp.MatchString("")).To(Ω.BeFalse()) - please.Expect(exp.MatchString("**[]**")).To(Ω.BeFalse()) - please.Expect(exp.MatchString("**[bugFix]**")).To(Ω.BeFalse()) - please.Expect(exp.MatchString("**[security]**")).To(Ω.BeFalse()) + please.Expect(err).NotTo(HaveOccurred()) + + please.Expect(exp.MatchString("**[Bug Fix]** Lorem Ipsum")).To(BeTrue()) + please.Expect(exp.MatchString("**[bug fix]** Lorem Ipsum")).To(BeTrue()) + please.Expect(exp.MatchString("**[Feature]** Lorem Ipsum")).To(BeTrue()) + please.Expect(exp.MatchString("**[feature improvement]** Lorem Ipsum")).To(BeTrue()) + please.Expect(exp.MatchString("**[security fix]** Lorem Ipsum")).To(BeTrue()) + + please.Expect(exp.MatchString("**[none]** Lorem Ipsum")).To(BeFalse()) + please.Expect(exp.MatchString("**[none]** feature bug fix security")).To(BeFalse()) + please.Expect(exp.MatchString("Lorem Ipsum")).To(BeFalse()) + please.Expect(exp.MatchString("")).To(BeFalse()) + please.Expect(exp.MatchString("**[]**")).To(BeFalse()) + please.Expect(exp.MatchString("**[bugFix]**")).To(BeFalse()) + please.Expect(exp.MatchString("**[security]**")).To(BeFalse()) } func getIssueTitleExp(t *testing.T) string { diff --git a/internal/release/notes_page.go b/pkg/notes/notes_page.go similarity index 68% rename from internal/release/notes_page.go rename to pkg/notes/notes_page.go index 8e69b1e38..664d69e0d 100644 --- a/internal/release/notes_page.go +++ b/pkg/notes/notes_page.go @@ -1,4 +1,4 @@ -package release +package notes import ( "bytes" @@ -14,39 +14,39 @@ const DefaultReleasesSentinel = "\n## Releases\n\n" var releaseNoteExp = regexp.MustCompile(`(?m)(?P### (\d+\.\d+\.\d+(-.+)?)\w*(?P.*)\n*((\*.*\n)|\n|(r(?P\d+)\.*)`).String() t.Run("multiple releases", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) input := "prefix.releases:r1.r2..r3r4...r5...suffix" - page, err := ParseNotesPageWithExpressionAndReleasesSentinel(input, exp, testReleasesSentinel) - please.Expect(err).NotTo(Ω.HaveOccurred()) + page, err := parseNotesPageWithExpressionAndReleasesSentinel(input, exp, testReleasesSentinel) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(page.Releases).To(Ω.HaveLen(5)) - please.Expect(page.Releases).To(Ω.Equal([]VersionNote{ + please.Expect(page.Releases).To(HaveLen(5)) + please.Expect(page.Releases).To(Equal([]TileVersionNote{ {Version: "1", Notes: "r1."}, {Version: "2", Notes: "r2.."}, {Version: "3", Notes: "r3"}, @@ -180,187 +180,187 @@ func TestParseNotesPageWithExpressionAndReleasesSentinel(t *testing.T) { {Version: "5", Notes: "r5..."}, })) - please.Expect(page.Prefix).To(Ω.Equal("prefix.releases:")) - please.Expect(page.Suffix).To(Ω.Equal("suffix")) + please.Expect(page.Prefix).To(Equal("prefix.releases:")) + please.Expect(page.Suffix).To(Equal("suffix")) }) t.Run("no releases", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) input := "prefix.releases:suffix" - page, err := ParseNotesPageWithExpressionAndReleasesSentinel(input, exp, testReleasesSentinel) - please.Expect(err).NotTo(Ω.HaveOccurred()) + page, err := parseNotesPageWithExpressionAndReleasesSentinel(input, exp, testReleasesSentinel) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(page.Releases).To(Ω.HaveLen(0)) - please.Expect(page.Prefix).To(Ω.Equal("prefix.releases:")) - please.Expect(page.Suffix).To(Ω.Equal("suffix")) + please.Expect(page.Releases).To(HaveLen(0)) + please.Expect(page.Prefix).To(Equal("prefix.releases:")) + please.Expect(page.Suffix).To(Equal("suffix")) }) } func Test_newFetchNotesData(t *testing.T) { t.Run("when called", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) f, err := newFetchNotesData(&git.Repository{}, "o", "r", "k", "ri", "rf", nil, IssuesQuery{ IssueMilestone: "BLA", }) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(f.repoOwner).To(Ω.Equal("o")) - please.Expect(f.repoName).To(Ω.Equal("r")) - please.Expect(f.kilnfilePath).To(Ω.Equal("k")) - please.Expect(f.initialRevision).To(Ω.Equal("ri")) - please.Expect(f.finalRevision).To(Ω.Equal("rf")) - please.Expect(f.historicKilnfile).NotTo(Ω.BeNil()) - please.Expect(f.historicVersion).NotTo(Ω.BeNil()) - please.Expect(f.issuesQuery).To(Ω.Equal(IssuesQuery{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(f.repoOwner).To(Equal("o")) + please.Expect(f.repoName).To(Equal("r")) + please.Expect(f.kilnfilePath).To(Equal("k")) + please.Expect(f.initialRevision).To(Equal("ri")) + please.Expect(f.finalRevision).To(Equal("rf")) + please.Expect(f.historicKilnfile).NotTo(BeNil()) + please.Expect(f.historicVersion).NotTo(BeNil()) + please.Expect(f.issuesQuery).To(Equal(IssuesQuery{ IssueMilestone: "BLA", })) }) t.Run("when repo is nil", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) _, err := newFetchNotesData(nil, "o", "r", "k", "ri", "rf", &github.Client{}, IssuesQuery{}) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) t.Run("when repo is not nil", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) f, err := newFetchNotesData(&git.Repository{ Storer: &memory.Storage{}, }, "o", "r", "k", "ri", "rf", &github.Client{}, IssuesQuery{}) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(f.repository).NotTo(Ω.BeNil()) - please.Expect(f.revisionResolver).NotTo(Ω.BeNil()) - please.Expect(f.Storer).NotTo(Ω.BeNil()) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(f.repository).NotTo(BeNil()) + please.Expect(f.revisionResolver).NotTo(BeNil()) + please.Expect(f.Storer).NotTo(BeNil()) }) t.Run("when github client is not nil", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) f, err := newFetchNotesData(&git.Repository{}, "o", "r", "k", "ri", "rf", &github.Client{ Issues: &github.IssuesService{}, Repositories: &github.RepositoriesService{}, }, IssuesQuery{}) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(f.issuesService).NotTo(Ω.BeNil()) - please.Expect(f.releasesService).NotTo(Ω.BeNil()) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(f.issuesService).NotTo(BeNil()) + please.Expect(f.releasesService).NotTo(BeNil()) }) t.Run("when github client is nil", func(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) f, err := newFetchNotesData(&git.Repository{}, "o", "r", "k", "ri", "rf", nil, IssuesQuery{}) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(f.issuesService).To(Ω.BeNil()) - please.Expect(f.releasesService).To(Ω.BeNil()) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(f.issuesService).To(BeNil()) + please.Expect(f.releasesService).To(BeNil()) }) } func TestReleaseNotesPage_Add(t *testing.T) { // I imagine if the function signature for Add also returned an integer - // func (page NotesPage) Add(note VersionNote) (int, error) + // func (page Page) Add(note TileVersionNote) (int, error) // it would be easier to test. It also would make logging where in the document // release was added easier. // For example, the release-notes could log something like: // The release notes for tile 2.7.43 were inserted at the top of the document (index 0) t.Run("initial release", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), // a simpler release expression } - note := VersionNote{Version: "1", Notes: "r1"} + note := TileVersionNote{Version: "1", Notes: "r1"} err := page.Add(note) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(page.Releases).To(Ω.ConsistOf(note)) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(page.Releases).To(ConsistOf(note)) }) t.Run("new latest release", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), - Releases: []VersionNote{ + Releases: []TileVersionNote{ {Version: "2", Notes: "r2"}, }, } - newNote := VersionNote{Version: "3", Notes: "r3"} + newNote := TileVersionNote{Version: "3", Notes: "r3"} err := page.Add(newNote) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(page.Releases).To(Ω.Equal([]VersionNote{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(page.Releases).To(Equal([]TileVersionNote{ {Version: "3", Notes: "r3"}, {Version: "2", Notes: "r2"}, })) }) t.Run("update existing release notes", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), - Releases: []VersionNote{ + Releases: []TileVersionNote{ {Version: "1", Notes: "r1"}, }, } - newNote := VersionNote{Version: "1", Notes: "r2"} + newNote := TileVersionNote{Version: "1", Notes: "r2"} err := page.Add(newNote) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(page.Releases).To(Ω.Equal([]VersionNote{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(page.Releases).To(Equal([]TileVersionNote{ {Version: "1", Notes: "r2"}, })) }) t.Run("insert between", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), - Releases: []VersionNote{ + Releases: []TileVersionNote{ {Version: "3", Notes: "r3"}, {Version: "1", Notes: "r1"}, }, } - newNote := VersionNote{Version: "2", Notes: "r2"} + newNote := TileVersionNote{Version: "2", Notes: "r2"} err := page.Add(newNote) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(page.Releases).To(Ω.Equal([]VersionNote{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(page.Releases).To(Equal([]TileVersionNote{ {Version: "3", Notes: "r3"}, {Version: "2", Notes: "r2"}, {Version: "1", Notes: "r1"}, })) }) t.Run("notes version field is invalid", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), - Releases: []VersionNote{ + Releases: []TileVersionNote{ {Version: "1", Notes: "r1"}, }, } - newNote := VersionNote{Version: "s", Notes: "r2"} + newNote := TileVersionNote{Version: "s", Notes: "r2"} err := page.Add(newNote) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) t.Run("add notes to end", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), - Releases: []VersionNote{ + Releases: []TileVersionNote{ {Version: "3", Notes: "r3"}, {Version: "2", Notes: "r2"}, }, } - newNote := VersionNote{Version: "1", Notes: "r1"} + newNote := TileVersionNote{Version: "1", Notes: "r1"} err := page.Add(newNote) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(page.Releases).To(Ω.Equal([]VersionNote{ + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(page.Releases).To(Equal([]TileVersionNote{ {Version: "3", Notes: "r3"}, {Version: "2", Notes: "r2"}, {Version: "1", Notes: "r1"}, })) }) t.Run("notes content does not match page regex", func(t *testing.T) { - please := Ω.NewWithT(t) - page := NotesPage{ + please := NewWithT(t) + page := Page{ Exp: regexp.MustCompile(`r\d+`), - Releases: []VersionNote{ + Releases: []TileVersionNote{ {Version: "1", Notes: "r1"}, }, } - newNote := VersionNote{Version: "2", Notes: "s2"} + newNote := TileVersionNote{Version: "2", Notes: "s2"} err := page.Add(newNote) - please.Expect(err).To(Ω.HaveOccurred()) + please.Expect(err).To(HaveOccurred()) }) } func TestReleaseNotesPage_WriteTo(t *testing.T) { - var _ io.WriterTo = (*NotesPage)(nil) + var _ io.WriterTo = (*Page)(nil) } diff --git a/internal/release/notes_template.go b/pkg/notes/notes_template.go similarity index 88% rename from internal/release/notes_template.go rename to pkg/notes/notes_template.go index 7ce38c401..b3ee14f5f 100644 --- a/internal/release/notes_template.go +++ b/pkg/notes/notes_template.go @@ -1,4 +1,4 @@ -package release +package notes import ( _ "embed" @@ -17,7 +17,7 @@ func DefaultNotesTemplate() string { return defaultReleaseNotesTemplate } -func DefaultTemplateFuncs(t *template.Template) *template.Template { +func DefaultTemplateFunctions(t *template.Template) *template.Template { return t.Funcs(sprig.TxtFuncMap()).Funcs(template.FuncMap{ "removeEmptyLines": removeEmptyLines, }) diff --git a/internal/release/notes_template_test.go b/pkg/notes/notes_template_test.go similarity index 61% rename from internal/release/notes_template_test.go rename to pkg/notes/notes_template_test.go index c12406320..c325f1882 100644 --- a/internal/release/notes_template_test.go +++ b/pkg/notes/notes_template_test.go @@ -1,4 +1,4 @@ -package release +package notes import ( "bytes" @@ -7,18 +7,19 @@ import ( "github.com/Masterminds/semver" "github.com/google/go-github/v40/github" - Ω "github.com/onsi/gomega" + + . "github.com/onsi/gomega" "github.com/pivotal-cf/kiln/internal/component" ) func Test_defaultReleaseNotesTemplate(t *testing.T) { t.Run("empty github release body", func(t *testing.T) { - please := Ω.NewWithT(t) - tmp, err := DefaultTemplateFuncs(template.New("")).Parse(DefaultNotesTemplate()) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please := NewWithT(t) + tmp, err := DefaultTemplateFunctions(template.New("")).Parse(DefaultNotesTemplate()) + please.Expect(err).NotTo(HaveOccurred()) var b bytes.Buffer - err = tmp.Execute(&b, NotesData{ + err = tmp.Execute(&b, Data{ Version: semver.MustParse("0.0"), Components: []ComponentData{ { @@ -30,7 +31,7 @@ func Test_defaultReleaseNotesTemplate(t *testing.T) { }, }, }) - please.Expect(err).NotTo(Ω.HaveOccurred()) - please.Expect(b.String()).To(Ω.ContainSubstring("banana1.2")) + please.Expect(err).NotTo(HaveOccurred()) + please.Expect(b.String()).To(ContainSubstring("banana1.2")) }) } diff --git a/internal/release/testdata/runtime-rn.html.md.erb b/pkg/notes/testdata/runtime-rn.html.md.erb similarity index 100% rename from internal/release/testdata/runtime-rn.html.md.erb rename to pkg/notes/testdata/runtime-rn.html.md.erb diff --git a/pkg/tile/metadata_test.go b/pkg/tile/metadata_test.go index ad64770d1..a4cf011bd 100644 --- a/pkg/tile/metadata_test.go +++ b/pkg/tile/metadata_test.go @@ -3,23 +3,23 @@ package tile_test import ( "testing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" "gopkg.in/yaml.v2" "github.com/pivotal-cf/kiln/pkg/tile" ) func TestReadMetadataFromFile(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) metadataBytes, err := tile.ReadMetadataFromFile("testdata/tile-0.1.2.pivotal") - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) var metadata struct { Name string `yaml:"name"` } err = yaml.Unmarshal(metadataBytes, &metadata) - please.Expect(err).NotTo(Ω.HaveOccurred(), string(metadataBytes)) + please.Expect(err).NotTo(HaveOccurred(), string(metadataBytes)) - please.Expect(metadata.Name).To(Ω.Equal("hello"), string(metadataBytes)) + please.Expect(metadata.Name).To(Equal("hello"), string(metadataBytes)) } diff --git a/pkg/tile/release.go b/pkg/tile/release.go index 3cddb6f33..2d6c21de2 100644 --- a/pkg/tile/release.go +++ b/pkg/tile/release.go @@ -8,10 +8,10 @@ import ( "os" "path" + "github.com/pivotal-cf/kiln/internal/proofing" + "golang.org/x/exp/slices" "gopkg.in/yaml.v2" - - "github.com/pivotal-cf/kiln/pkg/proofing" ) func ReadReleaseFromFile(tilePath, releaseName, releaseVersion string, releaseTarball io.Writer) (proofing.Release, error) { diff --git a/pkg/tile/releases_test.go b/pkg/tile/releases_test.go index 3d6e0edd0..538587244 100644 --- a/pkg/tile/releases_test.go +++ b/pkg/tile/releases_test.go @@ -5,21 +5,21 @@ import ( "io" "testing" - "github.com/pivotal-cf/kiln/pkg/proofing" + "github.com/pivotal-cf/kiln/internal/proofing" - Ω "github.com/onsi/gomega" + . "github.com/onsi/gomega" "github.com/pivotal-cf/kiln/pkg/tile" ) func TestReadReleaseFromFile(t *testing.T) { - please := Ω.NewWithT(t) + please := NewWithT(t) buf := bytes.NewBuffer(nil) releaseMetadata, err := tile.ReadReleaseFromFile("testdata/tile-0.1.2.pivotal", "hello-release", "v0.1.4", buf) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) - please.Expect(releaseMetadata).To(Ω.Equal(proofing.Release{ + please.Expect(releaseMetadata).To(Equal(proofing.Release{ File: "hello-release-v0.1.4-ubuntu-xenial-621.256.tgz", Name: "hello-release", SHA1: "c471ac6371eb8fc24508b14d9a49a44f9a5ef98c", @@ -27,5 +27,5 @@ func TestReadReleaseFromFile(t *testing.T) { })) _, err = io.ReadAll(buf) - please.Expect(err).NotTo(Ω.HaveOccurred()) + please.Expect(err).NotTo(HaveOccurred()) }