@jr2/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +18 -0
- package/bin/jr2.js +38 -0
- package/manifests/operator.yaml +6669 -0
- package/package.json +56 -0
- package/src/build.ts +1551 -0
- package/src/cli.ts +110 -0
- package/src/client.ts +219 -0
- package/src/commands/down.ts +104 -0
- package/src/commands/gc.ts +73 -0
- package/src/commands/init.ts +238 -0
- package/src/commands/kit.ts +141 -0
- package/src/commands/logs.ts +50 -0
- package/src/commands/run.ts +64 -0
- package/src/commands/runs.ts +19 -0
- package/src/commands/send.ts +83 -0
- package/src/commands/status.ts +90 -0
- package/src/commands/up.ts +1402 -0
- package/src/deploy.ts +592 -0
- package/src/env.ts +68 -0
- package/src/index.ts +11 -0
- package/src/instance.ts +105 -0
- package/src/kube.ts +809 -0
- package/src/nodes.ts +74 -0
- package/src/output.ts +211 -0
- package/src/repo-sweep.ts +134 -0
- package/src/run-id.ts +85 -0
- package/src/sse.ts +41 -0
- package/src/sweep.ts +232 -0
- package/src/typecheck.ts +75 -0
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// `jr2 status [runId|abbrev]` (ADR-0009): print a run's status as JSON on stdout, reading through to the
|
|
2
|
+
// store so a completed run still reports its terminal status + final context. A genuinely unknown run → 1.
|
|
3
|
+
//
|
|
4
|
+
// With NO run named, the verb answers about the INSTANCE instead (ADR-0048/0051): whether it has a
|
|
5
|
+
// data plane at all, and every Repo resource's per-node state, so a Repo that will not clone — an
|
|
6
|
+
// unregistered deploy key (ADR-0047), a wrong url, a git host outage — is discoverable by asking
|
|
7
|
+
// the thing that knows, rather than by tailing pod logs. The Orchestrator serves either way; only
|
|
8
|
+
// the Repo is degraded, and the cache agent retries it on its own.
|
|
9
|
+
|
|
10
|
+
import { parseArgs } from "node:util";
|
|
11
|
+
import { JR2Client } from "../client.ts";
|
|
12
|
+
import { resolveTarget, TARGET_ARGS, targetOptions } from "../instance.ts";
|
|
13
|
+
import { activity, result, type Io } from "../output.ts";
|
|
14
|
+
import { resolveRunId } from "../run-id.ts";
|
|
15
|
+
|
|
16
|
+
export async function status(args: string[], io: Io): Promise<number> {
|
|
17
|
+
const { values, positionals } = parseArgs({
|
|
18
|
+
args,
|
|
19
|
+
allowPositionals: true,
|
|
20
|
+
strict: false,
|
|
21
|
+
options: { ...TARGET_ARGS },
|
|
22
|
+
});
|
|
23
|
+
// NO run named, not an EMPTY one: `jr2 status "$RUNID"` with the variable unset asked about a run
|
|
24
|
+
// and got an empty string, and answering that with the instance's repos would report exit 0 on a
|
|
25
|
+
// question nobody asked. An empty positional falls through to the resolver, which says so.
|
|
26
|
+
const given = positionals.length === 0 ? undefined : positionals[0]!;
|
|
27
|
+
const target = await resolveTarget(io, targetOptions(values));
|
|
28
|
+
try {
|
|
29
|
+
const client = new JR2Client(target.url, io.fetch, target.token);
|
|
30
|
+
if (given === undefined) return await instanceStatus(client, io);
|
|
31
|
+
const ref = await resolveRunId(client, given);
|
|
32
|
+
if (!ref.ok) {
|
|
33
|
+
activity(io, ref.message);
|
|
34
|
+
return ref.code;
|
|
35
|
+
}
|
|
36
|
+
const s = await client.read(ref.runId);
|
|
37
|
+
if (!s) {
|
|
38
|
+
activity(io, `no run "${ref.runId}"`);
|
|
39
|
+
return 1;
|
|
40
|
+
}
|
|
41
|
+
result(io, s);
|
|
42
|
+
return 0;
|
|
43
|
+
} finally {
|
|
44
|
+
target.close?.();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The instance's own status: the data-plane switch and every Repo resource, on stdout as one JSON
|
|
50
|
+
* object (extensible — the instance has more to report eventually), and every node whose last
|
|
51
|
+
* attempt on a Repo FAILED spelled out on stderr with git's own error, since that is the line a
|
|
52
|
+
* human acts on. An instance with no data plane says so — "no registered Machine composes a
|
|
53
|
+
* Sandbox" is the answer, not an empty list.
|
|
54
|
+
*
|
|
55
|
+
* Two failures, two consequences (ADR-0004/0051): a cache that is ABSENT on the node (a cold clone
|
|
56
|
+
* failed) parks every Workspace that needs it there; a cache that is PRESENT but whose last fetch
|
|
57
|
+
* failed is STALE, and an attach proceeds on the objects it holds. Each node line names which, and
|
|
58
|
+
* the hint states the consequence for the cases actually seen — not the cold-node rule for both.
|
|
59
|
+
*
|
|
60
|
+
* Exit 0 even with Repos failing: this is a report, and a degraded Repo is a state the instance
|
|
61
|
+
* is serving in, not a failure of the asking.
|
|
62
|
+
*/
|
|
63
|
+
async function instanceStatus(client: JR2Client, io: Io): Promise<number> {
|
|
64
|
+
const { dataPlane, repos } = await client.repos();
|
|
65
|
+
if (!dataPlane) activity(io, "this instance has no data plane (no registered Machine composes a Sandbox)");
|
|
66
|
+
let absent = 0;
|
|
67
|
+
let stale = 0;
|
|
68
|
+
for (const repo of repos) {
|
|
69
|
+
for (const node of repo.nodes) {
|
|
70
|
+
if (node.synced || node.lastError === undefined) continue;
|
|
71
|
+
if (node.present) stale++;
|
|
72
|
+
else absent++;
|
|
73
|
+
activity(
|
|
74
|
+
io,
|
|
75
|
+
`repo ${repo.key} (${repo.url}) on node ${node.node}: ${node.present ? "stale" : "absent"} — ${node.lastError}`,
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
if (absent || stale) {
|
|
80
|
+
activity(
|
|
81
|
+
io,
|
|
82
|
+
"the cache agent keeps retrying these — register the deploy key with your git host, or fix the url or the " +
|
|
83
|
+
"git.credentials entry, and the next attempt lands (ADR-0047/0048/0051).",
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
if (absent) activity(io, "absent: Workspaces needing that cache on that node wait until it lands.");
|
|
87
|
+
if (stale) activity(io, "stale: attaches proceed on what the cache holds until the next fetch lands.");
|
|
88
|
+
result(io, { dataPlane, repos });
|
|
89
|
+
return 0;
|
|
90
|
+
}
|