Skip to content

Commit

Permalink
Merge pull request #1002 from CircleCI-Public/develop
Browse files Browse the repository at this point in the history
Release
  • Loading branch information
loderunner authored Sep 5, 2023
2 parents 663eda4 + a516872 commit 636da77
Show file tree
Hide file tree
Showing 50 changed files with 90 additions and 2,346 deletions.
6 changes: 0 additions & 6 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -137,10 +137,6 @@ jobs:
working_directory: integration_tests
environment:
TESTING: "true"
- run:
name: "Make sure simple command do not cause any timeout"
command: circleci version

test:
executor: go
steps:
Expand Down Expand Up @@ -382,14 +378,12 @@ workflows:
- devex-release
- deploy:
requires:
- cucumber
- test
- test_mac
- coverage
- lint
- deploy-test
- shellcheck/check
- vulnerability-scan
filters:
branches:
only: main
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ GOOS=$(shell go env GOOS)
GOARCH=$(shell go env GOARCH)

build: always
go build -o build/$(GOOS)/$(GOARCH)/circleci -ldflags='-X github.com/CircleCI-Public/circleci-cli/telemetry.SegmentEndpoint=https://api.segment.io'
go build -o build/$(GOOS)/$(GOARCH)/circleci

build-all: build/linux/amd64/circleci build/darwin/amd64/circleci

Expand Down
20 changes: 3 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,20 +180,6 @@ Please see the [documentation](https://circleci-public.github.io/circleci-cli) o

## Server compatibility

| Functionality | Impacted commands | Change description | Compatibility with Server |
| --- | --- | --- | --- |
| Config compilation and validation | <ul><li>`circleci config validate`</li><li>`circleci config process`</li><li>`circleci local execute`</li> | The config validation has been moved from the GraphQL API to a specific API endpoint | <ul><li>**Server v4.0.5, v4.1.3, v4.2.0 and above**: Commands use the new specific endpoint</li><li>**Previous version**: Commands use the GraphQL API</li></ul> |
| Orb compilation and validation of orb using private orbs | <ul><li>`circleci orb process`</li><li>`circleci orb validate`</li></ul> | To support the validation of orbs requesting private orbs (see [issue](https://github.com/CircleCI-Public/circleci-cli/issues/751)). A field `ownerId` has been added to the GraphQL orb validation endpoint. Thus allowing the `Impacted commands` to use the `--org-id` parameter to enable the orb compilation / validation | <ul><li>**Server v4.2.0 and above**: The field is accessible so you can use the parameter</li><li>**Previous versions**: The field does not exist making the functionality unavailable</li></ul> |

## Telemetry

The CircleCI CLI includes a telemetry feature that collects basic errors and feature usage data in order to help us improve the experience for everyone.

Telemetry works on an opt-in basis: when running a command for the first time, you will be asked for consent to enable telemetry. For non-TTY STDIN, telemetry is disabled by default, ensuring that scripts that use the CLI run smoothly.

You can disable or enable telemetry anytime in one of the following ways:

* Run the commands `circleci telemetry enable` or `circleci telemetry disable`

* Set the `CIRCLECI_CLI_TELEMETRY_OPTOUT` environment variable to `1` or `true` to disable it

There are some difference of behavior depending on the version you use:
- config validation will use the GraphQL API until **Server v4.0.5, v4.1.3, v4.2.0**. The above versions will use the new route `compile-config-with-defaults`
- `circleci orb validate` will only allow you to validate orbs using other private orbs with the option `--org-slug` from version **Server v4.2.0**
10 changes: 4 additions & 6 deletions Taskfile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,14 @@ tasks:
build:
desc: Build main
cmds:
# LDFlags sets the segment endpoint to an empty string thus letting the analytics library set the default endpoint on its own
# Not setting the `SegmentEndpoint` variable would let the value in the code ie "http://localhost"
- go build -v -o build/$(go env GOOS)/$(go env GOARCH)/circleci -ldflags='-X github.com/CircleCI-Public/circleci-cli/telemetry.SegmentEndpoint=https://api.segment.io' .

- go build -v -o build/darwin/amd64/circleci .

build-linux:
desc: Build main
cmds:
- go build -v -o build/linux/amd64/circleci .

cover:
desc: tests and generates a cover profile
cmds:
- TESTING=true go test -race -coverprofile=coverage.txt ./...
- TESTING=true go test -race -coverprofile=coverage.txt ./...
19 changes: 0 additions & 19 deletions api/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,11 @@ import (
"io"
"log"
"net/http"
"net/url"
"os"
"sort"
"strings"

"github.com/CircleCI-Public/circleci-cli/api/graphql"
"github.com/CircleCI-Public/circleci-cli/api/rest"
"github.com/CircleCI-Public/circleci-cli/references"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/Masterminds/semver"
Expand Down Expand Up @@ -1820,20 +1818,3 @@ func FollowProject(config settings.Config, vcs string, owner string, projectName

return fr, nil
}

type Me struct {
ID string `json:"id"`
Login string `json:"login"`
Name string `json:"name"`
}

func GetMe(client *rest.Client) (Me, error) {
req, err := client.NewRequest("GET", &url.URL{Path: "me"}, nil)
if err != nil {
return Me{}, errors.Wrap(err, "Unable to get user info")
}

var me Me
_, err = client.DoRequest(req, &me)
return me, err
}
22 changes: 4 additions & 18 deletions clitest/clitest.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,9 @@ import (
"runtime"

"github.com/CircleCI-Public/circleci-cli/api/graphql"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/onsi/gomega/gexec"
"github.com/onsi/gomega/ghttp"
"github.com/onsi/gomega/types"
"gopkg.in/yaml.v3"

"github.com/onsi/gomega"
)
Expand All @@ -32,12 +30,10 @@ func ShouldFail() types.GomegaMatcher {

// TempSettings contains useful settings for testing the CLI
type TempSettings struct {
Home string
TestServer *ghttp.Server
Config *TmpFile
Update *TmpFile
Telemetry *TmpFile
TelemetryDestPath string
Home string
TestServer *ghttp.Server
Config *TmpFile
Update *TmpFile
}

// Close should be called in an AfterEach and cleans up the temp directory and server process
Expand Down Expand Up @@ -72,16 +68,6 @@ func WithTempSettings() *TempSettings {
gomega.Expect(os.Mkdir(settingsPath, 0700)).To(gomega.Succeed())

tempSettings.Config = OpenTmpFile(settingsPath, "cli.yml")
tempSettings.Telemetry = OpenTmpFile(settingsPath, "telemetry.yml")
content, err := yaml.Marshal(settings.TelemetrySettings{
IsEnabled: false,
HasAnsweredPrompt: true,
})
gomega.Expect(err).ToNot(gomega.HaveOccurred())
_, err = tempSettings.Telemetry.File.Write(content)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
tempSettings.TelemetryDestPath = filepath.Join(tempSettings.Home, "telemetry-content")

tempSettings.Update = OpenTmpFile(settingsPath, "update_check.yml")

tempSettings.TestServer = ghttp.NewServer()
Expand Down
19 changes: 0 additions & 19 deletions clitest/telemetry.go

This file was deleted.

10 changes: 1 addition & 9 deletions cmd/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package cmd
import (
"github.com/CircleCI-Public/circleci-cli/local"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/CircleCI-Public/circleci-cli/telemetry"
"github.com/spf13/cobra"
)

Expand All @@ -17,14 +16,7 @@ func newLocalExecuteCommand(config *settings.Config) *cobra.Command {
return nil
},
RunE: func(cmd *cobra.Command, _ []string) error {
err := local.Execute(cmd.Flags(), config, args)

telemetryClient, ok := telemetry.FromContext(cmd.Context())
if ok {
_ = telemetryClient.Track(telemetry.CreateLocalExecuteEvent(telemetry.GetCommandInformation(cmd, true)))
}

return err
return local.Execute(cmd.Flags(), config, args)
},
Args: cobra.MinimumNArgs(1),
}
Expand Down
3 changes: 0 additions & 3 deletions cmd/cmd_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"os"
"os/exec"
"testing"
"time"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
Expand All @@ -15,8 +14,6 @@ import (
var pathCLI string

var _ = BeforeSuite(func() {
SetDefaultEventuallyTimeout(time.Second * 30)

var err error
pathCLI, err = gexec.Build("github.com/CircleCI-Public/circleci-cli")
Ω(err).ShouldNot(HaveOccurred())
Expand Down
10 changes: 1 addition & 9 deletions cmd/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,13 @@ package cmd
import (
"os"

"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/CircleCI-Public/circleci-cli/telemetry"
"github.com/spf13/cobra"
)

func newCompletionCommand(config *settings.Config) *cobra.Command {
func newCompletionCommand() *cobra.Command {
completionCmd := &cobra.Command{
Use: "completion",
Short: "Generate shell completion scripts",
PersistentPreRun: func(cmd *cobra.Command, _ []string) {
telemetryClient, ok := telemetry.FromContext(cmd.Context())
if ok {
_ = telemetryClient.Track(telemetry.CreateCompletionCommand(telemetry.GetCommandInformation(cmd, true)))
}
},
Run: func(cmd *cobra.Command, _ []string) {
err := cmd.Help()
if err != nil {
Expand Down
31 changes: 7 additions & 24 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ import (
"github.com/CircleCI-Public/circleci-config/labeling"
"github.com/CircleCI-Public/circleci-config/labeling/codebase"

"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"

"github.com/CircleCI-Public/circleci-cli/config"
"github.com/CircleCI-Public/circleci-cli/filetree"
"github.com/CircleCI-Public/circleci-cli/proxy"
"github.com/CircleCI-Public/circleci-cli/settings"
"github.com/CircleCI-Public/circleci-cli/telemetry"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"gopkg.in/yaml.v3"
)

// Path to the config.yml file to operate on.
Expand All @@ -37,14 +37,8 @@ func newConfigCommand(globalConfig *settings.Config) *cobra.Command {
packCommand := &cobra.Command{
Use: "pack <path>",
Short: "Pack up your CircleCI configuration into a single file.",
RunE: func(cmd *cobra.Command, args []string) error {
err := packConfig(args)

telemetryClient, ok := telemetry.FromContext(cmd.Context())
if ok {
_ = telemetryClient.Track(telemetry.CreateConfigEvent(telemetry.GetCommandInformation(cmd, true), err))
}
return err
RunE: func(_ *cobra.Command, args []string) error {
return packConfig(args)
},
Args: cobra.ExactArgs(1),
Annotations: make(map[string]string),
Expand All @@ -70,20 +64,13 @@ func newConfigCommand(globalConfig *settings.Config) *cobra.Command {
if len(args) == 1 {
path = args[0]
}

err = compiler.ValidateConfig(config.ValidateConfigOpts{
return compiler.ValidateConfig(config.ValidateConfigOpts{
ConfigPath: path,
OrgID: orgID,
OrgSlug: orgSlug,
IgnoreDeprecatedImages: ignoreDeprecatedImages,
VerboseOutput: verboseOutput,
})
telemetryClient, ok := telemetry.FromContext(cmd.Context())
if ok {
_ = telemetryClient.Track(telemetry.CreateConfigEvent(telemetry.GetCommandInformation(cmd, true), err))
}

return err
},
Args: cobra.MaximumNArgs(1),
Annotations: make(map[string]string),
Expand Down Expand Up @@ -125,10 +112,6 @@ func newConfigCommand(globalConfig *settings.Config) *cobra.Command {
PipelineParamsFilePath: pipelineParamsFilePath,
VerboseOutput: verboseOutput,
})
telemetryClient, ok := telemetry.FromContext(cmd.Context())
if ok {
_ = telemetryClient.Track(telemetry.CreateConfigEvent(telemetry.GetCommandInformation(cmd, true), err))
}
if err != nil {
return err
}
Expand Down
32 changes: 1 addition & 31 deletions cmd/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"path/filepath"

"github.com/CircleCI-Public/circleci-cli/clitest"
"github.com/CircleCI-Public/circleci-cli/telemetry"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
Expand All @@ -30,41 +29,12 @@ var _ = Describe("Config", func() {
tempSettings.Close()
})

Describe("telemetry", func() {
BeforeEach(func() {
tempSettings = clitest.WithTempSettings()
command = commandWithHome(pathCLI, tempSettings.Home,
"config", "pack",
"--skip-update-check",
filepath.Join("testdata", "hugo-pack", ".circleci"),
)
command.Env = append(command.Env, fmt.Sprintf("MOCK_TELEMETRY=%s", tempSettings.TelemetryDestPath))
})

AfterEach(func() {
tempSettings.Close()
})

It("should send telemetry event", func() {
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).ShouldNot(HaveOccurred())

Eventually(session).Should(gexec.Exit(0))
clitest.CompareTelemetryEvent(tempSettings, []telemetry.Event{
telemetry.CreateConfigEvent(telemetry.CommandInfo{
Name: "pack",
LocalArgs: map[string]string{"help": "false"},
}, nil),
})
})
})

Describe("a .circleci folder with config.yml and local orbs folder containing the hugo orb", func() {
BeforeEach(func() {
command = exec.Command(pathCLI,
"config", "pack",
"--skip-update-check",
filepath.Join("testdata", "hugo-pack", ".circleci"))
"testdata/hugo-pack/.circleci")
results = golden.Get(GinkgoT(), filepath.FromSlash("hugo-pack/result.yml"))
})

Expand Down
Loading

0 comments on commit 636da77

Please sign in to comment.