From 678be426d859201cf4afa537e734a4e5c1984981 Mon Sep 17 00:00:00 2001 From: hannahhenderson Date: Tue, 24 Jul 2018 15:34:13 -0700 Subject: [PATCH 01/11] Add create orb --- api/api.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++-- cmd/orb.go | 29 +++++++++++++- cmd/orb_test.go | 104 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 233 insertions(+), 4 deletions(-) diff --git a/api/api.go b/api/api.go index ac1477141..c9c2b91ad 100644 --- a/api/api.go +++ b/api/api.go @@ -54,6 +54,17 @@ type CreateNamespaceResponse struct { GQLResponseErrors } +// CreateOrbResponse type matches the data shape of the GQL response for +// creating an orb +type CreateOrbResponse struct { + Orb struct { + CreatedAt string + ID string + } + + GQLResponseErrors +} + // ToError returns all GraphQL errors for a single response concatenated, or // nil. func (response GQLResponseErrors) ToError() error { @@ -178,7 +189,7 @@ func OrbPublish(ctx context.Context, logger *logger.Logger, return &response.PublishOrb.PublishOrbResponse, err } -func createNamespaceByID(ctx context.Context, logger *logger.Logger, name string, ownerID string) (*CreateNamespaceResponse, error) { +func createNamespaceWithOwnerID(ctx context.Context, logger *logger.Logger, name string, ownerID string) (*CreateNamespaceResponse, error) { var response struct { CreateNamespace struct { CreateNamespaceResponse @@ -243,7 +254,7 @@ func getOrganization(ctx context.Context, logger *logger.Logger, organizationNam err := graphQLclient.Run(ctx, request, &response) if err != nil || response.Organization.ID == "" { - err = errors.Wrap(err, fmt.Sprintf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs)) + err = errors.New(fmt.Sprintf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs)) } return response.Organization.ID, err @@ -256,7 +267,7 @@ func CreateNamespace(ctx context.Context, logger *logger.Logger, name string, or return nil, err } - namespace, err := createNamespaceByID(ctx, logger, name, organizationID) + namespace, err := createNamespaceWithOwnerID(ctx, logger, name, organizationID) if err != nil { return nil, err @@ -264,3 +275,90 @@ func CreateNamespace(ctx context.Context, logger *logger.Logger, name string, or return namespace, err } + + +func getNamespace(ctx context.Context, logger *logger.Logger, name string) (string, error){ + var response struct { + Namespace struct { + ID string + } + } + + query := ` + query($name: String!) { + registryNamespace( + name: $name + ){ + id + } + }` + request := client.NewAuthorizedRequest(viper.GetString("token"), query) + request.Var("name", name) + + graphQLclient := client.NewClient(viper.GetString("endpoint"), logger) + + err := graphQLclient.Run(ctx, request, & response) +fmt.Println("response is: ", response) + + if err != nil || response.Namespace.ID == "" { + err = errors.New(fmt.Sprintf("Unable to find namespace %s", name)) + } + + return response.Namespace.ID, err +} + +func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, namespaceID string) (*CreateOrbResponse, error) { + var response struct { + CreateOrb struct { + CreateOrbResponse + } + } + + query := `mutation($name: String!, $registryNamespaceId: UUID!){ + createOrb( + name: $name, + registryNamespaceId: $registryNamespaceId + ){ + createdAt + id + } + errors { + message + type + } + }` + + request := client.NewAuthorizedRequest(viper.GetString("token"), query) + request.Var("name", name) + request.Var("registryNamespaceId", namespaceID) + + graphQLclient := client.NewClient(viper.GetString("endpoint"), logger) + + err := graphQLclient.Run(ctx, request, &response) + + if err != nil { + err = errors.Wrap(err, fmt.Sprintf("Unable to create orb %s for namespaceID %s", name, namespaceID)) + } + + return &response.CreateOrb.CreateOrbResponse, err +} + + +// CreateOrb creates (reserves) an orb within a namespace +func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespace string) (*CreateOrbResponse, error) { + fmt.Println("---- here we go") + namespaceID, err := getNamespace(ctx, logger, namespace) + + if err != nil { + return nil, err + } + + orb, err := createOrbWithNsID(ctx, logger, name, namespaceID) + fmt.Println("---- in theory, orb is:", orb) + + if err != nil { + return nil, err + } + + return orb, err +} \ No newline at end of file diff --git a/cmd/orb.go b/cmd/orb.go index 5fcc6fd77..9afa932e7 100644 --- a/cmd/orb.go +++ b/cmd/orb.go @@ -51,8 +51,15 @@ func newOrbCommand() *cobra.Command { orbPublishCommand.PersistentFlags().StringVarP(&orbVersion, "orb-version", "o", "", "version of orb to publish") orbPublishCommand.PersistentFlags().StringVarP(&orbID, "orb-id", "i", "", "id of orb to publish") + orbCreate := &cobra.Command{ + Use: "create ", + Short: "create an orb", + RunE: createOrb, + Args: cobra.ExactArgs(2), + } + orbCreateNamespace := &cobra.Command{ - Use: "create", + Use: "create ", Short: "create an orb namespace", RunE: createOrbNamespace, Args: cobra.ExactArgs(1), @@ -68,6 +75,7 @@ func newOrbCommand() *cobra.Command { } orbCommand.AddCommand(orbListCommand) + orbCommand.AddCommand(orbCreate) orbValidateCommand.PersistentFlags().StringVarP(&orbPath, "path", "p", "orb.yml", "path to orb file") orbCommand.AddCommand(orbValidateCommand) @@ -249,6 +257,25 @@ func publishOrb(cmd *cobra.Command, args []string) error { return nil } +func createOrb(cmd *cobra.Command, args []string) error { + var err error + ctx := context.Background() + + response, err := api.CreateOrb(ctx, Logger, args[0], args[1]) + + if err != nil { + return err + } + + if len(response.Errors) > 0 { + return response.ToError() + } + + Logger.Info("Orb created") + return nil +} + + func createOrbNamespace(cmd *cobra.Command, args []string) error { var err error ctx := context.Background() diff --git a/cmd/orb_test.go b/cmd/orb_test.go index ce07cab59..61ee2e73c 100644 --- a/cmd/orb_test.go +++ b/cmd/orb_test.go @@ -416,5 +416,109 @@ var _ = Describe("Orb integration tests", func() { Eventually(session).ShouldNot(gexec.Exit(0)) }) }) + + Describe("when creating / reserving an orb", func() { + BeforeEach(func() { + command = exec.Command(pathCLI, + "orb", "create", + "-t", token, + "-e", testServer.URL(), + "foo-orb", + "bar-ns", + ) + }) + + It("works", func() { + By("setting up a mock server") + + gqlNamespaceResponse := `{ + "namespace": { + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` + + expectedNamespaceRequest := `` + + gqlOrbResponse := `{ + "createOrb": { + "errors": [], + "orb": { + "createdAt": "2018-07-16T18:03:18.961Z", + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + } + }` + + expectedOrbRequest := `{ + + }` + + appendPostHandler(testServer, token, MockRequestResponse{ + Status: http.StatusOK, + Request: expectedNamespaceRequest, + Response: gqlNamespaceResponse}) + + appendPostHandler(testServer, token, MockRequestResponse{ + Status: http.StatusOK, + Request: expectedOrbRequest, + Response: gqlOrbResponse}) + + By("running the command") + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session.Out).Should(gbytes.Say("Orb created")) + Eventually(session).Should(gexec.Exit(0)) + }) + + //It("prints all errors returned by the GraphQL API", func() { + // By("setting up a mock server") + // + // gqlNamespaceResponse := `{ + // "namespace": { + // "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + // } + // }` + // + // expectedNamespaceRequest := `{ + // + // }` + // + // gqlOrbResponse := `{ + // "createOrb": { + // "errors": [ + // {"message": "error1"}, + // {"message": "error2"} + // ], + // "orb": null + // } + // }` + // + // expectedOrbRequest := `{ + // + // }` + // + // appendPostHandler(testServer, token, + // MockRequestResponse{ + // Status: http.StatusOK, + // Request: expectedNamespaceRequest, + // Response: gqlNamespaceResponse, + // }) + // appendPostHandler(testServer, token, + // MockRequestResponse{ + // Status: http.StatusOK, + // Request: expectedOrbRequest, + // Response: gqlOrbResponse, + // }) + // + // By("running the command") + // session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + // + // Expect(err).ShouldNot(HaveOccurred()) + // Eventually(session.Err).Should(gbytes.Say("Error: error1: error2")) + // Eventually(session).ShouldNot(gexec.Exit(0)) + //}) + }) + }) }) From 388ec43b056843630546235bf244d4dc906c1b2d Mon Sep 17 00:00:00 2001 From: John Swanson Date: Tue, 24 Jul 2018 16:12:19 -0700 Subject: [PATCH 02/11] fix up create orb Co-authored-by: Hannah Henderson <18273771+hannahhenderson@users.noreply.github.com> --- api/api.go | 31 ++++++------ cmd/orb_test.go | 130 +++++++++++++++++++++++++++--------------------- 2 files changed, 88 insertions(+), 73 deletions(-) diff --git a/api/api.go b/api/api.go index c9c2b91ad..ae3afecf8 100644 --- a/api/api.go +++ b/api/api.go @@ -276,10 +276,9 @@ func CreateNamespace(ctx context.Context, logger *logger.Logger, name string, or return namespace, err } - -func getNamespace(ctx context.Context, logger *logger.Logger, name string) (string, error){ +func getNamespace(ctx context.Context, logger *logger.Logger, name string) (string, error) { var response struct { - Namespace struct { + RegistryNamespace struct { ID string } } @@ -297,14 +296,13 @@ func getNamespace(ctx context.Context, logger *logger.Logger, name string) (stri graphQLclient := client.NewClient(viper.GetString("endpoint"), logger) - err := graphQLclient.Run(ctx, request, & response) -fmt.Println("response is: ", response) + err := graphQLclient.Run(ctx, request, &response) - if err != nil || response.Namespace.ID == "" { + if err != nil || response.RegistryNamespace.ID == "" { err = errors.New(fmt.Sprintf("Unable to find namespace %s", name)) } - return response.Namespace.ID, err + return response.RegistryNamespace.ID, err } func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, namespaceID string) (*CreateOrbResponse, error) { @@ -319,14 +317,16 @@ func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, name: $name, registryNamespaceId: $registryNamespaceId ){ - createdAt - id + orb { + createdAt + id + } + errors { + message + type + } } - errors { - message - type - } - }` +}` request := client.NewAuthorizedRequest(viper.GetString("token"), query) request.Var("name", name) @@ -343,7 +343,6 @@ func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, return &response.CreateOrb.CreateOrbResponse, err } - // CreateOrb creates (reserves) an orb within a namespace func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespace string) (*CreateOrbResponse, error) { fmt.Println("---- here we go") @@ -361,4 +360,4 @@ func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespac } return orb, err -} \ No newline at end of file +} diff --git a/cmd/orb_test.go b/cmd/orb_test.go index 61ee2e73c..0c9ddfb26 100644 --- a/cmd/orb_test.go +++ b/cmd/orb_test.go @@ -432,12 +432,17 @@ var _ = Describe("Orb integration tests", func() { By("setting up a mock server") gqlNamespaceResponse := `{ - "namespace": { - "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" - } - }` + "registryNamespace": { + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` - expectedNamespaceRequest := `` + expectedNamespaceRequest := `{ + "query": "\n\t\t\t\tquery($name: String!) {\n\t\t\t\t\tregistryNamespace(\n\t\t\t\t\t\tname: $name\n\t\t\t\t\t){\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t }", + "variables": { + "name": "bar-ns" + } + }` gqlOrbResponse := `{ "createOrb": { @@ -450,13 +455,17 @@ var _ = Describe("Orb integration tests", func() { }` expectedOrbRequest := `{ - - }` + "query": "mutation($name: String!, $registryNamespaceId: UUID!){\n\t\t\t\tcreateOrb(\n\t\t\t\t\tname: $name,\n\t\t\t\t\tregistryNamespaceId: $registryNamespaceId\n\t\t\t\t){\n\t\t\t\t orb {\n\t\t\t\t createdAt\n\t\t\t\t id\n\t\t\t\t }\n\t\t\t\t errors {\n\t\t\t\t message\n\t\t\t\t type\n\t\t\t\t }\n\t\t\t\t}\n}", + "variables": { + "name": "foo-orb", + "registryNamespaceId": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` appendPostHandler(testServer, token, MockRequestResponse{ - Status: http.StatusOK, - Request: expectedNamespaceRequest, - Response: gqlNamespaceResponse}) + Status: http.StatusOK, + Request: expectedNamespaceRequest, + Response: gqlNamespaceResponse}) appendPostHandler(testServer, token, MockRequestResponse{ Status: http.StatusOK, @@ -471,53 +480,60 @@ var _ = Describe("Orb integration tests", func() { Eventually(session).Should(gexec.Exit(0)) }) - //It("prints all errors returned by the GraphQL API", func() { - // By("setting up a mock server") - // - // gqlNamespaceResponse := `{ - // "namespace": { - // "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" - // } - // }` - // - // expectedNamespaceRequest := `{ - // - // }` - // - // gqlOrbResponse := `{ - // "createOrb": { - // "errors": [ - // {"message": "error1"}, - // {"message": "error2"} - // ], - // "orb": null - // } - // }` - // - // expectedOrbRequest := `{ - // - // }` - // - // appendPostHandler(testServer, token, - // MockRequestResponse{ - // Status: http.StatusOK, - // Request: expectedNamespaceRequest, - // Response: gqlNamespaceResponse, - // }) - // appendPostHandler(testServer, token, - // MockRequestResponse{ - // Status: http.StatusOK, - // Request: expectedOrbRequest, - // Response: gqlOrbResponse, - // }) - // - // By("running the command") - // session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) - // - // Expect(err).ShouldNot(HaveOccurred()) - // Eventually(session.Err).Should(gbytes.Say("Error: error1: error2")) - // Eventually(session).ShouldNot(gexec.Exit(0)) - //}) + It("prints all errors returned by the GraphQL API", func() { + By("setting up a mock server") + + gqlNamespaceResponse := `{ + "registryNamespace": { + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` + + expectedNamespaceRequest := `{ + "query": "\n\t\t\t\tquery($name: String!) {\n\t\t\t\t\tregistryNamespace(\n\t\t\t\t\t\tname: $name\n\t\t\t\t\t){\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t }", + "variables": { + "name": "bar-ns" + } + }` + + gqlOrbResponse := `{ + "createOrb": { + "errors": [ + {"message": "error1"}, + {"message": "error2"} + ], + "orb": null + } + }` + + expectedOrbRequest := `{ + "query": "mutation($name: String!, $registryNamespaceId: UUID!){\n\t\t\t\tcreateOrb(\n\t\t\t\t\tname: $name,\n\t\t\t\t\tregistryNamespaceId: $registryNamespaceId\n\t\t\t\t){\n\t\t\t\t orb {\n\t\t\t\t createdAt\n\t\t\t\t id\n\t\t\t\t }\n\t\t\t\t errors {\n\t\t\t\t message\n\t\t\t\t type\n\t\t\t\t }\n\t\t\t\t}\n}", + "variables": { + "name": "foo-orb", + "registryNamespaceId": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` + + appendPostHandler(testServer, token, + MockRequestResponse{ + Status: http.StatusOK, + Request: expectedNamespaceRequest, + Response: gqlNamespaceResponse, + }) + appendPostHandler(testServer, token, + MockRequestResponse{ + Status: http.StatusOK, + Request: expectedOrbRequest, + Response: gqlOrbResponse, + }) + + By("running the command") + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session.Err).Should(gbytes.Say("Error: error1: error2")) + Eventually(session).ShouldNot(gexec.Exit(0)) + }) }) }) From 4f4813fa8b541f6e834deff47bc73dd2bf15f42e Mon Sep 17 00:00:00 2001 From: John Swanson Date: Tue, 24 Jul 2018 16:22:46 -0700 Subject: [PATCH 03/11] pass in namespace-qualified orb name Co-authored-by: <+hannahenderson@users.noreply.github.com> --- api/api.go | 2 -- cmd/orb.go | 15 ++++++++++----- cmd/orb_test.go | 3 +-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/api/api.go b/api/api.go index ae3afecf8..ac161e55a 100644 --- a/api/api.go +++ b/api/api.go @@ -345,7 +345,6 @@ func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, // CreateOrb creates (reserves) an orb within a namespace func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespace string) (*CreateOrbResponse, error) { - fmt.Println("---- here we go") namespaceID, err := getNamespace(ctx, logger, namespace) if err != nil { @@ -353,7 +352,6 @@ func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespac } orb, err := createOrbWithNsID(ctx, logger, name, namespaceID) - fmt.Println("---- in theory, orb is:", orb) if err != nil { return nil, err diff --git a/cmd/orb.go b/cmd/orb.go index 9afa932e7..1b80de64d 100644 --- a/cmd/orb.go +++ b/cmd/orb.go @@ -52,10 +52,10 @@ func newOrbCommand() *cobra.Command { orbPublishCommand.PersistentFlags().StringVarP(&orbID, "orb-id", "i", "", "id of orb to publish") orbCreate := &cobra.Command{ - Use: "create ", + Use: "create /", Short: "create an orb", - RunE: createOrb, - Args: cobra.ExactArgs(2), + RunE: createOrb, + Args: cobra.ExactArgs(1), } orbCreateNamespace := &cobra.Command{ @@ -261,7 +261,13 @@ func createOrb(cmd *cobra.Command, args []string) error { var err error ctx := context.Background() - response, err := api.CreateOrb(ctx, Logger, args[0], args[1]) + arr := strings.Split(args[0], "/") + + if len(arr) != 2 { + return errors.New(fmt.Sprintf("Invalid orb name: %s", args[0])) + } + + response, err := api.CreateOrb(ctx, Logger, arr[1], arr[0]) if err != nil { return err @@ -275,7 +281,6 @@ func createOrb(cmd *cobra.Command, args []string) error { return nil } - func createOrbNamespace(cmd *cobra.Command, args []string) error { var err error ctx := context.Background() diff --git a/cmd/orb_test.go b/cmd/orb_test.go index 0c9ddfb26..13a2b800e 100644 --- a/cmd/orb_test.go +++ b/cmd/orb_test.go @@ -423,8 +423,7 @@ var _ = Describe("Orb integration tests", func() { "orb", "create", "-t", token, "-e", testServer.URL(), - "foo-orb", - "bar-ns", + "bar-ns/foo-orb", ) }) From 2c5b8202d28b43bc6eb82481898ffc467845ea8d Mon Sep 17 00:00:00 2001 From: hannahhenderson Date: Tue, 24 Jul 2018 16:36:37 -0700 Subject: [PATCH 04/11] Lint file --- api/api.go | 6 +++--- cmd/build.go | 2 +- cmd/diagnostic.go | 4 ++-- cmd/orb.go | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/api/api.go b/api/api.go index ac161e55a..1a2d7b5e2 100644 --- a/api/api.go +++ b/api/api.go @@ -74,7 +74,7 @@ func (response GQLResponseErrors) ToError() error { messages = append(messages, response.Errors[i].Message) } - return errors.New(strings.Join(messages, ": ")) + return fmt.Errorf(strings.Join(messages, ": ")) } func loadYaml(path string) (string, error) { @@ -254,7 +254,7 @@ func getOrganization(ctx context.Context, logger *logger.Logger, organizationNam err := graphQLclient.Run(ctx, request, &response) if err != nil || response.Organization.ID == "" { - err = errors.New(fmt.Sprintf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs)) + err = fmt.Errorf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs) } return response.Organization.ID, err @@ -299,7 +299,7 @@ func getNamespace(ctx context.Context, logger *logger.Logger, name string) (stri err := graphQLclient.Run(ctx, request, &response) if err != nil || response.RegistryNamespace.ID == "" { - err = errors.New(fmt.Sprintf("Unable to find namespace %s", name)) + err = fmt.Errorf("Unable to find namespace %s", name) } return response.RegistryNamespace.ID, err diff --git a/cmd/build.go b/cmd/build.go index 37331ea45..de7679fc8 100644 --- a/cmd/build.go +++ b/cmd/build.go @@ -95,7 +95,7 @@ func findLatestPicardSha() (string, error) { latest := sha256.FindString(output) if latest == "" { - return "", errors.New("failed to parse sha256 from docker pull output") + return "", fmt.Errorf("failed to parse sha256 from docker pull output") } err = storeBuildAgentSha(latest) diff --git a/cmd/diagnostic.go b/cmd/diagnostic.go index fcdd471eb..9ad36bb90 100644 --- a/cmd/diagnostic.go +++ b/cmd/diagnostic.go @@ -1,7 +1,7 @@ package cmd import ( - "errors" + "fmt" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -25,7 +25,7 @@ func diagnostic(cmd *cobra.Command, args []string) error { Logger.Infof("GraphQL API endpoint: %s\n", endpoint) if token == "token" || token == "" { - return errors.New("please set a token") + return fmt.Errorf("please set a token") } Logger.Infoln("OK, got a token.") Logger.Infof("Verbose mode: %v\n", viper.GetBool("verbose")) diff --git a/cmd/orb.go b/cmd/orb.go index 1b80de64d..7af66bd6e 100644 --- a/cmd/orb.go +++ b/cmd/orb.go @@ -264,7 +264,7 @@ func createOrb(cmd *cobra.Command, args []string) error { arr := strings.Split(args[0], "/") if len(arr) != 2 { - return errors.New(fmt.Sprintf("Invalid orb name: %s", args[0])) + return fmt.Errorf("Invalid orb name: %s", args[0]) } response, err := api.CreateOrb(ctx, Logger, arr[1], arr[0]) From ea1e55f2afbd26c491b1822bb69f8bcc48c5d663 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 06:59:28 +0900 Subject: [PATCH 05/11] [CIRCLE-12673] Update gometalinter config to match renamed gosec Please run `make dev` to get the latest version or `make lint` won't work for you. --- .gometalinter.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gometalinter.json b/.gometalinter.json index 1f271e081..02e7ab8f1 100644 --- a/.gometalinter.json +++ b/.gometalinter.json @@ -10,12 +10,12 @@ "Enable": [ "deadcode", "errcheck", - "gas", "goconst", "gocyclo", "gofmt", "goimports", "golint", + "gosec", "gosimple", "gotype", "gotypex", From e22f63fe21c1eeaf838d0815a344bd9643c2c60b Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 07:03:30 +0900 Subject: [PATCH 06/11] Make gosec linter happy We should come back to this and make sure addOrbElementsToBuffer error is handled properly. --- api/api.go | 2 +- cmd/orb.go | 33 +++++++++++++++++++++++++++------ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/api/api.go b/api/api.go index 1a2d7b5e2..32b31210c 100644 --- a/api/api.go +++ b/api/api.go @@ -78,7 +78,7 @@ func (response GQLResponseErrors) ToError() error { } func loadYaml(path string) (string, error) { - + // nolint: gosec config, err := ioutil.ReadFile(path) if err != nil { diff --git a/cmd/orb.go b/cmd/orb.go index 7af66bd6e..1adf0452c 100644 --- a/cmd/orb.go +++ b/cmd/orb.go @@ -99,20 +99,41 @@ type orb struct { Executors map[string]struct{} } -func addOrbElementsToBuffer(buf *bytes.Buffer, name string, elems map[string]struct{}) { +func addOrbElementsToBuffer(buf *bytes.Buffer, name string, elems map[string]struct{}) error { + var err error + if len(elems) > 0 { - buf.WriteString(fmt.Sprintf(" %s:\n", name)) + _, err = buf.WriteString(fmt.Sprintf(" %s:\n", name)) + if err != nil { + return err + } for key := range elems { - buf.WriteString(fmt.Sprintf(" - %s\n", key)) + _, err = buf.WriteString(fmt.Sprintf(" - %s\n", key)) + if err != nil { + return err + } } } + + return err } func (orb orb) String() string { var buffer bytes.Buffer - addOrbElementsToBuffer(&buffer, "Commands", orb.Commands) - addOrbElementsToBuffer(&buffer, "Jobs", orb.Jobs) - addOrbElementsToBuffer(&buffer, "Executors", orb.Executors) + + err := addOrbElementsToBuffer(&buffer, "Commands", orb.Commands) + // FIXME: refactor this to handle the error + if err != nil { + panic(err) + } + err = addOrbElementsToBuffer(&buffer, "Jobs", orb.Jobs) + if err != nil { + panic(err) + } + err = addOrbElementsToBuffer(&buffer, "Executors", orb.Executors) + if err != nil { + panic(err) + } return buffer.String() } From b202629f49d9c0d8794f87e988f9d9e75fac3aa5 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 07:46:54 +0900 Subject: [PATCH 07/11] Apply feedback from Marc WRT: error handling and unused createdAt in responses --- api/api.go | 18 +++++++++--------- cmd/diagnostic.go | 5 ++--- cmd/orb_test.go | 15 ++++++--------- 3 files changed, 17 insertions(+), 21 deletions(-) diff --git a/api/api.go b/api/api.go index 32b31210c..3ceba356a 100644 --- a/api/api.go +++ b/api/api.go @@ -58,8 +58,7 @@ type CreateNamespaceResponse struct { // creating an orb type CreateOrbResponse struct { Orb struct { - CreatedAt string - ID string + ID string } GQLResponseErrors @@ -74,7 +73,7 @@ func (response GQLResponseErrors) ToError() error { messages = append(messages, response.Errors[i].Message) } - return fmt.Errorf(strings.Join(messages, ": ")) + return errors.New(strings.Join(messages, ": ")) } func loadYaml(path string) (string, error) { @@ -167,7 +166,6 @@ func OrbPublish(ctx context.Context, logger *logger.Logger, ) { orb { version - createdAt } errors { message } } @@ -203,7 +201,6 @@ func createNamespaceWithOwnerID(ctx context.Context, logger *logger.Logger, name organizationId: $organizationId ) { namespace { - createdAt id } errors { @@ -253,7 +250,9 @@ func getOrganization(ctx context.Context, logger *logger.Logger, organizationNam err := graphQLclient.Run(ctx, request, &response) - if err != nil || response.Organization.ID == "" { + if err != nil { + err = errors.Wrapf(err, "Unable to find organization %s of vcs-type %s", organizationName, organizationVcs) + } else if response.Organization.ID == "" { err = fmt.Errorf("Unable to find organization %s of vcs-type %s", organizationName, organizationVcs) } @@ -298,7 +297,9 @@ func getNamespace(ctx context.Context, logger *logger.Logger, name string) (stri err := graphQLclient.Run(ctx, request, &response) - if err != nil || response.RegistryNamespace.ID == "" { + if err != nil { + err = errors.Wrapf(err, "Unable to find namespace %s", name) + } else if response.RegistryNamespace.ID == "" { err = fmt.Errorf("Unable to find namespace %s", name) } @@ -318,7 +319,6 @@ func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, registryNamespaceId: $registryNamespaceId ){ orb { - createdAt id } errors { @@ -337,7 +337,7 @@ func createOrbWithNsID(ctx context.Context, logger *logger.Logger, name string, err := graphQLclient.Run(ctx, request, &response) if err != nil { - err = errors.Wrap(err, fmt.Sprintf("Unable to create orb %s for namespaceID %s", name, namespaceID)) + err = errors.Wrapf(err, "Unable to create orb %s for namespaceID %s", name, namespaceID) } return &response.CreateOrb.CreateOrbResponse, err diff --git a/cmd/diagnostic.go b/cmd/diagnostic.go index 9ad36bb90..2d18e7789 100644 --- a/cmd/diagnostic.go +++ b/cmd/diagnostic.go @@ -1,8 +1,7 @@ package cmd import ( - "fmt" - + "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -25,7 +24,7 @@ func diagnostic(cmd *cobra.Command, args []string) error { Logger.Infof("GraphQL API endpoint: %s\n", endpoint) if token == "token" || token == "" { - return fmt.Errorf("please set a token") + return errors.New("please set a token") } Logger.Infoln("OK, got a token.") Logger.Infof("Verbose mode: %v\n", viper.GetBool("verbose")) diff --git a/cmd/orb_test.go b/cmd/orb_test.go index 13a2b800e..7e27b5a48 100644 --- a/cmd/orb_test.go +++ b/cmd/orb_test.go @@ -224,14 +224,13 @@ var _ = Describe("Orb integration tests", func() { "publishOrb": { "errors": [], "orb": { - "createdAt": "2018-07-16T18:03:18.961Z", "version": "0.0.1" } } }` expectedRequestJson := `{ - "query": "\n\t\tmutation($config: String!, $orbId: UUID!, $version: String!) {\n\t\t\tpublishOrb(\n\t\t\t\torbId: $orbId,\n\t\t\t\torbYaml: $config,\n\t\t\t\tversion: $version\n\t\t\t) {\n\t\t\t\torb {\n\t\t\t\t\tversion\n\t\t\t\t\tcreatedAt\n\t\t\t\t}\n\t\t\t\terrors { message }\n\t\t\t}\n\t\t}\n\t", + "query": "\n\t\tmutation($config: String!, $orbId: UUID!, $version: String!) {\n\t\t\tpublishOrb(\n\t\t\t\torbId: $orbId,\n\t\t\t\torbYaml: $config,\n\t\t\t\tversion: $version\n\t\t\t) {\n\t\t\t\torb {\n\t\t\t\t\tversion\n\t\t\t\t}\n\t\t\t\terrors { message }\n\t\t\t}\n\t\t}\n\t", "variables": { "config": "some orb", "orbId": "bb604b45-b6b0-4b81-ad80-796f15eddf87", @@ -269,7 +268,7 @@ var _ = Describe("Orb integration tests", func() { }` expectedRequestJson := `{ - "query": "\n\t\tmutation($config: String!, $orbId: UUID!, $version: String!) {\n\t\t\tpublishOrb(\n\t\t\t\torbId: $orbId,\n\t\t\t\torbYaml: $config,\n\t\t\t\tversion: $version\n\t\t\t) {\n\t\t\t\torb {\n\t\t\t\t\tversion\n\t\t\t\t\tcreatedAt\n\t\t\t\t}\n\t\t\t\terrors { message }\n\t\t\t}\n\t\t}\n\t", + "query": "\n\t\tmutation($config: String!, $orbId: UUID!, $version: String!) {\n\t\t\tpublishOrb(\n\t\t\t\torbId: $orbId,\n\t\t\t\torbYaml: $config,\n\t\t\t\tversion: $version\n\t\t\t) {\n\t\t\t\torb {\n\t\t\t\t\tversion\n\t\t\t\t}\n\t\t\t\terrors { message }\n\t\t\t}\n\t\t}\n\t", "variables": { "config": "some orb", "orbId": "bb604b45-b6b0-4b81-ad80-796f15eddf87", @@ -327,14 +326,13 @@ var _ = Describe("Orb integration tests", func() { "createNamespace": { "errors": [], "namespace": { - "createdAt": "2018-07-16T18:03:18.961Z", "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" } } }` expectedNsRequest := `{ - "query": "\n\t\t\tmutation($name: String!, $organizationId: UUID!) {\n\t\t\t\tcreateNamespace(\n\t\t\t\t\tname: $name,\n\t\t\t\t\torganizationId: $organizationId\n\t\t\t\t) {\n\t\t\t\t\tnamespace {\n\t\t\t\t\t\tcreatedAt\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t\terrors {\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\ttype\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}", + "query": "\n\t\t\tmutation($name: String!, $organizationId: UUID!) {\n\t\t\t\tcreateNamespace(\n\t\t\t\t\tname: $name,\n\t\t\t\t\torganizationId: $organizationId\n\t\t\t\t) {\n\t\t\t\t\tnamespace {\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t\terrors {\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\ttype\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}", "variables": { "name": "foo-ns", "organizationId": "bb604b45-b6b0-4b81-ad80-796f15eddf87" @@ -388,7 +386,7 @@ var _ = Describe("Orb integration tests", func() { }` expectedRequestJson := `{ - "query": "\n\t\t\tmutation($name: String!, $organizationId: UUID!) {\n\t\t\t\tcreateNamespace(\n\t\t\t\t\tname: $name,\n\t\t\t\t\torganizationId: $organizationId\n\t\t\t\t) {\n\t\t\t\t\tnamespace {\n\t\t\t\t\t\tcreatedAt\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t\terrors {\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\ttype\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}", + "query": "\n\t\t\tmutation($name: String!, $organizationId: UUID!) {\n\t\t\t\tcreateNamespace(\n\t\t\t\t\tname: $name,\n\t\t\t\t\torganizationId: $organizationId\n\t\t\t\t) {\n\t\t\t\t\tnamespace {\n\t\t\t\t\t\tid\n\t\t\t\t\t}\n\t\t\t\t\terrors {\n\t\t\t\t\t\tmessage\n\t\t\t\t\t\ttype\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}", "variables": { "name": "foo-ns", "organizationId": "bb604b45-b6b0-4b81-ad80-796f15eddf87" @@ -447,14 +445,13 @@ var _ = Describe("Orb integration tests", func() { "createOrb": { "errors": [], "orb": { - "createdAt": "2018-07-16T18:03:18.961Z", "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" } } }` expectedOrbRequest := `{ - "query": "mutation($name: String!, $registryNamespaceId: UUID!){\n\t\t\t\tcreateOrb(\n\t\t\t\t\tname: $name,\n\t\t\t\t\tregistryNamespaceId: $registryNamespaceId\n\t\t\t\t){\n\t\t\t\t orb {\n\t\t\t\t createdAt\n\t\t\t\t id\n\t\t\t\t }\n\t\t\t\t errors {\n\t\t\t\t message\n\t\t\t\t type\n\t\t\t\t }\n\t\t\t\t}\n}", + "query": "mutation($name: String!, $registryNamespaceId: UUID!){\n\t\t\t\tcreateOrb(\n\t\t\t\t\tname: $name,\n\t\t\t\t\tregistryNamespaceId: $registryNamespaceId\n\t\t\t\t){\n\t\t\t\t orb {\n\t\t\t\t id\n\t\t\t\t }\n\t\t\t\t errors {\n\t\t\t\t message\n\t\t\t\t type\n\t\t\t\t }\n\t\t\t\t}\n}", "variables": { "name": "foo-orb", "registryNamespaceId": "bb604b45-b6b0-4b81-ad80-796f15eddf87" @@ -506,7 +503,7 @@ var _ = Describe("Orb integration tests", func() { }` expectedOrbRequest := `{ - "query": "mutation($name: String!, $registryNamespaceId: UUID!){\n\t\t\t\tcreateOrb(\n\t\t\t\t\tname: $name,\n\t\t\t\t\tregistryNamespaceId: $registryNamespaceId\n\t\t\t\t){\n\t\t\t\t orb {\n\t\t\t\t createdAt\n\t\t\t\t id\n\t\t\t\t }\n\t\t\t\t errors {\n\t\t\t\t message\n\t\t\t\t type\n\t\t\t\t }\n\t\t\t\t}\n}", + "query": "mutation($name: String!, $registryNamespaceId: UUID!){\n\t\t\t\tcreateOrb(\n\t\t\t\t\tname: $name,\n\t\t\t\t\tregistryNamespaceId: $registryNamespaceId\n\t\t\t\t){\n\t\t\t\t orb {\n\t\t\t\t id\n\t\t\t\t }\n\t\t\t\t errors {\n\t\t\t\t message\n\t\t\t\t type\n\t\t\t\t }\n\t\t\t\t}\n}", "variables": { "name": "foo-orb", "registryNamespaceId": "bb604b45-b6b0-4b81-ad80-796f15eddf87" From 1f63f6f12427929311b27c40a4434cfa242d49c9 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 07:52:43 +0900 Subject: [PATCH 08/11] Ensure latest gometalinter is installed for lint job Until this docker image is updated: https://github.com/supinf/dockerized-tools/tree/master/golang/gometalinter --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 9ce276f41..32b535462 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -34,6 +34,9 @@ jobs: CGO_ENABLED: 0 steps: - checkout + - run: | + go get -u github.com/alecthomas/gometalinter + gometalinter --install - run: gometalinter ./... deploy: From 232d2e04bae254b42a0f8b70ecd33c8a5d11972d Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 07:57:17 +0900 Subject: [PATCH 09/11] supinf/gometalinter doesn't have git so use our golang image --- .circleci/config.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 32b535462..510a980a2 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -28,15 +28,15 @@ jobs: lint: docker: - - image: supinf/gometalinter:latest + # TODO: use this image once it updates latest gometalinter + #- image: supinf/gometalinter:latest + - image: circleci/golang:1.10 working_directory: /go/src/github.com/CircleCI-Public/circleci-cli environment: CGO_ENABLED: 0 steps: - checkout - - run: | - go get -u github.com/alecthomas/gometalinter - gometalinter --install + - run: make dev - run: gometalinter ./... deploy: From c89051d4ac6786f1460221f687f315c217918b8a Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 08:15:59 +0900 Subject: [PATCH 10/11] Fix calling appendPostHandler after rebase --- cmd/orb_test.go | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/cmd/orb_test.go b/cmd/orb_test.go index 6fa2d187c..381ed9a14 100644 --- a/cmd/orb_test.go +++ b/cmd/orb_test.go @@ -95,7 +95,10 @@ var _ = Describe("Orb integration tests", func() { expected, err := json.Marshal(response) Expect(err).ShouldNot(HaveOccurred()) - appendPostHandler(testServer, token, http.StatusOK, string(expected), gqlResponse) + appendPostHandler(testServer, token, MockRequestResponse{ + Status: http.StatusOK, + Request: string(expected), + Response: gqlResponse}) session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) Expect(err).ShouldNot(HaveOccurred()) @@ -144,7 +147,10 @@ var _ = Describe("Orb integration tests", func() { } }` - appendPostHandler(testServer, token, http.StatusOK, expectedRequestJson, gqlResponse) + appendPostHandler(testServer, token, MockRequestResponse{ + Status: http.StatusOK, + Request: expectedRequestJson, + Response: gqlResponse}) By("running the command") session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) @@ -461,11 +467,10 @@ var _ = Describe("Orb integration tests", func() { } }` - appendPostHandler(testServer, token, - MockRequestResponse{Status: http.StatusOK, - Request: expectedOrganizationRequest, - Response: gqlOrganizationResponse}) - + appendPostHandler(testServer, token, MockRequestResponse{ + Status: http.StatusOK, + Request: expectedOrganizationRequest, + Response: gqlOrganizationResponse}) appendPostHandler(testServer, token, MockRequestResponse{ Status: http.StatusOK, Request: expectedNsRequest, From 08bddb817ac656dabe3b7d0287d9a715d03dbb66 Mon Sep 17 00:00:00 2001 From: Zachary Scott Date: Thu, 26 Jul 2018 08:23:04 +0900 Subject: [PATCH 11/11] Cleanup CreateOrb to remove unnecessary err check --- api/api.go | 5 ----- 1 file changed, 5 deletions(-) diff --git a/api/api.go b/api/api.go index f19ccd42c..61fa3403e 100644 --- a/api/api.go +++ b/api/api.go @@ -359,10 +359,5 @@ func CreateOrb(ctx context.Context, logger *logger.Logger, name string, namespac } orb, err := createOrbWithNsID(ctx, logger, name, namespaceID) - - if err != nil { - return nil, err - } - return orb, err }