From 0a3c0e1ee53be2438ad97109ddce406981b4fbbb Mon Sep 17 00:00:00 2001 From: JulesFaucherre Date: Wed, 14 Feb 2024 16:36:56 +0100 Subject: [PATCH] Revert "remove VCS functionality" This reverts commit 169d9e38b3cb9d13c76b8f807ca0a7d5e7545e4d. --- cmd/.circleci/update_check.yml | 2 +- cmd/namespace.go | 42 ++++++- cmd/namespace_test.go | 209 +++++++++++++++++++++++++++++++++ 3 files changed, 247 insertions(+), 6 deletions(-) diff --git a/cmd/.circleci/update_check.yml b/cmd/.circleci/update_check.yml index c2d7a0089..b4e5bdc0f 100644 --- a/cmd/.circleci/update_check.yml +++ b/cmd/.circleci/update_check.yml @@ -1 +1 @@ -last_update_check: 2024-01-11T10:44:52.12818Z +last_update_check: 2023-12-11T13:24:04.24843+01:00 diff --git a/cmd/namespace.go b/cmd/namespace.go index d6cf8945a..aa90b3e2d 100644 --- a/cmd/namespace.go +++ b/cmd/namespace.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "strings" "github.com/CircleCI-Public/circleci-cli/api" "github.com/CircleCI-Public/circleci-cli/api/graphql" @@ -83,9 +84,9 @@ Please note that at this time all namespaces created in the registry are world-r return err }, - Args: cobra.ExactArgs(1), + Args: cobra.RangeArgs(1, 3), Annotations: make(map[string]string), - Example: ` circleci namespace create NamespaceName --org-id 00000000-0000-0000-0000-000000000000`, + Example: `circleci namespace create NamespaceName --org-id 00000000-0000-0000-0000-000000000000`, } createCmd.Annotations[""] = "The name to give your new namespace" @@ -137,11 +138,42 @@ To change the namespace, you will have to contact CircleCI customer support. return nil } +func createNamespaceWithVcsTypeAndOrgName(opts namespaceOptions, namespaceName, vcsType, orgName string) error { + if !opts.noPrompt { + fmt.Printf(`You are creating a namespace called "%s". + +This is the only namespace permitted for your %s organization, %s. + +To change the namespace, you will have to contact CircleCI customer support. + +`, namespaceName, strings.ToLower(opts.args[1]), opts.args[2]) + } + + confirm := fmt.Sprintf("Are you sure you wish to create the namespace: `%s`", namespaceName) + if opts.noPrompt || opts.tty.askUserToConfirm(confirm) { + _, err := api.CreateNamespace(opts.cl, namespaceName, opts.args[2], strings.ToUpper(opts.args[1])) + if err != nil { + return err + } + + fmt.Printf("Namespace `%s` created.\n", namespaceName) + fmt.Println("Please note that any orbs you publish in this namespace are open orbs and are world-readable.") + } + return nil +} + func createNamespace(cmd *cobra.Command, opts namespaceOptions) error { namespaceName := opts.args[0] - _, err := uuid.Parse(*opts.orgID) - if err == nil { - return createNamespaceWithOrgId(opts, namespaceName, *opts.orgID) + //skip if no orgid provided + if opts.orgID != nil && strings.TrimSpace(*opts.orgID) != "" { + _, err := uuid.Parse(*opts.orgID) + if err == nil { + return createNamespaceWithOrgId(opts, namespaceName, *opts.orgID) + } + + //skip if no vcs type and org name provided + } else if len(opts.args) == 3 { + return createNamespaceWithVcsTypeAndOrgName(opts, namespaceName, opts.args[1], opts.args[2]) } return cmd.Help() } diff --git a/cmd/namespace_test.go b/cmd/namespace_test.go index bf45842e8..216817c96 100644 --- a/cmd/namespace_test.go +++ b/cmd/namespace_test.go @@ -9,6 +9,7 @@ import ( "github.com/CircleCI-Public/circleci-cli/telemetry" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/onsi/gomega/gbytes" "github.com/onsi/gomega/gexec" ) @@ -118,5 +119,213 @@ Namespace %s created. Please note that any orbs you publish in this namespace are open orbs and are world-readable.`, "foo-ns", "bb604b45-b6b0-4b81-ad80-796f15eddf87", "`foo-ns`", "`foo-ns`"))) }) }) + + Describe("registering a namespace with OrgName and OrgVcs", func() { + BeforeEach(func() { + command = exec.Command(pathCLI, + "namespace", "create", + "--skip-update-check", + "--token", token, + "--host", tempSettings.TestServer.URL(), + "--integration-testing", + "foo-ns", + "BITBUCKET", + "test-org", + ) + }) + + It("works with organizationName and organizationVcs", func() { + By("setting up a mock server") + + gqlOrganizationResponse := `{ + "organization": { + "name": "test-org", + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` + + expectedOrganizationRequest := `{ + "query": "query($organizationName: String!, $organizationVcs: VCSType!) {\n\t\t\t\torganization(\n\t\t\t\t\tname: $organizationName\n\t\t\t\t\tvcsType: $organizationVcs\n\t\t\t\t) {\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t}","variables":{"organizationName":"test-org","organizationVcs":"BITBUCKET"}}` + + gqlNsResponse := `{ + "createNamespace": { + "errors": [], + "namespace": { + "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\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" + } + }` + + tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: expectedOrganizationRequest, + Response: gqlOrganizationResponse}) + tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: expectedNsRequest, + Response: gqlNsResponse}) + + By("running the command") + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(gexec.Exit(0)) + + stdout := session.Wait().Out.Contents() + + Expect(string(stdout)).To(ContainSubstring(fmt.Sprintf(`You are creating a namespace called "%s". + +This is the only namespace permitted for your bitbucket organization, test-org. + +To change the namespace, you will have to contact CircleCI customer support. + +Are you sure you wish to create the namespace: %s +Namespace %s created. +Please note that any orbs you publish in this namespace are open orbs and are world-readable.`, "foo-ns", "`foo-ns`", "`foo-ns`"))) + }) + }) + + Describe("when creating / reserving a namespace", func() { + BeforeEach(func() { + command = exec.Command(pathCLI, + "namespace", "create", + "--skip-update-check", + "--token", token, + "--host", tempSettings.TestServer.URL(), + "--integration-testing", + "foo-ns", + "BITBUCKET", + "test-org", + ) + }) + + It("works with organizationName and organizationVcs", func() { + By("setting up a mock server") + + gqlOrganizationResponse := `{ + "organization": { + "name": "test-org", + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` + + expectedOrganizationRequest := `{ + "query": "query($organizationName: String!, $organizationVcs: VCSType!) {\n\t\t\t\torganization(\n\t\t\t\t\tname: $organizationName\n\t\t\t\t\tvcsType: $organizationVcs\n\t\t\t\t) {\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t}", + "variables": { + "organizationName": "test-org", + "organizationVcs": "BITBUCKET" + } + }` + + gqlNsResponse := `{ + "createNamespace": { + "errors": [], + "namespace": { + "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\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" + } + }` + + tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: expectedOrganizationRequest, + Response: gqlOrganizationResponse}) + tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: expectedNsRequest, + Response: gqlNsResponse}) + + By("running the command") + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session).Should(gexec.Exit(0)) + + stdout := session.Wait().Out.Contents() + + Expect(string(stdout)).To(ContainSubstring(fmt.Sprintf(`You are creating a namespace called "%s". + +This is the only namespace permitted for your bitbucket organization, test-org. + +To change the namespace, you will have to contact CircleCI customer support. + +Are you sure you wish to create the namespace: %s +Namespace %s created. +Please note that any orbs you publish in this namespace are open orbs and are world-readable.`, "foo-ns", "`foo-ns`", "`foo-ns`"))) + }) + + It("prints all in-band errors returned by the GraphQL API", func() { + By("setting up a mock server") + + gqlOrganizationResponse := `{ + "organization": { + "name": "test-org", + "id": "bb604b45-b6b0-4b81-ad80-796f15eddf87" + } + }` + + expectedOrganizationRequest := `{ + "query": "query($organizationName: String!, $organizationVcs: VCSType!) {\n\t\t\t\torganization(\n\t\t\t\t\tname: $organizationName\n\t\t\t\t\tvcsType: $organizationVcs\n\t\t\t\t) {\n\t\t\t\t\tid\n\t\t\t\t}\n\t\t\t}", + "variables": { + "organizationName": "test-org", + "organizationVcs": "BITBUCKET" + } + }` + + gqlResponse := `{ + "createNamespace": { + "errors": [ + {"message": "error1"}, + {"message": "error2"} + ], + "namespace": null + } + }` + + gqlNativeErrors := `[ { "message": "ignored error" } ]` + + 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\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" + } + }` + + tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: expectedOrganizationRequest, + Response: gqlOrganizationResponse, + }) + tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: expectedRequestJSON, + Response: gqlResponse, + ErrorResponse: gqlNativeErrors, + }) + + 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)) + }) + }) }) })