Skip to content

Commit cf00054

Browse files
introduce ci flag for template building
1 parent d22794f commit cf00054

File tree

3 files changed

+109
-67
lines changed

3 files changed

+109
-67
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@codesandbox/sdk",
3-
"version": "2.0.0-rc.4",
3+
"version": "2.0.0-rc.5",
44
"description": "The CodeSandbox SDK",
55
"author": "CodeSandbox",
66
"license": "MIT",

src/Sandboxes.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,11 @@ export class Sandboxes {
7171
const templateId = opts?.id || this.defaultTemplateId;
7272
const privacy = opts?.privacy || "unlisted";
7373
const tags = opts?.tags || ["sdk"];
74-
const path = opts?.path || "/SDK";
74+
let path = opts?.path || "/SDK";
75+
76+
if (!path.startsWith("/")) {
77+
path = "/" + path;
78+
}
7579

7680
// Always add the "sdk" tag to the sandbox, this is used to identify sandboxes created by the SDK.
7781
const tagsWithSdk = tags.includes("sdk") ? tags : [...tags, "sdk"];

src/bin/commands/build.ts

Lines changed: 103 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export type BuildCommandArgs = {
2828
path?: string;
2929
alias?: string;
3030
ports?: number[];
31+
ci: boolean;
3132
fromSandbox?: string;
3233
skipFiles?: boolean;
3334
vmTier?: VmUpdateSpecsRequest["tier"];
@@ -71,6 +72,11 @@ export const buildCommand: yargs.CommandModule<
7172
"Alias that should point to the created template. Alias namespace defaults to template directory, but you can explicitly pass `namespace@alias`",
7273
type: "string",
7374
})
75+
.option("ci", {
76+
describe: "CI mode, will exit process if any error occurs",
77+
default: false,
78+
type: "boolean",
79+
})
7480
.positional("directory", {
7581
describe: "Path to the project that we'll create a snapshot from",
7682
type: "string",
@@ -166,8 +172,8 @@ export const buildCommand: yargs.CommandModule<
166172
})
167173
);
168174

169-
const results = await Promise.allSettled(
170-
sandboxes.map(async ({ sandboxId, filePaths, cluster }, index) => {
175+
const tasks = sandboxes.map(
176+
async ({ sandboxId, filePaths, cluster }, index) => {
171177
const clusterApiClient: Client = createClient(
172178
createConfig({
173179
baseUrl: BASE_URL,
@@ -199,14 +205,18 @@ export const buildCommand: yargs.CommandModule<
199205
`${baseUrl}/api/v1/cluster/${sandboxId}?preferredManager=${cluster}`
200206
).then((res) => res.json());
201207

202-
const startResponse = await startVm(clusterApiClient, sandboxId, {
203-
vmTier: VMTier.fromName("Micro"),
204-
});
208+
const startResponse = await withCustomError(
209+
startVm(clusterApiClient, sandboxId, {
210+
vmTier: VMTier.fromName("Micro"),
211+
}),
212+
"Failed to start sandbox"
213+
);
205214
let sandbox = new Sandbox(
206215
sandboxId,
207216
clusterApiClient,
208217
startResponse
209218
);
219+
210220
let session = await sandbox.connect();
211221

212222
spinner.start(
@@ -216,29 +226,39 @@ export const buildCommand: yargs.CommandModule<
216226
sandboxId
217227
)
218228
);
219-
let i = 0;
220-
for (const filePath of filePaths) {
221-
i++;
222-
const fullPath = path.join(argv.directory, filePath);
223-
const content = await fs.readFile(fullPath);
224-
const dirname = path.dirname(filePath);
225-
await session.fs.mkdir(dirname, true);
226-
await session.fs.writeFile(filePath, content, {
227-
create: true,
228-
overwrite: true,
229-
});
229+
try {
230+
let i = 0;
231+
for (const filePath of filePaths) {
232+
i++;
233+
const fullPath = path.join(argv.directory, filePath);
234+
const content = await fs.readFile(fullPath);
235+
const dirname = path.dirname(filePath);
236+
await session.fs.mkdir(dirname, true);
237+
await session.fs.writeFile(filePath, content, {
238+
create: true,
239+
overwrite: true,
240+
});
241+
}
242+
} catch (error) {
243+
throw new Error(`Failed to write files to sandbox: ${error}`);
230244
}
231245

232246
spinner.start(
233247
updateSpinnerMessage(index, "Restarting sandbox...", sandboxId)
234248
);
235-
sandbox = await sdk.sandboxes.restart(sandbox.id, {
236-
vmTier: argv.vmTier
237-
? VMTier.fromName(argv.vmTier)
238-
: VMTier.fromName("Micro"),
239-
});
249+
sandbox = await withCustomError(
250+
sdk.sandboxes.restart(sandbox.id, {
251+
vmTier: argv.vmTier
252+
? VMTier.fromName(argv.vmTier)
253+
: VMTier.fromName("Micro"),
254+
}),
255+
"Failed to restart sandbox"
256+
);
240257

241-
session = await sandbox.connect();
258+
session = await withCustomError(
259+
sandbox.connect(),
260+
"Failed to connect to sandbox"
261+
);
242262

243263
const disposableStore = new DisposableStore();
244264

@@ -326,7 +346,10 @@ export const buildCommand: yargs.CommandModule<
326346
spinner.start(
327347
updateSpinnerMessage(index, "Creating snapshot...", sandboxId)
328348
);
329-
await sdk.sandboxes.hibernate(sandbox.id);
349+
await withCustomError(
350+
sdk.sandboxes.hibernate(sandbox.id),
351+
"Failed to hibernate"
352+
);
330353
spinner.start(
331354
updateSpinnerMessage(index, "Snapshot created", sandboxId)
332355
);
@@ -337,64 +360,73 @@ export const buildCommand: yargs.CommandModule<
337360
updateSpinnerMessage(
338361
index,
339362
"Failed, please manually verify at https://codesandbox.io/s/" +
340-
sandboxId,
363+
sandboxId +
364+
" - " +
365+
String(error),
341366
sandboxId
342367
)
343368
);
344369

345370
throw error;
346371
}
347-
})
348-
);
349-
350-
const failedSandboxes = sandboxes.filter(
351-
(_, index) => results[index].status === "rejected"
372+
}
352373
);
353374

354-
if (failedSandboxes.length > 0) {
355-
spinner.info(`\n${spinnerMessages.join("\n")}`);
375+
if (argv.ci) {
376+
await Promise.all(tasks);
377+
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
378+
} else {
379+
const results = await Promise.allSettled(tasks);
356380

357-
await waitForEnter(
358-
`\nThere was an issue preparing the sandboxes. Verify ${failedSandboxes
359-
.map((sandbox) => sandbox.sandboxId)
360-
.join(", ")} and press ENTER to create snapshot...\n`
381+
const failedSandboxes = sandboxes.filter(
382+
(_, index) => results[index].status === "rejected"
361383
);
362384

363-
failedSandboxes.forEach(({ sandboxId }) => {
364-
updateSpinnerMessage(
365-
sandboxes.findIndex((sandbox) => sandbox.sandboxId === sandboxId),
366-
"Creating snapshot...",
367-
sandboxId
385+
if (failedSandboxes.length > 0) {
386+
spinner.info(`\n${spinnerMessages.join("\n")}`);
387+
388+
await waitForEnter(
389+
`\nThere was an issue preparing the sandboxes. Verify ${failedSandboxes
390+
.map((sandbox) => sandbox.sandboxId)
391+
.join(", ")} and press ENTER to create snapshot...\n`
368392
);
369-
});
370393

371-
spinner.start(`\n${spinnerMessages.join("\n")}`);
394+
failedSandboxes.forEach(({ sandboxId }) => {
395+
updateSpinnerMessage(
396+
sandboxes.findIndex((sandbox) => sandbox.sandboxId === sandboxId),
397+
"Creating snapshot...",
398+
sandboxId
399+
);
400+
});
372401

373-
await Promise.all(
374-
failedSandboxes.map(async ({ sandboxId, cluster }) => {
375-
const sdk = new CodeSandbox(API_KEY, {
376-
baseUrl: BASE_URL,
377-
headers: {
378-
"x-pitcher-manager-url": `https://${cluster}/api/v1`,
379-
},
380-
});
402+
spinner.start(`\n${spinnerMessages.join("\n")}`);
381403

382-
await sdk.sandboxes.hibernate(sandboxId);
404+
await Promise.all(
405+
failedSandboxes.map(async ({ sandboxId, cluster }) => {
406+
const sdk = new CodeSandbox(API_KEY, {
407+
baseUrl: BASE_URL,
408+
headers: {
409+
"x-pitcher-manager-url": `https://${cluster}/api/v1`,
410+
},
411+
});
383412

384-
spinner.start(
385-
updateSpinnerMessage(
386-
sandboxes.findIndex(
387-
(sandbox) => sandbox.sandboxId === sandboxId
388-
),
389-
"Snapshot created",
390-
sandboxId
391-
)
392-
);
393-
})
394-
);
395-
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
396-
} else {
397-
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
413+
await sdk.sandboxes.hibernate(sandboxId);
414+
415+
spinner.start(
416+
updateSpinnerMessage(
417+
sandboxes.findIndex(
418+
(sandbox) => sandbox.sandboxId === sandboxId
419+
),
420+
"Snapshot created",
421+
sandboxId
422+
)
423+
);
424+
})
425+
);
426+
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
427+
} else {
428+
spinner.succeed(`\n${spinnerMessages.join("\n")}`);
429+
}
398430
}
399431

400432
const data = handleResponse(
@@ -444,6 +476,12 @@ type CreateSandboxParams = {
444476
ipcountry?: string;
445477
};
446478

479+
function withCustomError<T extends Promise<any>>(promise: T, message: string) {
480+
return promise.catch((error) => {
481+
throw new Error(message + ": " + error.message);
482+
});
483+
}
484+
447485
function waitForEnter(message: string) {
448486
const rl = readline.createInterface({
449487
input: process.stdin,

0 commit comments

Comments
 (0)