Skip to content

feat(npm): restart stale tsmd on package upgrade#9

Merged
tashian merged 1 commit into
mainfrom
feat/npm-postinstall-restart
May 5, 2026
Merged

feat(npm): restart stale tsmd on package upgrade#9
tashian merged 1 commit into
mainfrom
feat/npm-postinstall-restart

Conversation

@tashian

@tashian tashian commented May 5, 2026

Copy link
Copy Markdown
Owner

Summary

  • Adds a postinstall script to the npm wrapper that SIGTERMs any running tsmd on darwin so the next tsm command picks up the new binary.
  • Idempotent and side-effect-light: no respawn, no pidfile, no JSON-RPC dependency.
  • Skips silently on non-darwin (e.g. Linux CI installing the wrapper).
  • Handles cross-prefix upgrades (Homebrew → npm) via a permissive owned-pid pass.

Closes #5

Implementation notes

  • Script is refactored into pure-ish functions (resolveTsmdPath, findRunningTsmdPids, stopPids, main) with injectable deps (requireResolve, execFileSync, process.kill) so node:test covers every branch without spawning real processes.
  • if (require.main === module) main() keeps require() side-effect-free for the test harness.
  • EPERM on kill (daemon owned by another user after a stray sudo) downgrades to a warning, never fails the install. ESRCH swallowed silently (race between pgrep and kill). Unknown error codes are warned but still non-fatal.
  • package.json files lists scripts/postinstall.js explicitly so the test file (scripts/postinstall.test.js) is not shipped in the published tarball.
  • npm/wrapper/README.md notes the upgrade behavior and the --ignore-scripts opt-out.
  • RELEASING.md gets a one-liner about the postinstall.

Deferred

  • T6 (CI smoke test step) is deferred. Per repo conventions for this PR I did not add a new GH Actions workflow file; extending ci.yml with a Node test step is a follow-up. The unit tests are runnable today via node --test npm/wrapper/scripts/postinstall.test.js.
  • T7 (real npm install -g . smoke test) is deferred to manual verification by the maintainer, per the task constraints (do not mutate the user's global npm prefix from automation).

Test plan

  • node --test npm/wrapper/scripts/postinstall.test.js passes (16/16)
  • npm pack --dry-run from npm/wrapper/ includes scripts/postinstall.js and excludes the test file
  • Manual on darwin: tsm status (spawn daemon) → cd npm/wrapper && npm install -g .pgrep -fl tsmd empty → tsm status respawns

Adds a postinstall script to the npm wrapper that SIGTERMs any running
tsmd on darwin so the next `tsm` invocation picks up the freshly
installed binary via EnsureRunning. No respawn, no pidfile, no JSON-RPC
dependency.

Two pgrep passes: a path-strict pass against the new tsmd's absolute
path, plus a permissive owned-pid pass (`pgrep -u $USER -f 'tsmd( |$)'`)
to catch cross-prefix upgrades like Homebrew to npm. EPERM is downgraded
to a warning, ESRCH is silent, and any other error keeps the install
succeeding.

Refactored as small functions (resolveTsmdPath, findRunningTsmdPids,
stopPids, main) with injectable dependencies so node:test can cover
every branch without spawning real processes.

Closes #5
@tashian tashian merged commit 0050bb6 into main May 5, 2026
1 check passed
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.

restart tsmd as part of post-install for npm package

1 participant