Skip to content

Commit 16acd35

Browse files
author
JulesFaucherre
authored
Merge pull request #1044 from CircleCI-Public/develop
Release
2 parents 9c87a3e + 430c09a commit 16acd35

File tree

3 files changed

+247
-6
lines changed

3 files changed

+247
-6
lines changed

cmd/.circleci/update_check.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
last_update_check: 2024-01-11T10:44:52.12818Z
1+
last_update_check: 2023-12-11T13:24:04.24843+01:00

cmd/namespace.go

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/CircleCI-Public/circleci-cli/api"
78
"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
8384

8485
return err
8586
},
86-
Args: cobra.ExactArgs(1),
87+
Args: cobra.RangeArgs(1, 3),
8788
Annotations: make(map[string]string),
88-
Example: ` circleci namespace create NamespaceName --org-id 00000000-0000-0000-0000-000000000000`,
89+
Example: `circleci namespace create NamespaceName --org-id 00000000-0000-0000-0000-000000000000`,
8990
}
9091

9192
createCmd.Annotations["<name>"] = "The name to give your new namespace"
@@ -137,11 +138,42 @@ To change the namespace, you will have to contact CircleCI customer support.
137138
return nil
138139
}
139140

141+
func createNamespaceWithVcsTypeAndOrgName(opts namespaceOptions, namespaceName, vcsType, orgName string) error {
142+
if !opts.noPrompt {
143+
fmt.Printf(`You are creating a namespace called "%s".
144+
145+
This is the only namespace permitted for your %s organization, %s.
146+
147+
To change the namespace, you will have to contact CircleCI customer support.
148+
149+
`, namespaceName, strings.ToLower(opts.args[1]), opts.args[2])
150+
}
151+
152+
confirm := fmt.Sprintf("Are you sure you wish to create the namespace: `%s`", namespaceName)
153+
if opts.noPrompt || opts.tty.askUserToConfirm(confirm) {
154+
_, err := api.CreateNamespace(opts.cl, namespaceName, opts.args[2], strings.ToUpper(opts.args[1]))
155+
if err != nil {
156+
return err
157+
}
158+
159+
fmt.Printf("Namespace `%s` created.\n", namespaceName)
160+
fmt.Println("Please note that any orbs you publish in this namespace are open orbs and are world-readable.")
161+
}
162+
return nil
163+
}
164+
140165
func createNamespace(cmd *cobra.Command, opts namespaceOptions) error {
141166
namespaceName := opts.args[0]
142-
_, err := uuid.Parse(*opts.orgID)
143-
if err == nil {
144-
return createNamespaceWithOrgId(opts, namespaceName, *opts.orgID)
167+
//skip if no orgid provided
168+
if opts.orgID != nil && strings.TrimSpace(*opts.orgID) != "" {
169+
_, err := uuid.Parse(*opts.orgID)
170+
if err == nil {
171+
return createNamespaceWithOrgId(opts, namespaceName, *opts.orgID)
172+
}
173+
174+
//skip if no vcs type and org name provided
175+
} else if len(opts.args) == 3 {
176+
return createNamespaceWithVcsTypeAndOrgName(opts, namespaceName, opts.args[1], opts.args[2])
145177
}
146178
return cmd.Help()
147179
}

cmd/namespace_test.go

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/CircleCI-Public/circleci-cli/telemetry"
1010
. "github.com/onsi/ginkgo"
1111
. "github.com/onsi/gomega"
12+
"github.com/onsi/gomega/gbytes"
1213
"github.com/onsi/gomega/gexec"
1314
)
1415

@@ -118,5 +119,213 @@ Namespace %s created.
118119
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`")))
119120
})
120121
})
122+
123+
Describe("registering a namespace with OrgName and OrgVcs", func() {
124+
BeforeEach(func() {
125+
command = exec.Command(pathCLI,
126+
"namespace", "create",
127+
"--skip-update-check",
128+
"--token", token,
129+
"--host", tempSettings.TestServer.URL(),
130+
"--integration-testing",
131+
"foo-ns",
132+
"BITBUCKET",
133+
"test-org",
134+
)
135+
})
136+
137+
It("works with organizationName and organizationVcs", func() {
138+
By("setting up a mock server")
139+
140+
gqlOrganizationResponse := `{
141+
"organization": {
142+
"name": "test-org",
143+
"id": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
144+
}
145+
}`
146+
147+
expectedOrganizationRequest := `{
148+
"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"}}`
149+
150+
gqlNsResponse := `{
151+
"createNamespace": {
152+
"errors": [],
153+
"namespace": {
154+
"id": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
155+
}
156+
}
157+
}`
158+
159+
expectedNsRequest := `{
160+
"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}",
161+
"variables": {
162+
"name": "foo-ns",
163+
"organizationId": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
164+
}
165+
}`
166+
167+
tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{
168+
Status: http.StatusOK,
169+
Request: expectedOrganizationRequest,
170+
Response: gqlOrganizationResponse})
171+
tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{
172+
Status: http.StatusOK,
173+
Request: expectedNsRequest,
174+
Response: gqlNsResponse})
175+
176+
By("running the command")
177+
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
178+
Expect(err).ShouldNot(HaveOccurred())
179+
Eventually(session).Should(gexec.Exit(0))
180+
181+
stdout := session.Wait().Out.Contents()
182+
183+
Expect(string(stdout)).To(ContainSubstring(fmt.Sprintf(`You are creating a namespace called "%s".
184+
185+
This is the only namespace permitted for your bitbucket organization, test-org.
186+
187+
To change the namespace, you will have to contact CircleCI customer support.
188+
189+
Are you sure you wish to create the namespace: %s
190+
Namespace %s created.
191+
Please note that any orbs you publish in this namespace are open orbs and are world-readable.`, "foo-ns", "`foo-ns`", "`foo-ns`")))
192+
})
193+
})
194+
195+
Describe("when creating / reserving a namespace", func() {
196+
BeforeEach(func() {
197+
command = exec.Command(pathCLI,
198+
"namespace", "create",
199+
"--skip-update-check",
200+
"--token", token,
201+
"--host", tempSettings.TestServer.URL(),
202+
"--integration-testing",
203+
"foo-ns",
204+
"BITBUCKET",
205+
"test-org",
206+
)
207+
})
208+
209+
It("works with organizationName and organizationVcs", func() {
210+
By("setting up a mock server")
211+
212+
gqlOrganizationResponse := `{
213+
"organization": {
214+
"name": "test-org",
215+
"id": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
216+
}
217+
}`
218+
219+
expectedOrganizationRequest := `{
220+
"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}",
221+
"variables": {
222+
"organizationName": "test-org",
223+
"organizationVcs": "BITBUCKET"
224+
}
225+
}`
226+
227+
gqlNsResponse := `{
228+
"createNamespace": {
229+
"errors": [],
230+
"namespace": {
231+
"id": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
232+
}
233+
}
234+
}`
235+
236+
expectedNsRequest := `{
237+
"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}",
238+
"variables": {
239+
"name": "foo-ns",
240+
"organizationId": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
241+
}
242+
}`
243+
244+
tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{
245+
Status: http.StatusOK,
246+
Request: expectedOrganizationRequest,
247+
Response: gqlOrganizationResponse})
248+
tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{
249+
Status: http.StatusOK,
250+
Request: expectedNsRequest,
251+
Response: gqlNsResponse})
252+
253+
By("running the command")
254+
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
255+
Expect(err).ShouldNot(HaveOccurred())
256+
Eventually(session).Should(gexec.Exit(0))
257+
258+
stdout := session.Wait().Out.Contents()
259+
260+
Expect(string(stdout)).To(ContainSubstring(fmt.Sprintf(`You are creating a namespace called "%s".
261+
262+
This is the only namespace permitted for your bitbucket organization, test-org.
263+
264+
To change the namespace, you will have to contact CircleCI customer support.
265+
266+
Are you sure you wish to create the namespace: %s
267+
Namespace %s created.
268+
Please note that any orbs you publish in this namespace are open orbs and are world-readable.`, "foo-ns", "`foo-ns`", "`foo-ns`")))
269+
})
270+
271+
It("prints all in-band errors returned by the GraphQL API", func() {
272+
By("setting up a mock server")
273+
274+
gqlOrganizationResponse := `{
275+
"organization": {
276+
"name": "test-org",
277+
"id": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
278+
}
279+
}`
280+
281+
expectedOrganizationRequest := `{
282+
"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}",
283+
"variables": {
284+
"organizationName": "test-org",
285+
"organizationVcs": "BITBUCKET"
286+
}
287+
}`
288+
289+
gqlResponse := `{
290+
"createNamespace": {
291+
"errors": [
292+
{"message": "error1"},
293+
{"message": "error2"}
294+
],
295+
"namespace": null
296+
}
297+
}`
298+
299+
gqlNativeErrors := `[ { "message": "ignored error" } ]`
300+
301+
expectedRequestJSON := `{
302+
"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}",
303+
"variables": {
304+
"name": "foo-ns",
305+
"organizationId": "bb604b45-b6b0-4b81-ad80-796f15eddf87"
306+
}
307+
}`
308+
309+
tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{
310+
Status: http.StatusOK,
311+
Request: expectedOrganizationRequest,
312+
Response: gqlOrganizationResponse,
313+
})
314+
tempSettings.AppendPostHandler(token, clitest.MockRequestResponse{
315+
Status: http.StatusOK,
316+
Request: expectedRequestJSON,
317+
Response: gqlResponse,
318+
ErrorResponse: gqlNativeErrors,
319+
})
320+
321+
By("running the command")
322+
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
323+
324+
Expect(err).ShouldNot(HaveOccurred())
325+
Eventually(session.Err).Should(gbytes.Say(`Error: error1
326+
error2`))
327+
Eventually(session).ShouldNot(gexec.Exit(0))
328+
})
329+
})
121330
})
122331
})

0 commit comments

Comments
 (0)