cicy-desktop 2.1.99 → 2.1.101
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/package.json +1 -1
- package/src/sidecar/docker.js +58 -8
package/package.json
CHANGED
package/src/sidecar/docker.js
CHANGED
|
@@ -28,9 +28,30 @@ const DOCKER_DESKTOP_MIRROR = process.env.CICY_DOCKER_DESKTOP_MIRROR
|
|
|
28
28
|
// CICY_* env vars forwarded into the container (team onboarding, version pin…).
|
|
29
29
|
const PASS_ENV = ["CICY_TEAM_TOKEN", "CICY_CODE_VERSION", "NPM_REGISTRY", "CICY_NPM_REGISTRY", "CICY_AGENTS", "ENABLE_CDN", "CICY_CLOUDFLARED_TOKEN"];
|
|
30
30
|
|
|
31
|
+
// Resolve the docker CLI. CRITICAL on Windows: right after Docker Desktop
|
|
32
|
+
// installs, it adds `...\Docker\resources\bin` to the SYSTEM PATH — but the
|
|
33
|
+
// ALREADY-RUNNING cicy-desktop process keeps its stale PATH, so a bare
|
|
34
|
+
// `execFile("docker", …)` ENOENTs and dockerOk() stays false forever (the
|
|
35
|
+
// "已安装但起不来 / 卡在正在启动" bug). Probe the known absolute install paths
|
|
36
|
+
// first; only fall back to PATH (and never cache that fallback, so a later
|
|
37
|
+
// install is picked up).
|
|
38
|
+
let _dockerBin = null;
|
|
39
|
+
function dockerBin() {
|
|
40
|
+
if (_dockerBin) return _dockerBin;
|
|
41
|
+
if (process.platform === "win32") {
|
|
42
|
+
const cands = [
|
|
43
|
+
path.join(process.env["ProgramFiles"] || "C:\\Program Files", "Docker", "Docker", "resources", "bin", "docker.exe"),
|
|
44
|
+
path.join(process.env["ProgramW6432"] || "", "Docker", "Docker", "resources", "bin", "docker.exe"),
|
|
45
|
+
path.join(process.env["LOCALAPPDATA"] || "", "Docker", "Docker", "resources", "bin", "docker.exe"),
|
|
46
|
+
].filter((c) => c && !c.startsWith("Docker"));
|
|
47
|
+
for (const c of cands) { try { if (fs.existsSync(c)) { _dockerBin = c; return c; } } catch {} }
|
|
48
|
+
}
|
|
49
|
+
return "docker"; // PATH fallback (mac/linux, or before Docker is installed)
|
|
50
|
+
}
|
|
51
|
+
|
|
31
52
|
function run(args, { timeout = 30000 } = {}) {
|
|
32
53
|
return new Promise((resolve, reject) => {
|
|
33
|
-
execFile(
|
|
54
|
+
execFile(dockerBin(), args, { timeout, windowsHide: true }, (err, stdout, stderr) => {
|
|
34
55
|
if (err) { err.stdout = String(stdout || ""); err.stderr = String(stderr || ""); return reject(err); }
|
|
35
56
|
resolve({ stdout: String(stdout), stderr: String(stderr) });
|
|
36
57
|
});
|
|
@@ -387,15 +408,44 @@ async function installDocker({ emit, dest } = {}) {
|
|
|
387
408
|
await ensureDownloaded(DOCKER_DESKTOP_URL, target, DOCKER_DESKTOP_MIRROR, {
|
|
388
409
|
emit, phase: "install-docker", label: "下载 Docker Desktop",
|
|
389
410
|
});
|
|
390
|
-
e({ phase: "install-docker", status: "running", message: "安装 Docker Desktop
|
|
391
|
-
await
|
|
411
|
+
e({ phase: "install-docker", status: "running", message: "安装 Docker Desktop(请在弹出的管理员授权框点「是」,装完可能需重启)…" });
|
|
412
|
+
await launchElevated(target, ["install", "--quiet", "--accept-license"], { emit: e });
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// Run an admin-manifest exe (Docker Desktop Installer) ELEVATED. A plain
|
|
416
|
+
// child_process.spawn of a requireAdministrator exe from a non-elevated process
|
|
417
|
+
// fails with ERROR_ELEVATION_REQUIRED (740) and never shows UAC — which is why
|
|
418
|
+
// the installer "downloaded but didn't auto-install". ShellExecute with the
|
|
419
|
+
// "runas" verb is the only way to raise the UAC prompt + elevate. We drive it
|
|
420
|
+
// via VBScript/cscript because PowerShell is blocked by 360 on these machines.
|
|
421
|
+
// ShellExecute returns immediately (installer runs in the background); bootstrap
|
|
422
|
+
// then polls dockerOk(). Falls back to a direct spawn if cscript is unavailable.
|
|
423
|
+
function launchElevated(exe, args, { emit } = {}) {
|
|
424
|
+
return new Promise((resolve) => {
|
|
392
425
|
try {
|
|
393
|
-
const
|
|
394
|
-
|
|
426
|
+
const vbs = path.join(os.tmpdir(), "cicy-docker-elevate.vbs");
|
|
427
|
+
const argStr = args.join(" ").replace(/"/g, '""');
|
|
428
|
+
const exeEsc = String(exe).replace(/"/g, '""');
|
|
429
|
+
// chr(34) = a literal double-quote inside the VBS string literals.
|
|
430
|
+
fs.writeFileSync(vbs,
|
|
431
|
+
`Set s = CreateObject("Shell.Application")\r\n` +
|
|
432
|
+
`s.ShellExecute "${exeEsc}", "${argStr}", "", "runas", 1\r\n`,
|
|
433
|
+
"utf8");
|
|
434
|
+
const child = spawn("cscript", ["//nologo", vbs], { windowsHide: true, detached: true, stdio: "ignore" });
|
|
435
|
+
let done = false;
|
|
436
|
+
const fin = (ok) => { if (done) return; done = true; resolve(ok); };
|
|
437
|
+
child.on("error", () => {
|
|
438
|
+
// cscript missing/blocked → best-effort direct spawn (works if elevated).
|
|
439
|
+
try {
|
|
440
|
+
emit && emit({ phase: "install-docker", status: "running", message: "提权脚本不可用,尝试直接启动安装包…" });
|
|
441
|
+
const c2 = spawn(exe, args, { windowsHide: false, detached: true, stdio: "ignore" });
|
|
442
|
+
c2.on("error", () => fin(false));
|
|
443
|
+
c2.on("spawn", () => fin(true));
|
|
444
|
+
c2.on("exit", () => fin(true));
|
|
445
|
+
} catch { fin(false); }
|
|
395
446
|
});
|
|
396
|
-
child.on("
|
|
397
|
-
|
|
398
|
-
} catch { resolve(); }
|
|
447
|
+
child.on("exit", () => fin(true));
|
|
448
|
+
} catch { resolve(false); }
|
|
399
449
|
});
|
|
400
450
|
}
|
|
401
451
|
|