diff --git a/cmd/orb.go b/cmd/orb.go index 332b451fe..2d8db7f46 100644 --- a/cmd/orb.go +++ b/cmd/orb.go @@ -621,7 +621,7 @@ func formatListOrbsResult(list api.OrbsForListing, opts orbOptions) (string, err } } - if !opts.private { + if !opts.private && opts.cfg.Host == defaultHost { b.WriteString("\nIn order to see more details about each orb, type: `circleci orb info orb-namespace/orb-name`\n") b.WriteString("\nSearch, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/") } diff --git a/cmd/orb_test.go b/cmd/orb_test.go index df41dd4dd..fec3eebfc 100644 --- a/cmd/orb_test.go +++ b/cmd/orb_test.go @@ -2229,9 +2229,6 @@ second (0.8.0) third (0.9.0) first (0.7.0) -In order to see more details about each orb, type: ` + "`circleci orb info orb-namespace/orb-name`" + ` - -Search, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/ `)) }) @@ -2256,9 +2253,6 @@ third (0.9.0) first (0.7.0) second (0.8.0) -In order to see more details about each orb, type: ` + "`circleci orb info orb-namespace/orb-name`" + ` - -Search, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/ `)) }) @@ -2283,9 +2277,6 @@ second (0.8.0) first (0.7.0) third (0.9.0) -In order to see more details about each orb, type: ` + "`circleci orb info orb-namespace/orb-name`" + ` - -Search, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/ `)) }) }) @@ -2396,7 +2387,83 @@ query ListOrbs ($after: String!, $certifiedOnly: Boolean!) { }) }) - Describe("when listing all orbs with --uncertified", func() { + Describe("when listing all orbs default host", func() { + BeforeEach(func() { + command = exec.Command(pathCLI, + "orb", "list", + "--skip-update-check", + ) + By("setting up a mock server") + + query := ` +query ListOrbs ($after: String!, $certifiedOnly: Boolean!) { + orbs(first: 20, after: $after, certifiedOnly: $certifiedOnly) { + totalCount, + edges { + cursor + node { + name + statistics { + last30DaysBuildCount, + last30DaysProjectCount, + last30DaysOrganizationCount + } + versions(count: 1) { + version, + source + } + } + } + pageInfo { + hasNextPage + } + } +} +` + + firstRequest := graphql.NewRequest(query) + firstRequest.Variables["after"] = "" + firstRequest.Variables["certifiedOnly"] = false + + firstRequestEncoded, err := firstRequest.Encode() + Expect(err).ShouldNot(HaveOccurred()) + + secondRequest := graphql.NewRequest(query) + secondRequest.Variables["after"] = "test/here-we-go" + secondRequest.Variables["certifiedOnly"] = false + + secondRequestEncoded, err := secondRequest.Encode() + Expect(err).ShouldNot(HaveOccurred()) + + tmpBytes := golden.Get(GinkgoT(), filepath.FromSlash("gql_orb_list_uncertified/first_response.json")) + firstResponse := string(tmpBytes) + + tmpBytes = golden.Get(GinkgoT(), filepath.FromSlash("gql_orb_list_uncertified/second_response.json")) + secondResponse := string(tmpBytes) + + tempSettings.AppendPostHandler("", clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: firstRequestEncoded.String(), + Response: firstResponse, + }) + tempSettings.AppendPostHandler("", clitest.MockRequestResponse{ + Status: http.StatusOK, + Request: secondRequestEncoded.String(), + Response: secondResponse, + }) + }) + + It("includes a link to the docs'", func() { + By("running the command") + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + + Expect(err).ShouldNot(HaveOccurred()) + Eventually(session.Out).Should(gbytes.Say("In order to see more details about each orb, type: `circleci orb info orb-namespace/orb-name`")) + Eventually(session.Out).Should(gbytes.Say("Search, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/")) + }) + }) + + Describe("when listing all orbs with --uncertified and custom host", func() { BeforeEach(func() { command = exec.Command(pathCLI, "orb", "list", @@ -2475,9 +2542,6 @@ query ListOrbs ($after: String!, $certifiedOnly: Boolean!) { Eventually(session.Out).Should(gbytes.Say("circleci/codecov-clojure \\(0.0.4\\)")) // Include an orb with contents from the second mocked response Eventually(session.Out).Should(gbytes.Say("zzak/test4 \\(0.1.0\\)")) - - Eventually(session.Out).Should(gbytes.Say("In order to see more details about each orb, type: `circleci orb info orb-namespace/orb-name`")) - Eventually(session.Out).Should(gbytes.Say("Search, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/")) Expect(tempSettings.TestServer.ReceivedRequests()).Should(HaveLen(2)) }) @@ -2584,9 +2648,6 @@ foo/test (0.7.0) - last30DaysOrganizationCount: 0 - last30DaysProjectCount: 0 -In order to see more details about each orb, type: ` + "`circleci orb info orb-namespace/orb-name`" + ` - -Search, filter, and view sources for all Orbs online at https://circleci.com/developer/orbs/ `)) Eventually(session).Should(gexec.Exit(0)) Expect(tempSettings.TestServer.ReceivedRequests()).Should(HaveLen(1)) diff --git a/cmd/runner/runner.go b/cmd/runner/runner.go index 72424c1b6..e620b53b3 100644 --- a/cmd/runner/runner.go +++ b/cmd/runner/runner.go @@ -15,7 +15,12 @@ type runnerOpts struct { r running } -func NewCommand(config *settings.Config, preRunE validator.Validator) *cobra.Command { +func NewCommand(rootConfig *settings.Config, preRunE validator.Validator) *cobra.Command { + // The runner API versioning is decoupled from the other Circle APIs. Here we make a copy of the root configuration, + // and update the rest endpoint accordingly + config := *rootConfig + config.RestEndpoint = "/api/v3" + var opts runnerOpts cmd := &cobra.Command{ Use: "runner", @@ -27,7 +32,7 @@ func NewCommand(config *settings.Config, preRunE validator.Validator) *cobra.Com } else { host = config.Host } - opts.r = runner.New(rest.NewFromConfig(host, config)) + opts.r = runner.New(rest.NewFromConfig(host, &config)) }, } diff --git a/cmd/runner/runner_test.go b/cmd/runner/runner_test.go new file mode 100644 index 000000000..cfef51286 --- /dev/null +++ b/cmd/runner/runner_test.go @@ -0,0 +1,31 @@ +package runner + +import ( + "net/http" + "net/http/httptest" + "testing" + + "gotest.tools/v3/assert" + "gotest.tools/v3/assert/cmp" + + "github.com/CircleCI-Public/circleci-cli/settings" +) + +func Test_NewCommand(t *testing.T) { + t.Run("Runner uses /api/v3", func(t *testing.T) { + server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + assert.Check(t, cmp.Equal(r.URL.EscapedPath(), "/api/v3/runner")) + + w.Header().Set("Content-Type", "application/json") + _, err := w.Write([]byte(`{"items":[]}`)) + assert.NilError(t, err) + w.WriteHeader(http.StatusOK) + })) + t.Cleanup(server.Close) + + cmd := NewCommand(&settings.Config{Host: server.URL, HTTPClient: &http.Client{}}, nil) + cmd.SetArgs([]string{"instance", "ls", "my-namespace"}) + err := cmd.Execute() + assert.NilError(t, err) + }) +} diff --git a/integration_tests/features/circleci_config.feature b/integration_tests/features/circleci_config.feature index 9628d3bf3..17354219b 100644 --- a/integration_tests/features/circleci_config.feature +++ b/integration_tests/features/circleci_config.feature @@ -84,30 +84,6 @@ Feature: Config checking Then the exit status should be 0 And the output should contain "Config file at config.yml is valid" - Scenario: Checking a valid config file with a private org - Given a file named "config.yml" with: - """ - version: 2.1 - - orbs: - node: circleci/node@5.0.3 - - jobs: - datadog-hello-world: - docker: - - image: cimg/base:stable - steps: - - run: | - echo "doing something really cool" - workflows: - datadog-hello-world: - jobs: - - datadog-hello-world - """ - When I run `circleci config validate --skip-update-check --org-id bb604b45-b6b0-4b81-ad80-796f15eddf87 -c config.yml` - Then the output should contain "Config file at config.yml is valid" - And the exit status should be 0 - Scenario: Checking a valid config file with a non-existant orb Given a file named "config.yml" with: """