Skip to content

Commit 7af9cef

Browse files
bdougiejpmcb
andauthored
✨ feat: Add anonymous PostHog telemetry to mb CLI (#43)
Co-authored-by: John McBride <john@papercompute.com>
1 parent 3b570ea commit 7af9cef

18 files changed

Lines changed: 586 additions & 22 deletions

File tree

.dagger/main.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,10 @@ func (m *Masterblaster) BuildRelease(
9292

9393
// Git commit SHA of build
9494
commit string,
95+
96+
// PostHog telemetry public key
97+
// +optional
98+
postHogPublicKey string,
9599
) *dagger.Directory {
96100
buildtime := time.Now()
97101

@@ -103,6 +107,10 @@ func (m *Masterblaster) BuildRelease(
103107
fmt.Sprintf("-X 'github.com/papercomputeco/masterblaster/pkg/utils.Buildtime=%s'", buildtime),
104108
}
105109

110+
if postHogPublicKey != "" {
111+
ldflags = append(ldflags, fmt.Sprintf("-X 'github.com/papercomputeco/masterblaster/pkg/telemetry.PostHogAPIKey=%s'", postHogPublicKey))
112+
}
113+
106114
dir := m.Build(ctx, strings.Join(ldflags, " "))
107115
return dag.Checksumer().Checksum(dir)
108116
}

.dagger/release.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,12 @@ func (m *Masterblaster) ReleaseLatest(
2929

3030
// Bucket secret access key
3131
secretAccessKey *dagger.Secret,
32+
33+
// PostHog telemetry public key
34+
// +optional
35+
postHogPublicKey string,
3236
) (*dagger.Directory, error) {
33-
artifacts := m.BuildRelease(ctx, version, commit)
37+
artifacts := m.BuildRelease(ctx, version, commit, postHogPublicKey)
3438

3539
uploader := dag.Bucketuploader(endpoint, bucket, accessKeyId, secretAccessKey)
3640
if err := uploader.UploadLatest(ctx, artifacts, version); err != nil {
@@ -59,8 +63,12 @@ func (m *Masterblaster) ReleaseNightly(
5963

6064
// Bucket secret access key
6165
secretAccessKey *dagger.Secret,
66+
67+
// PostHog telemetry public key
68+
// +optional
69+
postHogPublicKey string,
6270
) (*dagger.Directory, error) {
63-
artifacts := m.BuildRelease(ctx, "nightly", commit)
71+
artifacts := m.BuildRelease(ctx, "nightly", commit, postHogPublicKey)
6472

6573
uploader := dag.Bucketuploader(endpoint, bucket, accessKeyId, secretAccessKey)
6674
if err := uploader.UploadNightly(ctx, artifacts); err != nil {

.github/workflows/nightly.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ jobs:
7979
dagger call \
8080
release-nightly \
8181
--commit="${{ github.sha }}" \
82+
--post-hog-public-key="${{ secrets.POSTHOG_API_KEY }}" \
8283
--endpoint=env://BUCKET_ENDPOINT \
8384
--bucket=env://BUCKET_NAME \
8485
--access-key-id=env://BUCKET_ACCESS_KEY_ID \
@@ -114,7 +115,7 @@ jobs:
114115
go-version-file: go.mod
115116

116117
- name: Build and codesign darwin/arm64 binary
117-
run: make apple-build VERSION=nightly COMMIT="${{ github.sha }}"
118+
run: make apple-build VERSION=nightly COMMIT="${{ github.sha }}" POSTHOG_API_KEY="${{ secrets.POSTHOG_API_KEY }}"
118119

119120
- name: Generate checksum
120121
run: shasum -a 256 build/darwin/arm64/mb > build/darwin/arm64/mb.sha256

.github/workflows/release.yaml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ jobs:
2929
release-latest \
3030
--version="${{ github.event.release.tag_name }}" \
3131
--commit="${{ github.sha }}" \
32+
--post-hog-public-key="${{ secrets.POSTHOG_API_KEY }}" \
3233
--endpoint=env://BUCKET_ENDPOINT \
3334
--bucket=env://BUCKET_NAME \
3435
--access-key-id=env://BUCKET_ACCESS_KEY_ID \
@@ -65,7 +66,7 @@ jobs:
6566
go-version-file: go.mod
6667

6768
- name: Build and codesign darwin/arm64 binary
68-
run: make apple-build
69+
run: make apple-build POSTHOG_API_KEY="${{ secrets.POSTHOG_API_KEY }}"
6970

7071
- name: Generate checksum
7172
run: shasum -a 256 build/darwin/arm64/mb > build/darwin/arm64/mb.sha256

cmd/down/down.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"github.com/spf13/cobra"
99

1010
"github.com/papercomputeco/masterblaster/pkg/daemon/client"
11+
"github.com/papercomputeco/masterblaster/pkg/telemetry"
1112
"github.com/papercomputeco/masterblaster/pkg/ui"
1213
)
1314

@@ -35,12 +36,14 @@ func NewDownCmd(configDirFn func() string) *cobra.Command {
3536
Short: downShortDesc,
3637
Long: downLongDesc,
3738
Args: cobra.MaximumNArgs(1),
38-
RunE: func(_ *cobra.Command, args []string) error {
39+
RunE: func(cmd *cobra.Command, args []string) error {
3940
name := ""
4041
if len(args) > 0 {
4142
name = args[0]
4243
}
43-
return runDown(configDirFn(), name, force)
44+
telem := telemetry.FromContext(cmd.Context())
45+
telem.CaptureCommandRun(cmd.CommandPath())
46+
return runDown(configDirFn(), name, force, telem)
4447
},
4548
}
4649

@@ -49,14 +52,18 @@ func NewDownCmd(configDirFn func() string) *cobra.Command {
4952
return cmd
5053
}
5154

52-
func runDown(baseDir, name string, force bool) error {
55+
func runDown(baseDir, name string, force bool, telem *telemetry.PosthogClient) error {
5356
if err := client.EnsureDaemon(baseDir); err != nil {
5457
return err
5558
}
5659

5760
c := client.New(baseDir)
58-
return ui.Step(os.Stderr, "Stopping sandbox...", func() error {
61+
err := ui.Step(os.Stderr, "Stopping sandbox...", func() error {
5962
_, err := c.Down(name, force)
6063
return err
6164
})
65+
66+
telem.CaptureDown(err == nil)
67+
68+
return err
6269
}

cmd/pull/pull.go

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/spf13/cobra"
1010

1111
"github.com/papercomputeco/masterblaster/pkg/mixtapes"
12+
"github.com/papercomputeco/masterblaster/pkg/telemetry"
1213
"github.com/papercomputeco/masterblaster/pkg/ui"
1314
)
1415

@@ -40,14 +41,20 @@ func NewPullCmd(configDirFn func() string) *cobra.Command {
4041
Short: pullShortDesc,
4142
Long: pullLongDesc,
4243
Args: cobra.ExactArgs(1),
43-
RunE: func(_ *cobra.Command, args []string) error {
44-
return runPull(configDirFn(), args[0])
44+
RunE: func(cmd *cobra.Command, args []string) error {
45+
telem := telemetry.FromContext(cmd.Context())
46+
telem.CaptureCommandRun(cmd.CommandPath())
47+
return runPull(configDirFn(), args[0], telem)
4548
},
4649
}
4750
}
4851

49-
func runPull(baseDir, rawRef string) error {
50-
return ui.Step(os.Stderr, fmt.Sprintf("Pulling mixtape %q...", rawRef), func() error {
52+
func runPull(baseDir, rawRef string, telem *telemetry.PosthogClient) error {
53+
err := ui.Step(os.Stderr, fmt.Sprintf("Pulling mixtape %q...", rawRef), func() error {
5154
return mixtapes.Pull(baseDir, rawRef)
5255
})
56+
57+
telem.CapturePull(rawRef, err == nil)
58+
59+
return err
5360
}

cmd/ssh/ssh.go

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
"github.com/papercomputeco/masterblaster/pkg/daemon/client"
1111
"github.com/papercomputeco/masterblaster/pkg/ssh"
12+
"github.com/papercomputeco/masterblaster/pkg/telemetry"
1213
"github.com/papercomputeco/masterblaster/pkg/ui"
1314
)
1415

@@ -35,12 +36,14 @@ func NewSSHCmd(configDirFn func() string, verboseFn func() bool) *cobra.Command
3536
Short: sshShortDesc,
3637
Long: sshLongDesc,
3738
Args: cobra.MaximumNArgs(1),
38-
RunE: func(_ *cobra.Command, args []string) error {
39+
RunE: func(cmd *cobra.Command, args []string) error {
3940
name := ""
4041
if len(args) > 0 {
4142
name = args[0]
4243
}
43-
return runSSH(configDirFn(), name, user, verboseFn())
44+
telem := telemetry.FromContext(cmd.Context())
45+
telem.CaptureCommandRun(cmd.CommandPath())
46+
return runSSH(configDirFn(), name, user, verboseFn(), telem)
4447
},
4548
}
4649

@@ -49,7 +52,7 @@ func NewSSHCmd(configDirFn func() string, verboseFn func() bool) *cobra.Command
4952
return cmd
5053
}
5154

52-
func runSSH(baseDir, name, user string, verbose bool) error {
55+
func runSSH(baseDir, name, user string, verbose bool, telem *telemetry.PosthogClient) error {
5356
if err := client.EnsureDaemon(baseDir); err != nil {
5457
return err
5558
}
@@ -73,5 +76,10 @@ func runSSH(baseDir, name, user string, verbose bool) error {
7376
ui.Info("Connecting to %s@127.0.0.1:%d", user, sb.SSHPort)
7477
}
7578

79+
telem.CaptureSSH()
80+
// ExecSSH replaces the process via syscall.Exec, so PersistentPostRunE
81+
// never runs. Flush telemetry now to ensure events reach PostHog.
82+
telem.Done()
83+
7684
return ssh.ExecSSH(user, "127.0.0.1", sb.SSHPort, sb.SSHKeyPath)
7785
}

cmd/up/up.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212

1313
"github.com/papercomputeco/masterblaster/pkg/daemon"
1414
"github.com/papercomputeco/masterblaster/pkg/daemon/client"
15+
"github.com/papercomputeco/masterblaster/pkg/telemetry"
1516
"github.com/papercomputeco/masterblaster/pkg/ui"
1617
)
1718

@@ -37,8 +38,10 @@ func NewUpCmd(configDirFn func() string) *cobra.Command {
3738
Short: upShortDesc,
3839
Long: upLongDesc,
3940
Args: cobra.NoArgs,
40-
RunE: func(_ *cobra.Command, _ []string) error {
41-
return runUp(configDirFn(), cfgPath)
41+
RunE: func(cmd *cobra.Command, _ []string) error {
42+
telem := telemetry.FromContext(cmd.Context())
43+
telem.CaptureCommandRun(cmd.CommandPath())
44+
return runUp(configDirFn(), cfgPath, telem)
4245
},
4346
}
4447

@@ -47,7 +50,7 @@ func NewUpCmd(configDirFn func() string) *cobra.Command {
4750
return cmd
4851
}
4952

50-
func runUp(baseDir, cfgPath string) error {
53+
func runUp(baseDir, cfgPath string, telem *telemetry.PosthogClient) error {
5154
// Resolve config path
5255
if cfgPath == "" {
5356
cwd, err := os.Getwd()
@@ -78,9 +81,16 @@ func runUp(baseDir, cfgPath string) error {
7881
resp, stepErr = c.Up("", cfgPath)
7982
return stepErr
8083
}); err != nil {
84+
telem.CaptureUp("", false)
8185
return err
8286
}
8387

88+
mixtapeName := ""
89+
if len(resp.Sandboxes) > 0 {
90+
mixtapeName = resp.Sandboxes[0].Mixtape
91+
}
92+
telem.CaptureUp(mixtapeName, true)
93+
8494
if len(resp.Sandboxes) > 0 {
8595
sb := resp.Sandboxes[0]
8696
fmt.Fprintln(os.Stderr)

go.mod

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@ require (
99
github.com/charmbracelet/lipgloss v1.1.0
1010
github.com/charmbracelet/x/term v0.2.2
1111
github.com/google/go-containerregistry v0.21.0
12+
github.com/google/uuid v1.6.0
1213
github.com/klauspost/compress v1.18.4
1314
github.com/onsi/ginkgo/v2 v2.28.1
1415
github.com/onsi/gomega v1.39.1
16+
github.com/posthog/posthog-go v1.10.0
1517
github.com/spf13/cobra v1.10.2
1618
github.com/spf13/viper v1.21.0
1719
golang.org/x/crypto v0.48.0
@@ -40,8 +42,10 @@ require (
4042
github.com/go-logr/logr v1.4.3 // indirect
4143
github.com/go-task/slim-sprig/v3 v3.0.0 // indirect
4244
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
45+
github.com/goccy/go-json v0.10.5 // indirect
4346
github.com/google/go-cmp v0.7.0 // indirect
4447
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 // indirect
48+
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
4549
github.com/inconshreveable/mousetrap v1.1.0 // indirect
4650
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
4751
github.com/mattn/go-isatty v0.0.20 // indirect

go.sum

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
7878
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
7979
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
8080
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
81+
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
82+
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
8183
github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw=
8284
github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
8385
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
@@ -86,6 +88,10 @@ github.com/google/go-containerregistry v0.21.0 h1:ocqxUOczFwAZQBMNE7kuzfqvDe0VWo
8688
github.com/google/go-containerregistry v0.21.0/go.mod h1:ctO5aCaewH4AK1AumSF5DPW+0+R+d2FmylMJdp5G7p0=
8789
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
8890
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
91+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
92+
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
93+
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
94+
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
8995
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
9096
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
9197
github.com/joshdk/go-junit v1.0.0 h1:S86cUKIdwBHWwA6xCmFlf3RTLfVXYQfvanM5Uh+K6GE=
@@ -132,6 +138,8 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
132138
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
133139
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
134140
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
141+
github.com/posthog/posthog-go v1.10.0 h1:wfoy7Jfb4LigCoHYyMZoiJmmEoCLOkSaYfDxM/NtCqY=
142+
github.com/posthog/posthog-go v1.10.0/go.mod h1:wB3/9Q7d9gGb1P/yf/Wri9VBlbP8oA8z++prRzL5OcY=
135143
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
136144
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
137145
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=

0 commit comments

Comments
 (0)