refactor(status): share update channel display + one-liner

This commit is contained in:
Peter Steinberger
2026-02-17 00:29:15 +00:00
parent 1dc9bb8d62
commit ed74f48bd5
4 changed files with 40 additions and 96 deletions

View File

@@ -5,9 +5,8 @@ import {
} from "../../commands/status.update.js"; } from "../../commands/status.update.js";
import { readConfigFileSnapshot } from "../../config/config.js"; import { readConfigFileSnapshot } from "../../config/config.js";
import { import {
formatUpdateChannelLabel,
normalizeUpdateChannel, normalizeUpdateChannel,
resolveEffectiveUpdateChannel, resolveUpdateChannelDisplay,
} from "../../infra/update-channels.js"; } from "../../infra/update-channels.js";
import { checkUpdateStatus } from "../../infra/update-check.js"; import { checkUpdateStatus } from "../../infra/update-check.js";
import { defaultRuntime } from "../../runtime.js"; import { defaultRuntime } from "../../runtime.js";
@@ -52,17 +51,13 @@ export async function updateStatusCommand(opts: UpdateStatusOptions): Promise<vo
includeRegistry: true, includeRegistry: true,
}); });
const channelInfo = resolveEffectiveUpdateChannel({ const channelInfo = resolveUpdateChannelDisplay({
configChannel, configChannel,
installKind: update.installKind, installKind: update.installKind,
git: update.git ? { tag: update.git.tag, branch: update.git.branch } : undefined,
});
const channelLabel = formatUpdateChannelLabel({
channel: channelInfo.channel,
source: channelInfo.source,
gitTag: update.git?.tag ?? null, gitTag: update.git?.tag ?? null,
gitBranch: update.git?.branch ?? null, gitBranch: update.git?.branch ?? null,
}); });
const channelLabel = channelInfo.label;
const gitLabel = const gitLabel =
update.installKind === "git" update.installKind === "git"

View File

@@ -17,16 +17,8 @@ import { inspectPortUsage } from "../infra/ports.js";
import { readRestartSentinel } from "../infra/restart-sentinel.js"; import { readRestartSentinel } from "../infra/restart-sentinel.js";
import { getRemoteSkillEligibility } from "../infra/skills-remote.js"; import { getRemoteSkillEligibility } from "../infra/skills-remote.js";
import { readTailscaleStatusJson } from "../infra/tailscale.js"; import { readTailscaleStatusJson } from "../infra/tailscale.js";
import { import { normalizeUpdateChannel, resolveUpdateChannelDisplay } from "../infra/update-channels.js";
formatUpdateChannelLabel, import { checkUpdateStatus, formatGitInstallLabel } from "../infra/update-check.js";
normalizeUpdateChannel,
resolveEffectiveUpdateChannel,
} from "../infra/update-channels.js";
import {
checkUpdateStatus,
compareSemverStrings,
formatGitInstallLabel,
} from "../infra/update-check.js";
import { runExec } from "../process/exec.js"; import { runExec } from "../process/exec.js";
import type { RuntimeEnv } from "../runtime.js"; import type { RuntimeEnv } from "../runtime.js";
import { VERSION } from "../version.js"; import { VERSION } from "../version.js";
@@ -36,6 +28,7 @@ import { buildChannelsTable } from "./status-all/channels.js";
import { formatDurationPrecise, formatGatewayAuthUsed } from "./status-all/format.js"; import { formatDurationPrecise, formatGatewayAuthUsed } from "./status-all/format.js";
import { pickGatewaySelfPresence } from "./status-all/gateway.js"; import { pickGatewaySelfPresence } from "./status-all/gateway.js";
import { buildStatusAllReportLines } from "./status-all/report-lines.js"; import { buildStatusAllReportLines } from "./status-all/report-lines.js";
import { formatUpdateOneLiner } from "./status.update.js";
export async function statusAllCommand( export async function statusAllCommand(
runtime: RuntimeEnv, runtime: RuntimeEnv,
@@ -98,17 +91,13 @@ export async function statusAllCommand(
includeRegistry: true, includeRegistry: true,
}); });
const configChannel = normalizeUpdateChannel(cfg.update?.channel); const configChannel = normalizeUpdateChannel(cfg.update?.channel);
const channelInfo = resolveEffectiveUpdateChannel({ const channelInfo = resolveUpdateChannelDisplay({
configChannel, configChannel,
installKind: update.installKind, installKind: update.installKind,
git: update.git ? { tag: update.git.tag, branch: update.git.branch } : undefined,
});
const channelLabel = formatUpdateChannelLabel({
channel: channelInfo.channel,
source: channelInfo.source,
gitTag: update.git?.tag ?? null, gitTag: update.git?.tag ?? null,
gitBranch: update.git?.branch ?? null, gitBranch: update.git?.branch ?? null,
}); });
const channelLabel = channelInfo.label;
const gitLabel = formatGitInstallLabel(update); const gitLabel = formatGitInstallLabel(update);
progress.tick(); progress.tick();
@@ -243,65 +232,7 @@ export async function statusAllCommand(
}).httpUrl }).httpUrl
: null; : null;
const updateLine = (() => { const updateLine = formatUpdateOneLiner(update).replace(/^Update:\s*/i, "");
const appendRegistryAndDepsStatus = (parts: string[]) => {
const latest = update.registry?.latestVersion;
if (latest) {
const cmp = compareSemverStrings(VERSION, latest);
if (cmp === 0) {
parts.push(`npm latest ${latest}`);
} else if (cmp != null && cmp < 0) {
parts.push(`npm update ${latest}`);
} else {
parts.push(`npm latest ${latest} (local newer)`);
}
} else if (update.registry?.error) {
parts.push("npm latest unknown");
}
if (update.deps?.status === "ok") {
parts.push("deps ok");
}
if (update.deps?.status === "stale") {
parts.push("deps stale");
}
if (update.deps?.status === "missing") {
parts.push("deps missing");
}
};
if (update.installKind === "git" && update.git) {
const parts: string[] = [];
parts.push(update.git.branch ? `git ${update.git.branch}` : "git");
if (update.git.upstream) {
parts.push(`${update.git.upstream}`);
}
if (update.git.dirty) {
parts.push("dirty");
}
if (update.git.behind != null && update.git.ahead != null) {
if (update.git.behind === 0 && update.git.ahead === 0) {
parts.push("up to date");
} else if (update.git.behind > 0 && update.git.ahead === 0) {
parts.push(`behind ${update.git.behind}`);
} else if (update.git.behind === 0 && update.git.ahead > 0) {
parts.push(`ahead ${update.git.ahead}`);
} else {
parts.push(`diverged (ahead ${update.git.ahead}, behind ${update.git.behind})`);
}
}
if (update.git.fetchOk === false) {
parts.push("fetch failed");
}
appendRegistryAndDepsStatus(parts);
return parts.join(" · ");
}
const parts: string[] = [];
parts.push(update.packageManager !== "unknown" ? update.packageManager : "pkg");
appendRegistryAndDepsStatus(parts);
return parts.join(" · ");
})();
const gatewayTarget = remoteUrlMissing ? `fallback ${connection.url}` : connection.url; const gatewayTarget = remoteUrlMissing ? `fallback ${connection.url}` : connection.url;
const gatewayStatus = gatewayReachable const gatewayStatus = gatewayReachable

View File

@@ -6,11 +6,7 @@ import { info } from "../globals.js";
import { formatTimeAgo } from "../infra/format-time/format-relative.ts"; import { formatTimeAgo } from "../infra/format-time/format-relative.ts";
import type { HeartbeatEventPayload } from "../infra/heartbeat-events.js"; import type { HeartbeatEventPayload } from "../infra/heartbeat-events.js";
import { formatUsageReportLines, loadProviderUsageSummary } from "../infra/provider-usage.js"; import { formatUsageReportLines, loadProviderUsageSummary } from "../infra/provider-usage.js";
import { import { normalizeUpdateChannel, resolveUpdateChannelDisplay } from "../infra/update-channels.js";
formatUpdateChannelLabel,
normalizeUpdateChannel,
resolveEffectiveUpdateChannel,
} from "../infra/update-channels.js";
import { formatGitInstallLabel } from "../infra/update-check.js"; import { formatGitInstallLabel } from "../infra/update-check.js";
import { import {
resolveMemoryCacheSummary, resolveMemoryCacheSummary,
@@ -132,10 +128,11 @@ export async function statusCommand(
: null; : null;
const configChannel = normalizeUpdateChannel(cfg.update?.channel); const configChannel = normalizeUpdateChannel(cfg.update?.channel);
const channelInfo = resolveEffectiveUpdateChannel({ const channelInfo = resolveUpdateChannelDisplay({
configChannel, configChannel,
installKind: update.installKind, installKind: update.installKind,
git: update.git ? { tag: update.git.tag, branch: update.git.branch } : undefined, gitTag: update.git?.tag ?? null,
gitBranch: update.git?.branch ?? null,
}); });
if (opts.json) { if (opts.json) {
@@ -352,12 +349,7 @@ export async function statusCommand(
const updateAvailability = resolveUpdateAvailability(update); const updateAvailability = resolveUpdateAvailability(update);
const updateLine = formatUpdateOneLiner(update).replace(/^Update:\s*/i, ""); const updateLine = formatUpdateOneLiner(update).replace(/^Update:\s*/i, "");
const channelLabel = formatUpdateChannelLabel({ const channelLabel = channelInfo.label;
channel: channelInfo.channel,
source: channelInfo.source,
gitTag: update.git?.tag ?? null,
gitBranch: update.git?.branch ?? null,
});
const gitLabel = formatGitInstallLabel(update); const gitLabel = formatGitInstallLabel(update);
const overviewRows = [ const overviewRows = [

View File

@@ -81,3 +81,29 @@ export function formatUpdateChannelLabel(params: {
} }
return `${params.channel} (default)`; return `${params.channel} (default)`;
} }
export function resolveUpdateChannelDisplay(params: {
configChannel?: UpdateChannel | null;
installKind: "git" | "package" | "unknown";
gitTag?: string | null;
gitBranch?: string | null;
}): { channel: UpdateChannel; source: UpdateChannelSource; label: string } {
const channelInfo = resolveEffectiveUpdateChannel({
configChannel: params.configChannel,
installKind: params.installKind,
git:
params.gitTag || params.gitBranch
? { tag: params.gitTag ?? null, branch: params.gitBranch ?? null }
: undefined,
});
return {
channel: channelInfo.channel,
source: channelInfo.source,
label: formatUpdateChannelLabel({
channel: channelInfo.channel,
source: channelInfo.source,
gitTag: params.gitTag ?? null,
gitBranch: params.gitBranch ?? null,
}),
};
}