@shopify/oxygen-cli 1.5.0 → 1.6.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.
- package/README.md +2 -0
- package/dist/commands/oxygen/deploy.d.ts +9 -9
- package/dist/commands/oxygen/deploy.js +57 -43
- package/dist/deploy/health-check.d.ts +12 -0
- package/dist/deploy/health-check.js +44 -0
- package/dist/deploy/health-check.test.d.ts +2 -0
- package/dist/deploy/health-check.test.js +92 -0
- package/dist/deploy/index.js +14 -3
- package/dist/deploy/types.d.ts +8 -1
- package/dist/deploy/types.js +3 -1
- package/dist/utils/test-helper.js +2 -0
- package/dist/utils/utils.js +1 -0
- package/oclif.manifest.json +51 -34
- package/package.json +7 -7
package/README.md
CHANGED
@@ -42,6 +42,8 @@ oxygen:deploy [options]
|
|
42
42
|
- -o, --workerOnly: Worker only deployment.
|
43
43
|
- -s, --skipBuild: Skip running build command.
|
44
44
|
- -b, --buildCommand <buildCommand>: Build command (default: `yarn build`).
|
45
|
+
- -h, --skipHealthCheck: Skip running the health check on the deployment
|
46
|
+
- -d, --healthCheckMaxDuration: The maximum duration (in seconds) that the health check is allowed to run before it is considered failed. Accepts values between 10 and 300.
|
45
47
|
- --publicDeployment: set the deployment to be publicly accessible.
|
46
48
|
- --metadataUrl <metadataUrl>: URL that links to the deployment.
|
47
49
|
- --metadataUser <metadataUser>: User that initiated the deployment.
|
@@ -1,20 +1,21 @@
|
|
1
1
|
import * as _oclif_core_lib_interfaces_parser_js from '@oclif/core/lib/interfaces/parser.js';
|
2
2
|
import { Command } from '@oclif/core';
|
3
|
-
import { DeploymentConfig } from '../../deploy/types.js';
|
4
3
|
|
5
4
|
declare class Deploy extends Command {
|
6
5
|
static description: string;
|
7
6
|
static hidden: boolean;
|
8
7
|
static flags: {
|
9
|
-
token: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
10
|
-
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
11
|
-
environmentTag: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
12
|
-
workerFolder: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
13
8
|
assetsFolder: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
14
|
-
workerOnly: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
15
|
-
skipBuild: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
16
9
|
buildCommand: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
10
|
+
environmentTag: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
11
|
+
healthCheckMaxDuration: _oclif_core_lib_interfaces_parser_js.OptionFlag<number, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
12
|
+
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
17
13
|
publicDeployment: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
14
|
+
skipBuild: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
15
|
+
skipHealthCheck: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
16
|
+
token: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
17
|
+
workerFolder: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
18
|
+
workerOnly: _oclif_core_lib_interfaces_parser_js.BooleanFlag<boolean>;
|
18
19
|
metadataUrl: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
19
20
|
metadataUser: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
20
21
|
metadataVersion: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
@@ -22,6 +23,5 @@ declare class Deploy extends Command {
|
|
22
23
|
static hasCustomBuildCommand: boolean;
|
23
24
|
run(): Promise<void>;
|
24
25
|
}
|
25
|
-
declare function runInit(config: DeploymentConfig): void;
|
26
26
|
|
27
|
-
export { Deploy
|
27
|
+
export { Deploy };
|
@@ -3,52 +3,18 @@ import { consoleError } from '@shopify/cli-kit/node/output';
|
|
3
3
|
import { normalizePath } from '@shopify/cli-kit/node/path';
|
4
4
|
import { createDeploy } from '../../deploy/index.js';
|
5
5
|
import { deployDefaults, parseToken, verifyConfig, getBuildCommandFromLockFile } from '../../utils/utils.js';
|
6
|
+
import { HealthCheckError } from '../../deploy/types.js';
|
6
7
|
|
7
8
|
class Deploy extends Command {
|
8
9
|
static description = "Creates a deployment to Oxygen";
|
9
10
|
static hidden = false;
|
10
11
|
static flags = {
|
11
|
-
token: Flags.string({
|
12
|
-
char: "t",
|
13
|
-
description: "Oxygen deployment token",
|
14
|
-
env: "OXYGEN_DEPLOYMENT_TOKEN",
|
15
|
-
required: true
|
16
|
-
}),
|
17
|
-
path: Flags.string({
|
18
|
-
char: "p",
|
19
|
-
description: "Root path",
|
20
|
-
default: "./",
|
21
|
-
required: false
|
22
|
-
}),
|
23
|
-
environmentTag: Flags.string({
|
24
|
-
char: "e",
|
25
|
-
description: "Tag of the environment to deploy to",
|
26
|
-
required: false
|
27
|
-
}),
|
28
|
-
workerFolder: Flags.string({
|
29
|
-
char: "w",
|
30
|
-
description: "Worker folder",
|
31
|
-
default: String(deployDefaults.workerDirDefault),
|
32
|
-
required: false
|
33
|
-
}),
|
34
12
|
assetsFolder: Flags.string({
|
35
13
|
char: "a",
|
36
14
|
description: "Assets folder",
|
37
15
|
default: String(deployDefaults.assetsDirDefault),
|
38
16
|
required: false
|
39
17
|
}),
|
40
|
-
workerOnly: Flags.boolean({
|
41
|
-
char: "o",
|
42
|
-
description: "Worker only deployment",
|
43
|
-
default: false,
|
44
|
-
required: false
|
45
|
-
}),
|
46
|
-
skipBuild: Flags.boolean({
|
47
|
-
char: "s",
|
48
|
-
description: "Skip running build command",
|
49
|
-
required: false,
|
50
|
-
default: false
|
51
|
-
}),
|
52
18
|
buildCommand: Flags.string({
|
53
19
|
char: "b",
|
54
20
|
description: "Build command",
|
@@ -59,12 +25,61 @@ class Deploy extends Command {
|
|
59
25
|
return Promise.resolve(input);
|
60
26
|
}
|
61
27
|
}),
|
28
|
+
environmentTag: Flags.string({
|
29
|
+
char: "e",
|
30
|
+
description: "Tag of the environment to deploy to",
|
31
|
+
required: false
|
32
|
+
}),
|
33
|
+
healthCheckMaxDuration: Flags.integer({
|
34
|
+
char: "d",
|
35
|
+
description: "the maximum duration (in seconds) that the health check is allowed to run before it is considered failed.",
|
36
|
+
min: 10,
|
37
|
+
max: 300,
|
38
|
+
required: false,
|
39
|
+
default: deployDefaults.healthCheckMaxDurationDefault
|
40
|
+
}),
|
41
|
+
path: Flags.string({
|
42
|
+
char: "p",
|
43
|
+
description: "Root path",
|
44
|
+
default: "./",
|
45
|
+
required: false
|
46
|
+
}),
|
62
47
|
publicDeployment: Flags.boolean({
|
63
48
|
env: "OXYGEN_PUBLIC_DEPLOYMENT",
|
64
49
|
description: "Marks a preview deployment as publicly accessible.",
|
65
50
|
required: false,
|
66
51
|
default: false
|
67
52
|
}),
|
53
|
+
skipBuild: Flags.boolean({
|
54
|
+
char: "s",
|
55
|
+
description: "Skip running build command",
|
56
|
+
required: false,
|
57
|
+
default: false
|
58
|
+
}),
|
59
|
+
skipHealthCheck: Flags.boolean({
|
60
|
+
char: "h",
|
61
|
+
description: "Skip running deployment health check",
|
62
|
+
required: false,
|
63
|
+
default: false
|
64
|
+
}),
|
65
|
+
token: Flags.string({
|
66
|
+
char: "t",
|
67
|
+
description: "Oxygen deployment token",
|
68
|
+
env: "OXYGEN_DEPLOYMENT_TOKEN",
|
69
|
+
required: true
|
70
|
+
}),
|
71
|
+
workerFolder: Flags.string({
|
72
|
+
char: "w",
|
73
|
+
description: "Worker folder",
|
74
|
+
default: String(deployDefaults.workerDirDefault),
|
75
|
+
required: false
|
76
|
+
}),
|
77
|
+
workerOnly: Flags.boolean({
|
78
|
+
char: "o",
|
79
|
+
description: "Worker only deployment",
|
80
|
+
default: false,
|
81
|
+
required: false
|
82
|
+
}),
|
68
83
|
metadataUrl: Flags.string({
|
69
84
|
description: "URL that links to the deployment. Will be saved and displayed in the Shopify admin",
|
70
85
|
required: false,
|
@@ -96,6 +111,7 @@ class Deploy extends Command {
|
|
96
111
|
deploymentToken: parseToken(flags.token),
|
97
112
|
environmentTag: flags.environmentTag,
|
98
113
|
deploymentUrl,
|
114
|
+
healthCheckMaxDuration: flags.healthCheckMaxDuration,
|
99
115
|
metadata: {
|
100
116
|
url: flags.metadataUrl,
|
101
117
|
user: flags.metadataUser,
|
@@ -104,6 +120,7 @@ class Deploy extends Command {
|
|
104
120
|
publicDeployment: flags.publicDeployment,
|
105
121
|
rootPath: normalizePath(flags.path),
|
106
122
|
skipBuild: flags.skipBuild,
|
123
|
+
skipHealthCheck: flags.skipHealthCheck,
|
107
124
|
workerDir: normalizePath(flags.workerFolder),
|
108
125
|
workerOnly: flags.workerOnly
|
109
126
|
};
|
@@ -111,19 +128,16 @@ class Deploy extends Command {
|
|
111
128
|
if (!Deploy.hasCustomBuildCommand && !config.skipBuild) {
|
112
129
|
config.buildCommand = getBuildCommandFromLockFile(config);
|
113
130
|
}
|
114
|
-
|
131
|
+
await createDeploy({ config });
|
115
132
|
} catch (error) {
|
116
|
-
if (error instanceof Error) {
|
133
|
+
if (!(error instanceof Error)) {
|
134
|
+
consoleError(error);
|
135
|
+
} else if (!(error instanceof HealthCheckError)) {
|
117
136
|
consoleError(error.message);
|
118
|
-
} else {
|
119
|
-
console.error(error);
|
120
137
|
}
|
121
138
|
this.exit(1);
|
122
139
|
}
|
123
140
|
}
|
124
141
|
}
|
125
|
-
function runInit(config) {
|
126
|
-
createDeploy({ config });
|
127
|
-
}
|
128
142
|
|
129
|
-
export { Deploy
|
143
|
+
export { Deploy };
|
@@ -0,0 +1,12 @@
|
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig, DeploymentHooks } from './types.js';
|
3
|
+
|
4
|
+
interface HealthCheckOptions {
|
5
|
+
config: DeploymentConfig;
|
6
|
+
hooks?: DeploymentHooks;
|
7
|
+
logger: Logger;
|
8
|
+
url: string;
|
9
|
+
}
|
10
|
+
declare function healthCheck(options: HealthCheckOptions): Promise<void>;
|
11
|
+
|
12
|
+
export { healthCheck };
|
@@ -0,0 +1,44 @@
|
|
1
|
+
import { fetch } from '@shopify/cli-kit/node/http';
|
2
|
+
import { outputInfo } from '@shopify/cli-kit/node/output';
|
3
|
+
import { HealthCheckError } from './types.js';
|
4
|
+
|
5
|
+
async function healthCheck(options) {
|
6
|
+
const { config, url, logger, hooks } = options;
|
7
|
+
hooks?.onHealthCheckStart?.();
|
8
|
+
outputInfo("Performing health check on the deployment...", logger);
|
9
|
+
let attempts = 0;
|
10
|
+
let delay = 0;
|
11
|
+
const startTime = Date.now();
|
12
|
+
const handleInterval = async () => {
|
13
|
+
if (attempts < 10) {
|
14
|
+
delay = 500;
|
15
|
+
} else if (attempts % 5 === 0) {
|
16
|
+
delay += 5e3;
|
17
|
+
}
|
18
|
+
const elapsedTime = (Date.now() - startTime) / 1e3;
|
19
|
+
if (elapsedTime + delay / 1e3 > config.healthCheckMaxDuration) {
|
20
|
+
const error = new HealthCheckError("Unable to verify deployment health.");
|
21
|
+
hooks?.onHealthCheckError?.(error);
|
22
|
+
throw error;
|
23
|
+
}
|
24
|
+
attempts++;
|
25
|
+
await new Promise((resolve) => setTimeout(resolve, delay));
|
26
|
+
await check();
|
27
|
+
};
|
28
|
+
const check = async () => {
|
29
|
+
try {
|
30
|
+
const response = await fetch(`${url}/.oxygen/deployment`);
|
31
|
+
if (response.status === 200) {
|
32
|
+
outputInfo("Deployment health check passed", logger);
|
33
|
+
hooks?.onHealthCheckComplete?.();
|
34
|
+
return Promise.resolve();
|
35
|
+
}
|
36
|
+
await handleInterval();
|
37
|
+
} catch {
|
38
|
+
await handleInterval();
|
39
|
+
}
|
40
|
+
};
|
41
|
+
await check();
|
42
|
+
}
|
43
|
+
|
44
|
+
export { healthCheck };
|
@@ -0,0 +1,92 @@
|
|
1
|
+
import { vi, describe, beforeEach, it, expect } from 'vitest';
|
2
|
+
import { fetch } from '@shopify/cli-kit/node/http';
|
3
|
+
import { Response } from 'node-fetch';
|
4
|
+
import { stderrLogger } from '../utils/utils.js';
|
5
|
+
import { createTestConfig } from '../utils/test-helper.js';
|
6
|
+
import { HealthCheckError } from './types.js';
|
7
|
+
import { healthCheck } from './health-check.js';
|
8
|
+
|
9
|
+
vi.mock("@shopify/cli-kit/node/http", async () => {
|
10
|
+
const actual = await vi.importActual("@shopify/cli-kit/node/http");
|
11
|
+
return {
|
12
|
+
...actual,
|
13
|
+
fetch: vi.fn()
|
14
|
+
};
|
15
|
+
});
|
16
|
+
vi.mock("@shopify/cli-kit/node/output");
|
17
|
+
const testConfig = createTestConfig("rootFolder");
|
18
|
+
describe("healthCheck", () => {
|
19
|
+
let setTimeoutSpy;
|
20
|
+
const hooks = {
|
21
|
+
onHealthCheckError: vi.fn(),
|
22
|
+
onHealthCheckStart: vi.fn(),
|
23
|
+
onHealthCheckComplete: vi.fn()
|
24
|
+
};
|
25
|
+
const url = "http://example.com";
|
26
|
+
beforeEach(() => {
|
27
|
+
vi.mocked(fetch).mockReset();
|
28
|
+
setTimeoutSpy = vi.spyOn(global, "setTimeout").mockImplementation((cb, _delay) => {
|
29
|
+
cb();
|
30
|
+
return {};
|
31
|
+
});
|
32
|
+
});
|
33
|
+
it("resolves when URL is accessible", async () => {
|
34
|
+
const response = new Response();
|
35
|
+
vi.mocked(fetch).mockResolvedValueOnce(response);
|
36
|
+
await healthCheck({ config: testConfig, url, logger: stderrLogger, hooks });
|
37
|
+
expect(fetch).toHaveBeenCalledTimes(1);
|
38
|
+
expect(fetch).toHaveBeenCalledWith(`${url}/.oxygen/deployment`);
|
39
|
+
expect(hooks.onHealthCheckStart).toBeCalled();
|
40
|
+
expect(hooks.onHealthCheckComplete).toBeCalled();
|
41
|
+
});
|
42
|
+
it("repeats request until URL is accessible with progressive timeout", async () => {
|
43
|
+
const responseFail = new Response(null, { status: 404 });
|
44
|
+
const responseSuccess = new Response(null, { status: 200 });
|
45
|
+
let attempts = 0;
|
46
|
+
vi.mocked(fetch).mockImplementation(() => {
|
47
|
+
if (attempts === 30) {
|
48
|
+
return Promise.resolve(responseSuccess);
|
49
|
+
}
|
50
|
+
attempts++;
|
51
|
+
return Promise.resolve(responseFail);
|
52
|
+
});
|
53
|
+
await new Promise((resolve, reject) => {
|
54
|
+
healthCheck({ config: testConfig, url, logger: stderrLogger, hooks }).then(() => {
|
55
|
+
expect(fetch).toHaveBeenCalledTimes(attempts + 1);
|
56
|
+
expect(fetch).toHaveBeenCalledWith(`${url}/.oxygen/deployment`);
|
57
|
+
expect(setTimeoutSpy).toHaveBeenCalledTimes(attempts);
|
58
|
+
expect(hooks.onHealthCheckStart).toBeCalled();
|
59
|
+
expect(hooks.onHealthCheckComplete).toBeCalled();
|
60
|
+
let expectedDuration = 500;
|
61
|
+
setTimeoutSpy.mock.calls.forEach(
|
62
|
+
(call, index) => {
|
63
|
+
if (index >= 10 && index % 5 === 0) {
|
64
|
+
expectedDuration += 5e3;
|
65
|
+
}
|
66
|
+
expect(call[1]).toBe(expectedDuration);
|
67
|
+
}
|
68
|
+
);
|
69
|
+
resolve();
|
70
|
+
}).catch((error) => {
|
71
|
+
reject(error);
|
72
|
+
});
|
73
|
+
});
|
74
|
+
});
|
75
|
+
it("throws an error after max duration", async () => {
|
76
|
+
vi.useFakeTimers();
|
77
|
+
const responseFail = new Response(null, { status: 404 });
|
78
|
+
vi.mocked(fetch).mockResolvedValue(responseFail);
|
79
|
+
const healthCheckPromise = healthCheck({
|
80
|
+
config: testConfig,
|
81
|
+
url,
|
82
|
+
logger: stderrLogger,
|
83
|
+
hooks
|
84
|
+
});
|
85
|
+
vi.setSystemTime(Date.now() + testConfig.healthCheckMaxDuration * 1e3);
|
86
|
+
await expect(healthCheckPromise).rejects.toThrow(HealthCheckError);
|
87
|
+
expect(fetch).toHaveBeenCalledOnce();
|
88
|
+
expect(hooks.onHealthCheckStart).toBeCalled();
|
89
|
+
expect(hooks.onHealthCheckError).toBeCalled();
|
90
|
+
vi.useRealTimers();
|
91
|
+
});
|
92
|
+
});
|
package/dist/deploy/index.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { outputSuccess, outputInfo, outputWarn
|
1
|
+
import { outputSuccess, outputInfo, outputWarn } from '@shopify/cli-kit/node/output';
|
2
2
|
import { stderrLogger, verifyConfig } from '../utils/utils.js';
|
3
3
|
export { parseToken } from '../utils/utils.js';
|
4
4
|
import { buildInitiate } from './build-initiate.js';
|
@@ -6,8 +6,10 @@ import { buildCancel } from './build-cancel.js';
|
|
6
6
|
import { getUploadFiles } from './get-upload-files.js';
|
7
7
|
import { deploymentInitiate } from './deployment-initiate.js';
|
8
8
|
import { deploymentComplete } from './deployment-complete.js';
|
9
|
+
import { healthCheck } from './health-check.js';
|
9
10
|
import { deploymentCancel, DeploymentCancelReason } from './deployment-cancel.js';
|
10
11
|
import { uploadFiles } from './upload-files.js';
|
12
|
+
import { HealthCheckError } from './types.js';
|
11
13
|
import { buildProject } from './build-project.js';
|
12
14
|
import { getMetadata, createLabels, getEnvironmentInput } from './metadata.js';
|
13
15
|
|
@@ -52,6 +54,14 @@ async function createDeploy(options) {
|
|
52
54
|
config,
|
53
55
|
deployment.deployment.id
|
54
56
|
);
|
57
|
+
if (!config.skipHealthCheck) {
|
58
|
+
await healthCheck({
|
59
|
+
config,
|
60
|
+
url: deploymentCompleteOp.deployment.url,
|
61
|
+
logger,
|
62
|
+
hooks
|
63
|
+
});
|
64
|
+
}
|
55
65
|
const urlMessage = config.publicDeployment ? "Public" : "Private";
|
56
66
|
outputSuccess(
|
57
67
|
`Deployment complete.
|
@@ -67,7 +77,9 @@ ${urlMessage} preview URL: ${deploymentCompleteOp.deployment.url}`,
|
|
67
77
|
console.error("Unknown error", error);
|
68
78
|
return Promise.reject(new Error("Unknown error"));
|
69
79
|
}
|
70
|
-
if (
|
80
|
+
if (error instanceof HealthCheckError) {
|
81
|
+
outputWarn(error.message, logger);
|
82
|
+
} else if (build.id && !buildCompleted) {
|
71
83
|
outputWarn(
|
72
84
|
`Build failed with: ${error.message}, cancelling build.`,
|
73
85
|
logger
|
@@ -98,7 +110,6 @@ ${urlMessage} preview URL: ${deploymentCompleteOp.deployment.url}`,
|
|
98
110
|
}
|
99
111
|
});
|
100
112
|
}
|
101
|
-
consoleError(error.message);
|
102
113
|
return Promise.reject(error);
|
103
114
|
}
|
104
115
|
}
|
package/dist/deploy/types.d.ts
CHANGED
@@ -9,6 +9,9 @@ interface DeploymentHooks {
|
|
9
9
|
onBuildStart?: () => void;
|
10
10
|
onBuildComplete?: () => void;
|
11
11
|
onBuildError?: (error: Error) => void;
|
12
|
+
onHealthCheckStart?: () => void;
|
13
|
+
onHealthCheckComplete?: () => void;
|
14
|
+
onHealthCheckError?: (error: Error) => void;
|
12
15
|
onUploadFilesStart?: () => void;
|
13
16
|
onUploadFilesComplete?: () => void;
|
14
17
|
}
|
@@ -19,6 +22,7 @@ interface DeploymentConfig {
|
|
19
22
|
deploymentToken: DeploymentToken;
|
20
23
|
deploymentUrl: string;
|
21
24
|
environmentTag?: string;
|
25
|
+
healthCheckMaxDuration: number;
|
22
26
|
metadata: {
|
23
27
|
user?: string;
|
24
28
|
version?: string;
|
@@ -27,6 +31,7 @@ interface DeploymentConfig {
|
|
27
31
|
publicDeployment: boolean;
|
28
32
|
rootPath?: string;
|
29
33
|
skipBuild: boolean;
|
34
|
+
skipHealthCheck: boolean;
|
30
35
|
workerDir?: string;
|
31
36
|
workerOnly: boolean;
|
32
37
|
}
|
@@ -57,5 +62,7 @@ declare enum FileType {
|
|
57
62
|
interface OxygenError {
|
58
63
|
message: string;
|
59
64
|
}
|
65
|
+
declare class HealthCheckError extends Error {
|
66
|
+
}
|
60
67
|
|
61
|
-
export { Build, ClientError, DeploymentConfig, DeploymentHooks, DeploymentManifestFile, DeploymentToken, EnvironmentInput, FileType, OxygenError };
|
68
|
+
export { Build, ClientError, DeploymentConfig, DeploymentHooks, DeploymentManifestFile, DeploymentToken, EnvironmentInput, FileType, HealthCheckError, OxygenError };
|
package/dist/deploy/types.js
CHANGED
@@ -17,10 +17,12 @@ function createTestConfig(rootFolder) {
|
|
17
17
|
deploymentToken: testToken,
|
18
18
|
environmentTag: "environment",
|
19
19
|
deploymentUrl: "https://localhost:3000",
|
20
|
+
healthCheckMaxDuration: 300,
|
20
21
|
metadata: {},
|
21
22
|
rootPath: rootFolder,
|
22
23
|
publicDeployment: false,
|
23
24
|
skipBuild: false,
|
25
|
+
skipHealthCheck: false,
|
24
26
|
workerDir: "/worker/",
|
25
27
|
workerOnly: false
|
26
28
|
};
|
package/dist/utils/utils.js
CHANGED
@@ -6,6 +6,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
6
6
|
const deployDefaults = {
|
7
7
|
assetsDirDefault: "dist/client/",
|
8
8
|
buildCommandDefault: "yarn build",
|
9
|
+
healthCheckMaxDurationDefault: 180,
|
9
10
|
maxUploadAttempts: 3,
|
10
11
|
maxResumabeUploadAttempts: 9,
|
11
12
|
workerDirDefault: "dist/worker/"
|
package/oclif.manifest.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": "1.
|
2
|
+
"version": "1.6.0",
|
3
3
|
"commands": {
|
4
4
|
"oxygen:deploy": {
|
5
5
|
"id": "oxygen:deploy",
|
@@ -11,22 +11,23 @@
|
|
11
11
|
"hidden": false,
|
12
12
|
"aliases": [],
|
13
13
|
"flags": {
|
14
|
-
"
|
15
|
-
"name": "
|
14
|
+
"assetsFolder": {
|
15
|
+
"name": "assetsFolder",
|
16
16
|
"type": "option",
|
17
|
-
"char": "
|
18
|
-
"description": "
|
19
|
-
"required":
|
20
|
-
"multiple": false
|
17
|
+
"char": "a",
|
18
|
+
"description": "Assets folder",
|
19
|
+
"required": false,
|
20
|
+
"multiple": false,
|
21
|
+
"default": "dist/client/"
|
21
22
|
},
|
22
|
-
"
|
23
|
-
"name": "
|
23
|
+
"buildCommand": {
|
24
|
+
"name": "buildCommand",
|
24
25
|
"type": "option",
|
25
|
-
"char": "
|
26
|
-
"description": "
|
26
|
+
"char": "b",
|
27
|
+
"description": "Build command",
|
27
28
|
"required": false,
|
28
29
|
"multiple": false,
|
29
|
-
"default": "
|
30
|
+
"default": "yarn build"
|
30
31
|
},
|
31
32
|
"environmentTag": {
|
32
33
|
"name": "environmentTag",
|
@@ -36,29 +37,28 @@
|
|
36
37
|
"required": false,
|
37
38
|
"multiple": false
|
38
39
|
},
|
39
|
-
"
|
40
|
-
"name": "
|
40
|
+
"healthCheckMaxDuration": {
|
41
|
+
"name": "healthCheckMaxDuration",
|
41
42
|
"type": "option",
|
42
|
-
"char": "
|
43
|
-
"description": "
|
43
|
+
"char": "d",
|
44
|
+
"description": "the maximum duration (in seconds) that the health check is allowed to run before it is considered failed.",
|
44
45
|
"required": false,
|
45
46
|
"multiple": false,
|
46
|
-
"default":
|
47
|
+
"default": 180
|
47
48
|
},
|
48
|
-
"
|
49
|
-
"name": "
|
49
|
+
"path": {
|
50
|
+
"name": "path",
|
50
51
|
"type": "option",
|
51
|
-
"char": "
|
52
|
-
"description": "
|
52
|
+
"char": "p",
|
53
|
+
"description": "Root path",
|
53
54
|
"required": false,
|
54
55
|
"multiple": false,
|
55
|
-
"default": "
|
56
|
+
"default": "./"
|
56
57
|
},
|
57
|
-
"
|
58
|
-
"name": "
|
58
|
+
"publicDeployment": {
|
59
|
+
"name": "publicDeployment",
|
59
60
|
"type": "boolean",
|
60
|
-
"
|
61
|
-
"description": "Worker only deployment",
|
61
|
+
"description": "Marks a preview deployment as publicly accessible.",
|
62
62
|
"required": false,
|
63
63
|
"allowNo": false
|
64
64
|
},
|
@@ -70,19 +70,36 @@
|
|
70
70
|
"required": false,
|
71
71
|
"allowNo": false
|
72
72
|
},
|
73
|
-
"
|
74
|
-
"name": "
|
73
|
+
"skipHealthCheck": {
|
74
|
+
"name": "skipHealthCheck",
|
75
|
+
"type": "boolean",
|
76
|
+
"char": "h",
|
77
|
+
"description": "Skip running deployment health check",
|
78
|
+
"required": false,
|
79
|
+
"allowNo": false
|
80
|
+
},
|
81
|
+
"token": {
|
82
|
+
"name": "token",
|
75
83
|
"type": "option",
|
76
|
-
"char": "
|
77
|
-
"description": "
|
84
|
+
"char": "t",
|
85
|
+
"description": "Oxygen deployment token",
|
86
|
+
"required": true,
|
87
|
+
"multiple": false
|
88
|
+
},
|
89
|
+
"workerFolder": {
|
90
|
+
"name": "workerFolder",
|
91
|
+
"type": "option",
|
92
|
+
"char": "w",
|
93
|
+
"description": "Worker folder",
|
78
94
|
"required": false,
|
79
95
|
"multiple": false,
|
80
|
-
"default": "
|
96
|
+
"default": "dist/worker/"
|
81
97
|
},
|
82
|
-
"
|
83
|
-
"name": "
|
98
|
+
"workerOnly": {
|
99
|
+
"name": "workerOnly",
|
84
100
|
"type": "boolean",
|
85
|
-
"
|
101
|
+
"char": "o",
|
102
|
+
"description": "Worker only deployment",
|
86
103
|
"required": false,
|
87
104
|
"allowNo": false
|
88
105
|
},
|
package/package.json
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
"@shopify:registry": "https://registry.npmjs.org"
|
6
6
|
},
|
7
7
|
"license": "MIT",
|
8
|
-
"version": "1.
|
8
|
+
"version": "1.6.0",
|
9
9
|
"type": "module",
|
10
10
|
"scripts": {
|
11
11
|
"build": "tsup --clean --config ./tsup.config.ts && oclif manifest",
|
@@ -31,8 +31,8 @@
|
|
31
31
|
"/oclif.manifest.json"
|
32
32
|
],
|
33
33
|
"dependencies": {
|
34
|
-
"@oclif/core": "2.
|
35
|
-
"@shopify/cli-kit": "^3.
|
34
|
+
"@oclif/core": "2.9.4",
|
35
|
+
"@shopify/cli-kit": "^3.47.5",
|
36
36
|
"async": "^3.2.4"
|
37
37
|
},
|
38
38
|
"devDependencies": {
|
@@ -40,15 +40,15 @@
|
|
40
40
|
"@shopify/eslint-plugin": "^42.1.0",
|
41
41
|
"@shopify/prettier-config": "^1.1.2",
|
42
42
|
"@types/async": "^3.2.18",
|
43
|
-
"@types/node": "^20.
|
43
|
+
"@types/node": "^20.4.2",
|
44
44
|
"@types/prettier": "^2.7.3",
|
45
|
-
"eslint": "^8.
|
45
|
+
"eslint": "^8.45.0",
|
46
46
|
"node-fetch": "^3.3.1",
|
47
47
|
"oclif": "^3",
|
48
48
|
"tsup": "^7.1.0",
|
49
49
|
"typescript": "^5.1.3",
|
50
|
-
"vite": "^4.
|
51
|
-
"vitest": "^0.
|
50
|
+
"vite": "^4.4.4",
|
51
|
+
"vitest": "^0.33.0"
|
52
52
|
},
|
53
53
|
"prettier": "@shopify/prettier-config",
|
54
54
|
"oclif": {
|