fix(install): isolate installer telemetry failures
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { afterEach, describe, expect, it, mock, spyOn } from "bun:test"
|
||||
import * as configManager from "./config-manager"
|
||||
import type { InstallArgs } from "./types"
|
||||
|
||||
describe("runCliInstaller telemetry isolation", () => {
|
||||
afterEach(() => {
|
||||
mock.restore()
|
||||
})
|
||||
|
||||
it("does not crash CLI install when telemetry shutdown throws", async () => {
|
||||
// given
|
||||
const restoreSpies = [
|
||||
spyOn(configManager, "detectCurrentConfig").mockReturnValue({
|
||||
isInstalled: false,
|
||||
installedVersion: null,
|
||||
hasClaude: false,
|
||||
isMax20: false,
|
||||
hasOpenAI: false,
|
||||
hasGemini: false,
|
||||
hasCopilot: false,
|
||||
hasOpencodeZen: false,
|
||||
hasZaiCodingPlan: false,
|
||||
hasKimiForCoding: false,
|
||||
hasOpencodeGo: false,
|
||||
}),
|
||||
spyOn(configManager, "isOpenCodeInstalled").mockResolvedValue(true),
|
||||
spyOn(configManager, "getOpenCodeVersion").mockResolvedValue("1.4.0"),
|
||||
spyOn(configManager, "addPluginToOpenCodeConfig").mockResolvedValue({
|
||||
success: true,
|
||||
configPath: "/tmp/opencode.jsonc",
|
||||
}),
|
||||
spyOn(configManager, "writeOmoConfig").mockReturnValue({
|
||||
success: true,
|
||||
configPath: "/tmp/oh-my-opencode.jsonc",
|
||||
}),
|
||||
]
|
||||
|
||||
mock.module("../shared/posthog", () => ({
|
||||
createCliPostHog: mock(() => ({
|
||||
trackActive: mock(() => {}),
|
||||
capture: mock(() => {}),
|
||||
captureException: mock(() => {}),
|
||||
shutdown: mock(async () => {
|
||||
throw new Error("shutdown failed")
|
||||
}),
|
||||
})),
|
||||
getPostHogDistinctId: mock(() => "install-distinct-id"),
|
||||
}))
|
||||
|
||||
const { runCliInstaller } = await import(`./cli-installer?telemetry=${Date.now()}-${Math.random()}`)
|
||||
const args: InstallArgs = {
|
||||
tui: false,
|
||||
claude: "no",
|
||||
openai: "yes",
|
||||
gemini: "no",
|
||||
copilot: "yes",
|
||||
opencodeZen: "no",
|
||||
zaiCodingPlan: "no",
|
||||
kimiForCoding: "no",
|
||||
opencodeGo: "no",
|
||||
}
|
||||
|
||||
// when
|
||||
const result = await runCliInstaller(args, "3.4.0")
|
||||
|
||||
// then
|
||||
expect(result).toBe(0)
|
||||
|
||||
for (const spy of restoreSpies) {
|
||||
spy.mockRestore()
|
||||
}
|
||||
})
|
||||
})
|
||||
+52
-20
@@ -65,8 +65,16 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
const unsupportedVersionMessage = getUnsupportedOpenCodeVersionMessage(openCodeVersion)
|
||||
if (unsupportedVersionMessage) {
|
||||
printWarning(unsupportedVersionMessage)
|
||||
posthog.capture({ distinctId, event: "install_failed", properties: { command: "install", reason: "unsupported_opencode_version", is_update: isUpdate } })
|
||||
await posthog.shutdown()
|
||||
try {
|
||||
posthog.capture({ distinctId, event: "install_failed", properties: { command: "install", reason: "unsupported_opencode_version", is_update: isUpdate } })
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
try {
|
||||
await posthog.shutdown()
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
return 1
|
||||
}
|
||||
}
|
||||
@@ -82,8 +90,16 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
const pluginResult = await addPluginToOpenCodeConfig(version)
|
||||
if (!pluginResult.success) {
|
||||
printError(`Failed: ${pluginResult.error}`)
|
||||
posthog.capture({ distinctId, event: "install_failed", properties: { command: "install", reason: "plugin_config_write_failed", is_update: isUpdate } })
|
||||
await posthog.shutdown()
|
||||
try {
|
||||
posthog.capture({ distinctId, event: "install_failed", properties: { command: "install", reason: "plugin_config_write_failed", is_update: isUpdate } })
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
try {
|
||||
await posthog.shutdown()
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
return 1
|
||||
}
|
||||
printSuccess(
|
||||
@@ -94,8 +110,16 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
const omoResult = writeOmoConfig(config)
|
||||
if (!omoResult.success) {
|
||||
printError(`Failed: ${omoResult.error}`)
|
||||
posthog.capture({ distinctId, event: "install_failed", properties: { command: "install", reason: "omo_config_write_failed", is_update: isUpdate } })
|
||||
await posthog.shutdown()
|
||||
try {
|
||||
posthog.capture({ distinctId, event: "install_failed", properties: { command: "install", reason: "omo_config_write_failed", is_update: isUpdate } })
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
try {
|
||||
await posthog.shutdown()
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
return 1
|
||||
}
|
||||
printSuccess(`Config written ${SYMBOLS.arrow} ${color.dim(omoResult.configPath)}`)
|
||||
@@ -144,20 +168,28 @@ export async function runCliInstaller(args: InstallArgs, version: string): Promi
|
||||
console.log(color.dim("oMoMoMoMo... Enjoy!"))
|
||||
console.log()
|
||||
|
||||
posthog.capture({
|
||||
distinctId,
|
||||
event: "install_completed",
|
||||
properties: {
|
||||
command: "install",
|
||||
is_update: isUpdate,
|
||||
has_claude: config.hasClaude,
|
||||
has_openai: config.hasOpenAI,
|
||||
has_gemini: config.hasGemini,
|
||||
has_copilot: config.hasCopilot,
|
||||
has_opencode_zen: config.hasOpencodeZen,
|
||||
},
|
||||
})
|
||||
await posthog.shutdown()
|
||||
try {
|
||||
posthog.capture({
|
||||
distinctId,
|
||||
event: "install_completed",
|
||||
properties: {
|
||||
command: "install",
|
||||
is_update: isUpdate,
|
||||
has_claude: config.hasClaude,
|
||||
has_openai: config.hasOpenAI,
|
||||
has_gemini: config.hasGemini,
|
||||
has_copilot: config.hasCopilot,
|
||||
has_opencode_zen: config.hasOpencodeZen,
|
||||
},
|
||||
})
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
try {
|
||||
await posthog.shutdown()
|
||||
} catch {
|
||||
// telemetry failure is non-fatal, silently ignore
|
||||
}
|
||||
|
||||
if ((config.hasClaude || config.hasGemini || config.hasCopilot) && !args.skipAuth) {
|
||||
printBox(
|
||||
|
||||
Reference in New Issue
Block a user