fix(desktop): separate env files by context to prevent renderer crashes#421
fix(desktop): separate env files by context to prevent renderer crashes#421saddlepaddle merged 7 commits intomainfrom
Conversation
|
Warning Rate limit exceeded@saddlepaddle has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 14 minutes and 18 seconds before requesting another review. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. 📒 Files selected for processing (12)
WalkthroughThe desktop app's environment variable handling is reorganized into separate modules for main process, renderer, and shared contexts. PostHog analytics configuration is added to the release workflow, and environment variables are exposed through the Electron build configuration. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20–25 minutes
Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- Remove env.ts imports from shared code (constants.ts, electron-router-dom.ts) that gets bundled into renderer - env.ts uses ...process.env which doesn't work in browser context - Use process.env.NODE_ENV directly which Vite replaces at build time - Add NEXT_PUBLIC_API_URL and NEXT_PUBLIC_WEB_URL to Vite's define block - Re-enable PostHog now that the root cause is fixed The issue was that renderer code imported from shared/constants.ts which imported env.ts. When bundled for the browser, the ...process.env spread in env.ts would fail since process.env doesn't exist in browser context. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add environment: production to build job to access env secrets - Pass NEXT_PUBLIC_POSTHOG_KEY and NEXT_PUBLIC_POSTHOG_HOST to compile step 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Create separate env files for each Electron process: - src/main/env.ts: Main process env with t3-env (runtime process.env) - src/renderer/env.ts: Renderer env with Zod (build-time Vite defines) This makes it clear which env file to use based on where the code runs: - Main process code imports from main/env - Renderer code imports from renderer/env - Shared code should NOT import env (use process.env.NODE_ENV directly) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Renamed files: - src/main/env.ts → src/main/env.main.ts - src/renderer/env.ts → src/renderer/env.renderer.ts Added: - src/shared/env.shared.ts - For shared code that only needs NODE_ENV The naming convention makes it explicit which context each env file is for: - env.main.ts: Main process (t3-env + runtime process.env) - env.renderer.ts: Renderer process (Zod + build-time Vite defines) - env.shared.ts: Shared code (only vars defined in both contexts) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update constants.ts and electron-router-dom.ts to import from env.shared.ts instead of using process.env.NODE_ENV directly. This ensures all env var access goes through one of the three typed env files (env.main.ts, env.renderer.ts, env.shared.ts). 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ce85157 to
1d6043f
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (2)
apps/desktop/src/renderer/env.renderer.ts (2)
10-10: Minor documentation inconsistency in comment.The comment references
src/main/env.tsbut the actual file issrc/main/env.main.ts.🔎 Suggested fix
- * For main process env vars, use src/main/env.ts instead. + * For main process env vars, use src/main/env.main.ts instead.
14-22: Consider usingz.url()for PostHog host validation.The
NEXT_PUBLIC_POSTHOG_HOSTfield usesz.string().default()while the API URLs usez.url().default(). Since the PostHog host is also a URL, consider usingz.url()for consistency and stricter validation.🔎 Proposed refactor
NEXT_PUBLIC_POSTHOG_KEY: z.string().optional(), - NEXT_PUBLIC_POSTHOG_HOST: z.string().default("https://us.i.posthog.com"), + NEXT_PUBLIC_POSTHOG_HOST: z.url().default("https://us.i.posthog.com"), });
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
.github/workflows/release-desktop.yml(2 hunks)apps/desktop/electron.vite.config.ts(1 hunks)apps/desktop/src/lib/electron-app/factories/app/setup.ts(1 hunks)apps/desktop/src/lib/electron-router-dom.ts(1 hunks)apps/desktop/src/main/env.main.ts(2 hunks)apps/desktop/src/main/lib/api-client.ts(1 hunks)apps/desktop/src/main/lib/auth/auth-service.ts(1 hunks)apps/desktop/src/main/lib/auth/deep-link-handler.ts(1 hunks)apps/desktop/src/main/lib/auto-updater.ts(1 hunks)apps/desktop/src/main/lib/sound-paths.ts(1 hunks)apps/desktop/src/main/lib/terminal-history.ts(1 hunks)apps/desktop/src/renderer/env.renderer.ts(1 hunks)apps/desktop/src/shared/constants.ts(2 hunks)apps/desktop/src/shared/env.shared.ts(1 hunks)
🧰 Additional context used
📓 Path-based instructions (6)
apps/desktop/**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (apps/desktop/AGENTS.md)
apps/desktop/**/*.{ts,tsx,js,jsx}: For Electron interprocess communication, ALWAYS use trpc as defined insrc/lib/trpc
Use alias as defined intsconfig.jsonwhen possible
Prefer zustand for state management if it makes sense. Do not use effect unless absolutely necessary.
Files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/shared/env.shared.tsapps/desktop/src/shared/constants.tsapps/desktop/electron.vite.config.tsapps/desktop/src/main/lib/auth/auth-service.tsapps/desktop/src/lib/electron-router-dom.tsapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/lib/electron-app/factories/app/setup.tsapps/desktop/src/main/env.main.ts
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Avoid using any type in TypeScript - maintain type safety unless absolutely necessary
Files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/shared/env.shared.tsapps/desktop/src/shared/constants.tsapps/desktop/electron.vite.config.tsapps/desktop/src/main/lib/auth/auth-service.tsapps/desktop/src/lib/electron-router-dom.tsapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/lib/electron-app/factories/app/setup.tsapps/desktop/src/main/env.main.ts
**/*.{ts,tsx,js,jsx}
📄 CodeRabbit inference engine (AGENTS.md)
Run Biome for formatting, linting, import organization, and safe fixes at the root level using bun run lint:fix
Files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/shared/env.shared.tsapps/desktop/src/shared/constants.tsapps/desktop/electron.vite.config.tsapps/desktop/src/main/lib/auth/auth-service.tsapps/desktop/src/lib/electron-router-dom.tsapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/lib/electron-app/factories/app/setup.tsapps/desktop/src/main/env.main.ts
apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers
Files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/main/lib/auth/auth-service.tsapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/main/env.main.ts
apps/desktop/src/main/**/*.ts
📄 CodeRabbit inference engine (AGENTS.md)
Accept object parameters in IPC handlers - do not use positional parameters in ipcMain.handle()
Files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/main/lib/auth/auth-service.tsapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/main/env.main.ts
apps/desktop/src/renderer/**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)
Files:
apps/desktop/src/renderer/env.renderer.ts
🧠 Learnings (7)
📓 Common learnings
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in src/main/index.ts and electron.vite.config.ts with override: true before other imports
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to apps/desktop/src/main/index.ts : Load environment variables in src/main/index.ts and electron.vite.config.ts with override: true before other imports
Applied to files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/shared/env.shared.tsapps/desktop/src/shared/constants.tsapps/desktop/electron.vite.config.tsapps/desktop/src/main/lib/auth/auth-service.tsapps/desktop/src/lib/electron-router-dom.ts.github/workflows/release-desktop.ymlapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/lib/electron-app/factories/app/setup.tsapps/desktop/src/main/env.main.ts
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to apps/desktop/src/renderer/**/*.{ts,tsx} : Never import Node.js modules in renderer process or shared code - use only in main process (src/main/)
Applied to files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/shared/env.shared.tsapps/desktop/electron.vite.config.tsapps/desktop/src/lib/electron-router-dom.tsapps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/renderer/env.renderer.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/main/lib/auto-updater.tsapps/desktop/src/lib/electron-app/factories/app/setup.tsapps/desktop/src/main/env.main.ts
📚 Learning: 2025-12-18T17:26:38.664Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-18T17:26:38.664Z
Learning: Applies to apps/desktop/**/*.{ts,tsx,js,jsx} : For Electron interprocess communication, ALWAYS use trpc as defined in `src/lib/trpc`
Applied to files:
apps/desktop/src/main/lib/api-client.tsapps/desktop/src/shared/constants.tsapps/desktop/src/lib/electron-router-dom.tsapps/desktop/src/lib/electron-app/factories/app/setup.ts
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to apps/desktop/src/{main,renderer,preload}/**/*.{ts,tsx} : Use type-safe IPC communication - define channel types in apps/desktop/src/shared/ipc-channels.ts before implementing handlers
Applied to files:
apps/desktop/src/shared/env.shared.tsapps/desktop/src/shared/constants.ts
📚 Learning: 2025-12-18T23:19:10.405Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-18T23:19:10.405Z
Learning: Applies to apps/desktop/src/main/**/*.ts : Accept object parameters in IPC handlers - do not use positional parameters in ipcMain.handle()
Applied to files:
apps/desktop/src/main/lib/auth/deep-link-handler.ts
📚 Learning: 2025-12-18T17:26:38.664Z
Learnt from: CR
Repo: superset-sh/superset PR: 0
File: apps/desktop/AGENTS.md:0-0
Timestamp: 2025-12-18T17:26:38.664Z
Learning: Applies to apps/desktop/**/*.{ts,tsx,js,jsx} : Use alias as defined in `tsconfig.json` when possible
Applied to files:
apps/desktop/src/main/lib/auth/deep-link-handler.tsapps/desktop/src/main/lib/terminal-history.tsapps/desktop/src/main/lib/sound-paths.tsapps/desktop/src/lib/electron-app/factories/app/setup.ts
🧬 Code graph analysis (3)
apps/desktop/src/shared/env.shared.ts (2)
apps/desktop/src/main/env.main.ts (1)
env(12-29)apps/desktop/src/renderer/env.renderer.ts (1)
env(43-43)
apps/desktop/src/shared/constants.ts (2)
apps/web/src/env.ts (1)
env(5-44)apps/api/src/env.ts (1)
env(4-23)
apps/desktop/src/renderer/env.renderer.ts (2)
apps/desktop/src/main/env.main.ts (1)
env(12-29)apps/desktop/src/shared/env.shared.ts (1)
env(28-30)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
- GitHub Check: Deploy Docs
- GitHub Check: Build - macOS (arm64)
- GitHub Check: Build
🔇 Additional comments (14)
.github/workflows/release-desktop.yml (1)
21-21: LGTM! PostHog configuration properly injected at build time.The addition of
environment: productionand the PostHog environment variables in the compile step aligns with the PR's objective to prevent renderer crashes by ensuring build-time injection of these values. The host is appropriately hardcoded while the key is sourced from GitHub secrets.Also applies to: 58-61
apps/desktop/src/lib/electron-app/factories/app/setup.ts (1)
9-9: LGTM! Correct import path for main process environment.The updated import path
main/env.mainproperly references the main process environment module and uses the TypeScript path alias as per coding guidelines.apps/desktop/src/lib/electron-router-dom.ts (1)
4-4: LGTM! Appropriate use of shared environment module.The import path correctly references
shared/env.shared, which is suitable for this routing utility that operates in both main and renderer contexts and only accessesNODE_ENV.apps/desktop/src/shared/constants.ts (1)
1-1: LGTM! Correct import path for shared environment.The updated import path
./env.sharedproperly references the new shared environment module within the same directory.apps/desktop/src/renderer/env.renderer.ts (1)
30-43: LGTM! Proper build-time environment variable handling for renderer.The implementation correctly uses individual
process.env.Xandimport.meta.env.Xaccesses (which Vite replaces at build time) rather than spreadingprocess.env. The Zod validation with sensible defaults ensures the renderer receives valid configuration values.apps/desktop/electron.vite.config.ts (1)
109-119: LGTM! API URL environment variables properly exposed for renderer.The addition of
NEXT_PUBLIC_API_URLandNEXT_PUBLIC_WEB_URLto thedefineblock correctly enables build-time injection of these values into the renderer process. The defaults align with those specified insrc/renderer/env.renderer.ts, ensuring consistency across the environment configuration.apps/desktop/src/main/lib/terminal-history.ts (1)
4-4: LGTM! Correct import path for main process environment.The updated import path
../env.mainproperly references the main process environment module. Note that you could also use the alias pathmain/env.mainas per coding guidelines, but the relative path is clear and acceptable.apps/desktop/src/shared/env.shared.ts (1)
1-30: LGTM! Clean separation of shared environment variables.The module correctly isolates NODE_ENV as the only shared environment variable, with clear documentation explaining why spreading
process.envis unsafe in renderer contexts. The Zod v4.1.13 schema with.default()and.enum()correctly applies defaults even within optional fields, aligning with Zod 4's improved behavior.The access to
process.env.NODE_ENVis safe because Vite replaces individual property accesses at build time for the renderer, while the main process reads the actual value at runtime.apps/desktop/src/main/lib/auth/auth-service.ts (1)
5-5: LGTM! Import path correctly updated for main process context.The import path change from
"../../../env"to"../../env.main"properly separates main process environment variables, preventing the renderer crash issue described in the PR objectives.apps/desktop/src/main/lib/api-client.ts (1)
4-4: LGTM! Import path correctly updated.The relative path change properly resolves to the main process environment module.
apps/desktop/src/main/lib/auto-updater.ts (1)
4-4: LGTM! Import path correctly updated.apps/desktop/src/main/lib/auth/deep-link-handler.ts (1)
3-3: LGTM! Import path correctly updated.apps/desktop/src/main/lib/sound-paths.ts (1)
4-4: LGTM! Import path correctly updated.apps/desktop/src/main/env.main.ts (1)
12-29: LGTM! Environment configuration is correct for main process.The t3-env configuration properly uses:
- Zod v4 schemas with appropriate validators (
z.enum(),z.url(),.default())- Runtime
process.envspreading, which is safe in the Node.js main processisServer: trueflag, correctly indicating the trusted Node.js environmentThis approach prevents the renderer crash issue by keeping runtime
process.envaccess isolated to the main process.
🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
| working-directory: apps/desktop | ||
| env: | ||
| NEXT_PUBLIC_POSTHOG_KEY: ${{ secrets.NEXT_PUBLIC_POSTHOG_KEY }} | ||
| NEXT_PUBLIC_POSTHOG_HOST: https://us.i.posthog.com |
There was a problem hiding this comment.
maybe don't hard code this?
There was a problem hiding this comment.
LOOL ur so valid for that - mb i missed that
| import { type BrowserWindow, shell } from "electron"; | ||
| import type { AuthProvider, AuthSession, SignInResult } from "shared/auth"; | ||
| import { env } from "../../../env"; | ||
| import { env } from "../../env.main"; |
There was a problem hiding this comment.
should we just do the alias? main/env.main instead of relative?
| import type { AuthSession } from "shared/auth"; | ||
| import { PROTOCOL_SCHEMES } from "shared/constants"; | ||
| import { env } from "../../../env"; | ||
| import { env } from "../../env.main"; |
There was a problem hiding this comment.
same should we just do the alias? main/env.main instead of relative?
| import { createTRPCClient, httpBatchLink } from "@trpc/client"; | ||
| import superjson from "superjson"; | ||
| import { env } from "../../env"; | ||
| import { env } from "../env.main"; |
There was a problem hiding this comment.
should we just do the alias? main/env.main instead of relative?
| import { autoUpdater } from "electron-updater"; | ||
| import { PLATFORM } from "shared/constants"; | ||
| import { env } from "../../env"; | ||
| import { env } from "../env.main"; |
There was a problem hiding this comment.
should we just do the alias? main/env.main instead of relative?
| import { join } from "node:path"; | ||
| import { app } from "electron"; | ||
| import { env } from "../../env"; | ||
| import { env } from "../env.main"; |
There was a problem hiding this comment.
should we just do the alias? main/env.main instead of relative?
- Use secret for NEXT_PUBLIC_POSTHOG_HOST instead of hardcoding in CI - Use alias imports (main/env.main) instead of relative paths - Wire PostHog to use NEXT_PUBLIC_POSTHOG_HOST env var - Fix doc comments to reference correct env file names 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
9b4e345 to
a1eba49
Compare
Summary
...process.envspread being bundled into renderer codesrc/main/env.main.ts- Main process env vars (can use t3-env with...process.env)src/renderer/env.renderer.ts- Renderer env vars (uses Zod with Vite-injected values)src/shared/env.shared.ts- Shared env vars (only NODE_ENV, works in both contexts)Why this works
Vite can only replace individual
process.env.Xproperty accesses at build time. The spread...process.envrequires an actual object at runtime, which doesn't exist in the browser. By splitting the env files:process.env(Node.js has this)defineblock)env.shared.tswhich only accessesprocess.env.NODE_ENV(replaced by Vite)Test plan
🤖 Generated with Claude Code
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.