fix(cli): align installer flags and restart health

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
DottaandPaperclip committed 2026-07-22 19:38:47 +00:00
1 parent 5aa6080ca8
commit c18d1d378f
5 files changed
+32 -16

No files matched your search

@@ -3,7 +3,9 @@ import os from "node:os";
import path from "node:path";
import { describe, expect, it, vi } from "vitest";
import { serviceHealthChecks } from "../checks/service-health-check.js";
import { resolveRestartExpectedVersion } from "../commands/service.js";
import type { PaperclipConfig } from "../config/schema.js";
import { packageVersion } from "../version.js";
const config = {
server: { host: "127.0.0.1", port: 3100 },
@@ -38,6 +40,11 @@ function managerFixture(active = true) {
}
describe("service health doctor checks", () => {
it("uses the bare package version when restart health has no prior server version", () => {
expect(resolveRestartExpectedVersion(null)).toBe(packageVersion);
expect(resolveRestartExpectedVersion("1.2.3")).toBe("1.2.3");
});
it("passes for a current, active, healthy service", async () => {
const manager = managerFixture();
const results = await serviceHealthChecks(config, {
+6 -2
View File
@@ -2,7 +2,7 @@ import fs from "node:fs/promises";
import path from "node:path";
import * as p from "@clack/prompts";
import type { Command } from "commander";
import { cliVersion } from "../version.js";
import { packageVersion } from "../version.js";
import { readConfig, resolveConfigPath } from "../config/store.js";
import { resolvePaperclipHomeDir, resolvePaperclipInstanceId } from "../config/home.js";
import { detectServiceManager, type ServiceManager, type ServiceStatus } from "../services/service-manager.js";
@@ -53,6 +53,10 @@ async function waitForHealth(instanceId: string, expectedVersion: string | null,
throw new Error(`Paperclip service did not become healthy${expectedVersion ? ` at version ${expectedVersion}` : ""}: ${last.error ?? `reported ${last.serverVersion ?? "no version"}`}`);
}
export function resolveRestartExpectedVersion(serverVersion: string | null): string {
return serverVersion ?? packageVersion;
}
async function writeHotRestartIntent(status: ServiceStatus, instanceId: string, drainRequired: boolean): Promise<{ requestedAt: string; previousVersion: string }> {
if (!status.pid) throw new Error(`Cannot restart ${status.serviceName}: supervisor did not report a server pid.`);
const health = await probeHealth(instanceId);
@@ -68,7 +72,7 @@ async function writeHotRestartIntent(status: ServiceStatus, instanceId: string,
drainRequired,
requestedByRunId: process.env.PAPERCLIP_RUN_ID?.trim() || null,
}, null, 2)}\n`, "utf8");
return { requestedAt, previousVersion: health.serverVersion ?? cliVersion };
return { requestedAt, previousVersion: resolveRestartExpectedVersion(health.serverVersion) };
}
async function waitForRestartReport(requestedAt: string, timeoutMs = 10_000): Promise<unknown | null> {
+1 -1
View File
@@ -12,7 +12,7 @@ type PackageJson = {
const require = createRequire(import.meta.url);
const pkg = require("../package.json") as PackageJson;
const packageVersion = pkg.version ?? "0.0.0";
export const packageVersion = pkg.version ?? "0.0.0";
export function resolveCliVersion(executablePath = process.argv[1]): string {
try {
+1 -6
View File
@@ -335,12 +335,7 @@ fi
INSTALL_ARGS=(install)
[ "$CANARY" = "1" ] && INSTALL_ARGS+=(--canary)
[ -n "$VERSION" ] && INSTALL_ARGS+=(--version "$VERSION")
[ -n "$REF" ] && INSTALL_ARGS+=(--ref "$REF")
[ -n "$REPO" ] && INSTALL_ARGS+=(--repo "$REPO")
[ "$NO_PROMPT" = "1" ] && INSTALL_ARGS+=(--no-prompt)
[ "$INSTALL_SERVICE" = "1" ] && INSTALL_ARGS+=(--install-service)
[ "$DRY_RUN" = "1" ] && INSTALL_ARGS+=(--dry-run)
[ "$VERBOSE" = "1" ] && INSTALL_ARGS+=(--verbose)
[ "$NO_PROMPT" = "1" ] && INSTALL_ARGS+=(--yes)
log "Delegating to the Paperclip CLI"
print_command npx --yes "$PACKAGE_SPEC" "${INSTALL_ARGS[@]}"
+17 -7
View File
@@ -50,6 +50,16 @@ assert_line() {
}
}
assert_no_line() {
local file="$1"
local unexpected="$2"
if grep -Fx -- "$unexpected" "$file" >/dev/null; then
printf 'Did not expect %q in %s\n' "$unexpected" "$file" >&2
cat "$file" >&2
exit 1
fi
}
echo "==> shellcheck"
run_shellcheck
@@ -57,16 +67,16 @@ echo "==> existing Node"
run_with_node with-node bash /paperclip-scripts/install.sh --no-onboard
assert_line "$RESULTS_DIR/with-node.args" "paperclipai@latest"
assert_line "$RESULTS_DIR/with-node.args" "install"
assert_line "$RESULTS_DIR/with-node.args" "--no-prompt"
assert_line "$RESULTS_DIR/with-node.args" "--yes"
echo "==> --ref master"
run_with_node ref-master bash /paperclip-scripts/install.sh --ref master --no-onboard
assert_line "$RESULTS_DIR/ref-master.args" "--ref"
assert_line "$RESULTS_DIR/ref-master.args" "master"
assert_no_line "$RESULTS_DIR/ref-master.args" "--ref"
assert_no_line "$RESULTS_DIR/ref-master.args" "master"
echo "==> piped --no-prompt"
run_with_node piped bash -c 'cat /paperclip-scripts/install.sh | bash -s -- --no-prompt --no-onboard'
assert_line "$RESULTS_DIR/piped.args" "--no-prompt"
assert_line "$RESULTS_DIR/piped.args" "--yes"
echo "==> environment twins"
docker run --rm \
@@ -83,9 +93,9 @@ docker run --rm \
assert_line "$RESULTS_DIR/env.args" "paperclipai@2026.722.0"
assert_line "$RESULTS_DIR/env.args" "--version"
assert_line "$RESULTS_DIR/env.args" "2026.722.0"
assert_line "$RESULTS_DIR/env.args" "--repo"
assert_line "$RESULTS_DIR/env.args" "example/paperclip"
assert_line "$RESULTS_DIR/env.args" "--install-service"
assert_no_line "$RESULTS_DIR/env.args" "--repo"
assert_no_line "$RESULTS_DIR/env.args" "example/paperclip"
assert_no_line "$RESULTS_DIR/env.args" "--install-service"
echo "==> no Node, apt bootstrap"
docker run --rm \