From efd8024430f8ec6d90086688bf6bb259a1b5af4c Mon Sep 17 00:00:00 2001 From: Brendan Allan <14191578+Brendonovich@users.noreply.github.com> Date: Wed, 6 May 2026 12:30:20 +0800 Subject: [PATCH] feat(desktop): add OPENCODE_TEST_ONBOARDING env (#25968) --- packages/desktop/src/main/index.ts | 35 ++++++++++++++++++++++++----- packages/desktop/src/main/server.ts | 2 +- packages/desktop/src/main/store.ts | 8 ++++++- 3 files changed, 38 insertions(+), 7 deletions(-) diff --git a/packages/desktop/src/main/index.ts b/packages/desktop/src/main/index.ts index a1eba8b98d..cbac5aa449 100644 --- a/packages/desktop/src/main/index.ts +++ b/packages/desktop/src/main/index.ts @@ -1,9 +1,9 @@ import { randomUUID } from "node:crypto" import { EventEmitter } from "node:events" -import { existsSync } from "node:fs" +import { existsSync, mkdirSync, rmSync } from "node:fs" import * as http from "node:http" import { createServer } from "node:net" -import { homedir } from "node:os" +import { homedir, tmpdir } from "node:os" import { join } from "node:path" import { getCACertificates, setDefaultCACertificates } from "node:tls" import type { Event } from "electron" @@ -30,10 +30,17 @@ const APP_IDS: Record = { beta: "ai.opencode.desktop.beta", prod: "ai.opencode.desktop", } +const TEST_ONBOARDING = process.env.OPENCODE_TEST_ONBOARDING === "1" const appId = app.isPackaged ? APP_IDS[CHANNEL] : "ai.opencode.desktop.dev" +const onboardingTestRoot = setupOnboardingTestEnv() app.setName(app.isPackaged ? APP_NAMES[CHANNEL] : "OpenCode Dev") app.setAppUserModelId(appId) -app.setPath("userData", join(app.getPath("appData"), appId)) +app.setPath( + "userData", + onboardingTestRoot ? join(onboardingTestRoot, "desktop") : join(app.getPath("appData"), appId), +) +if (onboardingTestRoot) app.setPath("sessionData", join(onboardingTestRoot, "session")) +const logger = initLogging() const { autoUpdater } = pkg import type { InitStep, ServerReadyData, SqliteMigrationProgress, WslConfig } from "../preload/types" @@ -65,13 +72,29 @@ const loadingComplete = defer() const pendingDeepLinks: string[] = [] const serverReady = defer() -const logger = initLogging() useSystemCertificates() +function setupOnboardingTestEnv() { + if (!TEST_ONBOARDING) return + + const root = join(tmpdir(), `opencode-onboarding-${randomUUID()}`) + rmSync(root, { recursive: true, force: true }) + ;["data", "config", "cache", "state", "desktop", "session"].forEach((dir) => + mkdirSync(join(root, dir), { recursive: true }), + ) + process.env.OPENCODE_DB = ":memory:" + process.env.XDG_DATA_HOME = join(root, "data") + process.env.XDG_CONFIG_HOME = join(root, "config") + process.env.XDG_CACHE_HOME = join(root, "cache") + process.env.XDG_STATE_HOME = join(root, "state") + return root +} + logger.log("app starting", { version: app.getVersion(), packaged: app.isPackaged, + onboardingTest: Boolean(onboardingTestRoot), }) setupApp() @@ -118,7 +141,7 @@ function setupApp() { } void app.whenReady().then(async () => { - migrate() + if (!TEST_ONBOARDING) migrate() app.setAsDefaultProtocolClient("opencode") registerRendererProtocol() setDockIcon() @@ -344,6 +367,8 @@ async function getSidecarPort() { } function sqliteFileExists() { + if (process.env.OPENCODE_DB === ":memory:") return true + const xdg = process.env.XDG_DATA_HOME const base = xdg && xdg.length > 0 ? xdg : join(homedir(), ".local", "share") return existsSync(join(base, "opencode", "opencode.db")) diff --git a/packages/desktop/src/main/server.ts b/packages/desktop/src/main/server.ts index fab09eb1b1..4b8cb04943 100644 --- a/packages/desktop/src/main/server.ts +++ b/packages/desktop/src/main/server.ts @@ -70,7 +70,7 @@ function prepareServerEnv(password: string) { OPENCODE_CLIENT: "desktop", OPENCODE_SERVER_USERNAME: "opencode", OPENCODE_SERVER_PASSWORD: password, - XDG_STATE_HOME: app.getPath("userData"), + XDG_STATE_HOME: process.env.XDG_STATE_HOME ?? app.getPath("userData"), } Object.assign(process.env, env) } diff --git a/packages/desktop/src/main/store.ts b/packages/desktop/src/main/store.ts index 7b3bd7c660..a591f878de 100644 --- a/packages/desktop/src/main/store.ts +++ b/packages/desktop/src/main/store.ts @@ -1,4 +1,5 @@ import Store from "electron-store" +import { app } from "electron" import { SETTINGS_STORE } from "./constants" @@ -11,7 +12,12 @@ const cache = new Map() export function getStore(name = SETTINGS_STORE) { const cached = cache.get(name) if (cached) return cached - const next = new Store({ name, fileExtension: "", accessPropertiesByDotNotation: false }) + const next = new Store({ + name, + cwd: app.getPath("userData"), + fileExtension: "", + accessPropertiesByDotNotation: false, + }) cache.set(name, next) return next }