Skip to content

fix: make update check non-blocking by spawning detached child process#246

Draft
bukinoshita wants to merge 3 commits intomainfrom
fix/update-check-non-blocking-e9aa
Draft

fix: make update check non-blocking by spawning detached child process#246
bukinoshita wants to merge 3 commits intomainfrom
fix/update-check-non-blocking-e9aa

Conversation

@bukinoshita
Copy link
Copy Markdown
Member

@bukinoshita bukinoshita commented Apr 9, 2026

Summary by cubic

Make the CLI update check non‑blocking by moving the network fetch to a detached background process. Commands now exit immediately even on slow/offline networks, addressing BU-642.

  • Bug Fixes
    • checkForUpdates() is now synchronous; uses cached state, shows a stale notice if it indicates a newer version, and spawns a background refresh when the cache is stale/missing. Respects --json/--quiet to skip the notice.
    • Introduced spawnBackgroundRefresh() to run node -e detached with stdio: 'ignore' and .unref(); spawn failures are ignored so the main process always exits.
    • buildRefreshScript() fetches the latest GitHub release and writes update-state.json, writing the current version on any failure or invalid response to avoid repeated retries.
    • Improved resolveNodePath() to prefer process.execPath, fall back to argv[0], and handle standalone binary installs across platforms.
    • src/cli.ts: call checkForUpdates() inside a try/catch so the update check is non‑critical.
    • Tests: mock node:child_process spawn; add coverage for background refresh, resolveNodePath, JSON skip behavior, spawn failure handling, and stale notice behavior.

Written for commit 6831172. Summary will update on new commits.

cursoragent and others added 2 commits April 9, 2026 17:56
When the update-state cache is stale or missing, the CLI now spawns a
detached child process to refresh the cache in the background instead of
awaiting a fetch() in the main process. This prevents commands from
appearing to hang for up to 5 seconds on slow or offline networks.

Key changes:
- checkForUpdates() is now synchronous; it reads cached state, shows
  any stale notice, and kicks off a detached node process to refresh
- buildRefreshScript() generates a self-contained Node script that
  fetches the latest version and writes update-state.json, writing
  the current version as fallback on any failure (prevents repeated
  retries on every command)
- spawnBackgroundRefresh() spawns the script detached with stdio
  ignored and unrefs the child so the main process exits immediately
- All functions converted to const arrow functions per coding standards
- Removed JSDoc comments per coding standards

Resolves BU-642

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
@bukinoshita
Copy link
Copy Markdown
Member Author

@cubic-dev-ai can you review?

@cubic-dev-ai
Copy link
Copy Markdown
Contributor

cubic-dev-ai bot commented Apr 9, 2026

@cubic-dev-ai can you review?

@bukinoshita I have started the AI code review. It will take a few minutes to complete.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 3 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="src/lib/update-check.ts">

<violation number="1" location="src/lib/update-check.ts:30">
P2: Falling back to `'node'` disables background update refresh for standalone binary installs that do not have Node in PATH.</violation>
</file>

<file name="src/cli.ts">

<violation number="1" location="src/cli.ts:189">
P2: Wrap `checkForUpdates()` in a local guard; it can still throw on malformed cached state and currently bubbles into the global error handler.</violation>
</file>

Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review, or fix all with cubic.

Comment thread src/lib/update-check.ts Outdated
Comment thread src/cli.ts Outdated
@bukinoshita
Copy link
Copy Markdown
Member Author

@cursor fix conflicts

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 13, 2026

Resolved all merge conflicts with main and addressed both cubic review items:

  • Conflicts resolved across src/cli.ts, src/lib/update-check.ts, and tests/lib/update-check.test.ts — integrated the upstream UpdateCheckOptions / json skip option, new commands (automations, events, listCommands), and dependency updates with our non-blocking update check implementation.
  • Cubic review fix 1: Wrapped checkForUpdates() in a try/catch in cli.ts so malformed cached state can't bubble into the global error handler.
  • Cubic review fix 2: Improved resolveNodePath() to check process.argv[0] as a fallback, and ultimately fall back to process.execPath (instead of bare 'node') for standalone binary installs where Node may not be in PATH.
  • All 795 tests pass, TypeScript typechecks, and Biome lint is clean.
Open in Web Open in Cursor 

Integrate upstream changes from main (new commands, json skip option,
dependency updates) with the non-blocking update check implementation.

- Merge UpdateCheckOptions type and json skip into synchronous checkForUpdates
- Wrap checkForUpdates() call in try/catch in cli.ts per review feedback
- Improve resolveNodePath() to check argv[0] and fall back to execPath
  for standalone binary installs without node in PATH
- Include new commands: automations, events, listCommands
- Rewrite json-option tests for synchronous checkForUpdates

Co-authored-by: Bu Kinoshita <bukinoshita@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants