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.
- package/README.md +1 -1
- package/deploy-vm.mjs +84 -43
- 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`,
|
|
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
|
-
|
|
191
|
-
|
|
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
|
|
213
|
-
"
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
725
|
-
|
|
726
|
-
|
|
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
|
|
731
|
-
|
|
732
|
-
|
|
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
|
-
|
|
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
|
}
|