-
Notifications
You must be signed in to change notification settings - Fork 14
chore: Add analytics setup #104
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
Changes from all commits
e3bd7dc
e45cd11
7a034c1
b10379d
eba4c8f
2045e86
5fb89f9
33633df
3ca7563
250512d
e1daf8c
2dda61b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,7 +15,7 @@ inputs: | |
| description: 'Tag to upload artifacts to.' | ||
| required: true | ||
| outputs: | ||
| hashes: | ||
| hashes: | ||
| description: sha256sum hashes of built artifacts | ||
| value: ${{ steps.hash.outputs.hashes }} | ||
|
|
||
|
|
@@ -40,8 +40,8 @@ runs: | |
| env: | ||
| GITHUB_TOKEN: ${{ inputs.token }} | ||
| HOMEBREW_DEPLOY_KEY: ${{ inputs.homebrew-gh-secret }} | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. did we mean to remove the
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nope. Probably a weird merge. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh thanks for restoring that |
||
| - name: Hash build artifacts for provenance | ||
| - name: Hash build artifacts for provenance | ||
| id: hash | ||
| shell: bash | ||
| run: | | ||
| run: | | ||
| echo "hashes=$(sha256sum dist/*.tar.gz | base64 -w0)" >> "$GITHUB_OUTPUT" | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -9,14 +9,18 @@ import ( | |
|
|
||
| "ldcli/cmd/cliflags" | ||
| "ldcli/cmd/validators" | ||
| "ldcli/internal/analytics" | ||
| "ldcli/internal/environments" | ||
| ) | ||
|
|
||
| func NewGetCmd(client environments.Client) (*cobra.Command, error) { | ||
| func NewGetCmd( | ||
| analyticsTracker analytics.Tracker, | ||
| client environments.Client, | ||
| ) (*cobra.Command, error) { | ||
| cmd := &cobra.Command{ | ||
| Args: validators.Validate(), | ||
| Long: "Return an environment", | ||
| RunE: runGet(client), | ||
| RunE: runGet(analyticsTracker, client), | ||
| Short: "Return an environment", | ||
| Use: "get", | ||
| } | ||
|
|
@@ -45,7 +49,10 @@ func NewGetCmd(client environments.Client) (*cobra.Command, error) { | |
| return cmd, nil | ||
| } | ||
|
|
||
| func runGet(client environments.Client) func(*cobra.Command, []string) error { | ||
| func runGet( | ||
| analyticsTracker analytics.Tracker, | ||
| client environments.Client, | ||
| ) func(*cobra.Command, []string) error { | ||
| return func(cmd *cobra.Command, args []string) error { | ||
| _ = viper.BindPFlag(cliflags.EnvironmentFlag, cmd.Flags().Lookup(cliflags.EnvironmentFlag)) | ||
| _ = viper.BindPFlag(cliflags.ProjectFlag, cmd.Flags().Lookup(cliflags.ProjectFlag)) | ||
|
|
@@ -61,6 +68,15 @@ func runGet(client environments.Client) func(*cobra.Command, []string) error { | |
| return err | ||
| } | ||
|
|
||
| analyticsTracker.SendEvent( | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an example event. We're going to come up with a list of events to track and will implement those in another PR. |
||
| viper.GetString(cliflags.AccessTokenFlag), | ||
| viper.GetString(cliflags.BaseURIFlag), | ||
| "environment_get", | ||
| map[string]interface{}{ | ||
| "key": viper.GetString(cliflags.EnvironmentFlag), | ||
| "projectKey": viper.GetString(cliflags.ProjectFlag), | ||
| }) | ||
|
|
||
| fmt.Fprintf(cmd.OutOrStdout(), string(response)+"\n") | ||
|
|
||
| return nil | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,89 @@ | ||
| package analytics | ||
|
|
||
| import ( | ||
| "bytes" | ||
| "encoding/json" | ||
| "fmt" | ||
| "io" | ||
| "net/http" | ||
| "sync" | ||
| ) | ||
|
|
||
| type Tracker interface { | ||
| SendEvent( | ||
| accessToken string, | ||
| baseURI string, | ||
| eventName string, | ||
| properties map[string]interface{}, | ||
| ) | ||
| } | ||
|
|
||
| type Client struct { | ||
| HTTPClient *http.Client | ||
| wg sync.WaitGroup | ||
| } | ||
|
|
||
| // SendEvent makes an async request to track the given event with properties. | ||
| func (c *Client) SendEvent( | ||
| accessToken string, | ||
| baseURI string, | ||
| eventName string, | ||
| properties map[string]interface{}, | ||
| ) { | ||
| input := struct { | ||
| Event string `json:"event"` | ||
| Properties map[string]interface{} `json:"properties"` | ||
| }{ | ||
| Event: eventName, | ||
| Properties: properties, | ||
| } | ||
|
|
||
| c.wg.Add(1) | ||
| body, err := json.Marshal(input) | ||
| if err != nil { //nolint:staticcheck | ||
| // TODO: log error | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We'll probably want to add debugging at some point with a flag to enable it. |
||
| c.wg.Done() | ||
| return | ||
| } | ||
|
|
||
| req, err := http.NewRequest("POST", fmt.Sprintf("%s/api/v2/tracking", baseURI), bytes.NewBuffer(body)) | ||
| if err != nil { //nolint:staticcheck | ||
| // TODO: log error | ||
| c.wg.Done() | ||
| return | ||
| } | ||
|
|
||
| req.Header.Add("Authorization", accessToken) | ||
| req.Header.Add("Content-Type", "application/json") | ||
| req.Header.Add("User-Agent", "launchdarkly-cli/v0.1.1") | ||
| var resp *http.Response | ||
| go func() { | ||
| resp, err = c.HTTPClient.Do(req) | ||
| if err != nil { //nolint:staticcheck | ||
| // TODO: log error | ||
| } | ||
| if resp != nil { | ||
| resp.Body.Close() | ||
| } | ||
|
|
||
| _, err := io.ReadAll(resp.Body) | ||
| if err != nil { //nolint:staticcheck | ||
| // TODO: log error | ||
| } | ||
| c.wg.Done() | ||
| }() | ||
| } | ||
|
|
||
| func (a *Client) Wait() { | ||
| a.wg.Wait() | ||
| } | ||
|
|
||
| type NoopClient struct{} | ||
|
|
||
| func (c *NoopClient) SendEvent( | ||
| accessToken string, | ||
| baseURI string, | ||
| eventName string, | ||
| properties map[string]interface{}, | ||
| ) { | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,12 +1,23 @@ | ||
| package main | ||
|
|
||
| import "ldcli/cmd" | ||
| import ( | ||
| "net/http" | ||
| "time" | ||
|
|
||
| "ldcli/cmd" | ||
| "ldcli/internal/analytics" | ||
| ) | ||
|
|
||
| // main.version is set at build time via ldflags by go releaser https://goreleaser.com/cookbooks/using-main.version/ | ||
| var ( | ||
| version = "dev" | ||
| ) | ||
|
|
||
| func main() { | ||
| cmd.Execute(version) | ||
| httpClient := &http.Client{ | ||
| Timeout: time.Second * 3, | ||
| } | ||
| analyticsClient := &analytics.Client{HTTPClient: httpClient} | ||
| cmd.Execute(analyticsClient, version) | ||
| analyticsClient.Wait() | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is created here so we can call |
||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are removing trailing newlines since my editor does that automatically.