Repository navigation
feat(cli): Check npm for updates and install them from the CLI and the gateway console - #1246
Conversation
…e gateway console
…, Download then Restart & update
|
@claude review the code |
|
Claude finished @kotevcode's task in 48s —— View job Review of #1246: update checks and updates from the CLI and gateway consoleI read the changed code, mainly the installer script, the root-updater protocol, the gateway hold logic, the console API handler and the watcher/notifier. I did not run the build or tests, and I did not read the console UI ( The design is solid. The request file can only pick a step, never a version. The status directory is root-owned. The release-directory plus atomic symlink swap, the rollback, and the ECONNREFUSED-only retry (so a request is never sent twice) are all well reasoned. Issues worth fixing
Smaller notes
VerdictNothing blocking beyond a real-host smoke test. I'd fix items 1 and 2 and either address or document item 3 before merge. |
# Conflicts: # CHANGELOG.md
…sion and harden the update request
|
@kc-zero-lab could you review this? |
|
@kc-zero-lab |
reviewant
left a comment
There was a problem hiding this comment.
Review requested by @kotevcode (comment).
2 issues should be fixed before merge.
- Adds npm update checks, CLI installation, two-step console updates, desktop integration, and restart-time request buffering.
- Core files read fully: apps/cli/src/gateway/updates.ts, apps/cli/src/gateway/console.ts, apps/cli/src/gateway/console-api/deps.ts, apps/cli/src/gateway/console-api/handlers/index.ts, and apps/cli/src/gateway/console-api/handlers/update.ts. Also inspected updater modules, installer lifecycle, desktop integration, and gateway/buyer shutdown and retry paths. Full-file coverage of the larger core files remains incomplete.
- Checked authorization, update handoff, rollback, cancellation, version compatibility, and changelog coverage. Findings concern unintended installation and loss of the downloaded-release action. No verified decentralization or payment-protocol issue was identified in the inspected changes; this is not a complete funds-safety assessment.
- Validation: installer passes bash syntax checking. Automated tests were not run because checkout dependencies are unavailable.
|
|
||
| /** Asks the root updater for `@antseed/cli@latest`. Writing the file is all it takes. */ | ||
| export function requestRootUpdate(paths: RootUpdaterPaths, requestedBy: string, now = Date.now(), action: RootUpdateAction = 'install'): void { | ||
| writeFileSync(paths.request, `${JSON.stringify({ requestedAt: now, requestedBy, action })}\n`, { mode: 0o644 }) |
There was a problem hiding this comment.
[P2] Publish update requests atomically. writeFileSync creates the watched request path before writing its JSON. The systemd PathExists watcher can therefore start the updater while the file is empty; the updater treats anything without the download marker as install. A Download click can consequently restart the buyer and gateway without the separate restart confirmation. The desktop poller likewise defaults unreadable JSON to installation. Write the complete request to a temporary sibling and rename it onto the watched path, and reject incomplete requests rather than defaulting them to an install.
| /** The downloaded version waiting for Restart & update, if any. */ | ||
| export function readyVersion(update: GatewayUpdate): string | null { | ||
| const progress = update.progress | ||
| return progress?.state === 'ready' && progress.to && progress.to === update.latest && update.available ? progress.to : null |
There was a problem hiding this comment.
[P2] Keep a downloaded release installable when npm publishes a newer release. After downloading version B, if a periodic check discovers version C before the operator restarts, progress.to !== update.latest makes readyVersion() return null. Both console surfaces then replace Restart & update with Download, so the operator cannot install the already-staged B through the intended two-step UI. This contradicts the updater's explicit behavior of installing the staged version even after npm moves on. Derive readiness from a valid ready progress record whose version is newer than the running version, independently of the latest registry answer; display that staged version in the badge and confirmation. Add coverage for a registry change between download and installation.
|
@kotevcode I already reviewed this commit (e602e05): #1246 (review) |
|
Superseded by a newer review: #1246 (comment) (previously reviewed |
…sion installable after npm moves on
|
@kc-zero-lab re-review Both P2s are addressed in f6d7b23:
Tests: CLI 1249/1250 (0 failures, 1 skipped), desktop main 375/375, console 194/194; the updater script in a Linux container 47/47, including empty and half-written requests. |
|
@kc-zero-lab re-review Fixed in 590d288: the root updater now parses the request with the installed Node ( Tests: the parser against those inputs with real Node; the updater script in a Linux container 51/51 (truncated nested object, brace text, unknown action, array, whitespace download); desktop main 375/375. |
|
Superseded by a newer review: #1246 (comment) (previously reviewed |
|
@kc-zero-lab re-review Both P2s are addressed in f0a72ba:
Tests: desktop |
|
Superseded by a newer review: #1246 (comment) (previously reviewed |
|
@kc-zero-lab re-review |
|
Addressed review 4: the gateway supervisor now waits |
|
Superseded by a newer review: #1246 (comment) (previously reviewed |
|
@kc-zero-lab re-review Addressed review 5: Check now on a desktop-hosted gateway writes |
Antseed Review SummaryThis PR adds npm update discovery and an update command to the CLI, plus download and install controls in the gateway console. Installer-managed gateways use a privileged update service with staged releases and rollback, while desktop-hosted gateways communicate with Electron's updater through request and status files. Gateway requests now wait through refused buyer connections, and the desktop Check now action uses a separate check-request file.
Confidence Score: 4/5Safe to merge after preserving the downloaded desktop version as the installation target. The separate desktop check-request path correctly avoids interpreting a check as an install, but checking after a download can make the bridge record the wrong installation target. The full CLI suite passed with 1,250 tests passing and one skipped; the desktop suites passed with 12 script tests, 376 main-process tests, and 502 renderer tests. An initial CLI invocation incorrectly appended source TypeScript test paths and failed module resolution; rerunning the package suite without those arguments passed. Actual systemd upgrades, rollback, and packaged Electron installation were assessed through code inspection rather than end-to-end execution. Files that need attention:
|
| Filename | Overview |
|---|---|
apps/cli/src/cli/commands/update.ts |
Adds explicit update checking and installation through package managers or the installer-managed update service. |
apps/cli/src/update/install-method.ts |
Classifies installation layouts to select an executable update command or operator guidance. |
apps/cli/src/update/root-updater.ts |
Defines file-based update requests, progress parsing, stale-run handling, and a separate desktop check request. |
apps/cli/src/gateway/updates.ts |
Combines npm checks and updater progress, and waits for desktop check results without issuing an install request. |
apps/cli/src/gateway/console-api/handlers/update.ts |
Adds administrator-only update endpoints, action validation, and installation audit records. |
apps/cli/src/gateway/server.ts |
Adds bounded waiting for buyer connection refusals and unavailable spend reporting, with cancellation and shutdown handling. |
apps/cli/src/gateway/buyer-process.ts |
Allows intentional buyer restarts without counting them as rapid startup failures. |
apps/cli/src/proxy/buyer-proxy.ts |
Adds the buyer restart contract used by supervised gateway processes. |
apps/desktop/src/main/public-tunnel/console-updates.ts |
Bridges console requests to the desktop updater; installation target tracking needs the correction described above. |
apps/desktop/src/main/main.ts |
Connects the bridge to updater checks, downloads, errors, and installation of the downloaded artifact. |
apps/gateway-console/src/components/UpdatePanel.tsx |
Adds update status, explicit checks, download controls, and restart confirmation. |
apps/website/static/install-gateway.sh |
Introduces staged CLI releases and a systemd updater with readiness probes and rollback; live upgrade behavior remains unverified. |
P2 Preserve the downloaded version as the installation target
P2 — apps/desktop/src/main/public-tunnel/console-updates.ts:178
At apps/desktop/src/main/public-tunnel/console-updates.ts:178, startRun always takes its target from app.latest, overwriting the previous ready run's target. For example, download version B while running A, then use Check now after C is published: checked(C) updates app.latest while the downloaded artifact remains B. The install callback in apps/desktop/src/main/main.ts:620-622 explicitly installs downloadedVersion B, but the persisted install run now targets C. On relaunch into B, the bridge's startup reconciliation compares B against C and marks the successful update as failed. This also contradicts the console confirmation and audit entry, which select the downloaded version.
Suggested fix
For an install action, preserve the ready run's to version before replacing run; use app.latest only when no downloaded release is being installed. Add a regression test covering download B, check C, install B, and relaunch into B, asserting that the run ends as succeeded.
Diagram
sequenceDiagram
participant Console
participant Gateway
participant Files
participant Desktop
participant Updater
Console->>Gateway: Check now
Gateway->>Files: Write separate check request
Desktop->>Files: Consume check request
Desktop->>Updater: Check for updates
Updater-->>Desktop: Release or error
Desktop->>Files: Write versions and checkedAt
Gateway->>Files: Wait for checkedAt change
Gateway-->>Console: Updated status
Console->>Gateway: Download or install
Gateway->>Files: Write action request
Desktop->>Files: Consume action request
Desktop->>Updater: Download or install
Desktop->>Files: Persist run progress
Core files read in full: apps/cli/src/gateway/buyer-process.ts, apps/cli/src/gateway/console.ts, apps/cli/src/gateway/console-api/handlers/update.ts, apps/cli/src/gateway/server.ts, apps/cli/src/gateway/updates.ts, apps/cli/src/proxy/buyer-proxy.ts
Reviews (6): Last reviewed commit: feat(cli): Check npm for updates and install them from the C (38ae4bde6a) | requested by @kotevcode | Tag @kc-zero-lab with "re-review" to run again
|
Addressed review 6: installing a finished download now targets that downloaded release even when a later check found a newer one, so the restart on it reports success. Test added. |
# Conflicts: # CHANGELOG.md
Summary
Adds update checks and updates to the CLI and the gateway console, the way the desktop app does them: check every 30 minutes, say a new version is out, and install only when someone asks. Nothing auto-installs. Checks are a small npm
dist-tagsrequest, cached in the data dir.CLI
antseed updatedetects how the CLI was installed and runs the matching command (npm install -g,pnpm add -g,yarn global add,bun add -g,volta install). For a root-owned npm prefix, Nix, npx, a project dependency or a source checkout it prints the command instead.--checkonly reports;--jsonprints a versioned report.--json, non-TTY stderr, CI,NO_UPDATE_NOTIFIERandANTSEED_NO_UPDATE_CHECK.ANTSEED_NPM_REGISTRY/npm_config_registryselect a mirror.seller start/buyer startchecks every 30 minutes and logs one line per new version, also under systemd or Docker:Antseed 0.1.195 is available (this seller runs 0.1.193). Run antseed update, then restart the seller.A buyer run by the gateway leaves this to the gateway.Gateway console
GET /update,POST /update/check,POST /updatewith{"action":"download"|"install"}(default install; org admins / admin-scope tokens;409 update_unsupported/up_to_date; only the install is audited, asgateway.update).Gateway installer
antseeduser and can't write/opt/antseed, so an update only creates/var/lib/antseed/update-request. A newantseed-update.pathunit starts a rootantseed-update.servicethat installs@antseed/cli@latest(the request can only pick the step, not a version)."action":"download"stops there (statusready); otherwise it also switches to it and restarts the buyer and gateway. It writes/var/lib/antseed-update/status.json, which the console polls.--uninstallremoves the new units. Existing servers get the updater by re-running the installer once; until then the console says the request wasn't picked up.Docs (commands, install, gateway server, management API) and CHANGELOG are updated.
No-downtime updates
/opt/antseed/releases/<version>next to the running one and swaps/opt/antseed/current(replacing/opt/antseed/cli). It restarts the buyer first, then the gateway, each only after the previous one answers, and rolls both back to the previous version if either does not start. Nothing is restarted when npm's latest is already installed, and a downloaded release is not installed again.502 buyer_unavailable; capped keys wait for the spend feed the same way. A request the buyer never received releases its budget hold at once.lb_try_duration 75s). The gateway and buyer give requests in flight up to a minute to finish on shutdown (TimeoutStopSec=90).Desktop app
ANTSEED_UPDATER_REQUEST/STATUSplusANTSEED_UPDATER_KIND=desktop. The console then shows the app's own version and newest release (product: 'desktop'onGET /update), Download has the app's electron-updater download the release, and Restart & update restarts the app into it; the run is finished (or reported failed) on the next launch. A download started from the app's own banner shows as ready in the console too.Testing
updatePhase, notice visibility).npm test(1236/1237; the one failure isdeposit-watch-hub.test.js, unrelated and passing on rerun in isolation), console typecheck + vitest (192/192), full workspace build.npm/systemctlfor success and failure;antseed updateend to end against a simulated update service; console flow clicked through in mock mode (?update=available|command|current).updatePhase/readyVersion; desktop download → ready → install, banner download, relaunch handling (7/7); updater container run for download → ready → install without re-running npm (34/34). CLI 1244/1245 (0 failures, 1 skipped), console 194/194.