@zuplo/cli 1.8.0 → 1.10.0

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.
@@ -1,4 +1,7 @@
1
- export function printToConsole(message, ...optionalParams) {
1
+ export function logDiagnosticsToConsole(message, ...optionalParams) {
2
+ console.error(message, ...optionalParams);
3
+ }
4
+ export function outputResultToConsole(message, ...optionalParams) {
2
5
  console.log(message, ...optionalParams);
3
6
  }
4
7
  //# sourceMappingURL=output.js.map
@@ -2,6 +2,12 @@ class Settings {
2
2
  get ZUPLO_DEVELOPER_API_ENDPOINT() {
3
3
  return process.env.ZUPLO_DEVELOPER_API_ENDPOINT ?? "https://dev.zuplo.com";
4
4
  }
5
+ get MAX_POLL_RETRIES() {
6
+ return parseInt(process.env.MAX_POLL_RETRIES ?? "30");
7
+ }
8
+ get POLL_INTERVAL() {
9
+ return parseInt(process.env.POLL_INTERVAL ?? "1000");
10
+ }
5
11
  }
6
12
  const settings = new Settings();
7
13
  export default settings;
@@ -6,8 +6,9 @@ import * as tar from "tar";
6
6
  import * as temp from "temp";
7
7
  import { DEPLOYER_METADATA_FILE } from "../common/constants.js";
8
8
  import { logger } from "../common/logger.js";
9
+ export const ARCHIVE_EXTENSION = ".tar.gz";
9
10
  export async function archive(dir) {
10
- const tarball = temp.path({ suffix: ".tar.gz" });
11
+ const tarball = temp.path({ suffix: ARCHIVE_EXTENSION });
11
12
  const ignoreFn = createIgnoreFunction(dir);
12
13
  const normalizedDir = join(relative(process.cwd(), dir));
13
14
  const metadata = await prepareDeployerMetadata(dir);
@@ -1,9 +1,11 @@
1
1
  import chalk from "chalk";
2
+ import { parse } from "path";
2
3
  import { logger } from "../common/logger.js";
3
- import { printToConsole } from "../common/output.js";
4
+ import { logDiagnosticsToConsole, outputResultToConsole, } from "../common/output.js";
4
5
  import settings from "../common/settings.js";
5
- import { archive } from "./archive.js";
6
+ import { archive, ARCHIVE_EXTENSION } from "./archive.js";
6
7
  import { upload } from "./file-upload.js";
8
+ import { pollDeployment } from "./poll-deployment.js";
7
9
  export async function deploy(argv) {
8
10
  const archiveMetadata = await archive(argv.dir);
9
11
  logger.info(`Tarball created locally at ${archiveMetadata}`);
@@ -25,13 +27,22 @@ export async function deploy(argv) {
25
27
  const { uploadUrl } = await uploadUrlResponse.json();
26
28
  const uploadResponse = await upload(archiveMetadata.tarball, uploadUrl);
27
29
  if (uploadResponse.ok) {
28
- printToConsole(chalk.green.bold(`Deploying the current branch ${archiveMetadata.metadata.branch} to project ${project} on account ${account}...`));
30
+ logDiagnosticsToConsole(chalk.green.bold(`Deploying the current branch ${archiveMetadata.metadata.branch} to project ${project} on account ${account}...`));
31
+ const fileId = parse(new URL(uploadUrl).pathname).base.replace(ARCHIVE_EXTENSION, "");
32
+ const { url } = await pollDeployment(argv, fileId, account, project);
33
+ if (url) {
34
+ outputResultToConsole(chalk.green.bold(`Deployed to ${url}`));
35
+ }
36
+ else {
37
+ logDiagnosticsToConsole(`Failed to deploy the current branch ${archiveMetadata.metadata.branch} to project ${project} on account ${account}`);
38
+ }
29
39
  }
30
40
  else {
31
41
  logger.error({
32
42
  status: uploadResponse.status,
33
43
  statusText: uploadResponse.statusText,
34
44
  }, "Failed to upload source to cloud storage");
45
+ process.exit(1);
35
46
  }
36
47
  }
37
48
  else {
@@ -39,10 +50,12 @@ export async function deploy(argv) {
39
50
  status: uploadUrlResponse.status,
40
51
  statusText: uploadUrlResponse.statusText,
41
52
  }, "Failed to retrieve uploadUrl");
53
+ process.exit(1);
42
54
  }
43
55
  }
44
56
  else {
45
57
  logger.error({ status: whoAmIResponse.status, statusText: whoAmIResponse.statusText }, "Failed to determine who-am-i");
58
+ process.exit();
46
59
  }
47
60
  }
48
61
  //# sourceMappingURL=handler.js.map
@@ -0,0 +1,50 @@
1
+ import chalk from "chalk";
2
+ import { logDiagnosticsToConsole } from "../common/output.js";
3
+ import settings from "../common/settings.js";
4
+ function wait(duration = settings.POLL_INTERVAL) {
5
+ return new Promise((resolve) => setTimeout(resolve, duration));
6
+ }
7
+ export async function pollDeployment(argv, fileId, account, project) {
8
+ for (let pollRetry = 0; pollRetry < settings.MAX_POLL_RETRIES; pollRetry++) {
9
+ logDiagnosticsToConsole(chalk.yellow(`Polling for deployment status... (${pollRetry}/${settings.MAX_POLL_RETRIES})`));
10
+ const response = await fetch(`${settings.ZUPLO_DEVELOPER_API_ENDPOINT}/v1/accounts/${account}/projects/${project}/deployment-status/${fileId}`, {
11
+ method: "GET",
12
+ headers: {
13
+ Authorization: `Bearer ${argv.apiKey}`,
14
+ },
15
+ });
16
+ if (response.ok) {
17
+ const { status, url } = await response.json();
18
+ switch (status) {
19
+ case "IN_PROGRESS":
20
+ await wait();
21
+ continue;
22
+ case "SUCCESS":
23
+ const zupResponse = await fetch(`${url}/__zuplo/build`);
24
+ if (zupResponse.ok) {
25
+ return {
26
+ url,
27
+ };
28
+ }
29
+ else {
30
+ continue;
31
+ }
32
+ case "ERROR":
33
+ return {
34
+ url: undefined,
35
+ };
36
+ }
37
+ }
38
+ else if (response.status === 404) {
39
+ await wait();
40
+ continue;
41
+ }
42
+ else {
43
+ throw new Error(`Unexpected response from server: ${response.status} ${response.statusText}`);
44
+ }
45
+ }
46
+ return {
47
+ url: undefined,
48
+ };
49
+ }
50
+ //# sourceMappingURL=poll-deployment.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zuplo/cli",
3
- "version": "1.8.0",
3
+ "version": "1.10.0",
4
4
  "type": "module",
5
5
  "repository": "https://github.com/zuplo/cli",
6
6
  "author": "Zuplo, Inc.",