feat: Add Electron wrapper for desktop app - #1964
Conversation
|
Caution Review failedThe pull request is closed. WalkthroughAdds an Electron desktop app (main, preload, packaging, icons, entitlements, build scripts, README), a Windows-focused GitHub Actions workflow for building and releasing the Electron app, updates CI backend release workflows to embed versioned binary names, .gitignore updates, and a web UI change to show Electron-aware database messaging. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
actor User
participant App as Electron Main
participant Server as Local Server (Go)
participant Probe as Health Probe
participant UI as BrowserWindow
participant Tray as System Tray
participant Pre as Preload (dataDir)
User->>App: Launch app
App->>Server: Spawn binary (PORT, SQLITE_PATH, env, version)
loop probe
App->>Probe: GET /health on localhost:PORT
Probe-->>App: 200 / error
end
alt Server ready
App->>Pre: expose dataDir via preload
App->>Tray: Create tray + menu (Show, Quit)
App->>UI: Create window -> load http://localhost:PORT
else Startup error
App->>User: Show error dialog (logs, save, guidance)
App->>Server: Terminate if running
App-->>User: Exit or keep in tray based on choice
end
sequenceDiagram
autonumber
participant Dev as Tag Push / Manual Dispatch
participant GHA as GitHub Actions
participant Windows as Windows Runner
Dev->>GHA: Trigger workflow (tag/manual)
GHA->>Windows: Checkout, setup Bun/Node/Go
Windows->>Windows: Build web (bun), build Go binary (ldflags VERSION), bump Electron version, npm install, build Windows package
Windows-->>GHA: Upload artifacts (windows-build)
GHA->>GHA: Release job downloads artifacts and creates GitHub Release (includes artifacts)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (4)
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 |
There was a problem hiding this comment.
Actionable comments posted: 8
🧹 Nitpick comments (5)
.github/workflows/electron-build.yml (2)
54-60: Consider implementing macOS code signing for production releases.Setting
CSC_IDENTITY_AUTO_DISCOVERY=falseskips code signing, which will trigger Gatekeeper warnings on macOS ("App cannot be opened because it is from an unidentified developer"). For production releases, obtain an Apple Developer ID certificate and configure signing to improve user experience.Store the certificate in GitHub Secrets and enable signing:
env: CSC_LINK: ${{ secrets.MAC_CERT_P12_BASE64 }} CSC_KEY_PASSWORD: ${{ secrets.MAC_CERT_PASSWORD }}
26-29: Upgrade Go version to 1.25.1 in the workflow. This brings GC (“Green Tea”), JSON v2, deterministic testing, runtime and compiler improvements, and enhanced tooling—verify project compatibility.electron/README.md (2)
10-10: Use heading syntax for option labels.Using bold emphasis (
**Option A:**) for section labels reduces document structure clarity. Use heading syntax for better navigation and accessibility.As per static analysis hints.
-**Option A: Use existing binary (without Go installed)** +#### Option A: Use existing binary (without Go installed)Apply the same change to "Option B" on line 16.
16-17: Address the TODO for building from source.The documentation is incomplete for users who want to build the Go binary from source. This is a key workflow for contributors and users without pre-built binaries.
Do you want me to generate the build instructions or open a new issue to track this task?
electron/build.sh (1)
15-39: Improve build script robustness.Consider these improvements for better reliability:
- Validate outputs exist: After building the Go binary, verify the file exists before proceeding to Electron build.
- Use consistent platform detection:
$OSTYPEis shell-dependent and fragile. Consider usingunameor Go's build constraints.- Add cleanup step: Remove old build artifacts before starting to ensure clean builds.
Example validation:
# After building Go binary if [[ ! -f "new-api" ]]; then echo "Error: Go binary build failed" exit 1 fi
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
electron/icon.pngis excluded by!**/*.pngelectron/tray-icon-windows.pngis excluded by!**/*.pngelectron/tray-iconTemplate.pngis excluded by!**/*.pngelectron/tray-iconTemplate@2x.pngis excluded by!**/*.png
📒 Files selected for processing (10)
.github/workflows/electron-build.yml(1 hunks).gitignore(1 hunks)electron/README.md(1 hunks)electron/build.sh(1 hunks)electron/create-tray-icon.js(1 hunks)electron/entitlements.mac.plist(1 hunks)electron/main.js(1 hunks)electron/package.json(1 hunks)electron/preload.js(1 hunks)web/package.json(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
electron/main.js (1)
electron/preload.js (1)
require(1-1)
electron/create-tray-icon.js (1)
electron/main.js (3)
fs(5-5)require(1-1)require(2-2)
🪛 actionlint (1.7.7)
.github/workflows/electron-build.yml
95-95: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
🪛 markdownlint-cli2 (0.18.1)
electron/README.md
10-10: Emphasis used instead of a heading
(MD036, no-emphasis-as-heading)
🔇 Additional comments (5)
.gitignore (1)
14-18: LGTM! Appropriate ignore patterns for Electron artifacts.The additions correctly exclude Electron build outputs, dependencies, and the ESLint cache.
electron/preload.js (1)
1-6: LGTM! Secure preload implementation.The use of
contextBridge.exposeInMainWorldfollows Electron security best practices by providing controlled, minimal access to Electron APIs. The exposed metadata (version and platform) is safe for renderer consumption.electron/create-tray-icon.js (1)
1-60: LGTM! Well-designed tray icon generation with fallback.The script correctly:
- Uses 22×22px for macOS tray icon sizing
- Follows Template naming convention for automatic theme adaptation
- Provides graceful fallback with clear user guidance when the canvas module is unavailable
- Generates multiple icon variants for different use cases
The error handling and fallback approach ensures the build process doesn't break in environments lacking the canvas dependency.
web/package.json (1)
13-13: antd ^5.27.4 is up-to-date and has no known security vulnerabilities.electron/entitlements.mac.plist (1)
5-12: Minimize macOS entitlements and enable hardened runtime.
disable-library-validationandallow-dyld-environment-variablesbypass library signing and allow code injection—remove unless strictly required.- Keep only
allow-jit/allow-unsigned-executable-memoryif V8 JIT is essential.- Enable
hardenedRuntime: trueandgatekeeperAssess: truein your build config to restore macOS protections.Can you confirm which of these entitlements are mandatory for your Electron app’s functionality?
| strategy: | ||
| matrix: | ||
| os: [macos-latest, windows-latest] |
There was a problem hiding this comment.
Add Linux to the build matrix.
The README documents Linux support (.AppImage and .deb), but the workflow only builds for macOS and Windows. Add ubuntu-latest to the matrix to ensure Linux binaries are built and released.
strategy:
matrix:
- os: [macos-latest, windows-latest]
+ os: [macos-latest, windows-latest, ubuntu-latest]You'll also need to add corresponding build and upload steps for Linux artifacts.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| strategy: | |
| matrix: | |
| os: [macos-latest, windows-latest] | |
| strategy: | |
| matrix: | |
| os: [macos-latest, windows-latest, ubuntu-latest] |
🤖 Prompt for AI Agents
.github/workflows/electron-build.yml lines 11-13: the CI matrix currently
targets only macOS and Windows so Linux artifacts are not produced; add
"ubuntu-latest" to the matrix os list and update the workflow to include
Linux-specific build and upload steps: run the electron-builder commands that
produce .AppImage and .deb on ubuntu, ensure any Linux-specific dependencies or
setup (e.g., apt-get install, snapcraft or appimage tooling if used) are
executed in preceding steps, and add artifact upload/publish actions for the
generated .AppImage and .deb files so releases include Linux binaries.
|
|
||
| if [[ "$OSTYPE" == "darwin"* ]]; then | ||
| echo "Building for macOS..." | ||
| CGO_ENABLED=1 go build -ldflags="-s -w" -o new-api |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
❓ Verification inconclusive
Verify CGO is required before enabling it.
Setting CGO_ENABLED=1 increases build complexity, requires C toolchain dependencies, and reduces binary portability. Many Go applications do not require CGO.
If CGO is not required, remove CGO_ENABLED=1 to simplify builds and improve portability.
🏁 Script executed:
#!/bin/bash
# Check if the codebase uses CGO
# Search for CGO-specific imports
rg -n -C2 'import\s+"C"' --type=go
# Search for CGO build tags
rg -n -C2 '//\s*go:build.*cgo' --type=go
# Search for .c, .cpp, .h files (C/C++ sources)
fd -e c -e cpp -e h -e ccLength of output: 0
Remove CGO_ENABLED=1 from electron/build.sh
No CGO imports, build tags, or C/C++ sources detected—omit CGO for simpler, portable builds.
🤖 Prompt for AI Agents
In electron/build.sh around line 17, the go build invocation prefixes the
command with CGO_ENABLED=1 even though there are no CGO imports or C/C++
sources; remove the CGO_ENABLED=1 prefix (or set it to 0) so the build runs
without enabling cgo, leaving the rest of the build flags and output name
unchanged and committing that change.
| const PORT = 3000; | ||
|
|
There was a problem hiding this comment.
Make the embedded server port collision-resistant.
Hard-coding the local API to port 3000 means the desktop app simply refuses to launch whenever that port is already occupied (very common on developer machines). The child process exits, waitForServer never succeeds, and the user only sees the fatal dialog. Please probe for a free port (e.g., via get-port) or honor a configurable PORT override, then update the spawn env and loadURL to use the negotiated value.
🤖 Prompt for AI Agents
In electron/main.js around lines 10-11 the embedded server port is hard-coded to
3000 which causes startup failures when that port is in use; change this to
first check for a user override (process.env.PORT or CLI flag) and if absent
negotiate a free port (use an existing library like get-port or net.createServer
probe) before spawning the child. After obtaining the port, set it into the
child process env and use the negotiated value when building the URL passed to
loadURL and when waitForServer polls; ensure waitForServer uses the same
host:port pair and surface the chosen port in logs/errors.
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
electron/main.js (1)
11-12: Avoid hard-coding port 3000.The app still binds the bundled server to a fixed
3000, so startup fails outright whenever that port is in use—a very common case on developer machines. Please negotiate a free port (e.g., honorprocess.env.PORTor probe withget-port) and propagate the chosen value to the child process, health check, andloadURL.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
.gitignore(1 hunks)electron/main.js(1 hunks)electron/package.json(1 hunks)electron/preload.js(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- electron/package.json
🧰 Additional context used
🧬 Code graph analysis (1)
electron/main.js (1)
electron/preload.js (1)
require(1-1)
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
electron/main.js (1)
11-12: Please negotiate a free backend port before spawning the server.We’re still pinning the embedded API to port 3000, so the app dies whenever anything else is listening there—a very common scenario on dev boxes and even on end-user machines. That’s the same collision issue flagged earlier: the Go binary exits with “address already in use”,
waitForServernever succeeds, and the user gets the fatal dialog.Replace the constant with logic that:
- Honors a user override (
process.env.PORTor CLI flag) when present.- Otherwise probes for an available port (e.g., via
net.createServer()or a helper such asget-port).- Propagates the negotiated value into the child
env, everycheckServerAvailabilitycall, the BrowserWindowloadURL, and any user-facing diagnostics.Without this change the desktop app is still non-functional on machines where 3000 is occupied, so we need to address it before shipping.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
electron/main.js(1 hunks)electron/package.json(1 hunks)electron/preload.js(1 hunks)web/src/components/setup/components/steps/DatabaseStep.jsx(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- electron/package.json
🧰 Additional context used
🧬 Code graph analysis (3)
electron/main.js (1)
electron/preload.js (2)
require(1-1)platform(6-6)
web/src/components/setup/components/steps/DatabaseStep.jsx (1)
web/src/components/setup/SetupWizard.jsx (1)
setupStatus(34-38)
electron/preload.js (1)
electron/main.js (3)
require(1-1)require(2-2)platform(152-152)
🪛 Biome (2.1.2)
electron/preload.js
[error] 13-16: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
…tagging and dependency management
…e for consistency
There was a problem hiding this comment.
Actionable comments posted: 3
♻️ Duplicate comments (1)
.github/workflows/electron-build.yml (1)
117-124: Upgradesoftprops/action-gh-releaseto@v2
softprops/action-gh-release@v1runs on the old Node.js 12 runtime, which GitHub Actions no longer supports. This step will fail, blocking releases. Move to@v2to restore compatibility.- - name: Create Release - uses: softprops/action-gh-release@v1 + - name: Create Release + uses: softprops/action-gh-release@v2
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
electron/package-lock.jsonis excluded by!**/package-lock.json
📒 Files selected for processing (6)
.github/workflows/electron-build.yml(1 hunks).github/workflows/linux-release.yml(1 hunks).github/workflows/macos-release.yml(1 hunks).github/workflows/windows-release.yml(1 hunks).gitignore(1 hunks)electron/preload.js(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- electron/preload.js
- .gitignore
🧰 Additional context used
🪛 actionlint (1.7.7)
.github/workflows/linux-release.yml
52-52: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
.github/workflows/windows-release.yml
47-47: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
.github/workflows/electron-build.yml
117-117: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
.github/workflows/macos-release.yml
45-45: the runner of "softprops/action-gh-release@v1" action is too old to run on GitHub Actions. update the action's version to fix this issue
(action)
feat: Add Electron wrapper for desktop app
Add Electron wrapper for desktop app
Summary by CodeRabbit
New Features
Documentation
Chores