Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
args: build --id devsy-${{ steps.os.outputs.runner_os }} --snapshot
env:
DEVSY_CLI_VERSION: ${{ inputs.tag || github.ref_name }}
DEVSY_POSTHOG_API_KEY: ${{ secrets.DEVSY_POSTHOG_API_KEY }}

- uses: actions/upload-artifact@v7
with:
Expand Down Expand Up @@ -177,6 +178,8 @@ jobs:
- name: build desktop app
working-directory: desktop
run: npx electron-vite build
env:
DEVSY_POSTHOG_API_KEY: ${{ secrets.DEVSY_POSTHOG_API_KEY }}

- name: package and publish with electron-builder (macOS, signed)
if: runner.os == 'macOS'
Expand Down
4 changes: 0 additions & 4 deletions .gitleaksignore
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
# PostHog project tokens are public write-only keys safe to commit.
# See: https://posthog.com/docs/libraries/js#config
pkg/telemetry/analytics/client.go:generic-api-key:9
desktop/src/main/analytics.ts:generic-api-key:7
16 changes: 8 additions & 8 deletions .goreleaser.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,17 @@ builds:
overrides:
- goos: linux
goarch: amd64
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
tags:
- netgo
- osusergo
- goos: linux
goarch: arm64
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
tags:
- netgo
- osusergo
ldflags: -s -w -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
env:
- CGO_ENABLED=0

Expand All @@ -36,7 +36,7 @@ builds:
goos: [linux]
goarch: [amd64, arm64]
binary: devsy-{{ .Os }}-{{ .Arch }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
env:
- CGO_ENABLED=0
tags:
Expand All @@ -50,23 +50,23 @@ builds:
goos: [darwin]
goarch: [amd64, arm64]
binary: devsy-{{ .Os }}-{{ .Arch }}
ldflags: -s -w -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
env:
- CGO_ENABLED=0

- id: devsy-windows
goos: [windows]
goarch: [amd64, arm64]
binary: devsy-{{ .Os }}-{{ .Arch }}
ldflags: -s -w -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
env:
- CGO_ENABLED=0

- id: devsy-dev
goos: [linux, darwin]
goarch: [amd64, arm64]
binary: devsy-{{ .Os }}-{{ .Arch }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
env:
- CGO_ENABLED=0
tags:
Expand All @@ -77,7 +77,7 @@ builds:
goos: [linux]
goarch: [amd64]
binary: devsy-{{ .Os }}-{{ .Arch }}-pro
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }}
ldflags: -s -w -extldflags '-static' -X main.build={{ .Env.DEVSY_CLI_VERSION }} -X main.commit={{ .Commit }} -X main.date={{ .Date }} -X github.com/devsy-org/devsy/pkg/version.version={{ .Env.DEVSY_CLI_VERSION }} -X github.com/devsy-org/devsy/pkg/telemetry/analytics.posthogAPIKey={{ envOrDefault "DEVSY_POSTHOG_API_KEY" "" }}
env:
- CGO_ENABLED=0
tags:
Expand Down
6 changes: 4 additions & 2 deletions cmd/context/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/devsy-org/devsy/pkg/config"
"github.com/devsy-org/devsy/pkg/output"
"github.com/devsy-org/devsy/pkg/table"
"github.com/devsy-org/devsy/pkg/telemetry"
"github.com/spf13/cobra"
)

Expand All @@ -24,8 +25,9 @@ func NewOptionsCmd(flags *flags.GlobalFlags) *cobra.Command {
GlobalFlags: flags,
}
optionsCmd := &cobra.Command{
Use: "get",
Short: "Show options of a context",
Use: "get",
Short: "Show options of a context",
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, args []string) error {
return cmd.Run(cobraCmd.Context(), args)
},
Expand Down
10 changes: 6 additions & 4 deletions cmd/ide/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/devsy-org/devsy/pkg/ide/ideparse"
"github.com/devsy-org/devsy/pkg/output"
"github.com/devsy-org/devsy/pkg/table"
"github.com/devsy-org/devsy/pkg/telemetry"
"github.com/spf13/cobra"
)

Expand All @@ -26,10 +27,11 @@ func NewListCmd(flags *flags.GlobalFlags) *cobra.Command {
GlobalFlags: flags,
}
listCmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List available IDEs",
Args: cobra.NoArgs,
Use: "list",
Aliases: []string{"ls"},
Short: "List available IDEs",
Args: cobra.NoArgs,
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, args []string) error {
return cmd.Run(cobraCmd.Context())
},
Expand Down
8 changes: 5 additions & 3 deletions cmd/pro/check_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/devsy-org/devsy/pkg/config"
"github.com/devsy-org/devsy/pkg/platform"
"github.com/devsy-org/devsy/pkg/provider"
"github.com/devsy-org/devsy/pkg/telemetry"
versionpkg "github.com/devsy-org/devsy/pkg/version"
"github.com/spf13/cobra"
)
Expand All @@ -28,9 +29,10 @@ func NewCheckUpdateCmd(globalFlags *flags.GlobalFlags) *cobra.Command {
GlobalFlags: globalFlags,
}
c := &cobra.Command{
Use: "check-update",
Short: "Check platform provider update",
Hidden: true,
Use: "check-update",
Short: "Check platform provider update",
Hidden: true,
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, args []string) error {
devsyConfig, provider, err := proutil.FindProProvider(
cobraCmd.Context(),
Expand Down
8 changes: 5 additions & 3 deletions cmd/pro/health.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/devsy-org/devsy/pkg/config"
"github.com/devsy-org/devsy/pkg/log"
"github.com/devsy-org/devsy/pkg/provider"
"github.com/devsy-org/devsy/pkg/telemetry"
"github.com/spf13/cobra"
)

Expand All @@ -30,9 +31,10 @@ func NewHealthCmd(globalFlags *flags.GlobalFlags) *cobra.Command {
GlobalFlags: globalFlags,
}
c := &cobra.Command{
Use: "health",
Short: "Check platform health",
Hidden: true,
Use: "health",
Short: "Check platform health",
Hidden: true,
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, args []string) error {
devsyConfig, provider, err := proutil.FindProProvider(
cobraCmd.Context(),
Expand Down
10 changes: 6 additions & 4 deletions cmd/pro/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"github.com/devsy-org/devsy/pkg/output"
"github.com/devsy-org/devsy/pkg/provider"
"github.com/devsy-org/devsy/pkg/table"
"github.com/devsy-org/devsy/pkg/telemetry"
"github.com/devsy-org/devsy/pkg/workspace"
"github.com/spf13/cobra"
)
Expand All @@ -29,10 +30,11 @@ func NewListCmd(flags *proflags.GlobalFlags) *cobra.Command {
GlobalFlags: *flags,
}
listCmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List available Devsy Pro instances",
Args: cobra.NoArgs,
Use: "list",
Aliases: []string{"ls"},
Short: "List available Devsy Pro instances",
Args: cobra.NoArgs,
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, args []string) error {
return cmd.Run(cobraCmd.Context())
},
Expand Down
10 changes: 6 additions & 4 deletions cmd/provider/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
devsyhttp "github.com/devsy-org/devsy/pkg/http"
"github.com/devsy-org/devsy/pkg/output"
"github.com/devsy-org/devsy/pkg/table"
"github.com/devsy-org/devsy/pkg/telemetry"
"github.com/devsy-org/devsy/pkg/types"
"github.com/devsy-org/devsy/pkg/workspace"
"github.com/spf13/cobra"
Expand All @@ -33,10 +34,11 @@ func NewListCmd(flags *flags.GlobalFlags) *cobra.Command {
GlobalFlags: flags,
}
listCmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "List providers",
Args: cobra.NoArgs,
Use: "list",
Aliases: []string{"ls"},
Short: "List providers",
Args: cobra.NoArgs,
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, args []string) error {
return cmd.Run(cobraCmd.Context())
},
Expand Down
29 changes: 26 additions & 3 deletions cmd/root.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cmd

import (
gocontext "context"
"errors"
"fmt"
"os"
Expand Down Expand Up @@ -55,9 +56,27 @@ func isMachineLogFormat(format string) bool {
func Execute() {
rootCmd, globalFlags := BuildRoot()

// Bootstrap pre-Execute so subcommands that override PersistentPreRunE
// without chaining (e.g. pro, agent) still get telemetry.
target := rootCmd
if found, _, findErr := rootCmd.Find(os.Args[1:]); findErr == nil && found != nil {
target = found
}
collector := telemetry.BootstrapCLI(target)
rootCmd.SetContext(telemetry.WithCollector(gocontext.Background(), collector))

err := rootCmd.Execute()
telemetry.CollectorCLI.RecordCLI(err)
telemetry.CollectorCLI.Flush()

// Re-apply opt-out post-Execute for the same PreRunE-bypass case.
if devsyConfig, cfgErr := config.LoadConfig(
globalFlags.Context,
globalFlags.Provider,
); cfgErr == nil {
collector = telemetry.ApplyCLIConfig(devsyConfig, collector)
}

collector.RecordCLI(err)
collector.Flush()
if err != nil {
//nolint:all
if sshExitErr, ok := err.(*ssh.ExitError); ok {
Expand Down Expand Up @@ -129,7 +148,11 @@ func BuildRoot() (*cobra.Command, *flags.GlobalFlags) {

devsyConfig, err := config.LoadConfig(globalFlags.Context, globalFlags.Provider)
if err == nil {
telemetry.StartCLI(devsyConfig, cobraCmd)
current := telemetry.FromContext(cobraCmd.Context())
cobraCmd.SetContext(telemetry.WithCollector(
cobraCmd.Context(),
telemetry.ApplyCLIConfig(devsyConfig, current),
))
}
return nil
}
Expand Down
10 changes: 6 additions & 4 deletions cmd/workspace/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/devsy-org/devsy/pkg/config"
"github.com/devsy-org/devsy/pkg/output"
"github.com/devsy-org/devsy/pkg/table"
"github.com/devsy-org/devsy/pkg/telemetry"
"github.com/devsy-org/devsy/pkg/workspace"
"github.com/spf13/cobra"
)
Expand All @@ -28,10 +29,11 @@ func NewListCmd(flags *flags.GlobalFlags) *cobra.Command {
GlobalFlags: flags,
}
listCmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Short: "Lists existing workspaces",
Args: cobra.NoArgs,
Use: "list",
Aliases: []string{"ls"},
Short: "Lists existing workspaces",
Args: cobra.NoArgs,
Annotations: telemetry.SkipInUIAnnotation(),
RunE: func(cobraCmd *cobra.Command, _ []string) error {
return cmd.Run(cobraCmd.Context())
},
Expand Down
2 changes: 1 addition & 1 deletion cmd/workspace/up/up.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ func (cmd *UpCmd) execute(cobraCmd *cobra.Command, args []string) error {
return fmt.Errorf("extra devcontainer file is only supported with local provider")
}

telemetry.CollectorCLI.SetClient(client)
telemetry.FromContext(cobraCmd.Context()).SetClient(client)
return cmd.Run(ctx, devsyConfig, client, args)
}

Expand Down
6 changes: 6 additions & 0 deletions desktop/electron.vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,15 @@ import { svelte } from "@sveltejs/vite-plugin-svelte"
import tailwindcss from "@tailwindcss/vite"
import { defineConfig, externalizeDepsPlugin } from "electron-vite"

// Empty in local builds, which makes the analytics module no-op.
const posthogApiKeyDefine = {
__DEVSY_POSTHOG_API_KEY__: JSON.stringify(process.env.DEVSY_POSTHOG_API_KEY ?? ""),
}

export default defineConfig({
main: {
plugins: [externalizeDepsPlugin()],
define: posthogApiKeyDefine,
build: {
outDir: "dist/main",
rollupOptions: {
Expand Down
14 changes: 11 additions & 3 deletions desktop/src/main/analytics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,20 @@ import { PostHog } from "posthog-node"
import { app } from "electron"
import { machineIdSync } from "./machine-id.js"

const POSTHOG_API_KEY = "phc_u3TY39zxfrRcyXJoqZ5WRFVTr75gZBHi2AUrfqJ6GCj2"
declare const __DEVSY_POSTHOG_API_KEY__: string | undefined
// `typeof` guard keeps the module loadable under vitest, which doesn't
// apply Vite's `define` replacement at test time.
const DEVSY_POSTHOG_API_KEY =
typeof __DEVSY_POSTHOG_API_KEY__ === "string" ? __DEVSY_POSTHOG_API_KEY__ : ""
const POSTHOG_HOST = "https://us.i.posthog.com"

let client: PostHog | null = null
let distinctId = ""

export function getAnalyticsDistinctId(): string {
return distinctId || getDistinctId()
}

function getDistinctId(): string {
const id = machineIdSync()
const home = homedir()
Expand All @@ -24,13 +32,13 @@ function isTelemetryDisabled(): boolean {

export function initAnalytics(): void {
if (isTelemetryDisabled()) return
if (!POSTHOG_API_KEY || POSTHOG_API_KEY === "phc_PLACEHOLDER") {
if (!DEVSY_POSTHOG_API_KEY) {
console.warn("[telemetry] PostHog API key not configured; analytics disabled")
return
}

distinctId = getDistinctId()
client = new PostHog(POSTHOG_API_KEY, {
client = new PostHog(DEVSY_POSTHOG_API_KEY, {
host: POSTHOG_HOST,
flushAt: 20,
flushInterval: 30_000,
Expand Down
14 changes: 10 additions & 4 deletions desktop/src/main/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { execFile as execFileCb, spawn } from "node:child_process"
import { createInterface } from "node:readline"
import { promisify } from "node:util"
import type { CLIError, CliLogLine } from "../shared/cli-error.js"
import { getAnalyticsDistinctId } from "./analytics.js"

const execFile = promisify(execFileCb)
const MAX_CONCURRENT = 50
Expand Down Expand Up @@ -76,7 +77,13 @@ function parseStderrLine(line: string): CliLogLine | undefined {
* We augment PATH so all spawned CLI processes can find these tools.
*/
function buildEnv(): NodeJS.ProcessEnv {
if (process.platform !== "darwin") return { ...process.env, DEVSY_UI: "true" }
const baseEnv = {
...process.env,
DEVSY_UI: "true",
DEVSY_TELEMETRY_DISTINCT_ID: getAnalyticsDistinctId(),
}

if (process.platform !== "darwin") return baseEnv

const currentPath = process.env.PATH ?? ""
const extraDirs = [
Expand All @@ -85,11 +92,10 @@ function buildEnv(): NodeJS.ProcessEnv {
"/opt/homebrew/sbin",
]
const missing = extraDirs.filter((d) => !currentPath.split(":").includes(d))
if (missing.length === 0) return { ...process.env, DEVSY_UI: "true" }
if (missing.length === 0) return baseEnv

return {
...process.env,
DEVSY_UI: "true",
...baseEnv,
PATH: `${missing.join(":")}:${currentPath}`,
}
}
Expand Down
Loading
Loading