diff --git a/Makefile b/Makefile index 7ab6ae7cf..516ecfef9 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ GOLANG_CROSS_VERSION ?= v1.20.2 PACKAGE ?= github.com/pluralsh/plural BASE_LDFLAGS ?= -s -w LDFLAGS ?= $(BASE_LDFLAGS) $\ + -X "$(PACKAGE)/pkg/utils.version=$(APP_VSN)" $\ -X "$(PACKAGE)/cmd/plural.Version=$(APP_VSN)" $\ -X "$(PACKAGE)/cmd/plural.Commit=$(BUILD)" $\ -X "$(PACKAGE)/cmd/plural.Date=$(APP_DATE)" $\ diff --git a/cmd/plural/config_test.go b/cmd/plural/config_test.go index 319db08e9..1a21e62fa 100644 --- a/cmd/plural/config_test.go +++ b/cmd/plural/config_test.go @@ -24,13 +24,13 @@ func TestPluralConfigCommand(t *testing.T) { { name: `test "config read" command when config file doesn't exists'`, args: []string{plural.ApplicationName, "config", "read"}, - expectedResponse: "apiVersion: platform.plural.sh/v1alpha1\nkind: Config\nmetadata: null\nspec:\n email: \"\"\n token: \"\"\n namespacePrefix: \"\"\n endpoint: \"\"\n lockProfile: \"\"\n reportErrors: false\n", + expectedResponse: "apiVersion: platform.plural.sh/v1alpha1\nkind: Config\nmetadata: null\nspec:\n email: \"\"\n id: \"\"\n token: \"\"\n namespacePrefix: \"\"\n endpoint: \"\"\n lockProfile: \"\"\n reportErrors: false\n", }, { name: `test "config read" command with default test config'`, args: []string{plural.ApplicationName, "config", "read"}, createConfig: true, - expectedResponse: "apiVersion: platform.plural.sh/v1alpha1\nkind: Config\nmetadata: null\nspec:\n email: test@plural.sh\n token: abc\n namespacePrefix: test\n endpoint: http://example.com\n lockProfile: abc\n reportErrors: false\n", + expectedResponse: "apiVersion: platform.plural.sh/v1alpha1\nkind: Config\nmetadata: null\nspec:\n email: test@plural.sh\n id: \"\"\n token: abc\n namespacePrefix: test\n endpoint: http://example.com\n lockProfile: abc\n reportErrors: false\n", }, } for _, test := range tests { diff --git a/cmd/plural/deploy.go b/cmd/plural/deploy.go index 2b307377f..e9a7bec42 100644 --- a/cmd/plural/deploy.go +++ b/cmd/plural/deploy.go @@ -217,8 +217,11 @@ func (p *Plural) deploy(c *cli.Context) error { if c.Bool("silence") { continue } - - if man, err := fetchManifest(repo); err == nil && man.Wait { + man, err := fetchManifest(repo) + if err != nil { + return err + } + if man.Wait { if kubeConf, err := kubernetes.KubeConfig(); err == nil { fmt.Printf("Waiting for %s to become ready...\n", repo) if err := application.SilentWait(kubeConf, repo); err != nil { @@ -227,7 +230,25 @@ func (p *Plural) deploy(c *cli.Context) error { fmt.Println("") } } - + for _, ch := range man.Charts { + utils.PosthogCapture(utils.DeployPosthogEvent, utils.PosthogProperties{ + ApplicationName: installation.Repository.Name, + ApplicationID: installation.Id, + PackageType: "helm", + PackageName: ch.Name, + PackageId: ch.Id, + PackageVersion: ch.Version, + }) + } + for _, tf := range man.Terraform { + utils.PosthogCapture(utils.DeployPosthogEvent, utils.PosthogProperties{ + ApplicationName: installation.Repository.Name, + ApplicationID: installation.Id, + PackageType: "terraform", + PackageName: tf.Name, + PackageId: tf.Id, + }) + } if err := scaffold.Notes(installation); err != nil { return err } diff --git a/cmd/plural/init.go b/cmd/plural/init.go index fc7f5820c..cf1161fcd 100644 --- a/cmd/plural/init.go +++ b/cmd/plural/init.go @@ -6,13 +6,14 @@ import ( "path/filepath" "time" + "github.com/pluralsh/plural/pkg/manifest" + "github.com/pkg/browser" "github.com/urfave/cli" "github.com/pluralsh/plural/pkg/api" "github.com/pluralsh/plural/pkg/config" "github.com/pluralsh/plural/pkg/crypto" - "github.com/pluralsh/plural/pkg/manifest" "github.com/pluralsh/plural/pkg/provider" "github.com/pluralsh/plural/pkg/scm" "github.com/pluralsh/plural/pkg/server" @@ -85,6 +86,16 @@ func (p *Plural) handleInit(c *cli.Context) error { return err } + project, err := manifest.FetchProject() + if err != nil { + return err + } + project.Owner.ID = me.Id + project.SendMetrics = affirm("Would you be willing to send installation metrics to Plural? We will store data in an aggregated form to analyze the application's deployment", "PLURAL_INIT_AFFIRM_SEND_METRICS") + if err := project.Write(manifest.ProjectManifestPath()); err != nil { + return err + } + utils.Success("Workspace is properly configured!\n") if gitCreated { utils.Highlight("Be sure to `cd %s` to use your configured git repo\n", repo) @@ -164,6 +175,7 @@ func postLogin(conf *config.Config, client api.Client, c *cli.Context) error { } conf.Email = me.Email + conf.ID = me.Id fmt.Printf("\nlogged in as %s!\n", me.Email) saEmail := c.String("service-account") diff --git a/cmd/plural/validation.go b/cmd/plural/validation.go index c6af905de..3d72056f8 100644 --- a/cmd/plural/validation.go +++ b/cmd/plural/validation.go @@ -81,13 +81,15 @@ func tracked(fn func(*cli.Context) error, event string) func(*cli.Context) error } else { event.Data = fmt.Sprint(err) } + utils.PosthogCapture(utils.ErrorPosthogEvent, utils.PosthogProperties{Error: err}) } - conf := config.Read() if conf.ReportErrors { client := api.FromConfig(&conf) if err := client.CreateEvent(&event); err != nil { - return api.GetErrorResponse(err, "CreateEvent") + err = api.GetErrorResponse(err, "CreateEvent") + utils.PosthogCapture(utils.ErrorPosthogEvent, utils.PosthogProperties{Error: err}) + return err } } return err diff --git a/go.mod b/go.mod index cb11be98b..85f07caaa 100644 --- a/go.mod +++ b/go.mod @@ -47,6 +47,7 @@ require ( github.com/pluralsh/gqlclient v1.3.15 github.com/pluralsh/plural-operator v0.5.3 github.com/pluralsh/polly v0.1.1 + github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a github.com/rodaine/hclencoder v0.0.1 github.com/samber/lo v1.33.0 github.com/thoas/go-funk v0.9.2 @@ -119,6 +120,7 @@ require ( github.com/valyala/fasttemplate v1.2.1 // indirect github.com/vektah/gqlparser/v2 v2.5.1 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect + github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect github.com/zclconf/go-cty v1.10.0 // indirect google.golang.org/genproto v0.0.0-20230216225411-c8e22ba71e44 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect @@ -262,10 +264,10 @@ require ( github.com/xlab/treeprint v1.1.0 // indirect go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect - golang.org/x/net v0.8.0 // indirect + golang.org/x/net v0.7.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/sys v0.6.0 // indirect - golang.org/x/term v0.6.0 + golang.org/x/term v0.5.0 golang.org/x/text v0.8.0 golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect diff --git a/go.sum b/go.sum index 5f162cec3..0126686a3 100644 --- a/go.sum +++ b/go.sum @@ -920,10 +920,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pluralsh/controller-reconcile-helper v0.0.4 h1:1o+7qYSyoeqKFjx+WgQTxDz4Q2VMpzprJIIKShxqG0E= github.com/pluralsh/controller-reconcile-helper v0.0.4/go.mod h1:AfY0gtteD6veBjmB6jiRx/aR4yevEf6K0M13/pGan/s= -github.com/pluralsh/gqlclient v1.3.11 h1:58vSsD4xur9isk4WncN9Q9CRENogSeUPv5sThRmpPQI= -github.com/pluralsh/gqlclient v1.3.11/go.mod h1:z1qHnvPeqIN/a+5OzFs40e6HI6tDxzh1+yJuEpvqGy4= -github.com/pluralsh/gqlclient v1.3.14 h1:MX3odnIfPSYT9PysegKkC31w/Vn8PZhrT/rZXZck/yU= -github.com/pluralsh/gqlclient v1.3.14/go.mod h1:z1qHnvPeqIN/a+5OzFs40e6HI6tDxzh1+yJuEpvqGy4= github.com/pluralsh/gqlclient v1.3.15 h1:QA6VEMDxeG0/e+qXvr7xgorHl45o4/Qg9CwsPyVn2gE= github.com/pluralsh/gqlclient v1.3.15/go.mod h1:z1qHnvPeqIN/a+5OzFs40e6HI6tDxzh1+yJuEpvqGy4= github.com/pluralsh/oauth v0.9.2 h1:tM9hBK4tCnJUeCOgX0ctxBBCS3hiCDPoxkJLODtedmQ= @@ -936,6 +932,8 @@ github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a h1:Ey0XWvrg6u6hyIn1Kd/jCCmL+bMv9El81tvuGBbxZGg= +github.com/posthog/posthog-go v0.0.0-20221221115252-24dfed35d71a/go.mod h1:oa2sAs9tGai3VldabTV0eWejt/O4/OOD7azP8GaikqU= github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= @@ -1075,6 +1073,7 @@ github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljT github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.10 h1:p8Fspmz3iTctJstry1PYS3HVdllxnEzTEsgIgtxTrCk= github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= @@ -1106,6 +1105,8 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk= github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g= +github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -1289,8 +1290,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1421,8 +1422,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210503060354-a79de5458b56/go.mod h1:tfny5GFUkzUvx4ps4ajbZsCe5lw1metzhBm9T3x7oIY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= diff --git a/hack/e2e/setup-plural.sh b/hack/e2e/setup-plural.sh index 61dc654a1..a3b65eee8 100755 --- a/hack/e2e/setup-plural.sh +++ b/hack/e2e/setup-plural.sh @@ -47,8 +47,10 @@ spec: project: "" provider: kind region: us-east-1 + sendmetrics: true owner: email: cli-e2e@pluraldev.sh + id: testcli network: subdomain: clie2e.onplural.sh pluraldns: true @@ -82,6 +84,8 @@ export PLURAL_LOGIN_AFFIRM_CURRENT_USER=true export PLURAL_INIT_AFFIRM_CURRENT_REPO=true export PLURAL_INIT_AFFIRM_BACKUP_KEY=false +export PLURAL_INIT_AFFIRM_SEND_METRICS=true + plural init plural repos reset plural bundle install console console-kind diff --git a/pkg/bundle/configuration_test.go b/pkg/bundle/configuration_test.go index f07c4f2f4..e0bc5c3c4 100644 --- a/pkg/bundle/configuration_test.go +++ b/pkg/bundle/configuration_test.go @@ -113,7 +113,7 @@ func TestConfigureEnvVariables(t *testing.T) { ctx: map[string]interface{}{}, repo: "test", envVars: map[string]string{"PLURAL_TEST_TEST_ITEM": "workspace.yaml"}, - expectedValue: "apiVersion: \"\"\nkind: \"\"\nmetadata: null\nspec:\n cluster: \"\"\n bucket: \"\"\n project: test\n provider: \"\"\n region: \"\"\n owner: null\n network: null\n bucketPrefix: \"\"\n context: {}\n", + expectedValue: "apiVersion: \"\"\nkind: \"\"\nmetadata: null\nspec:\n cluster: \"\"\n bucket: \"\"\n project: test\n provider: \"\"\n region: \"\"\n sendmetrics: false\n owner: null\n network: null\n bucketPrefix: \"\"\n context: {}\n", }, } for _, test := range tests { diff --git a/pkg/bundle/installer.go b/pkg/bundle/installer.go index 42d425c4c..f72cb7605 100644 --- a/pkg/bundle/installer.go +++ b/pkg/bundle/installer.go @@ -74,6 +74,10 @@ func doInstall(client api.Client, recipe *api.Recipe, repo, name string, refresh return err } + posthogProperty := utils.PosthogProperties{ + ApplicationName: repo, + RecipeName: recipe.Name, + } if err := performTests(context, recipe); err != nil { return err } @@ -81,6 +85,7 @@ func doInstall(client api.Client, recipe *api.Recipe, repo, name string, refresh if err := client.InstallRecipe(recipe.Id); err != nil { return fmt.Errorf("Install failed, does your plural user have install permissions? error: %w", api.GetErrorResponse(err, "InstallRecipe")) } + utils.PosthogCapture(utils.InstallPosthogEvent, posthogProperty) if recipe.OidcSettings == nil { return nil diff --git a/pkg/config/config.go b/pkg/config/config.go index 2e96cbeaf..404b9e4e1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -32,6 +32,7 @@ type Metadata struct { type Config struct { Email string `json:"email"` + ID string `yaml:"id" json:"id"` Token string `yaml:"token" json:"token"` NamespacePrefix string `yaml:"namespacePrefix"` Endpoint string `yaml:"endpoint"` diff --git a/pkg/manifest/types.go b/pkg/manifest/types.go index 8bc5443bc..889be0bc7 100644 --- a/pkg/manifest/types.go +++ b/pkg/manifest/types.go @@ -42,6 +42,7 @@ type Manifest struct { type Owner struct { Email string + ID string Endpoint string `yaml:"endpoint,omitempty"` } @@ -56,6 +57,7 @@ type ProjectManifest struct { Project string Provider string Region string + SendMetrics bool Owner *Owner Network *NetworkConfig BucketPrefix string `yaml:"bucketPrefix"` diff --git a/pkg/scaffold/scaffold.go b/pkg/scaffold/scaffold.go index dc4e81300..21d86715e 100644 --- a/pkg/scaffold/scaffold.go +++ b/pkg/scaffold/scaffold.go @@ -5,6 +5,7 @@ import ( "path/filepath" "github.com/pluralsh/plural/pkg/executor" + "github.com/pluralsh/plural/pkg/utils" "github.com/pluralsh/plural/pkg/utils/git" "github.com/pluralsh/plural/pkg/utils/pathing" "github.com/pluralsh/plural/pkg/wkspace" @@ -120,6 +121,17 @@ func (s *Scaffold) Execute(wk *wkspace.Workspace, force bool) error { preflight.Sha = "" } + for _, ch := range wk.Charts { + utils.PosthogCapture(utils.BuildPosthogEvent, utils.PosthogProperties{ + ApplicationName: wk.Installation.Repository.Name, + ApplicationID: wk.Installation.Id, + PackageType: s.Type, + PackageName: ch.Chart.Name, + PackageId: ch.Chart.Id, + PackageVersion: ch.Version.Version, + }) + } + sha, err := preflight.Execute(s.Root, ignore) if err != nil { return err diff --git a/pkg/scaffold/template/lua_test.go b/pkg/scaffold/template/lua_test.go index 3739ff618..bd6063ef4 100644 --- a/pkg/scaffold/template/lua_test.go +++ b/pkg/scaffold/template/lua_test.go @@ -82,6 +82,7 @@ test: metadata: null spec: email: test@plural.sh + id: "" token: abc namespacePrefix: test endpoint: http://example.com @@ -154,6 +155,7 @@ test: metadata: null spec: email: test@plural.sh + id: "" token: abc namespacePrefix: test endpoint: http://example.com diff --git a/pkg/utils/posthog.go b/pkg/utils/posthog.go new file mode 100644 index 000000000..890dcc7f1 --- /dev/null +++ b/pkg/utils/posthog.go @@ -0,0 +1,127 @@ +package utils + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/pluralsh/plural/pkg/utils/pathing" + "github.com/posthog/posthog-go" + "gopkg.in/yaml.v2" +) + +const ( + versionPlaceholder = "dev" +) + +var ( + version = versionPlaceholder +) + +type PosthogEvent string + +const ( + InstallPosthogEvent PosthogEvent = "cli_install" + BuildPosthogEvent PosthogEvent = "cli_build" + DeployPosthogEvent PosthogEvent = "cli_deploy" + ErrorPosthogEvent PosthogEvent = "cli_error" +) + +var posthogClient posthog.Client + +type ProjectInfo struct { + Spec *ProjectInfoSpec +} + +type ProjectInfoSpec struct { + SendMetrics bool + Cluster string + Provider string + Owner *ProjectInfoOwner +} +type ProjectInfoOwner struct { + ID string + Email string +} + +type PosthogProperties struct { + ApplicationName string `json:"applicationName,omitempty"` + ApplicationID string `json:"applicationID,omitempty"` + PackageType string `json:"packageType,omitempty"` + PackageName string `json:"packageName,omitempty"` + PackageId string `json:"packageID,omitempty"` + PackageVersion string `json:"packageVersion,omitempty"` + RecipeName string `json:"recipeName,omitempty"` + Error error `json:"error,omitempty"` +} + +func newPosthogClient() (posthog.Client, error) { + return posthog.NewWithConfig("phc_r0v4jbKz8Rr27mfqgO15AN5BMuuvnU8hCFedd6zpSDy", posthog.Config{ + Endpoint: "https://posthog.plural.sh", + }) +} + +func posthogCapture(posthogClient posthog.Client, event PosthogEvent, property PosthogProperties) error { + if project, err := getProjectInfo(); err == nil && project.Spec != nil && project.Spec.SendMetrics { + var properties map[string]interface{} + inrec, err := json.Marshal(property) + if err != nil { + return err + } + err = json.Unmarshal(inrec, &properties) + if err != nil { + return err + } + properties["clusterName"] = project.Spec.Cluster + properties["provider"] = project.Spec.Provider + properties["cliVersion"] = version + userID := "cli-user" + if project.Spec.Owner != nil { + userID = project.Spec.Owner.ID + if project.Spec.Owner.ID == "" { + userID = project.Spec.Owner.Email + } + } + LogInfo().Printf("send posthog event %v \n", properties) + return posthogClient.Enqueue(posthog.Capture{ + DistinctId: userID, + Event: string(event), + Properties: properties, + }) + } + LogInfo().Println("sending events disabled") + return nil +} + +func PosthogCapture(event PosthogEvent, property PosthogProperties) { + if posthogClient == nil { + var err error + posthogClient, err = newPosthogClient() + if err != nil { + LogError().Printf("Failed to create posthog client %v", err) + return + } + } + if err := posthogCapture(posthogClient, event, property); err != nil { + LogError().Printf("Failed to send posthog event %v", err) + } +} + +func getProjectInfo() (*ProjectInfo, error) { + root, found := ProjectRoot() + if found { + path := pathing.SanitizeFilepath(filepath.Join(root, "workspace.yaml")) + contents, err := os.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("could not find workspace.yaml file") + } + var projectInfo ProjectInfo + err = yaml.Unmarshal(contents, &projectInfo) + if err != nil { + return nil, err + } + return &projectInfo, nil + } + + return nil, fmt.Errorf("you are not in the project directory") +}