run-spaceapp 0.1.5 → 0.1.7

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/README.md CHANGED
@@ -24,10 +24,15 @@ The launcher requires Node.js 20.11 or newer, 4 CPUs, 8 GB RAM, and 15 GiB free
24
24
  disk. If Docker is missing, `spaceapp install` automatically installs it from
25
25
  official Docker sources on Windows, macOS, Ubuntu, Debian, Fedora, RHEL, and
26
26
  CentOS, starts it, and waits for Engine and Compose readiness before pulling
27
- images. Docker Desktop license acceptance and Linux `docker` group membership
28
- require confirmation inside the same command. On Windows, approve the UAC
29
- prompt if WSL2 must be enabled. If Windows requests one restart, rerun the same
30
- command afterward and installation continues safely.
27
+ images. Windows prefers Windows Package Manager's hash-pinned Docker Desktop
28
+ manifest and retains a signed direct-download fallback. Docker Desktop license
29
+ acceptance and Linux `docker` group membership require confirmation inside the
30
+ same command. On Windows, approve any UAC prompt required by WSL2 or Docker
31
+ Desktop. On Docker Desktop's first launch, select **Skip** in the top-right of
32
+ the **Welcome to Docker** window (or sign in), accept any remaining Docker
33
+ prompt, and keep the terminal open. SpaceApp waits for up to ten minutes and
34
+ continues automatically when Docker is ready. If Windows requests one restart,
35
+ rerun `spaceapp install` afterward and installation continues safely.
31
36
 
32
37
  The launcher selects the `light` profile below 12 GiB RAM and the `standard`
33
38
  profile otherwise; override this with `--profile light` or
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "run-spaceapp",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "Cross-platform Docker launcher for the SpaceApp self-hosted agent workspace",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -45,5 +45,5 @@
45
45
  "access": "public",
46
46
  "provenance": true
47
47
  },
48
- "gitHead": "e5e8bcd4f3250068785181faa8152c6795f624c9"
48
+ "gitHead": "3f5612291d2aea84f1a763c8b094ec0f42208fd1"
49
49
  }
package/src/cli.mjs CHANGED
@@ -35,6 +35,7 @@ const trustedCommands = new Set([
35
35
  "sg",
36
36
  "spctl",
37
37
  "sudo",
38
+ "winget.exe",
38
39
  "wsl.exe",
39
40
  "xdg-open"
40
41
  ]);
@@ -583,6 +584,7 @@ function spawnTrustedCommand(spec, options) {
583
584
  case "sg": return spawn("sg", args, options);
584
585
  case "spctl": return spawn("spctl", args, options);
585
586
  case "sudo": return spawn("sudo", args, options);
587
+ case "winget.exe": return spawn("winget.exe", args, options);
586
588
  case "wsl.exe": return spawn("wsl.exe", args, options);
587
589
  case "xdg-open": return spawn("xdg-open", args, options);
588
590
  default: throw new Error("SpaceApp refused to execute an untrusted command.");
@@ -19,6 +19,19 @@ const MAC_DOCKER_DOWNLOADS = Object.freeze({
19
19
  x64: "https://desktop.docker.com/mac/main/amd64/Docker.dmg",
20
20
  arm64: "https://desktop.docker.com/mac/main/arm64/Docker.dmg"
21
21
  });
22
+ // Sources:
23
+ // https://learn.microsoft.com/windows/package-manager/winget/install
24
+ // https://github.com/microsoft/winget-pkgs/tree/master/manifests/d/Docker/DockerDesktop
25
+ const WINDOWS_DOCKER_WINGET_ARGS = Object.freeze([
26
+ "install",
27
+ "--id", "Docker.DockerDesktop",
28
+ "--exact",
29
+ "--source", "winget",
30
+ "--silent",
31
+ "--accept-package-agreements",
32
+ "--accept-source-agreements",
33
+ "--disable-interactivity"
34
+ ]);
22
35
 
23
36
  export function windowsPowerShellArgs(operation) {
24
37
  const scripts = {
@@ -169,6 +182,35 @@ async function ensureWindowsDocker({
169
182
  }
170
183
  }
171
184
 
185
+ if (!application) {
186
+ const wingetCode = await execute(
187
+ { command: "winget.exe", args: ["--version"] },
188
+ { stdin, stdout: null, stderr: null }
189
+ );
190
+ if (wingetCode === 0) {
191
+ stdout.write(
192
+ "Installing Docker Desktop through Windows Package Manager with manifest hash verification...\n"
193
+ );
194
+ const installCode = await execute(
195
+ { command: "winget.exe", args: [...WINDOWS_DOCKER_WINGET_ARGS] },
196
+ { stdin, stdout, stderr }
197
+ );
198
+ if (installCode === 0) {
199
+ application = await firstExisting(paths.applications, pathExists);
200
+ if (!application) {
201
+ stderr.write(
202
+ "Windows Package Manager reported success, but Docker Desktop could not be found.\n"
203
+ );
204
+ return { code: 1, reexecuted: false };
205
+ }
206
+ } else {
207
+ stdout.write(
208
+ "Windows Package Manager could not install Docker Desktop; trying Docker's signed direct installer...\n"
209
+ );
210
+ }
211
+ }
212
+ }
213
+
172
214
  if (!application) {
173
215
  const downloadUrl = WINDOWS_DOCKER_DOWNLOADS[arch];
174
216
  if (!downloadUrl) {
@@ -220,6 +262,15 @@ async function ensureWindowsDocker({
220
262
  if (cliDirectory) {
221
263
  prependPath(env, cliDirectory);
222
264
  }
265
+ stdout.write(
266
+ "Opening Docker Desktop for its first-run setup.\n" +
267
+ "If Docker shows \"Welcome to Docker\", select \"Skip\" in the top-right (or sign in), and accept any remaining Docker prompt.\n" +
268
+ "Keep this terminal open; SpaceApp will continue automatically when Docker is ready (up to 10 minutes).\n"
269
+ );
270
+ await execute(
271
+ { command: "docker", args: ["desktop", "start", "--detach"] },
272
+ { stdin, stdout: null, stderr: null }
273
+ );
223
274
  const launchCode = await launch({
224
275
  operation: "start-docker-desktop",
225
276
  env: {
@@ -230,12 +281,12 @@ async function ensureWindowsDocker({
230
281
  stderr.write("Docker Desktop is installed, but SpaceApp could not start it.\n");
231
282
  return { code: launchCode, reexecuted: false };
232
283
  }
233
- if (await waitForDocker({ execute, sleep })) {
284
+ if (await waitForDocker({ execute, sleep, attempts: 300 })) {
234
285
  stdout.write("Docker Desktop is ready.\n");
235
286
  return { code: 0, reexecuted: false };
236
287
  }
237
288
  stderr.write(
238
- "Docker Desktop was installed but did not become ready. Complete any Docker Desktop prompt or restart Windows if requested, then run the same SpaceApp command again.\n"
289
+ "Docker Desktop did not become ready after 10 minutes. Open Docker Desktop and complete its first-run setup (select \"Skip\" on \"Welcome to Docker\" or sign in), restart Windows if requested, then run \"spaceapp install\" again.\n"
239
290
  );
240
291
  return { code: 1, reexecuted: false };
241
292
  }
@@ -653,12 +704,14 @@ function shellQuote(value) {
653
704
  return `'${String(value).replaceAll("'", "'\\''")}'`;
654
705
  }
655
706
 
656
- async function waitForDocker({ execute, sleep }) {
657
- for (let attempt = 0; attempt < 90; attempt += 1) {
707
+ async function waitForDocker({ execute, sleep, attempts = 90 }) {
708
+ for (let attempt = 0; attempt <= attempts; attempt += 1) {
658
709
  if (await dockerIsReady(execute)) {
659
710
  return true;
660
711
  }
661
- await sleep(2_000);
712
+ if (attempt < attempts) {
713
+ await sleep(2_000);
714
+ }
662
715
  }
663
716
  return false;
664
717
  }