@shopify/oxygen-cli 1.4.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 +58 -43
- package/dist/deploy/build-cancel.d.ts +9 -2
- package/dist/deploy/build-cancel.js +4 -3
- package/dist/deploy/build-cancel.test.js +21 -4
- package/dist/deploy/build-initiate.d.ts +9 -2
- package/dist/deploy/build-initiate.js +4 -3
- package/dist/deploy/build-initiate.test.js +19 -8
- package/dist/deploy/build-project.d.ts +7 -2
- package/dist/deploy/build-project.js +34 -19
- package/dist/deploy/build-project.test.js +14 -8
- package/dist/deploy/deployment-cancel.d.ts +9 -2
- package/dist/deploy/deployment-cancel.js +4 -3
- package/dist/deploy/deployment-cancel.test.js +19 -16
- package/dist/deploy/deployment-complete.d.ts +2 -2
- package/dist/deploy/deployment-initiate.d.ts +10 -4
- package/dist/deploy/deployment-initiate.js +4 -3
- package/dist/deploy/deployment-initiate.test.js +26 -10
- package/dist/deploy/get-upload-files.d.ts +2 -2
- 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.d.ts +10 -3
- package/dist/deploy/index.js +54 -26
- package/dist/deploy/metadata.d.ts +4 -3
- package/dist/deploy/metadata.js +3 -3
- package/dist/deploy/metadata.test.js +4 -4
- package/dist/deploy/types.d.ts +17 -2
- package/dist/deploy/types.js +3 -1
- package/dist/deploy/upload-files.d.ts +9 -2
- package/dist/deploy/upload-files.js +7 -4
- package/dist/deploy/upload-files.test.js +37 -18
- package/dist/utils/test-helper.d.ts +2 -2
- package/dist/utils/test-helper.js +3 -0
- package/dist/utils/utils.d.ts +3 -3
- package/dist/utils/utils.js +1 -5
- package/oclif.manifest.json +50 -33
- package/package.json +8 -8
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 { DeployConfig } 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 | undefined, _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(options: DeployConfig): 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: false
|
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,
|
@@ -92,9 +107,11 @@ class Deploy extends Command {
|
|
92
107
|
const config = {
|
93
108
|
assetsDir: normalizePath(flags.assetsFolder),
|
94
109
|
buildCommand: flags.buildCommand,
|
110
|
+
buildOutput: true,
|
95
111
|
deploymentToken: parseToken(flags.token),
|
96
112
|
environmentTag: flags.environmentTag,
|
97
113
|
deploymentUrl,
|
114
|
+
healthCheckMaxDuration: flags.healthCheckMaxDuration,
|
98
115
|
metadata: {
|
99
116
|
url: flags.metadataUrl,
|
100
117
|
user: flags.metadataUser,
|
@@ -103,6 +120,7 @@ class Deploy extends Command {
|
|
103
120
|
publicDeployment: flags.publicDeployment,
|
104
121
|
rootPath: normalizePath(flags.path),
|
105
122
|
skipBuild: flags.skipBuild,
|
123
|
+
skipHealthCheck: flags.skipHealthCheck,
|
106
124
|
workerDir: normalizePath(flags.workerFolder),
|
107
125
|
workerOnly: flags.workerOnly
|
108
126
|
};
|
@@ -110,19 +128,16 @@ class Deploy extends Command {
|
|
110
128
|
if (!Deploy.hasCustomBuildCommand && !config.skipBuild) {
|
111
129
|
config.buildCommand = getBuildCommandFromLockFile(config);
|
112
130
|
}
|
113
|
-
|
131
|
+
await createDeploy({ config });
|
114
132
|
} catch (error) {
|
115
|
-
if (error instanceof Error) {
|
133
|
+
if (!(error instanceof Error)) {
|
134
|
+
consoleError(error);
|
135
|
+
} else if (!(error instanceof HealthCheckError)) {
|
116
136
|
consoleError(error.message);
|
117
|
-
} else {
|
118
|
-
console.error(error);
|
119
137
|
}
|
120
138
|
this.exit(1);
|
121
139
|
}
|
122
140
|
}
|
123
141
|
}
|
124
|
-
function runInit(options) {
|
125
|
-
createDeploy(options);
|
126
|
-
}
|
127
142
|
|
128
|
-
export { Deploy
|
143
|
+
export { Deploy };
|
@@ -1,6 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig } from './types.js';
|
2
3
|
import { BuildCancelResponse } from './graphql/build-cancel.js';
|
3
4
|
|
4
|
-
|
5
|
+
interface BuildCancelOptions {
|
6
|
+
config: DeploymentConfig;
|
7
|
+
buildId: string;
|
8
|
+
reason: string;
|
9
|
+
logger: Logger;
|
10
|
+
}
|
11
|
+
declare function buildCancel(options: BuildCancelOptions): Promise<BuildCancelResponse>;
|
5
12
|
|
6
13
|
export { buildCancel };
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
2
2
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
3
3
|
import { outputInfo } from '@shopify/cli-kit/node/output';
|
4
|
-
import { Header,
|
4
|
+
import { Header, errorHandler } from '../utils/utils.js';
|
5
5
|
import { BuildCancelQuery } from './graphql/build-cancel.js';
|
6
6
|
|
7
|
-
async function buildCancel(
|
7
|
+
async function buildCancel(options) {
|
8
|
+
const { config, buildId, reason, logger } = options;
|
8
9
|
const variables = {
|
9
10
|
buildId,
|
10
11
|
reason
|
@@ -25,7 +26,7 @@ async function buildCancel(config, buildId, reason) {
|
|
25
26
|
`Failed to cancel build: ${response.buildCancel.userErrors[0]?.message}`
|
26
27
|
);
|
27
28
|
}
|
28
|
-
outputInfo(`Build with id ${buildId} cancelled.`,
|
29
|
+
outputInfo(`Build with id ${buildId} cancelled.`, logger);
|
29
30
|
return response.buildCancel;
|
30
31
|
} catch (error) {
|
31
32
|
errorHandler(error);
|
@@ -2,7 +2,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
2
|
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
3
3
|
import { vi, describe, test, expect } from 'vitest';
|
4
4
|
import { createTestConfig } from '../utils/test-helper.js';
|
5
|
-
import { Header } from '../utils/utils.js';
|
5
|
+
import { stderrLogger, Header } from '../utils/utils.js';
|
6
6
|
import { buildCancel } from './build-cancel.js';
|
7
7
|
|
8
8
|
vi.mock("@shopify/cli-kit/node/api/graphql");
|
@@ -20,7 +20,12 @@ describe("BuildCancel", () => {
|
|
20
20
|
}
|
21
21
|
};
|
22
22
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
23
|
-
const cancelResponse = await buildCancel(
|
23
|
+
const cancelResponse = await buildCancel({
|
24
|
+
config: testConfig,
|
25
|
+
buildId: "build-1",
|
26
|
+
reason: "because",
|
27
|
+
logger: stderrLogger
|
28
|
+
});
|
24
29
|
expect(cancelResponse).toEqual(response.buildCancel);
|
25
30
|
expect(graphqlRequest).toHaveBeenCalledWith({
|
26
31
|
query: expect.any(String),
|
@@ -47,7 +52,14 @@ describe("BuildCancel", () => {
|
|
47
52
|
}
|
48
53
|
};
|
49
54
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
50
|
-
await expect(
|
55
|
+
await expect(
|
56
|
+
buildCancel({
|
57
|
+
config: testConfig,
|
58
|
+
buildId: "build-1",
|
59
|
+
reason: "because",
|
60
|
+
logger: stderrLogger
|
61
|
+
})
|
62
|
+
).rejects.toThrow(
|
51
63
|
new AbortError(
|
52
64
|
`Failed to cancel build: ${response.buildCancel.userErrors[0]?.message}`
|
53
65
|
)
|
@@ -60,7 +72,12 @@ describe("BuildCancel", () => {
|
|
60
72
|
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
61
73
|
try {
|
62
74
|
await expect(
|
63
|
-
buildCancel(
|
75
|
+
buildCancel({
|
76
|
+
config: testConfig,
|
77
|
+
buildId: "build-1",
|
78
|
+
reason: "because",
|
79
|
+
logger: stderrLogger
|
80
|
+
})
|
64
81
|
).rejects.toThrow(
|
65
82
|
new AbortError(
|
66
83
|
"You are not authorized to perform this action. Please check your deployment token."
|
@@ -1,6 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig, EnvironmentInput } from './types.js';
|
2
3
|
import { BuildInitiateResponse } from './graphql/build-initiate.js';
|
3
4
|
|
4
|
-
|
5
|
+
interface BuildInitiateOptions {
|
6
|
+
config: DeploymentConfig;
|
7
|
+
logger: Logger;
|
8
|
+
environment?: EnvironmentInput;
|
9
|
+
labels?: string[];
|
10
|
+
}
|
11
|
+
declare function buildInitiate(options: BuildInitiateOptions): Promise<BuildInitiateResponse>;
|
5
12
|
|
6
13
|
export { buildInitiate };
|
@@ -1,10 +1,11 @@
|
|
1
1
|
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
2
2
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
3
3
|
import { outputCompleted } from '@shopify/cli-kit/node/output';
|
4
|
-
import { Header,
|
4
|
+
import { Header, errorHandler } from '../utils/utils.js';
|
5
5
|
import { BuildInitiateQuery } from './graphql/build-initiate.js';
|
6
6
|
|
7
|
-
async function buildInitiate(
|
7
|
+
async function buildInitiate(options) {
|
8
|
+
const { config, logger, environment, labels = [] } = options;
|
8
9
|
const variables = {
|
9
10
|
environment,
|
10
11
|
labels
|
@@ -27,7 +28,7 @@ async function buildInitiate(config, environment, labels = []) {
|
|
27
28
|
}
|
28
29
|
outputCompleted(
|
29
30
|
`Build initiated successfully with id ${response.buildInitiate.build.id}.`,
|
30
|
-
|
31
|
+
logger
|
31
32
|
);
|
32
33
|
return response.buildInitiate;
|
33
34
|
} catch (error) {
|
@@ -2,7 +2,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
2
|
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
3
3
|
import { outputCompleted } from '@shopify/cli-kit/node/output';
|
4
4
|
import { vi, describe, test, expect } from 'vitest';
|
5
|
-
import {
|
5
|
+
import { stderrLogger, Header } from '../utils/utils.js';
|
6
6
|
import { createTestConfig } from '../utils/test-helper.js';
|
7
7
|
import { buildInitiate } from './build-initiate.js';
|
8
8
|
|
@@ -20,13 +20,14 @@ describe("BuildInitiate", () => {
|
|
20
20
|
}
|
21
21
|
};
|
22
22
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
23
|
-
const initiateResponse = await buildInitiate(
|
24
|
-
testConfig,
|
25
|
-
{
|
23
|
+
const initiateResponse = await buildInitiate({
|
24
|
+
config: testConfig,
|
25
|
+
environment: {
|
26
26
|
tag: testConfig.environmentTag
|
27
27
|
},
|
28
|
-
[]
|
29
|
-
|
28
|
+
labels: [],
|
29
|
+
logger: stderrLogger
|
30
|
+
});
|
30
31
|
expect(initiateResponse).toEqual(response.buildInitiate);
|
31
32
|
expect(graphqlRequest).toHaveBeenCalledWith({
|
32
33
|
query: expect.any(String),
|
@@ -55,7 +56,12 @@ describe("BuildInitiate", () => {
|
|
55
56
|
};
|
56
57
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
57
58
|
await expect(
|
58
|
-
buildInitiate(
|
59
|
+
buildInitiate({
|
60
|
+
config: testConfig,
|
61
|
+
environment: { tag: "preview" },
|
62
|
+
labels: [],
|
63
|
+
logger: stderrLogger
|
64
|
+
})
|
59
65
|
).rejects.toThrow(
|
60
66
|
new AbortError(
|
61
67
|
`Failed to create build. ${response.buildInitiate.userErrors[0]?.message}`
|
@@ -69,7 +75,12 @@ describe("BuildInitiate", () => {
|
|
69
75
|
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
70
76
|
try {
|
71
77
|
await expect(
|
72
|
-
buildInitiate(
|
78
|
+
buildInitiate({
|
79
|
+
config: testConfig,
|
80
|
+
environment: { tag: "preview" },
|
81
|
+
labels: [],
|
82
|
+
logger: stderrLogger
|
83
|
+
})
|
73
84
|
).rejects.toThrow(
|
74
85
|
new AbortError(
|
75
86
|
"You are not authorized to perform this action. Please check your deployment token."
|
@@ -1,5 +1,10 @@
|
|
1
|
-
import {
|
1
|
+
import { DeploymentConfig, DeploymentHooks } from './types.js';
|
2
2
|
|
3
|
-
|
3
|
+
interface BuildProjectOptions {
|
4
|
+
config: DeploymentConfig;
|
5
|
+
assetPath?: string;
|
6
|
+
hooks?: DeploymentHooks;
|
7
|
+
}
|
8
|
+
declare function buildProject(options: BuildProjectOptions): Promise<void>;
|
4
9
|
|
5
10
|
export { buildProject };
|
@@ -1,28 +1,43 @@
|
|
1
1
|
import { spawn } from 'child_process';
|
2
2
|
|
3
|
-
async function buildProject(
|
3
|
+
async function buildProject(options) {
|
4
|
+
const { config, assetPath, hooks } = options;
|
5
|
+
hooks?.onBuildStart?.();
|
4
6
|
const assetPathEnvironment = assetPath ? { HYDROGEN_ASSET_BASE_URL: assetPath } : {};
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if (
|
19
|
-
|
7
|
+
try {
|
8
|
+
await new Promise((resolve, reject) => {
|
9
|
+
const buildCommand = spawn(config.buildCommand, [], {
|
10
|
+
stdio: config.buildOutput ? ["inherit", "pipe", "inherit"] : ["ignore", "ignore", "pipe"],
|
11
|
+
env: {
|
12
|
+
// eslint-disable-next-line no-process-env
|
13
|
+
...process.env,
|
14
|
+
...assetPathEnvironment
|
15
|
+
},
|
16
|
+
cwd: config.rootPath,
|
17
|
+
shell: true
|
18
|
+
});
|
19
|
+
let stderrOutput = "";
|
20
|
+
if (buildCommand.stderr) {
|
21
|
+
buildCommand.stderr.on("data", (data) => {
|
22
|
+
stderrOutput += data;
|
23
|
+
});
|
24
|
+
}
|
25
|
+
if (config.buildOutput && buildCommand.stdout) {
|
26
|
+
buildCommand.stdout.pipe(process.stderr);
|
20
27
|
}
|
21
|
-
|
28
|
+
buildCommand.on("close", (code) => {
|
29
|
+
if (code !== 0) {
|
30
|
+
hooks?.onBuildError?.(new Error(stderrOutput));
|
31
|
+
reject(code);
|
32
|
+
return;
|
33
|
+
}
|
34
|
+
hooks?.onBuildComplete?.();
|
35
|
+
resolve(code);
|
36
|
+
});
|
22
37
|
});
|
23
|
-
}
|
38
|
+
} catch (error) {
|
24
39
|
throw new Error(`Build failed with error code: ${error}`);
|
25
|
-
}
|
40
|
+
}
|
26
41
|
}
|
27
42
|
|
28
43
|
export { buildProject };
|
@@ -30,7 +30,11 @@ test("BuildProject builds the project successfully", async () => {
|
|
30
30
|
buildCommand: "npm run build"
|
31
31
|
};
|
32
32
|
const assetPath = "https://example.com/assets";
|
33
|
-
|
33
|
+
const hooks = {
|
34
|
+
onBuildStart: vi.fn(),
|
35
|
+
onBuildComplete: vi.fn()
|
36
|
+
};
|
37
|
+
await buildProject({ config, assetPath, hooks });
|
34
38
|
expect(spawn).toBeCalledWith("npm run build", [], {
|
35
39
|
cwd: "rootFolder",
|
36
40
|
shell: true,
|
@@ -41,15 +45,17 @@ test("BuildProject builds the project successfully", async () => {
|
|
41
45
|
HYDROGEN_ASSET_BASE_URL: "https://example.com/assets"
|
42
46
|
}
|
43
47
|
});
|
48
|
+
expect(hooks.onBuildStart).toBeCalled();
|
49
|
+
expect(hooks.onBuildComplete).toBeCalled();
|
44
50
|
});
|
45
51
|
test("should throw error on build command failure", async () => {
|
46
52
|
returnCode = 1;
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
});
|
53
|
+
const hooks = {
|
54
|
+
onBuildError: vi.fn()
|
55
|
+
};
|
51
56
|
const assetPath = "https://example.com/assets";
|
52
|
-
await expect(
|
53
|
-
|
54
|
-
);
|
57
|
+
await expect(
|
58
|
+
() => buildProject({ config: testConfig, assetPath, hooks })
|
59
|
+
).rejects.toThrow("Build failed with error code: 1");
|
60
|
+
expect(hooks.onBuildError).toBeCalled();
|
55
61
|
});
|
@@ -1,10 +1,17 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig } from './types.js';
|
2
3
|
import { DeploymentCancelResponse } from './graphql/deployment-cancel.js';
|
3
4
|
|
4
5
|
declare enum DeploymentCancelReason {
|
5
6
|
Failed = "FAILED",
|
6
7
|
Cancelled = "CANCELLED"
|
7
8
|
}
|
8
|
-
|
9
|
+
interface DeploymentCancelOptions {
|
10
|
+
config: DeploymentConfig;
|
11
|
+
deploymentId: string;
|
12
|
+
reason: DeploymentCancelReason;
|
13
|
+
logger: Logger;
|
14
|
+
}
|
15
|
+
declare function deploymentCancel(options: DeploymentCancelOptions): Promise<DeploymentCancelResponse>;
|
9
16
|
|
10
17
|
export { DeploymentCancelReason, deploymentCancel };
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
2
2
|
import { AbortError } from '@shopify/cli-kit/node/error';
|
3
3
|
import { outputInfo } from '@shopify/cli-kit/node/output';
|
4
|
-
import { Header,
|
4
|
+
import { Header, errorHandler } from '../utils/utils.js';
|
5
5
|
import { DeploymentCancelQuery } from './graphql/deployment-cancel.js';
|
6
6
|
|
7
7
|
var DeploymentCancelReason = /* @__PURE__ */ ((DeploymentCancelReason2) => {
|
@@ -9,7 +9,8 @@ var DeploymentCancelReason = /* @__PURE__ */ ((DeploymentCancelReason2) => {
|
|
9
9
|
DeploymentCancelReason2["Cancelled"] = "CANCELLED";
|
10
10
|
return DeploymentCancelReason2;
|
11
11
|
})(DeploymentCancelReason || {});
|
12
|
-
async function deploymentCancel(
|
12
|
+
async function deploymentCancel(options) {
|
13
|
+
const { config, deploymentId, reason, logger } = options;
|
13
14
|
const variables = {
|
14
15
|
deploymentId,
|
15
16
|
reason
|
@@ -30,7 +31,7 @@ async function deploymentCancel(config, deploymentId, reason) {
|
|
30
31
|
`Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
|
31
32
|
);
|
32
33
|
}
|
33
|
-
outputInfo(`Deployment with id ${deploymentId} cancelled.`,
|
34
|
+
outputInfo(`Deployment with id ${deploymentId} cancelled.`, logger);
|
34
35
|
return response.deploymentCancel;
|
35
36
|
} catch (error) {
|
36
37
|
errorHandler(error);
|
@@ -2,7 +2,7 @@ import { AbortError } from '@shopify/cli-kit/node/error';
|
|
2
2
|
import { graphqlRequest } from '@shopify/cli-kit/node/api/graphql';
|
3
3
|
import { vi, describe, test, expect } from 'vitest';
|
4
4
|
import { createTestConfig } from '../utils/test-helper.js';
|
5
|
-
import { Header } from '../utils/utils.js';
|
5
|
+
import { stderrLogger, Header } from '../utils/utils.js';
|
6
6
|
import { deploymentCancel, DeploymentCancelReason } from './deployment-cancel.js';
|
7
7
|
|
8
8
|
vi.mock("@shopify/cli-kit/node/api/graphql");
|
@@ -19,11 +19,12 @@ describe("DeploymentComplete", () => {
|
|
19
19
|
}
|
20
20
|
};
|
21
21
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
22
|
-
const completeResponse = await deploymentCancel(
|
23
|
-
testConfig,
|
24
|
-
"deployment-1",
|
25
|
-
DeploymentCancelReason.Failed
|
26
|
-
|
22
|
+
const completeResponse = await deploymentCancel({
|
23
|
+
config: testConfig,
|
24
|
+
deploymentId: "deployment-1",
|
25
|
+
reason: DeploymentCancelReason.Failed,
|
26
|
+
logger: stderrLogger
|
27
|
+
});
|
27
28
|
expect(completeResponse).toEqual(response.deploymentCancel);
|
28
29
|
expect(graphqlRequest).toHaveBeenCalledWith({
|
29
30
|
query: expect.any(String),
|
@@ -51,11 +52,12 @@ describe("DeploymentComplete", () => {
|
|
51
52
|
};
|
52
53
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
53
54
|
await expect(
|
54
|
-
deploymentCancel(
|
55
|
-
testConfig,
|
56
|
-
"deployment-1",
|
57
|
-
DeploymentCancelReason.Failed
|
58
|
-
|
55
|
+
deploymentCancel({
|
56
|
+
config: testConfig,
|
57
|
+
deploymentId: "deployment-1",
|
58
|
+
reason: DeploymentCancelReason.Failed,
|
59
|
+
logger: stderrLogger
|
60
|
+
})
|
59
61
|
).rejects.toThrow(
|
60
62
|
new AbortError(
|
61
63
|
`Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
|
@@ -69,11 +71,12 @@ describe("DeploymentComplete", () => {
|
|
69
71
|
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
70
72
|
try {
|
71
73
|
await expect(
|
72
|
-
deploymentCancel(
|
73
|
-
testConfig,
|
74
|
-
"deployment-1",
|
75
|
-
DeploymentCancelReason.Failed
|
76
|
-
|
74
|
+
deploymentCancel({
|
75
|
+
config: testConfig,
|
76
|
+
deploymentId: "deployment-1",
|
77
|
+
reason: DeploymentCancelReason.Failed,
|
78
|
+
logger: stderrLogger
|
79
|
+
})
|
77
80
|
).rejects.toThrow(
|
78
81
|
new AbortError(
|
79
82
|
"You are not authorized to perform this action. Please check your deployment token."
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { DeploymentCompleteResponse } from './graphql/deployment-complete.js';
|
2
|
-
import {
|
2
|
+
import { DeploymentConfig } from './types.js';
|
3
3
|
|
4
|
-
declare function deploymentComplete(config:
|
4
|
+
declare function deploymentComplete(config: DeploymentConfig, deploymentId: string): Promise<DeploymentCompleteResponse>;
|
5
5
|
|
6
6
|
export { deploymentComplete };
|
@@ -1,17 +1,23 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig, DeploymentManifestFile, EnvironmentInput } from './types.js';
|
2
3
|
import { DeploymentInitiateResponse } from './graphql/deployment-initiate.js';
|
3
4
|
|
4
5
|
type DeploymentInitiateInput = {
|
5
6
|
buildId: string;
|
6
7
|
environment?: never;
|
7
|
-
manifest: DeploymentManifestFile[];
|
8
8
|
labels?: string[];
|
9
|
+
manifest: DeploymentManifestFile[];
|
9
10
|
} | {
|
10
11
|
environment?: EnvironmentInput;
|
11
12
|
buildId?: never;
|
12
|
-
manifest: DeploymentManifestFile[];
|
13
13
|
labels?: string[];
|
14
|
+
manifest: DeploymentManifestFile[];
|
14
15
|
};
|
15
|
-
|
16
|
+
interface DeploymentInitiateOptions {
|
17
|
+
config: DeploymentConfig;
|
18
|
+
input: DeploymentInitiateInput;
|
19
|
+
logger: Logger;
|
20
|
+
}
|
21
|
+
declare function deploymentInitiate(options: DeploymentInitiateOptions): Promise<DeploymentInitiateResponse>;
|
16
22
|
|
17
23
|
export { deploymentInitiate };
|