Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release #1039

Merged
merged 18 commits into from
Feb 14, 2024
Merged

Release #1039

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ executors:
resource_class: macos.m1.medium.gen1
environment:
CGO_ENABLED: 0
HOMEBREW_NO_AUTO_UPDATE: 1
TERM: xterm-256color

commands:
Expand Down
2 changes: 1 addition & 1 deletion cmd/.circleci/update_check.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
last_update_check: 2023-12-11T13:24:04.24843+01:00
last_update_check: 2024-01-11T10:44:52.12818Z
3 changes: 2 additions & 1 deletion cmd/follow.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ func followProjectCommand(config *settings.Config) *cobra.Command {
}
followCommand := &cobra.Command{
Use: "follow",
Short: "Attempt to follow the project for the current git repository.",
Short: "Attempt to follow the project for the current git repository.\nThis command is intended to be run from a git repository with a remote named 'origin' that is hosted on Github or Bitbucket only. NOTE: this command is deprecated and is not reliable on Github projects created after September 2023",
RunE: func(cmd *cobra.Command, _ []string) error {
err := followProject(opts)

Expand All @@ -64,6 +64,7 @@ func followProjectCommand(config *settings.Config) *cobra.Command {

return err
},
Deprecated: "This command is deprecated and is not reliable on Github projects created after September 2023",
}
return followCommand
}
47 changes: 6 additions & 41 deletions cmd/namespace.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package cmd

import (
"fmt"
"strings"

"github.com/CircleCI-Public/circleci-cli/api"
"github.com/CircleCI-Public/circleci-cli/api/graphql"
Expand Down Expand Up @@ -58,7 +57,7 @@ func newNamespaceCommand(config *settings.Config) *cobra.Command {
}

createCmd := &cobra.Command{
Use: "create <name> [<vcs-type>] [<org-name>]",
Use: "create <name> --org-id <your-organization-id>",
Short: "Create a namespace",
Long: `Create a namespace.
Please note that at this time all namespaces created in the registry are world-readable.`,
Expand All @@ -84,15 +83,12 @@ Please note that at this time all namespaces created in the registry are world-r

return err
},
Args: cobra.RangeArgs(1, 3),
Args: cobra.ExactArgs(1),
Annotations: make(map[string]string),
Example: ` circleci namespace create NamespaceName github OrgName
circleci namespace create NamespaceName --org-id "your-org-id-here"`,
Example: ` circleci namespace create NamespaceName --org-id 00000000-0000-0000-0000-000000000000`,
}

createCmd.Annotations["<name>"] = "The name to give your new namespace"
createCmd.Annotations["[<vcs-type>]"] = `Your VCS provider, can be either "github" or "bitbucket". Optional when passing org-id flag.`
createCmd.Annotations["[<org-name>]"] = `The name used for your organization. Optional when passing org-id flag.`

createCmd.Flags().BoolVar(&opts.integrationTesting, "integration-testing", false, "Enable test mode to bypass interactive UI.")
if err := createCmd.Flags().MarkHidden("integration-testing"); err != nil {
Expand Down Expand Up @@ -141,42 +137,11 @@ 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]
//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])
_, err := uuid.Parse(*opts.orgID)
if err == nil {
return createNamespaceWithOrgId(opts, namespaceName, *opts.orgID)
}
return cmd.Help()
}
Expand Down
209 changes: 0 additions & 209 deletions cmd/namespace_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ 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"
)

Expand Down Expand Up @@ -119,213 +118,5 @@ 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))
})
})
})
})
7 changes: 3 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ require (
github.com/blang/semver v3.5.1+incompatible
github.com/briandowns/spinner v1.23.0
github.com/fatih/color v1.16.0
github.com/go-git/go-git/v5 v5.10.1
github.com/go-git/go-git/v5 v5.11.0
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/uuid v1.4.0
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf // indirect
Expand Down Expand Up @@ -56,7 +56,7 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/charmbracelet/bubbles v0.16.1 // indirect
github.com/charmbracelet/bubbletea v0.24.2 // indirect
github.com/cloudflare/circl v1.3.6 // indirect
github.com/cloudflare/circl v1.3.7 // indirect
github.com/containerd/console v1.0.4-0.20230313162750-1ae8d489ac81 // indirect
github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
Expand All @@ -71,7 +71,6 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-github v17.0.0+incompatible // indirect
github.com/google/go-github/v30 v30.1.0 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hinshun/vt10x v0.0.0-20220301184237-5011da428d02 // indirect
Expand Down Expand Up @@ -114,7 +113,7 @@ require (
go.opentelemetry.io/otel/metric v1.21.0 // indirect
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
go.opentelemetry.io/otel/trace v1.21.0 // indirect
golang.org/x/crypto v0.16.0 // indirect
golang.org/x/crypto v0.17.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/sync v0.5.0 // indirect
Expand Down
Loading