@getmonoceros/workbench 1.11.4 → 1.11.6
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/bin.js +109 -55
- package/dist/bin.js.map +1 -1
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -3953,18 +3953,68 @@ var spawnDockerCompose = (args, cwd) => {
|
|
|
3953
3953
|
child.on("exit", (code) => resolve(code ?? 0));
|
|
3954
3954
|
});
|
|
3955
3955
|
};
|
|
3956
|
-
var
|
|
3956
|
+
var spawnDocker = (args) => {
|
|
3957
3957
|
return new Promise((resolve, reject) => {
|
|
3958
|
-
const child = spawn5("
|
|
3959
|
-
|
|
3960
|
-
|
|
3958
|
+
const child = spawn5("docker", args, {
|
|
3959
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
3960
|
+
});
|
|
3961
|
+
let stdout = "";
|
|
3962
|
+
let stderr = "";
|
|
3963
|
+
child.stdout?.on("data", (chunk) => {
|
|
3964
|
+
stdout += chunk.toString("utf8");
|
|
3965
|
+
});
|
|
3966
|
+
child.stderr?.on("data", (chunk) => {
|
|
3967
|
+
stderr += chunk.toString("utf8");
|
|
3961
3968
|
});
|
|
3962
|
-
child.stdout?.pipe(createSecretMaskStream()).pipe(process.stdout);
|
|
3963
3969
|
child.stderr?.pipe(createSecretMaskStream()).pipe(process.stderr);
|
|
3964
3970
|
child.on("error", reject);
|
|
3965
|
-
child.on(
|
|
3971
|
+
child.on(
|
|
3972
|
+
"exit",
|
|
3973
|
+
(code) => resolve({ exitCode: code ?? 0, stdout, stderr })
|
|
3974
|
+
);
|
|
3966
3975
|
});
|
|
3967
3976
|
};
|
|
3977
|
+
async function findContainerIds(filters, exec = spawnDocker) {
|
|
3978
|
+
const ids = /* @__PURE__ */ new Set();
|
|
3979
|
+
for (const filter of filters) {
|
|
3980
|
+
const result = await exec(["ps", "-aq", "--filter", filter]);
|
|
3981
|
+
if (result.exitCode !== 0) continue;
|
|
3982
|
+
for (const line of result.stdout.split(/\r?\n/)) {
|
|
3983
|
+
const id = line.trim();
|
|
3984
|
+
if (id) ids.add(id);
|
|
3985
|
+
}
|
|
3986
|
+
}
|
|
3987
|
+
return [...ids];
|
|
3988
|
+
}
|
|
3989
|
+
async function cleanupDockerObjects(opts) {
|
|
3990
|
+
const exec = opts.exec ?? spawnDocker;
|
|
3991
|
+
const tag = opts.logTag ?? "cleanup";
|
|
3992
|
+
opts.logger.info(`[${tag}] tearing down docker project ${opts.projectName}\u2026`);
|
|
3993
|
+
const ids = await findContainerIds(opts.filters, exec);
|
|
3994
|
+
let rmExit = 0;
|
|
3995
|
+
if (ids.length > 0) {
|
|
3996
|
+
opts.logger.info(`[${tag}] removing containers: ${ids.join(" ")}`);
|
|
3997
|
+
const rmResult = await exec(["rm", "-f", ...ids]);
|
|
3998
|
+
rmExit = rmResult.exitCode;
|
|
3999
|
+
} else {
|
|
4000
|
+
opts.logger.info(`[${tag}] no containers found`);
|
|
4001
|
+
}
|
|
4002
|
+
if (opts.network) {
|
|
4003
|
+
const netResult = await exec(["network", "rm", opts.network]);
|
|
4004
|
+
if (netResult.exitCode === 0) {
|
|
4005
|
+
opts.logger.info(`[${tag}] network ${opts.network} removed`);
|
|
4006
|
+
}
|
|
4007
|
+
}
|
|
4008
|
+
opts.logger.info(`[${tag}] docker cleanup done`);
|
|
4009
|
+
return { exitCode: rmExit, removedIds: ids };
|
|
4010
|
+
}
|
|
4011
|
+
function dockerLocalFolderLabel(p) {
|
|
4012
|
+
if (process.platform !== "win32") return p;
|
|
4013
|
+
return p.replace(
|
|
4014
|
+
/^([A-Z]):/,
|
|
4015
|
+
(_, drive) => `${drive.toLowerCase()}:`
|
|
4016
|
+
);
|
|
4017
|
+
}
|
|
3968
4018
|
function composeProjectName(root) {
|
|
3969
4019
|
return `${path11.basename(root)}_devcontainer`;
|
|
3970
4020
|
}
|
|
@@ -4005,22 +4055,31 @@ async function runContainerCycle(root, opts) {
|
|
|
4005
4055
|
logger.info(
|
|
4006
4056
|
`Force-removing existing ${projectName} containers (volumes preserved)\u2026`
|
|
4007
4057
|
);
|
|
4008
|
-
const
|
|
4009
|
-
const
|
|
4010
|
-
`
|
|
4011
|
-
`
|
|
4012
|
-
|
|
4013
|
-
|
|
4014
|
-
|
|
4015
|
-
|
|
4016
|
-
|
|
4017
|
-
|
|
4018
|
-
|
|
4019
|
-
|
|
4020
|
-
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4058
|
+
const exec = opts.dockerExec ?? spawnDocker;
|
|
4059
|
+
const filters = [
|
|
4060
|
+
`label=com.docker.compose.project=${projectName}`,
|
|
4061
|
+
`name=^${projectName}-`
|
|
4062
|
+
];
|
|
4063
|
+
const { exitCode: rmExit } = await cleanupDockerObjects({
|
|
4064
|
+
projectName,
|
|
4065
|
+
filters,
|
|
4066
|
+
network: `${projectName}_default`,
|
|
4067
|
+
logger,
|
|
4068
|
+
exec
|
|
4069
|
+
});
|
|
4070
|
+
if (rmExit !== 0) return rmExit;
|
|
4071
|
+
const remaining = await findContainerIds(filters, exec);
|
|
4072
|
+
if (remaining.length > 0) {
|
|
4073
|
+
const warn = logger.warn ?? logger.info;
|
|
4074
|
+
warn(
|
|
4075
|
+
`ERROR: containers under project ${projectName} reappeared after removal.
|
|
4076
|
+
This typically means VS Code's Remote Containers extension is connected
|
|
4077
|
+
to this devcontainer and auto-recreated it. Close the dev container
|
|
4078
|
+
session in VS Code (Cmd+Shift+P \u2192 'Dev Containers: Close Remote Connection')
|
|
4079
|
+
and retry \`monoceros apply\`.`
|
|
4080
|
+
);
|
|
4081
|
+
return 1;
|
|
4082
|
+
}
|
|
4024
4083
|
return runStart({
|
|
4025
4084
|
root,
|
|
4026
4085
|
...opts.devcontainerSpawn ? { spawn: opts.devcontainerSpawn } : {},
|
|
@@ -4593,7 +4652,7 @@ ${sectionLine(label)}
|
|
|
4593
4652
|
}
|
|
4594
4653
|
const exitCode = await runContainerCycle(targetDir, {
|
|
4595
4654
|
hasCompose: needsCompose(createOpts),
|
|
4596
|
-
...opts.
|
|
4655
|
+
...opts.dockerExec !== void 0 ? { dockerExec: opts.dockerExec } : {},
|
|
4597
4656
|
...opts.devcontainerSpawn !== void 0 ? { devcontainerSpawn: opts.devcontainerSpawn } : {},
|
|
4598
4657
|
logger
|
|
4599
4658
|
});
|
|
@@ -4697,7 +4756,7 @@ async function persistPromptedIdentity(prompted, ymlPath, home, logger) {
|
|
|
4697
4756
|
}
|
|
4698
4757
|
|
|
4699
4758
|
// src/version.ts
|
|
4700
|
-
var CLI_VERSION = true ? "1.11.
|
|
4759
|
+
var CLI_VERSION = true ? "1.11.6" : "dev";
|
|
4701
4760
|
|
|
4702
4761
|
// src/commands/_dispatch.ts
|
|
4703
4762
|
import { consola as consola12 } from "consola";
|
|
@@ -6154,30 +6213,20 @@ async function runRemove(opts) {
|
|
|
6154
6213
|
);
|
|
6155
6214
|
}
|
|
6156
6215
|
const projectName = composeProjectName(containerPath);
|
|
6157
|
-
const
|
|
6158
|
-
const
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
`by_compose_name=$(docker ps -aq --filter "name=^${projectName}-" 2>/dev/null || true)`,
|
|
6172
|
-
// Image-mode devcontainer-cli name fallback (only kicks in when
|
|
6173
|
-
// the cli used a deterministic name — modern versions don't).
|
|
6174
|
-
`by_image_name=$(docker ps -aq --filter "name=^vsc-${opts.name}-" 2>/dev/null || true)`,
|
|
6175
|
-
`to_remove=$(printf "%s\\n%s\\n%s\\n%s\\n" "$by_label" "$by_dc_label" "$by_compose_name" "$by_image_name" | sort -u | grep -v "^$" || true)`,
|
|
6176
|
-
`if [ -n "$to_remove" ]; then echo "[remove] removing containers: $(echo $to_remove | tr "\\n" " ")"; docker rm -f $to_remove >/dev/null || true; else echo "[remove] no containers found"; fi`,
|
|
6177
|
-
`docker network rm ${projectName}_default 2>/dev/null && echo "[remove] network ${projectName}_default removed" || true`,
|
|
6178
|
-
`echo "[remove] docker cleanup done"`
|
|
6179
|
-
].join("; ");
|
|
6180
|
-
const dockerExitCode = await dockerSpawn(["-c", script], home);
|
|
6216
|
+
const dockerExec = opts.dockerExec ?? spawnDocker;
|
|
6217
|
+
const { exitCode: dockerExitCode } = await cleanupDockerObjects({
|
|
6218
|
+
projectName,
|
|
6219
|
+
filters: [
|
|
6220
|
+
`label=com.docker.compose.project=${projectName}`,
|
|
6221
|
+
`label=devcontainer.local_folder=${dockerLocalFolderLabel(containerPath)}`,
|
|
6222
|
+
`name=^${projectName}-`,
|
|
6223
|
+
`name=^vsc-${opts.name}-`
|
|
6224
|
+
],
|
|
6225
|
+
network: `${projectName}_default`,
|
|
6226
|
+
logTag: "remove",
|
|
6227
|
+
logger,
|
|
6228
|
+
exec: dockerExec
|
|
6229
|
+
});
|
|
6181
6230
|
let backupPath = null;
|
|
6182
6231
|
if (!opts.noBackup && (hasYml || hasContainer)) {
|
|
6183
6232
|
const ts = (opts.now ?? /* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
@@ -6207,13 +6256,18 @@ async function runRemove(opts) {
|
|
|
6207
6256
|
logger.info(
|
|
6208
6257
|
`[remove] host-side rm hit ${code} on ${prettyPath(containerPath)}; using a throw-away alpine container to clean root-owned files\u2026`
|
|
6209
6258
|
);
|
|
6210
|
-
const exit = await
|
|
6211
|
-
|
|
6212
|
-
|
|
6213
|
-
|
|
6214
|
-
|
|
6215
|
-
|
|
6216
|
-
|
|
6259
|
+
const { exitCode: exit } = await dockerExec([
|
|
6260
|
+
"run",
|
|
6261
|
+
"--rm",
|
|
6262
|
+
"-v",
|
|
6263
|
+
`${containerPath}:/target`,
|
|
6264
|
+
"alpine:3.21",
|
|
6265
|
+
"find",
|
|
6266
|
+
"/target",
|
|
6267
|
+
"-mindepth",
|
|
6268
|
+
"1",
|
|
6269
|
+
"-delete"
|
|
6270
|
+
]);
|
|
6217
6271
|
if (exit !== 0) {
|
|
6218
6272
|
throw new Error(
|
|
6219
6273
|
`docker-based cleanup of ${containerPath} exited ${exit}. Inspect with \`sudo ls -la ${containerPath}\` and clean manually.`
|