@devrouter/cli 0.1.2 → 0.1.3
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/dist/devrouter-lifecycle-worker.js +213 -54
- package/dist/devrouter.js +367 -92
- package/package.json +5 -1
- package/upgrade-prompts/0.1.3.md +55 -0
package/dist/devrouter.js
CHANGED
|
@@ -4275,7 +4275,7 @@ function loadRepoConfig(repoPath, read2 = (file) => import_node_fs7.default.read
|
|
|
4275
4275
|
const config = parseConfig(parsed ?? {}, configPath);
|
|
4276
4276
|
const requiredVersion = config.devrouter?.version;
|
|
4277
4277
|
if (requiredVersion && !hasWarnedVersionMismatch) {
|
|
4278
|
-
const cliVersion = true ? "0.1.
|
|
4278
|
+
const cliVersion = true ? "0.1.3" : "0.0.0-dev";
|
|
4279
4279
|
if (cliVersion !== "0.0.0-dev" && compareSemver(requiredVersion, cliVersion) > 0) {
|
|
4280
4280
|
hasWarnedVersionMismatch = true;
|
|
4281
4281
|
process.stderr.write(
|
|
@@ -6273,7 +6273,7 @@ var init_reliability_contract = __esm({
|
|
|
6273
6273
|
|
|
6274
6274
|
// src/core/reliability-operation-store.ts
|
|
6275
6275
|
function installedCliVersion() {
|
|
6276
|
-
return true ? "0.1.
|
|
6276
|
+
return true ? "0.1.3" : "0.0.0-dev";
|
|
6277
6277
|
}
|
|
6278
6278
|
function compareCliVersions(left, right) {
|
|
6279
6279
|
const parts = (value) => value.split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
@@ -6406,6 +6406,7 @@ function validate2(record5, identity2) {
|
|
|
6406
6406
|
"revision",
|
|
6407
6407
|
"state",
|
|
6408
6408
|
"worker",
|
|
6409
|
+
"stopWorkStarted",
|
|
6409
6410
|
"effectSequence",
|
|
6410
6411
|
"outcome",
|
|
6411
6412
|
"result",
|
|
@@ -6587,6 +6588,9 @@ function validate2(record5, identity2) {
|
|
|
6587
6588
|
throw new Error("Reliability worker identity is invalid.");
|
|
6588
6589
|
}
|
|
6589
6590
|
}
|
|
6591
|
+
if (record5.stopWorkStarted !== void 0 && record5.stopWorkStarted !== null) {
|
|
6592
|
+
if (record5.stopWorkStarted !== true) throw new Error("Invalid stop work marker.");
|
|
6593
|
+
}
|
|
6590
6594
|
}
|
|
6591
6595
|
function journalEntryLocation(name) {
|
|
6592
6596
|
const printable = name.replace(/[^A-Za-z0-9._-]/g, "?");
|
|
@@ -9186,9 +9190,11 @@ function listDevsyWorkspaces() {
|
|
|
9186
9190
|
);
|
|
9187
9191
|
if (result.status !== 0) {
|
|
9188
9192
|
const details = [result.error?.message, result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
9189
|
-
|
|
9193
|
+
const failure2 = new Error(
|
|
9190
9194
|
`devsy workspace list failed: ${details || "devsy is not installed or unavailable"}`
|
|
9191
9195
|
);
|
|
9196
|
+
if (result.error) failure2.code = result.error.code;
|
|
9197
|
+
throw failure2;
|
|
9192
9198
|
}
|
|
9193
9199
|
let parsed;
|
|
9194
9200
|
try {
|
|
@@ -10254,6 +10260,9 @@ ${JSON.stringify(effective, null, 2)}
|
|
|
10254
10260
|
contents
|
|
10255
10261
|
};
|
|
10256
10262
|
}
|
|
10263
|
+
function writeManagedDevcontainerConfig(plan) {
|
|
10264
|
+
writeFileAtomically(plan.generatedPath, plan.contents);
|
|
10265
|
+
}
|
|
10257
10266
|
function inspectManagedDevcontainerGeneratedConfig(plan) {
|
|
10258
10267
|
let stat;
|
|
10259
10268
|
try {
|
|
@@ -10422,7 +10431,11 @@ function listDevpodWorkspacesRaw(options = {}) {
|
|
|
10422
10431
|
}
|
|
10423
10432
|
if (result.error || result.status !== 0) {
|
|
10424
10433
|
const details = [result.error?.message, result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
10425
|
-
|
|
10434
|
+
const failure2 = new Error(
|
|
10435
|
+
`devpod list failed: ${details || "devpod is not installed or unavailable"}`
|
|
10436
|
+
);
|
|
10437
|
+
if (result.error) failure2.code = result.error.code;
|
|
10438
|
+
throw failure2;
|
|
10426
10439
|
}
|
|
10427
10440
|
let parsed;
|
|
10428
10441
|
try {
|
|
@@ -10714,25 +10727,23 @@ function writeWorkspaceRuntimeConfig(config) {
|
|
|
10714
10727
|
writeFileAtomically(RUNTIME_CONFIG_FILE, `${JSON.stringify(next, null, 2)}
|
|
10715
10728
|
`);
|
|
10716
10729
|
}
|
|
10730
|
+
function readRegistrySnapshot(runtime, read2, snapshots) {
|
|
10731
|
+
try {
|
|
10732
|
+
return read2();
|
|
10733
|
+
} catch (error) {
|
|
10734
|
+
if (error?.code === "ENOENT") return void 0;
|
|
10735
|
+
snapshots.unavailable.push(runtime);
|
|
10736
|
+
snapshots.errors[runtime] = error instanceof Error ? error.message : String(error);
|
|
10737
|
+
return void 0;
|
|
10738
|
+
}
|
|
10739
|
+
}
|
|
10717
10740
|
function getWorkspaceRegistrySnapshots() {
|
|
10718
10741
|
if (cachedSnapshots) return cachedSnapshots;
|
|
10719
10742
|
const snapshots = { unavailable: [], errors: {} };
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
snapshots.unavailable.push("devsy");
|
|
10725
|
-
snapshots.errors.devsy = error instanceof Error ? error.message : String(error);
|
|
10726
|
-
}
|
|
10727
|
-
}
|
|
10728
|
-
if (isRuntimeInstalled("devpod")) {
|
|
10729
|
-
try {
|
|
10730
|
-
snapshots.devpod = listDevpodWorkspacesRaw();
|
|
10731
|
-
} catch (error) {
|
|
10732
|
-
snapshots.unavailable.push("devpod");
|
|
10733
|
-
snapshots.errors.devpod = error instanceof Error ? error.message : String(error);
|
|
10734
|
-
}
|
|
10735
|
-
}
|
|
10743
|
+
const devsy = readRegistrySnapshot("devsy", listDevsyWorkspaces, snapshots);
|
|
10744
|
+
if (devsy !== void 0) snapshots.devsy = devsy;
|
|
10745
|
+
const devpod = readRegistrySnapshot("devpod", listDevpodWorkspacesRaw, snapshots);
|
|
10746
|
+
if (devpod !== void 0) snapshots.devpod = devpod;
|
|
10736
10747
|
cachedSnapshots = snapshots;
|
|
10737
10748
|
return snapshots;
|
|
10738
10749
|
}
|
|
@@ -11511,11 +11522,19 @@ function absentRegistrationIdentity(state) {
|
|
|
11511
11522
|
resetWorkspaceRuntimeCaches();
|
|
11512
11523
|
if (resolveWorkspaceRuntimeOrDefault(state.repoPath) !== "devsy")
|
|
11513
11524
|
throw new Error("Stop provider changed.");
|
|
11514
|
-
|
|
11515
|
-
|
|
11516
|
-
|
|
11517
|
-
|
|
11518
|
-
|
|
11525
|
+
const linked = isLinkedWorktree(state.repoPath);
|
|
11526
|
+
if (linked !== (state.workspace !== void 0))
|
|
11527
|
+
throw new Error("Absent stop requires the exact workspace identity.");
|
|
11528
|
+
let identity2;
|
|
11529
|
+
if (linked) {
|
|
11530
|
+
const workspace = state.workspace;
|
|
11531
|
+
const record5 = readWorkspaceOwnership(state.repoPath, workspace);
|
|
11532
|
+
if (!record5 || record5.workspace !== workspace || record5.devpodId !== state.devpodId || !sameWorkspacePath(record5.worktreePath, state.repoPath) || resolveWorktreeWorkspace(state.repoPath) !== workspace || inspectWorkspaceOwnership(record5, listGitWorktrees(state.repoPath), void 0).ownerStatus !== "present")
|
|
11533
|
+
throw new Error("Absent stop workspace ownership changed.");
|
|
11534
|
+
identity2 = { kind: "linked", record: record5, gitCommonDir: resolveGitCommonDir(state.repoPath) };
|
|
11535
|
+
} else {
|
|
11536
|
+
identity2 = { kind: "primary", repoPath: state.repoPath, devpodId: state.devpodId };
|
|
11537
|
+
}
|
|
11519
11538
|
for (const entries of [
|
|
11520
11539
|
listDevsyWorkspaces(),
|
|
11521
11540
|
listDevpodWorkspacesRaw({ allowMissingExecutable: true })
|
|
@@ -11525,7 +11544,7 @@ function absentRegistrationIdentity(state) {
|
|
|
11525
11544
|
))
|
|
11526
11545
|
throw new Error("Absent stop requires both provider registrations to remain absent.");
|
|
11527
11546
|
}
|
|
11528
|
-
return
|
|
11547
|
+
return identity2;
|
|
11529
11548
|
}
|
|
11530
11549
|
function replacementObservation(state) {
|
|
11531
11550
|
resetWorkspaceRuntimeCaches();
|
|
@@ -11635,7 +11654,7 @@ function proveManagedStop(state) {
|
|
|
11635
11654
|
const identityKeys = ["context", "providerId", "uid", "sourcePath", "sourceContainer"];
|
|
11636
11655
|
const current = identityOf(owner.workspace);
|
|
11637
11656
|
const changed = identityKeys.filter((key) => baseline[key] !== current[key]);
|
|
11638
|
-
if (changed.length === 0 &&
|
|
11657
|
+
if (changed.length === 0 && inspectManagedStopContainers(baseline.project, baseline.endpoint).length === 0) {
|
|
11639
11658
|
proveAbsentPopulationStop(state, baseline, current);
|
|
11640
11659
|
return { status: "proven-absent", containers: [] };
|
|
11641
11660
|
}
|
|
@@ -12586,6 +12605,41 @@ function stopInitialManagedDevsyWorkspace(repoPath, devsyId) {
|
|
|
12586
12605
|
throw new Error("Initial managed stop left a workload running.");
|
|
12587
12606
|
return true;
|
|
12588
12607
|
}
|
|
12608
|
+
function restoreRecordedManagedDevcontainerConfig(repoPath) {
|
|
12609
|
+
const plan = recordedManagedDevcontainerRestorePlan(repoPath);
|
|
12610
|
+
if (!plan) return false;
|
|
12611
|
+
writeManagedDevcontainerConfig(plan);
|
|
12612
|
+
if (inspectManagedDevcontainerGeneratedConfig(plan).status !== "valid") {
|
|
12613
|
+
throw new Error(
|
|
12614
|
+
`Managed Dev Container path '${plan.generatedPath}' could not be restored from the recorded state.`
|
|
12615
|
+
);
|
|
12616
|
+
}
|
|
12617
|
+
return true;
|
|
12618
|
+
}
|
|
12619
|
+
function recordedManagedDevcontainerRestorePlan(repoPath) {
|
|
12620
|
+
try {
|
|
12621
|
+
if (!import_node_fs25.default.existsSync(import_node_path33.default.join(repoPath, ".devrouter.yml"))) return void 0;
|
|
12622
|
+
const linked = isLinkedWorktree(repoPath);
|
|
12623
|
+
const workspace = linked ? resolveWorktreeWorkspace(repoPath) : void 0;
|
|
12624
|
+
const state = readManagedRuntimeState(repoPath, workspace);
|
|
12625
|
+
if (!state) return void 0;
|
|
12626
|
+
const runtime = loadRuntimeConfig(repoPath, workspace ?? "", state.profile);
|
|
12627
|
+
if (!runtime.config.managedRuntime || runtime.profile !== state.profile || runtime.workspace !== workspace)
|
|
12628
|
+
return void 0;
|
|
12629
|
+
const plan = inspectManagedDevcontainerConfig({
|
|
12630
|
+
repoPath,
|
|
12631
|
+
config: runtime.config,
|
|
12632
|
+
profile: runtime.resolvedProfile,
|
|
12633
|
+
linked
|
|
12634
|
+
});
|
|
12635
|
+
if (inspectManagedDevcontainerGeneratedConfig(plan).status !== "missing") return void 0;
|
|
12636
|
+
if (plan.sourceConfigSha256 !== state.sourceConfigSha256 || plan.effectiveConfigSha256 !== state.effectiveConfigSha256)
|
|
12637
|
+
return void 0;
|
|
12638
|
+
return plan;
|
|
12639
|
+
} catch {
|
|
12640
|
+
return void 0;
|
|
12641
|
+
}
|
|
12642
|
+
}
|
|
12589
12643
|
function stopRetainedManagedDevsyWorkspace(options) {
|
|
12590
12644
|
const { repoPath, devsyId } = options;
|
|
12591
12645
|
const linked = isLinkedWorktree(repoPath);
|
|
@@ -13984,6 +14038,7 @@ function inspectExactOwnership(devsyId, worktreePath) {
|
|
|
13984
14038
|
}
|
|
13985
14039
|
function mutateOwnedDevsyWorkspace(action2, devsyId, worktreePath) {
|
|
13986
14040
|
return withMutationLock(`Devsy ${action2}`, worktreePath, () => {
|
|
14041
|
+
restoreRecordedManagedDevcontainerConfig(worktreePath);
|
|
13987
14042
|
if (action2 === "stop") {
|
|
13988
14043
|
const stopped = stopRetainedManagedDevsyWorkspace({
|
|
13989
14044
|
repoPath: worktreePath,
|
|
@@ -14392,7 +14447,7 @@ function handleOperationRequest(state, event) {
|
|
|
14392
14447
|
if (state.phase === "stopping" || state.desired === "parked-for-capacity")
|
|
14393
14448
|
return blocked(
|
|
14394
14449
|
state,
|
|
14395
|
-
`phase is '${state.phase}' with desired '${state.desired}'; wait for the running stop to finish.`
|
|
14450
|
+
`phase is '${state.phase}' with desired '${state.desired}'; wait for the running stop to finish, or when no stop worker is running rerun 'devrouter stop <path> --delete', removing the exact provider registration first when the stop cannot prove the recorded population.`
|
|
14396
14451
|
);
|
|
14397
14452
|
if (event.kind === "exec" && (!event.runtimeRunning || state.desired !== "running" && state.intentRevision !== 0))
|
|
14398
14453
|
return blocked(
|
|
@@ -16027,6 +16082,103 @@ var init_managed_post_start = __esm({
|
|
|
16027
16082
|
}
|
|
16028
16083
|
});
|
|
16029
16084
|
|
|
16085
|
+
// src/core/managed-mount-nesting.ts
|
|
16086
|
+
function normalizeDestination(value) {
|
|
16087
|
+
const trimmed = value.trim().replace(/\/+$/, "");
|
|
16088
|
+
return trimmed === "" ? "/" : trimmed;
|
|
16089
|
+
}
|
|
16090
|
+
function isNestedWithin(destination, candidate) {
|
|
16091
|
+
return candidate === "/" ? destination !== "/" : destination.startsWith(`${candidate}/`);
|
|
16092
|
+
}
|
|
16093
|
+
function unescapeMountField(value) {
|
|
16094
|
+
return value.replace(
|
|
16095
|
+
/\\([0-7]{3})/g,
|
|
16096
|
+
(_match, octal) => String.fromCharCode(Number.parseInt(octal, 8))
|
|
16097
|
+
);
|
|
16098
|
+
}
|
|
16099
|
+
function parseMountinfoDestinations(text4) {
|
|
16100
|
+
const destinations = /* @__PURE__ */ new Set();
|
|
16101
|
+
for (const line of text4.split("\n")) {
|
|
16102
|
+
const fields2 = line.split(" ");
|
|
16103
|
+
if (fields2.length < 5 || !/^\d+$/.test(fields2[0] ?? "")) continue;
|
|
16104
|
+
destinations.add(normalizeDestination(unescapeMountField(fields2[4] ?? "")));
|
|
16105
|
+
}
|
|
16106
|
+
return [...destinations];
|
|
16107
|
+
}
|
|
16108
|
+
function isNestedIndex(destinations, index) {
|
|
16109
|
+
return destinations.some(
|
|
16110
|
+
(candidate, other) => other !== index && isNestedWithin(destinations[index] ?? "", candidate)
|
|
16111
|
+
);
|
|
16112
|
+
}
|
|
16113
|
+
function configuredDestinations(configured) {
|
|
16114
|
+
return configured.map((mount) => normalizeDestination(mount.Destination));
|
|
16115
|
+
}
|
|
16116
|
+
function classifyManagedMountNesting(configured, effectiveDestinations, containerId) {
|
|
16117
|
+
const destinations = configuredDestinations(configured);
|
|
16118
|
+
const nested = configured.filter((_mount, index) => isNestedIndex(destinations, index));
|
|
16119
|
+
const identity2 = containerId ? { container: containerId } : {};
|
|
16120
|
+
if (nested.length === 0) {
|
|
16121
|
+
return { status: "not-applicable", checked: [], unwound: [], reason: NESTED_MOUNT_REASON };
|
|
16122
|
+
}
|
|
16123
|
+
if (effectiveDestinations === null) {
|
|
16124
|
+
return {
|
|
16125
|
+
status: "unverified",
|
|
16126
|
+
checked: [],
|
|
16127
|
+
unwound: [],
|
|
16128
|
+
...identity2,
|
|
16129
|
+
reason: UNREADABLE_MOUNT_REASON
|
|
16130
|
+
};
|
|
16131
|
+
}
|
|
16132
|
+
const effective = new Set(effectiveDestinations.map(normalizeDestination));
|
|
16133
|
+
const checked = [];
|
|
16134
|
+
const unwound = [];
|
|
16135
|
+
for (const mount of nested) {
|
|
16136
|
+
const destination = normalizeDestination(mount.Destination);
|
|
16137
|
+
if (effective.has(destination)) {
|
|
16138
|
+
checked.push(mount.Destination);
|
|
16139
|
+
continue;
|
|
16140
|
+
}
|
|
16141
|
+
const nestedWithin = destinations.filter((candidate) => isNestedWithin(destination, candidate)).sort((a, b) => a.length - b.length)[0];
|
|
16142
|
+
unwound.push({
|
|
16143
|
+
destination: mount.Destination,
|
|
16144
|
+
source: mount.Source,
|
|
16145
|
+
nestedWithin: nestedWithin ?? "/"
|
|
16146
|
+
});
|
|
16147
|
+
}
|
|
16148
|
+
return {
|
|
16149
|
+
status: unwound.length > 0 ? "unwound" : "effective",
|
|
16150
|
+
checked,
|
|
16151
|
+
unwound,
|
|
16152
|
+
...identity2
|
|
16153
|
+
};
|
|
16154
|
+
}
|
|
16155
|
+
function readContainerMountinfo(containerId, options) {
|
|
16156
|
+
const result = (0, import_node_child_process24.spawnSync)("docker", ["exec", containerId, "cat", "/proc/self/mountinfo"], {
|
|
16157
|
+
encoding: "utf-8",
|
|
16158
|
+
timeout: options.timeoutMs ?? 5e3,
|
|
16159
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
16160
|
+
...networkDockerOptions()
|
|
16161
|
+
});
|
|
16162
|
+
if (result.status !== 0 || typeof result.stdout !== "string") return null;
|
|
16163
|
+
const destinations = parseMountinfoDestinations(result.stdout);
|
|
16164
|
+
return destinations.length > 0 ? destinations : null;
|
|
16165
|
+
}
|
|
16166
|
+
function observeManagedMountNesting(container, options = {}) {
|
|
16167
|
+
const destinations = configuredDestinations(container.mounts);
|
|
16168
|
+
const effective = destinations.some((_destination, index) => isNestedIndex(destinations, index)) ? readContainerMountinfo(container.id, options) : null;
|
|
16169
|
+
return classifyManagedMountNesting(container.mounts, effective, container.id);
|
|
16170
|
+
}
|
|
16171
|
+
var import_node_child_process24, NESTED_MOUNT_REASON, UNREADABLE_MOUNT_REASON;
|
|
16172
|
+
var init_managed_mount_nesting = __esm({
|
|
16173
|
+
"src/core/managed-mount-nesting.ts"() {
|
|
16174
|
+
"use strict";
|
|
16175
|
+
import_node_child_process24 = require("child_process");
|
|
16176
|
+
init_network_effect_scope();
|
|
16177
|
+
NESTED_MOUNT_REASON = "no configured mount is nested inside another configured mount";
|
|
16178
|
+
UNREADABLE_MOUNT_REASON = "the container's own mount table could not be read";
|
|
16179
|
+
}
|
|
16180
|
+
});
|
|
16181
|
+
|
|
16030
16182
|
// src/core/managed-runtime-status.ts
|
|
16031
16183
|
function recoveryPath(repoPath) {
|
|
16032
16184
|
if (/^[A-Za-z0-9_@%+=:,./-]+$/.test(repoPath)) return repoPath;
|
|
@@ -16302,6 +16454,7 @@ function inspectManagedRuntime(options) {
|
|
|
16302
16454
|
(mount) => mount.Type === "bind" && sameWorkspacePath(mount.Source, repoPath)
|
|
16303
16455
|
)?.Destination;
|
|
16304
16456
|
const primaryActive = Boolean(primary?.state.Running);
|
|
16457
|
+
const mountNesting = primary && primaryActive ? observeManagedMountNesting(primary) : void 0;
|
|
16305
16458
|
if (generatedConfigMissing && (state || primaryActive || managedServicesActive)) {
|
|
16306
16459
|
drift.push("managed generated Dev Container configuration is missing");
|
|
16307
16460
|
}
|
|
@@ -16368,7 +16521,8 @@ function inspectManagedRuntime(options) {
|
|
|
16368
16521
|
processStatuses,
|
|
16369
16522
|
activeServices: sortedUnique2(activeServices),
|
|
16370
16523
|
activeProcesses: sortedUnique2(activeProcesses),
|
|
16371
|
-
drift
|
|
16524
|
+
drift,
|
|
16525
|
+
...mountNesting ? { mountNesting } : {}
|
|
16372
16526
|
};
|
|
16373
16527
|
}
|
|
16374
16528
|
function collectManagedRuntimeStatus(options) {
|
|
@@ -16516,6 +16670,7 @@ function collectManagedRuntimeStatus(options) {
|
|
|
16516
16670
|
baseServiceStatuses: inspection.baseStatuses,
|
|
16517
16671
|
processStatuses: inspection.processStatuses,
|
|
16518
16672
|
drift: sortedUnique2(drift),
|
|
16673
|
+
...inspection.mountNesting ? { mountNesting: inspection.mountNesting } : {},
|
|
16519
16674
|
...inspection.plan?.sourceConfigSha256 || state?.sourceConfigSha256 ? { sourceConfigSha256: inspection.plan?.sourceConfigSha256 ?? state?.sourceConfigSha256 } : {},
|
|
16520
16675
|
...inspection.plan?.effectiveConfigSha256 || state?.effectiveConfigSha256 ? {
|
|
16521
16676
|
effectiveConfigSha256: inspection.plan?.effectiveConfigSha256 ?? state?.effectiveConfigSha256
|
|
@@ -16530,6 +16685,7 @@ var init_managed_runtime_status = __esm({
|
|
|
16530
16685
|
init_devcontainer_profile();
|
|
16531
16686
|
init_devpod_environment();
|
|
16532
16687
|
init_host_routes();
|
|
16688
|
+
init_managed_mount_nesting();
|
|
16533
16689
|
init_managed_post_start();
|
|
16534
16690
|
init_managed_runtime_state();
|
|
16535
16691
|
init_reliability_operation_store();
|
|
@@ -16549,7 +16705,7 @@ function readDocker(endpoint, args, timeoutMs) {
|
|
|
16549
16705
|
const env = { ...process.env };
|
|
16550
16706
|
delete env.DOCKER_CONTEXT;
|
|
16551
16707
|
delete env.DOCKER_HOST;
|
|
16552
|
-
const result = (0,
|
|
16708
|
+
const result = (0, import_node_child_process25.spawnSync)("docker", ["--host", endpoint, ...args], {
|
|
16553
16709
|
env,
|
|
16554
16710
|
encoding: "utf-8",
|
|
16555
16711
|
timeout: timeoutMs,
|
|
@@ -16580,7 +16736,14 @@ function id4(value) {
|
|
|
16580
16736
|
}
|
|
16581
16737
|
function rows(output2) {
|
|
16582
16738
|
const trimmed = output2.trim();
|
|
16583
|
-
return trimmed ? trimmed.split(/\r?\n/).map((line) =>
|
|
16739
|
+
return trimmed ? trimmed.split(/\r?\n/).map((line) => parseRecord(line)) : [];
|
|
16740
|
+
}
|
|
16741
|
+
function parseRecord(line) {
|
|
16742
|
+
try {
|
|
16743
|
+
return JSON.parse(line);
|
|
16744
|
+
} catch {
|
|
16745
|
+
throw new NetworkInventoryError("Docker network inventory contains a malformed record.");
|
|
16746
|
+
}
|
|
16584
16747
|
}
|
|
16585
16748
|
function ids(output2) {
|
|
16586
16749
|
const values = output2.trim() ? output2.trim().split(/\r?\n/).map(id4) : [];
|
|
@@ -16625,7 +16788,7 @@ function collectDockerNetworkInventory(options = {}, dependencies = {}) {
|
|
|
16625
16788
|
return output2;
|
|
16626
16789
|
};
|
|
16627
16790
|
const info = record4(
|
|
16628
|
-
|
|
16791
|
+
parseRecord(
|
|
16629
16792
|
read2(["info", "--format", '{"id":{{json .ID}},"pools":{{json .DefaultAddressPools}}}'])
|
|
16630
16793
|
)
|
|
16631
16794
|
);
|
|
@@ -16704,18 +16867,18 @@ function collectDockerNetworkInventory(options = {}, dependencies = {}) {
|
|
|
16704
16867
|
}
|
|
16705
16868
|
return result;
|
|
16706
16869
|
}
|
|
16707
|
-
var
|
|
16870
|
+
var import_node_child_process25, NetworkInventoryError, MAX_IDS, MAX_OUTPUT_BYTES, FULL_ID, NETWORK_TEMPLATE, CONTAINER_TEMPLATE;
|
|
16708
16871
|
var init_network_inventory = __esm({
|
|
16709
16872
|
"src/core/network-inventory.ts"() {
|
|
16710
16873
|
"use strict";
|
|
16711
|
-
|
|
16874
|
+
import_node_child_process25 = require("child_process");
|
|
16712
16875
|
init_devpod_environment();
|
|
16713
16876
|
NetworkInventoryError = class extends Error {
|
|
16714
16877
|
};
|
|
16715
16878
|
MAX_IDS = 4096;
|
|
16716
16879
|
MAX_OUTPUT_BYTES = 2 * 1024 * 1024;
|
|
16717
16880
|
FULL_ID = /^[a-f0-9]{64}$/;
|
|
16718
|
-
NETWORK_TEMPLATE = '{"id":{{json .Id}},"name":{{json .Name}},"driver":{{json .Driver}},"ipam":{{json .IPAM.Config}},"activeEndpoints":{{len .Containers}},"project":{{json (index .Labels "com.docker.compose.project")}},"network":{{json (index .Labels "com.docker.compose.network")}}';
|
|
16881
|
+
NETWORK_TEMPLATE = '{"id":{{json .Id}},"name":{{json .Name}},"driver":{{json .Driver}},"ipam":{{json .IPAM.Config}},"activeEndpoints":{{len .Containers}},"project":{{json (index .Labels "com.docker.compose.project")}},"network":{{json (index .Labels "com.docker.compose.network")}}}';
|
|
16719
16882
|
CONTAINER_TEMPLATE = '{"id":{{json .Id}},"networks":{{json .NetworkSettings.Networks}}}';
|
|
16720
16883
|
}
|
|
16721
16884
|
});
|
|
@@ -17102,7 +17265,7 @@ function parseLinuxNetworkRoutes(output2) {
|
|
|
17102
17265
|
function collectNetworkRoutes(options) {
|
|
17103
17266
|
if ((options.platform ?? process.platform) !== "linux" || !hasLocalDockerNetworkNamespace(options.endpoint))
|
|
17104
17267
|
return { status: "unknown", routes: [] };
|
|
17105
|
-
const result = (0,
|
|
17268
|
+
const result = (0, import_node_child_process26.spawnSync)("ip", ["-j", "-4", "route", "show", "table", "all"], {
|
|
17106
17269
|
encoding: "utf8",
|
|
17107
17270
|
timeout: 5e3,
|
|
17108
17271
|
maxBuffer: 1024 * 1024
|
|
@@ -17110,11 +17273,11 @@ function collectNetworkRoutes(options) {
|
|
|
17110
17273
|
if (result.error || result.status !== 0) return { status: "unknown", routes: [] };
|
|
17111
17274
|
return parseLinuxNetworkRoutes(result.stdout);
|
|
17112
17275
|
}
|
|
17113
|
-
var
|
|
17276
|
+
var import_node_child_process26, import_node_net3;
|
|
17114
17277
|
var init_network_routes = __esm({
|
|
17115
17278
|
"src/core/network-routes.ts"() {
|
|
17116
17279
|
"use strict";
|
|
17117
|
-
|
|
17280
|
+
import_node_child_process26 = require("child_process");
|
|
17118
17281
|
import_node_net3 = require("net");
|
|
17119
17282
|
init_network_capacity();
|
|
17120
17283
|
init_network_local_daemon();
|
|
@@ -17192,11 +17355,11 @@ var init_network_compose = __esm({
|
|
|
17192
17355
|
});
|
|
17193
17356
|
|
|
17194
17357
|
// src/core/network-compose-files.ts
|
|
17195
|
-
var
|
|
17358
|
+
var import_node_child_process27, import_node_crypto21, import_node_fs35, import_node_path43, import_yaml4, MAX_BYTES3;
|
|
17196
17359
|
var init_network_compose_files = __esm({
|
|
17197
17360
|
"src/core/network-compose-files.ts"() {
|
|
17198
17361
|
"use strict";
|
|
17199
|
-
|
|
17362
|
+
import_node_child_process27 = require("child_process");
|
|
17200
17363
|
import_node_crypto21 = require("crypto");
|
|
17201
17364
|
import_node_fs35 = __toESM(require("fs"));
|
|
17202
17365
|
import_node_path43 = __toESM(require("path"));
|
|
@@ -17209,11 +17372,11 @@ var init_network_compose_files = __esm({
|
|
|
17209
17372
|
});
|
|
17210
17373
|
|
|
17211
17374
|
// src/core/network-connected-route.ts
|
|
17212
|
-
var
|
|
17375
|
+
var import_node_child_process28;
|
|
17213
17376
|
var init_network_connected_route = __esm({
|
|
17214
17377
|
"src/core/network-connected-route.ts"() {
|
|
17215
17378
|
"use strict";
|
|
17216
|
-
|
|
17379
|
+
import_node_child_process28 = require("child_process");
|
|
17217
17380
|
init_network_capacity();
|
|
17218
17381
|
}
|
|
17219
17382
|
});
|
|
@@ -17303,11 +17466,11 @@ function resolveLinkedTarget(repoPath) {
|
|
|
17303
17466
|
gitCommonDir: resolveGitCommonDir(repoPath)
|
|
17304
17467
|
};
|
|
17305
17468
|
}
|
|
17306
|
-
var
|
|
17469
|
+
var import_node_child_process29, import_node_fs36, import_node_path44;
|
|
17307
17470
|
var init_workspace_ensure = __esm({
|
|
17308
17471
|
"src/core/workspace-ensure.ts"() {
|
|
17309
17472
|
"use strict";
|
|
17310
|
-
|
|
17473
|
+
import_node_child_process29 = require("child_process");
|
|
17311
17474
|
import_node_fs36 = __toESM(require("fs"));
|
|
17312
17475
|
import_node_path44 = __toESM(require("path"));
|
|
17313
17476
|
init_devcontainer_profile();
|
|
@@ -17587,6 +17750,44 @@ function restoreParkedIntentAfterFailedResume(input2) {
|
|
|
17587
17750
|
record5.state = transition2.state;
|
|
17588
17751
|
});
|
|
17589
17752
|
}
|
|
17753
|
+
function snapshotLifecycleStopIntent(state) {
|
|
17754
|
+
return {
|
|
17755
|
+
intentRevision: state.intentRevision,
|
|
17756
|
+
observationsAfterMs: state.observationsAfterMs,
|
|
17757
|
+
desired: state.desired,
|
|
17758
|
+
phase: state.phase,
|
|
17759
|
+
profile: state.profile,
|
|
17760
|
+
admission: state.admission,
|
|
17761
|
+
stopProof: { ...state.stopProof },
|
|
17762
|
+
requests: state.requests.map((request2) => ({ ...request2 })),
|
|
17763
|
+
observations: state.observations.map((observation) => ({ ...observation })),
|
|
17764
|
+
operation: state.operation ? { ...state.operation } : null
|
|
17765
|
+
};
|
|
17766
|
+
}
|
|
17767
|
+
function withdrawUnstartedLifecycleStop(input2) {
|
|
17768
|
+
return updateReliabilityOperation(input2.identity, (record5) => {
|
|
17769
|
+
const state = record5.state;
|
|
17770
|
+
const intent = input2.intent;
|
|
17771
|
+
if (!intent.wroteIntent) return false;
|
|
17772
|
+
if (!matchesFence(record5, intent.fence)) return false;
|
|
17773
|
+
if (record5.worker || record5.stopWorkStarted) return false;
|
|
17774
|
+
if (state.desired !== "stopped-by-user" || state.phase !== "stopping") return false;
|
|
17775
|
+
if (state.stopProof.workloadsStopped || state.stopProof.routesRemoved) return false;
|
|
17776
|
+
if (!(0, import_node_util11.isDeepStrictEqual)(state.operation, intent.recordedOperation)) return false;
|
|
17777
|
+
const prior = intent.prior;
|
|
17778
|
+
state.intentRevision = prior.intentRevision;
|
|
17779
|
+
state.observationsAfterMs = prior.observationsAfterMs;
|
|
17780
|
+
state.desired = prior.desired;
|
|
17781
|
+
state.phase = prior.phase;
|
|
17782
|
+
state.profile = prior.profile;
|
|
17783
|
+
state.admission = prior.admission;
|
|
17784
|
+
state.stopProof = { ...prior.stopProof };
|
|
17785
|
+
state.requests = prior.requests.map((request2) => ({ ...request2 }));
|
|
17786
|
+
state.observations = prior.observations.map((observation) => ({ ...observation }));
|
|
17787
|
+
state.operation = prior.operation ? { ...prior.operation } : null;
|
|
17788
|
+
return true;
|
|
17789
|
+
});
|
|
17790
|
+
}
|
|
17590
17791
|
function prepareResumeLifecycleOperation(input2) {
|
|
17591
17792
|
const ids2 = newLifecycleIds();
|
|
17592
17793
|
return updateReliabilityOperation(input2.identity, (record5) => {
|
|
@@ -17739,12 +17940,37 @@ async function superviseLifecycle(kind, repoPath, options = {}, command) {
|
|
|
17739
17940
|
const copiedOptions = { ...options };
|
|
17740
17941
|
const copiedCommand = command ? [...command] : void 0;
|
|
17741
17942
|
if (kind === "stop") {
|
|
17742
|
-
const
|
|
17943
|
+
const intent = updateReliabilityOperation(identity2, (record5) => {
|
|
17743
17944
|
reconcileDrained(record5);
|
|
17945
|
+
const prior = snapshotLifecycleStopIntent(record5.state);
|
|
17744
17946
|
stepRecord(record5, { ...reliabilityFence(record5.state), type: "stop" });
|
|
17745
|
-
return
|
|
17947
|
+
return {
|
|
17948
|
+
fence: reliabilityFence(record5.state),
|
|
17949
|
+
prior,
|
|
17950
|
+
recordedOperation: record5.state.operation ? { ...record5.state.operation } : null,
|
|
17951
|
+
wroteIntent: record5.state.intentRevision !== prior.intentRevision
|
|
17952
|
+
};
|
|
17746
17953
|
});
|
|
17747
|
-
|
|
17954
|
+
try {
|
|
17955
|
+
return await runLifecycleWorker({
|
|
17956
|
+
kind,
|
|
17957
|
+
repoPath,
|
|
17958
|
+
identity: identity2,
|
|
17959
|
+
...ids2,
|
|
17960
|
+
fence: intent.fence,
|
|
17961
|
+
options: copiedOptions
|
|
17962
|
+
});
|
|
17963
|
+
} catch (error) {
|
|
17964
|
+
try {
|
|
17965
|
+
withdrawUnstartedLifecycleStop({ identity: identity2, intent });
|
|
17966
|
+
} catch (withdrawal) {
|
|
17967
|
+
process.stderr.write(
|
|
17968
|
+
`Lifecycle stop intent could not be withdrawn: ${withdrawal instanceof Error ? withdrawal.message : String(withdrawal)}
|
|
17969
|
+
`
|
|
17970
|
+
);
|
|
17971
|
+
}
|
|
17972
|
+
throw error;
|
|
17973
|
+
}
|
|
17748
17974
|
}
|
|
17749
17975
|
const initial = readReliabilityOperation(identity2) ?? updateReliabilityOperation(identity2, (record5) => record5);
|
|
17750
17976
|
if (initial.state.executionPolicy === "capacity-managed" || capacityPolicyTargets(repoPath))
|
|
@@ -21995,6 +22221,13 @@ function appendManagedRuntimeRows(rows2, managedRuntime) {
|
|
|
21995
22221
|
rows2.push(["Effective config SHA-256", managedRuntime.effectiveConfigSha256 ?? "-"]);
|
|
21996
22222
|
rows2.push(["Transition phase", managedRuntime.transitionPhase ?? "-"]);
|
|
21997
22223
|
rows2.push(["Runtime drift", formatResourceNames(managedRuntime.drift)]);
|
|
22224
|
+
if (managedRuntime.mountNesting && managedRuntime.mountNesting.status !== "not-applicable") {
|
|
22225
|
+
const nesting = managedRuntime.mountNesting;
|
|
22226
|
+
rows2.push([
|
|
22227
|
+
"Mount nesting",
|
|
22228
|
+
nesting.status === "unwound" ? `unwound: ${nesting.unwound.map((entry) => entry.destination).join(", ")} (restart the container to re-apply)` : nesting.status === "unverified" ? `unverified (${nesting.reason ?? "unknown"})` : `effective (${nesting.checked.join(", ")})`
|
|
22229
|
+
]);
|
|
22230
|
+
}
|
|
21998
22231
|
if (managedRuntime.reliability) {
|
|
21999
22232
|
const reliability = managedRuntime.reliability;
|
|
22000
22233
|
rows2.push(["Lifecycle intent", reliability.desired]);
|
|
@@ -23106,6 +23339,11 @@ async function collectRouterStatus(repoPath) {
|
|
|
23106
23339
|
nextSteps.push(`Run: dev app ls --repo ${repo.path}`);
|
|
23107
23340
|
nextSteps.push("Run: dev app run <name> --repo <path> --yes");
|
|
23108
23341
|
nextSteps.push("Run: dev ls");
|
|
23342
|
+
if (repo.managedRuntime?.mountNesting?.status === "unwound") {
|
|
23343
|
+
nextSteps.push(
|
|
23344
|
+
`Run: devrouter stop ${repo.path} and then devrouter ensure ${repo.path} to re-apply the unwound nested mount`
|
|
23345
|
+
);
|
|
23346
|
+
}
|
|
23109
23347
|
}
|
|
23110
23348
|
const files = getRouterFileLayout();
|
|
23111
23349
|
if (files.missing.length > 0) {
|
|
@@ -23149,7 +23387,7 @@ function outputFromResult(result) {
|
|
|
23149
23387
|
return output2.length > 0 ? output2 : void 0;
|
|
23150
23388
|
}
|
|
23151
23389
|
function runTool(command, args = []) {
|
|
23152
|
-
const result = (0,
|
|
23390
|
+
const result = (0, import_node_child_process30.spawnSync)(command, args, {
|
|
23153
23391
|
encoding: "utf-8"
|
|
23154
23392
|
});
|
|
23155
23393
|
if (result.error) {
|
|
@@ -23340,7 +23578,7 @@ function displayPath(filePath) {
|
|
|
23340
23578
|
return `~${filePath.slice(home.length)}`;
|
|
23341
23579
|
}
|
|
23342
23580
|
function probeInstalledCliVersion(executable) {
|
|
23343
|
-
const result = (0,
|
|
23581
|
+
const result = (0, import_node_child_process30.spawnSync)(executable, ["-V"], {
|
|
23344
23582
|
encoding: "utf-8",
|
|
23345
23583
|
timeout: CLI_PATH_PROBE_TIMEOUT_MS
|
|
23346
23584
|
});
|
|
@@ -23351,7 +23589,7 @@ function probeInstalledCliVersion(executable) {
|
|
|
23351
23589
|
}
|
|
23352
23590
|
function buildCliPathCheck(options = {}) {
|
|
23353
23591
|
const id5 = "global.cli-path";
|
|
23354
|
-
const runningVersion = options.runningVersion ?? (true ? "0.1.
|
|
23592
|
+
const runningVersion = options.runningVersion ?? (true ? "0.1.3" : "0.0.0-dev");
|
|
23355
23593
|
if (runningVersion === "0.0.0-dev") {
|
|
23356
23594
|
return {
|
|
23357
23595
|
id: id5,
|
|
@@ -23526,11 +23764,11 @@ function buildGlobalToolChecksWithoutTelemetry(repoPath) {
|
|
|
23526
23764
|
checks.push(nodeToolchainCheck(repoPath));
|
|
23527
23765
|
return checks;
|
|
23528
23766
|
}
|
|
23529
|
-
var
|
|
23767
|
+
var import_node_child_process30, import_node_fs43, import_node_path54, DEVSY_DISABLE_TELEMETRY, CLI_PATH_PROBE_TIMEOUT_MS, INSTALLED_CLI_VERSION_RE;
|
|
23530
23768
|
var init_tool_diagnostics = __esm({
|
|
23531
23769
|
"src/core/tool-diagnostics.ts"() {
|
|
23532
23770
|
"use strict";
|
|
23533
|
-
|
|
23771
|
+
import_node_child_process30 = require("child_process");
|
|
23534
23772
|
import_node_fs43 = __toESM(require("fs"));
|
|
23535
23773
|
import_node_path54 = __toESM(require("path"));
|
|
23536
23774
|
init_devsy_agent();
|
|
@@ -24186,6 +24424,43 @@ async function buildDoctorReport(options = {}) {
|
|
|
24186
24424
|
...details ? { details } : {},
|
|
24187
24425
|
suggestion: managedRuntime.mode === "legacy" ? void 0 : managedRuntime.status === "failed-transition" ? `Inspect: dev status --repo ${repo.path}; resolve the reported drift before retrying ensure.` : managedRuntime.status === "ready" ? void 0 : `Run: dev ensure ${repo.path}`
|
|
24188
24426
|
});
|
|
24427
|
+
const mountNesting = managedRuntime.mountNesting;
|
|
24428
|
+
if (mountNesting && mountNesting.status !== "not-applicable") {
|
|
24429
|
+
const container = mountNesting.container ?? "unknown";
|
|
24430
|
+
const shortContainer = container === "unknown" ? container : container.slice(0, 12);
|
|
24431
|
+
if (mountNesting.status === "unwound") {
|
|
24432
|
+
const first = mountNesting.unwound[0];
|
|
24433
|
+
addCheck(checks, {
|
|
24434
|
+
id: "repo.managed-mount-nesting",
|
|
24435
|
+
level: "warn",
|
|
24436
|
+
summary: `Managed container ${shortContainer} no longer reports ${first?.destination ?? "a nested mount"} in its own mount table, so the mount underneath it is visible in the container.`,
|
|
24437
|
+
details: [
|
|
24438
|
+
`container=${container}`,
|
|
24439
|
+
...mountNesting.unwound.map(
|
|
24440
|
+
(entry) => `unwound=${entry.destination} (source ${entry.source} inside ${entry.nestedWithin})`
|
|
24441
|
+
)
|
|
24442
|
+
].join("; "),
|
|
24443
|
+
suggestion: `Run: devrouter stop ${repo.path} and then devrouter ensure ${repo.path} to restart the exact container, which re-applies the nested mount.`
|
|
24444
|
+
});
|
|
24445
|
+
} else if (mountNesting.status === "unverified") {
|
|
24446
|
+
addCheck(checks, {
|
|
24447
|
+
id: "repo.managed-mount-nesting",
|
|
24448
|
+
level: "warn",
|
|
24449
|
+
summary: `Managed container ${shortContainer} did not report its own mount table, so its nested mounts are unverified.`,
|
|
24450
|
+
details: [
|
|
24451
|
+
`container=${container}`,
|
|
24452
|
+
`reason=${mountNesting.reason ?? "unknown"}`
|
|
24453
|
+
].join("; "),
|
|
24454
|
+
suggestion: `Run: devrouter exec ${repo.path} -- cat /proc/self/mountinfo to read the container's own mount table.`
|
|
24455
|
+
});
|
|
24456
|
+
} else {
|
|
24457
|
+
addCheck(checks, {
|
|
24458
|
+
id: "repo.managed-mount-nesting",
|
|
24459
|
+
level: "ok",
|
|
24460
|
+
summary: `Managed container ${shortContainer} still reports ${mountNesting.checked.join(", ")} in its own mount table.`
|
|
24461
|
+
});
|
|
24462
|
+
}
|
|
24463
|
+
}
|
|
24189
24464
|
}
|
|
24190
24465
|
if (repo.appCount === 0) {
|
|
24191
24466
|
addCheck(checks, {
|
|
@@ -24210,7 +24485,7 @@ async function buildDoctorReport(options = {}) {
|
|
|
24210
24485
|
suggestion: `Remedy ${expansionNotice.remedy.code}: set a named default profile other than '${expansionNotice.profile}'${remedyCandidates}.`
|
|
24211
24486
|
});
|
|
24212
24487
|
}
|
|
24213
|
-
const cliVersion = true ? "0.1.
|
|
24488
|
+
const cliVersion = true ? "0.1.3" : "0.0.0-dev";
|
|
24214
24489
|
const configVersion = config.devrouter?.version;
|
|
24215
24490
|
const installedKnown = cliVersion !== "0.0.0-dev";
|
|
24216
24491
|
const versionComparison = installedKnown && configVersion ? compareSemver(configVersion, cliVersion) : void 0;
|
|
@@ -24774,12 +25049,12 @@ function parseSsPortListeners(stdout, port) {
|
|
|
24774
25049
|
return listeners;
|
|
24775
25050
|
}
|
|
24776
25051
|
function findPortListeners(port) {
|
|
24777
|
-
const result = (0,
|
|
25052
|
+
const result = (0, import_node_child_process31.spawnSync)("lsof", ["-nP", `-iTCP:${port}`, "-sTCP:LISTEN"], {
|
|
24778
25053
|
encoding: "utf-8"
|
|
24779
25054
|
});
|
|
24780
25055
|
if (result.error && result.error.code === "ENOENT") {
|
|
24781
25056
|
if (process.platform === "linux") {
|
|
24782
|
-
const ssResult = (0,
|
|
25057
|
+
const ssResult = (0, import_node_child_process31.spawnSync)("ss", ["-H", "-lntp", "-p"], { encoding: "utf-8" });
|
|
24783
25058
|
if (ssResult.status === 0 && ssResult.stdout) {
|
|
24784
25059
|
return parseSsPortListeners(ssResult.stdout, port);
|
|
24785
25060
|
}
|
|
@@ -24808,11 +25083,11 @@ function findPortListeners(port) {
|
|
|
24808
25083
|
};
|
|
24809
25084
|
});
|
|
24810
25085
|
}
|
|
24811
|
-
var
|
|
25086
|
+
var import_node_child_process31;
|
|
24812
25087
|
var init_ports = __esm({
|
|
24813
25088
|
"src/util/ports.ts"() {
|
|
24814
25089
|
"use strict";
|
|
24815
|
-
|
|
25090
|
+
import_node_child_process31 = require("child_process");
|
|
24816
25091
|
}
|
|
24817
25092
|
});
|
|
24818
25093
|
|
|
@@ -25793,7 +26068,7 @@ async function runOpenCommand(name) {
|
|
|
25793
26068
|
);
|
|
25794
26069
|
return;
|
|
25795
26070
|
}
|
|
25796
|
-
const result = (0,
|
|
26071
|
+
const result = (0, import_node_child_process32.spawnSync)("open", [url], { encoding: "utf-8" });
|
|
25797
26072
|
if (result.status !== 0) {
|
|
25798
26073
|
const details = [result.stdout, result.stderr].filter(Boolean).join("\n").trim();
|
|
25799
26074
|
throw new Error(`Unable to open '${url}': ${details || "unknown error"}`);
|
|
@@ -25801,11 +26076,11 @@ async function runOpenCommand(name) {
|
|
|
25801
26076
|
process.stdout.write(`Opened ${url}
|
|
25802
26077
|
`);
|
|
25803
26078
|
}
|
|
25804
|
-
var
|
|
26079
|
+
var import_node_child_process32;
|
|
25805
26080
|
var init_open = __esm({
|
|
25806
26081
|
"src/commands/open.ts"() {
|
|
25807
26082
|
"use strict";
|
|
25808
|
-
|
|
26083
|
+
import_node_child_process32 = require("child_process");
|
|
25809
26084
|
init_docker();
|
|
25810
26085
|
init_host_routes();
|
|
25811
26086
|
init_repo_config();
|
|
@@ -25828,7 +26103,7 @@ async function runLogsCommand(options) {
|
|
|
25828
26103
|
const args = ["logs", "--tail", tail, ROUTER_CONTAINER_NAME];
|
|
25829
26104
|
if (options.follow) {
|
|
25830
26105
|
args.splice(1, 0, "-f");
|
|
25831
|
-
const child = (0,
|
|
26106
|
+
const child = (0, import_node_child_process33.spawn)("docker", args, { stdio: "inherit" });
|
|
25832
26107
|
const onSignal = () => {
|
|
25833
26108
|
child.kill("SIGTERM");
|
|
25834
26109
|
};
|
|
@@ -25842,17 +26117,17 @@ async function runLogsCommand(options) {
|
|
|
25842
26117
|
});
|
|
25843
26118
|
});
|
|
25844
26119
|
} else {
|
|
25845
|
-
const result = (0,
|
|
26120
|
+
const result = (0, import_node_child_process33.spawnSync)("docker", args, { stdio: "inherit" });
|
|
25846
26121
|
if (result.status !== 0) {
|
|
25847
26122
|
throw new Error("Failed to retrieve router logs.");
|
|
25848
26123
|
}
|
|
25849
26124
|
}
|
|
25850
26125
|
}
|
|
25851
|
-
var
|
|
26126
|
+
var import_node_child_process33;
|
|
25852
26127
|
var init_logs = __esm({
|
|
25853
26128
|
"src/commands/logs.ts"() {
|
|
25854
26129
|
"use strict";
|
|
25855
|
-
|
|
26130
|
+
import_node_child_process33 = require("child_process");
|
|
25856
26131
|
init_docker();
|
|
25857
26132
|
init_router();
|
|
25858
26133
|
}
|
|
@@ -27898,7 +28173,7 @@ function runDockerComposeUp(repoPath, composeFiles2, overlayPath, services) {
|
|
|
27898
28173
|
fileArgs.push("-f", resolved);
|
|
27899
28174
|
}
|
|
27900
28175
|
const args = ["compose", ...fileArgs, "-f", overlayPath, "up", "-d", "--wait", ...services];
|
|
27901
|
-
const result = (0,
|
|
28176
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27902
28177
|
encoding: "utf-8",
|
|
27903
28178
|
cwd: repoPath
|
|
27904
28179
|
});
|
|
@@ -27926,7 +28201,7 @@ function queryRunningComposeServices(repoPath, composeFiles2, overlayPath, servi
|
|
|
27926
28201
|
"--services",
|
|
27927
28202
|
...services
|
|
27928
28203
|
];
|
|
27929
|
-
const result = (0,
|
|
28204
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27930
28205
|
encoding: "utf-8",
|
|
27931
28206
|
cwd: repoPath
|
|
27932
28207
|
});
|
|
@@ -27952,7 +28227,7 @@ function runDockerComposeStop(repoPath, composeFiles2, overlayPath, services) {
|
|
|
27952
28227
|
fileArgs.push("-f", resolved);
|
|
27953
28228
|
}
|
|
27954
28229
|
const args = ["compose", ...fileArgs, "-f", overlayPath, "stop", ...services];
|
|
27955
|
-
const result = (0,
|
|
28230
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27956
28231
|
encoding: "utf-8",
|
|
27957
28232
|
cwd: repoPath
|
|
27958
28233
|
});
|
|
@@ -27978,7 +28253,7 @@ function runDockerComposeLogs(repoPath, composeFiles2, overlayPath, services, ta
|
|
|
27978
28253
|
String(tail),
|
|
27979
28254
|
...services
|
|
27980
28255
|
];
|
|
27981
|
-
(0,
|
|
28256
|
+
(0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27982
28257
|
stdio: "inherit",
|
|
27983
28258
|
cwd: repoPath
|
|
27984
28259
|
});
|
|
@@ -27990,7 +28265,7 @@ function queryMappedPort(repoPath, composeFiles2, overlayPath, service, internal
|
|
|
27990
28265
|
fileArgs.push("-f", resolved);
|
|
27991
28266
|
}
|
|
27992
28267
|
const args = ["compose", ...fileArgs, "-f", overlayPath, "port", service, String(internalPort)];
|
|
27993
|
-
const result = (0,
|
|
28268
|
+
const result = (0, import_node_child_process34.spawnSync)("docker", args, {
|
|
27994
28269
|
encoding: "utf-8",
|
|
27995
28270
|
cwd: repoPath
|
|
27996
28271
|
});
|
|
@@ -28004,11 +28279,11 @@ function queryMappedPort(repoPath, composeFiles2, overlayPath, service, internal
|
|
|
28004
28279
|
const port = Number(match[1]);
|
|
28005
28280
|
return Number.isInteger(port) && port > 0 ? port : void 0;
|
|
28006
28281
|
}
|
|
28007
|
-
var
|
|
28282
|
+
var import_node_child_process34, import_node_crypto29, import_node_fs51, import_node_path64, import_yaml9;
|
|
28008
28283
|
var init_docker_run = __esm({
|
|
28009
28284
|
"src/core/docker-run.ts"() {
|
|
28010
28285
|
"use strict";
|
|
28011
|
-
|
|
28286
|
+
import_node_child_process34 = require("child_process");
|
|
28012
28287
|
import_node_crypto29 = require("crypto");
|
|
28013
28288
|
import_node_fs51 = __toESM(require("fs"));
|
|
28014
28289
|
import_node_path64 = __toESM(require("path"));
|
|
@@ -28101,7 +28376,7 @@ function isProcessRunning(pid) {
|
|
|
28101
28376
|
}
|
|
28102
28377
|
}
|
|
28103
28378
|
function readProcessTree(rootPid) {
|
|
28104
|
-
const result = (0,
|
|
28379
|
+
const result = (0, import_node_child_process35.spawnSync)("ps", ["-ax", "-o", "pid=,ppid="], { encoding: "utf-8" });
|
|
28105
28380
|
if (result.status !== 0) {
|
|
28106
28381
|
return [rootPid];
|
|
28107
28382
|
}
|
|
@@ -28212,12 +28487,12 @@ function detectListeningPorts(pids) {
|
|
|
28212
28487
|
if (pids.length === 0) {
|
|
28213
28488
|
return [];
|
|
28214
28489
|
}
|
|
28215
|
-
const result = (0,
|
|
28490
|
+
const result = (0, import_node_child_process35.spawnSync)("lsof", ["-nP", "-iTCP", "-sTCP:LISTEN", "-a", "-p", pids.join(",")], {
|
|
28216
28491
|
encoding: "utf-8"
|
|
28217
28492
|
});
|
|
28218
28493
|
if (result.error && result.error.code === "ENOENT") {
|
|
28219
28494
|
if (process.platform === "linux") {
|
|
28220
|
-
const ssResult = (0,
|
|
28495
|
+
const ssResult = (0, import_node_child_process35.spawnSync)("ss", ["-H", "-lntp", "-p"], { encoding: "utf-8" });
|
|
28221
28496
|
if (ssResult.status === 0 && ssResult.stdout) {
|
|
28222
28497
|
return parseSsListeningPorts(ssResult.stdout, new Set(pids));
|
|
28223
28498
|
}
|
|
@@ -28276,7 +28551,7 @@ async function runHostApp(repoPath, app, extraEnv = {}, secretManager, env, work
|
|
|
28276
28551
|
app.hostRun.command,
|
|
28277
28552
|
true
|
|
28278
28553
|
) : app.hostRun.command;
|
|
28279
|
-
const child = (0,
|
|
28554
|
+
const child = (0, import_node_child_process35.spawn)(spawnCommand, {
|
|
28280
28555
|
cwd: commandCwd,
|
|
28281
28556
|
stdio: "inherit",
|
|
28282
28557
|
shell: true,
|
|
@@ -28644,7 +28919,7 @@ async function execWithAppEnv(options) {
|
|
|
28644
28919
|
options.command[0],
|
|
28645
28920
|
true
|
|
28646
28921
|
);
|
|
28647
|
-
child = (0,
|
|
28922
|
+
child = (0, import_node_child_process35.spawn)(wrapped, {
|
|
28648
28923
|
cwd: deps.repoPath,
|
|
28649
28924
|
stdio: "inherit",
|
|
28650
28925
|
shell: true,
|
|
@@ -28658,7 +28933,7 @@ async function execWithAppEnv(options) {
|
|
|
28658
28933
|
false
|
|
28659
28934
|
);
|
|
28660
28935
|
const [cmd, ...wrappedArgs] = wrapped;
|
|
28661
|
-
child = (0,
|
|
28936
|
+
child = (0, import_node_child_process35.spawn)(cmd, wrappedArgs, {
|
|
28662
28937
|
cwd: deps.repoPath,
|
|
28663
28938
|
stdio: "inherit",
|
|
28664
28939
|
shell: false,
|
|
@@ -28666,7 +28941,7 @@ async function execWithAppEnv(options) {
|
|
|
28666
28941
|
});
|
|
28667
28942
|
}
|
|
28668
28943
|
} else if (options.shell) {
|
|
28669
|
-
child = (0,
|
|
28944
|
+
child = (0, import_node_child_process35.spawn)(options.command[0], {
|
|
28670
28945
|
cwd: deps.repoPath,
|
|
28671
28946
|
stdio: "inherit",
|
|
28672
28947
|
shell: true,
|
|
@@ -28674,7 +28949,7 @@ async function execWithAppEnv(options) {
|
|
|
28674
28949
|
});
|
|
28675
28950
|
} else {
|
|
28676
28951
|
const [command, ...args] = options.command;
|
|
28677
|
-
child = (0,
|
|
28952
|
+
child = (0, import_node_child_process35.spawn)(command, args, {
|
|
28678
28953
|
cwd: deps.repoPath,
|
|
28679
28954
|
stdio: "inherit",
|
|
28680
28955
|
shell: false,
|
|
@@ -28695,11 +28970,11 @@ async function execWithAppEnv(options) {
|
|
|
28695
28970
|
deps.stopDeps();
|
|
28696
28971
|
}
|
|
28697
28972
|
}
|
|
28698
|
-
var
|
|
28973
|
+
var import_node_child_process35, import_node_net5, import_node_process, import_promises, POLL_INTERVAL_MS, DEFAULT_PORT_TIMEOUT_MS, PROCESS_TERMINATION_GRACE_MS;
|
|
28699
28974
|
var init_app_run = __esm({
|
|
28700
28975
|
"src/core/app-run.ts"() {
|
|
28701
28976
|
"use strict";
|
|
28702
|
-
|
|
28977
|
+
import_node_child_process35 = require("child_process");
|
|
28703
28978
|
import_node_net5 = __toESM(require("net"));
|
|
28704
28979
|
import_node_process = require("process");
|
|
28705
28980
|
import_promises = require("readline/promises");
|
|
@@ -29623,11 +29898,11 @@ function buildWorkspaceCleanupReport(options = {}, dependencies = {}) {
|
|
|
29623
29898
|
networkCapacity: (dependencies.inspectNetworkCapacity ?? inspectNetworkCapacity)()
|
|
29624
29899
|
};
|
|
29625
29900
|
}
|
|
29626
|
-
var
|
|
29901
|
+
var import_node_child_process36, import_node_fs53, DEFAULT_INACTIVE_FOR, READ_ONLY_GIT_ENV2, ACTIVITY_SOURCES, defaultCommandRunner;
|
|
29627
29902
|
var init_workspace_cleanup = __esm({
|
|
29628
29903
|
"src/core/workspace-cleanup.ts"() {
|
|
29629
29904
|
"use strict";
|
|
29630
|
-
|
|
29905
|
+
import_node_child_process36 = require("child_process");
|
|
29631
29906
|
import_node_fs53 = __toESM(require("fs"));
|
|
29632
29907
|
init_devpod_workspaces();
|
|
29633
29908
|
init_host_routes();
|
|
@@ -29646,7 +29921,7 @@ var init_workspace_cleanup = __esm({
|
|
|
29646
29921
|
];
|
|
29647
29922
|
defaultCommandRunner = (command, args, input2) => {
|
|
29648
29923
|
const environment = command === "git" ? READ_ONLY_GIT_ENV2 : { ...process.env, LC_ALL: "C" };
|
|
29649
|
-
const result = (0,
|
|
29924
|
+
const result = (0, import_node_child_process36.spawnSync)(command, args, {
|
|
29650
29925
|
encoding: "utf-8",
|
|
29651
29926
|
env: environment,
|
|
29652
29927
|
...input2 === void 0 ? {} : { input: input2 }
|
|
@@ -29743,7 +30018,7 @@ function defaultWorktreePath(mainRepo, ws) {
|
|
|
29743
30018
|
return import_node_path66.default.join(mainRepo, "trees", ws);
|
|
29744
30019
|
}
|
|
29745
30020
|
function assertDefaultWorktreeRootIgnored(mainRepo) {
|
|
29746
|
-
const ignored = (0,
|
|
30021
|
+
const ignored = (0, import_node_child_process37.spawnSync)("git", ["-C", mainRepo, "check-ignore", "-q", "--no-index", "trees/"], {
|
|
29747
30022
|
encoding: "utf-8"
|
|
29748
30023
|
});
|
|
29749
30024
|
if (ignored.status !== 0) {
|
|
@@ -29871,7 +30146,7 @@ function assertFullDownPreflight(mainRepo, target) {
|
|
|
29871
30146
|
`Worktree '${target.worktreePath}' is locked; unlock it before workspace down.`
|
|
29872
30147
|
);
|
|
29873
30148
|
}
|
|
29874
|
-
const status = (0,
|
|
30149
|
+
const status = (0, import_node_child_process37.spawnSync)(
|
|
29875
30150
|
"git",
|
|
29876
30151
|
["-C", target.worktreePath, "status", "--porcelain", "--untracked-files=normal"],
|
|
29877
30152
|
{ encoding: "utf-8" }
|
|
@@ -29935,11 +30210,11 @@ async function workspaceUp(branch, opts = {}) {
|
|
|
29935
30210
|
return selectedPath;
|
|
29936
30211
|
}
|
|
29937
30212
|
if (!opts.path) assertDefaultWorktreeRootIgnored(mainRepo);
|
|
29938
|
-
const add = (0,
|
|
30213
|
+
const add = (0, import_node_child_process37.spawnSync)("git", ["-C", mainRepo, "worktree", "add", selectedPath, branch], {
|
|
29939
30214
|
encoding: "utf-8"
|
|
29940
30215
|
});
|
|
29941
30216
|
if (add.status !== 0) {
|
|
29942
|
-
const addNew = (0,
|
|
30217
|
+
const addNew = (0, import_node_child_process37.spawnSync)(
|
|
29943
30218
|
"git",
|
|
29944
30219
|
["-C", mainRepo, "worktree", "add", "-b", branch, selectedPath],
|
|
29945
30220
|
{ encoding: "utf-8" }
|
|
@@ -30080,7 +30355,7 @@ async function runWorkspaceLifecycle(action2, target, opts = {}) {
|
|
|
30080
30355
|
const result = await mutateWorkspaceRuntime("delete", resolved, worktrees, opts.quiet);
|
|
30081
30356
|
if (removeWorktree) {
|
|
30082
30357
|
if (resolved.worktree && !resolved.worktree.prunable && import_node_fs54.default.existsSync(resolved.worktreePath)) {
|
|
30083
|
-
const rm = (0,
|
|
30358
|
+
const rm = (0, import_node_child_process37.spawnSync)("git", ["-C", mainRepo, "worktree", "remove", resolved.worktreePath], {
|
|
30084
30359
|
encoding: "utf-8"
|
|
30085
30360
|
});
|
|
30086
30361
|
if (rm.status !== 0) {
|
|
@@ -30106,11 +30381,11 @@ async function workspaceStop(target, opts = {}) {
|
|
|
30106
30381
|
async function workspaceDown(target, opts = {}) {
|
|
30107
30382
|
return runWorkspaceLifecycle("down", target, opts);
|
|
30108
30383
|
}
|
|
30109
|
-
var
|
|
30384
|
+
var import_node_child_process37, import_node_fs54, import_node_path66, WORKSPACE_ALLOCATION_LOCK_WAIT_MS;
|
|
30110
30385
|
var init_workspace_lifecycle = __esm({
|
|
30111
30386
|
"src/core/workspace-lifecycle.ts"() {
|
|
30112
30387
|
"use strict";
|
|
30113
|
-
|
|
30388
|
+
import_node_child_process37 = require("child_process");
|
|
30114
30389
|
import_node_fs54 = __toESM(require("fs"));
|
|
30115
30390
|
import_node_path66 = __toESM(require("path"));
|
|
30116
30391
|
init_devpod_mutation();
|
|
@@ -30296,7 +30571,7 @@ var init_version = __esm({
|
|
|
30296
30571
|
|
|
30297
30572
|
// src/cli.ts
|
|
30298
30573
|
var import_commander = require("commander");
|
|
30299
|
-
var CLI_VERSION = true ? "0.1.
|
|
30574
|
+
var CLI_VERSION = true ? "0.1.3" : "0.0.0-dev";
|
|
30300
30575
|
var VERSION_FLAGS = /* @__PURE__ */ new Set(["-V", "--version"]);
|
|
30301
30576
|
function withErrorHandling(action2) {
|
|
30302
30577
|
return async (...args) => {
|