vercel-vm-factory 0.10.8 → 0.12.8

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.
Files changed (3) hide show
  1. package/README.md +1 -1
  2. package/deploy-vm.mjs +84 -43
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -78,7 +78,7 @@ Choosing bash or zsh adds the matching package to the generated Dockerfile when
78
78
 
79
79
  Generated shell setup examples:
80
80
 
81
- - Alpine + `/bin/zsh`: installs `zsh curl git`, installs oh-my-zsh unattended, and writes `/root/.zshrc`.
81
+ - Alpine + `/bin/zsh`: installs `zsh curl git`, clones oh-my-zsh into `/root/.oh-my-zsh`, and writes `/root/.zshrc`.
82
82
  - Ubuntu/Debian + `/bin/bash`: installs `bash` with `apt-get`.
83
83
  - `/bin/sh`: no extra shell package is installed.
84
84
 
package/deploy-vm.mjs CHANGED
@@ -187,43 +187,30 @@ async function main() {
187
187
  )
188
188
  : "";
189
189
 
190
- await writeDefaults(defaultsPath, {
191
- ...defaults,
192
- "vm-image": vmImageName,
193
- scope: scope || undefined,
194
- project,
195
- from: wsShellImage,
196
- shell,
197
- tools,
198
- "auth-mode": authMode,
199
- "auth-user": authUsername,
200
- "auth-password": authPassword,
201
- "client-id": githubClientId,
202
- "client-secret": githubClientSecret,
203
- "github-userid": allowedUserIds,
204
- });
205
-
206
- const commonArgs = [];
207
- if (args.token) commonArgs.push("--token", args.token);
208
- if (scope) commonArgs.push("--scope", scope);
190
+ let activeScope = scope;
191
+ const commonArgs = () => makeCommonArgs(activeScope);
209
192
 
210
193
  if (!skipLink) {
211
194
  step("Linking Vercel project");
212
- await runNoUrl("vercel", [
213
- "link",
214
- "--yes",
215
- "--project",
216
- project,
217
- "--cwd",
218
- appDir,
219
- ...commonArgs,
220
- ]);
195
+ await withScopeFallback(activeScope, async () =>
196
+ runNoUrl("vercel", [
197
+ "link",
198
+ "--yes",
199
+ "--project",
200
+ project,
201
+ "--cwd",
202
+ appDir,
203
+ ...commonArgs(),
204
+ ]),
205
+ );
221
206
  } else {
222
207
  warn("skip-link enabled; using existing .vercel/project.json");
223
208
  }
224
209
 
225
210
  step("Setting project framework=container");
226
- await setContainerFramework(appDir, commonArgs);
211
+ await withScopeFallback(activeScope, async () =>
212
+ setContainerFramework(appDir, commonArgs()),
213
+ );
227
214
 
228
215
  const vercelArgs = ["deploy", appDir, "--yes", "--logs"];
229
216
 
@@ -238,13 +225,40 @@ async function main() {
238
225
  if (allowedUserIds)
239
226
  vercelArgs.push("--env", `ALLOWED_USER_IDS=${allowedUserIds}`);
240
227
  if (prod) vercelArgs.push("--prod");
241
- vercelArgs.push(...commonArgs);
242
228
 
243
229
  step("Deploying");
244
- const deploymentUrl = await run("vercel", vercelArgs);
230
+ const deploymentUrl = await withScopeFallback(activeScope, async () =>
231
+ run("vercel", [...vercelArgs, ...commonArgs()]),
232
+ );
233
+ await writeDefaults(defaultsPath, {
234
+ ...defaults,
235
+ "vm-image": vmImageName,
236
+ scope: activeScope || undefined,
237
+ project,
238
+ from: wsShellImage,
239
+ shell,
240
+ tools,
241
+ "auth-mode": authMode,
242
+ "auth-user": authUsername,
243
+ "auth-password": authPassword,
244
+ "client-id": githubClientId,
245
+ "client-secret": githubClientSecret,
246
+ "github-userid": allowedUserIds,
247
+ });
245
248
  console.log(
246
249
  `\n${color.green("Deployment URL:")} ${color.bold(deploymentUrl)}`,
247
250
  );
251
+
252
+ async function withScopeFallback(scopeValue, action) {
253
+ try {
254
+ return await action();
255
+ } catch (error) {
256
+ if (!scopeValue || !isMissingScope(error)) throw error;
257
+ warn(`scope "${scopeValue}" not found; retrying with default Vercel scope`);
258
+ activeScope = "";
259
+ return action();
260
+ }
261
+ }
248
262
  }
249
263
 
250
264
  async function setContainerFramework(appDir, commonArgs) {
@@ -366,7 +380,7 @@ function makeDockerfile({ shell, tools, vmImage, vmImageName, wsShellImage }) {
366
380
  const shellInstall = makeShellInstall({ shell, vmImageName });
367
381
  const ohMyZshInstall =
368
382
  path.basename(shell) === "zsh"
369
- ? `RUN RUNZSH=no CHSH=no KEEP_ZSHRC=no sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" "" --unattended \\
383
+ ? `RUN git clone --depth=1 https://github.com/ohmyzsh/ohmyzsh.git /root/.oh-my-zsh \\
370
384
  && printf '%s\\n' \\
371
385
  'export ZSH="$HOME/.oh-my-zsh"' \\
372
386
  'ZSH_THEME="robbyrussell"' \\
@@ -383,14 +397,14 @@ ARG VM_IMAGE=${vmImage}
383
397
 
384
398
  FROM \${WS_SHELL_IMAGE} AS ws-shell
385
399
  FROM \${VM_IMAGE} AS vm
400
+ ENV HOME=/root
401
+ ENV SHELL=${shell}
386
402
  ${shellSetup ? `\n${shellSetup}\n` : ""}
387
403
  # wsterm already embeds the web UI; runtime config comes from environment variables.
388
404
  COPY --from=ws-shell /app/bin/wsterm /app/bin/wsterm
389
405
 
390
406
  WORKDIR /app
391
407
  ENV ENABLE_SSL=false
392
- ENV HOME=/root
393
- ENV SHELL=${shell}
394
408
  EXPOSE 80
395
409
  CMD ["/app/bin/wsterm","-bind",":80","-fork","${shell}"]
396
410
  `;
@@ -713,23 +727,37 @@ function parseCommand(argv) {
713
727
  return { command: "create", args: parseArgs(argv) };
714
728
  }
715
729
 
730
+ function makeCommonArgs(scope) {
731
+ const commonArgs = [];
732
+ if (args.token) commonArgs.push("--token", args.token);
733
+ if (scope) commonArgs.push("--scope", scope);
734
+ return commonArgs;
735
+ }
736
+
737
+ function isMissingScope(error) {
738
+ return String(error?.message || error).includes("scope does not exist");
739
+ }
740
+
716
741
  function run(command, commandArgs) {
717
742
  return new Promise((resolve, reject) => {
718
743
  let seenUrl = "";
744
+ let text = "";
719
745
  const child = spawn(command, commandArgs, {
720
746
  stdio: ["inherit", "pipe", "pipe"],
721
747
  });
722
748
 
723
749
  child.stdout.on("data", (chunk) => {
724
- const text = chunk.toString();
725
- output.write(text);
726
- seenUrl = findLastUrl(text) || seenUrl;
750
+ const chunkText = chunk.toString();
751
+ text += chunkText;
752
+ output.write(chunkText);
753
+ seenUrl = findLastUrl(chunkText) || seenUrl;
727
754
  });
728
755
 
729
756
  child.stderr.on("data", (chunk) => {
730
- const text = chunk.toString();
731
- output.write(text);
732
- seenUrl = findLastUrl(text) || seenUrl;
757
+ const chunkText = chunk.toString();
758
+ text += chunkText;
759
+ output.write(chunkText);
760
+ seenUrl = findLastUrl(chunkText) || seenUrl;
733
761
  });
734
762
 
735
763
  child.on("error", reject);
@@ -737,7 +765,7 @@ function run(command, commandArgs) {
737
765
  if (code === 0 && seenUrl) resolve(seenUrl);
738
766
  else if (code === 0)
739
767
  reject(new Error("vercel finished but no deployment url was found"));
740
- else reject(new Error(`vercel exited with code ${code}`));
768
+ else reject(new Error(text.trim() || `vercel exited with code ${code}`));
741
769
  });
742
770
  });
743
771
  }
@@ -765,11 +793,24 @@ function runCapture(command, commandArgs) {
765
793
 
766
794
  function runNoUrl(command, commandArgs) {
767
795
  return new Promise((resolve, reject) => {
768
- const child = spawn(command, commandArgs, { stdio: "inherit" });
796
+ let text = "";
797
+ const child = spawn(command, commandArgs, {
798
+ stdio: ["inherit", "pipe", "pipe"],
799
+ });
800
+ child.stdout.on("data", (chunk) => {
801
+ const chunkText = chunk.toString();
802
+ text += chunkText;
803
+ output.write(chunkText);
804
+ });
805
+ child.stderr.on("data", (chunk) => {
806
+ const chunkText = chunk.toString();
807
+ text += chunkText;
808
+ output.write(chunkText);
809
+ });
769
810
  child.on("error", reject);
770
811
  child.on("close", (code) => {
771
812
  if (code === 0) resolve();
772
- else reject(new Error(`${command} exited with code ${code}`));
813
+ else reject(new Error(text.trim() || `${command} exited with code ${code}`));
773
814
  });
774
815
  });
775
816
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vercel-vm-factory",
3
- "version": "0.10.8",
3
+ "version": "0.12.8",
4
4
  "description": "Create Vercel Container deployments for ws-shell from selectable VM images.",
5
5
  "license": "MIT",
6
6
  "type": "module",