@shopify/oxygen-cli 1.4.0 → 1.5.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/commands/oxygen/deploy.d.ts +3 -3
- package/dist/commands/oxygen/deploy.js +4 -3
- 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/index.d.ts +10 -3
- package/dist/deploy/index.js +40 -23
- 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 +10 -2
- 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 +1 -0
- package/dist/utils/utils.d.ts +3 -3
- package/dist/utils/utils.js +0 -5
- package/oclif.manifest.json +2 -2
- package/package.json +3 -3
@@ -1,12 +1,12 @@
|
|
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 {
|
3
|
+
import { DeploymentConfig } from '../../deploy/types.js';
|
4
4
|
|
5
5
|
declare class Deploy extends Command {
|
6
6
|
static description: string;
|
7
7
|
static hidden: boolean;
|
8
8
|
static flags: {
|
9
|
-
token: _oclif_core_lib_interfaces_parser_js.OptionFlag<string
|
9
|
+
token: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
10
10
|
path: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
11
11
|
environmentTag: _oclif_core_lib_interfaces_parser_js.OptionFlag<string | undefined, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
12
12
|
workerFolder: _oclif_core_lib_interfaces_parser_js.OptionFlag<string, _oclif_core_lib_interfaces_parser_js.CustomOptions>;
|
@@ -22,6 +22,6 @@ declare class Deploy extends Command {
|
|
22
22
|
static hasCustomBuildCommand: boolean;
|
23
23
|
run(): Promise<void>;
|
24
24
|
}
|
25
|
-
declare function runInit(
|
25
|
+
declare function runInit(config: DeploymentConfig): void;
|
26
26
|
|
27
27
|
export { Deploy, runInit };
|
@@ -12,7 +12,7 @@ class Deploy extends Command {
|
|
12
12
|
char: "t",
|
13
13
|
description: "Oxygen deployment token",
|
14
14
|
env: "OXYGEN_DEPLOYMENT_TOKEN",
|
15
|
-
required:
|
15
|
+
required: true
|
16
16
|
}),
|
17
17
|
path: Flags.string({
|
18
18
|
char: "p",
|
@@ -92,6 +92,7 @@ class Deploy extends Command {
|
|
92
92
|
const config = {
|
93
93
|
assetsDir: normalizePath(flags.assetsFolder),
|
94
94
|
buildCommand: flags.buildCommand,
|
95
|
+
buildOutput: true,
|
95
96
|
deploymentToken: parseToken(flags.token),
|
96
97
|
environmentTag: flags.environmentTag,
|
97
98
|
deploymentUrl,
|
@@ -121,8 +122,8 @@ class Deploy extends Command {
|
|
121
122
|
}
|
122
123
|
}
|
123
124
|
}
|
124
|
-
function runInit(
|
125
|
-
createDeploy(
|
125
|
+
function runInit(config) {
|
126
|
+
createDeploy({ config });
|
126
127
|
}
|
127
128
|
|
128
129
|
export { Deploy, runInit };
|
@@ -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 };
|
@@ -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 { DeploymentInitiateQuery } from './graphql/deployment-initiate.js';
|
6
6
|
|
7
|
-
async function deploymentInitiate(
|
7
|
+
async function deploymentInitiate(options) {
|
8
|
+
const { config, input, logger } = options;
|
8
9
|
const variables = {
|
9
10
|
buildId: input.buildId,
|
10
11
|
environment: input.environment,
|
@@ -30,7 +31,7 @@ async function deploymentInitiate(config, input) {
|
|
30
31
|
}
|
31
32
|
outputCompleted(
|
32
33
|
`Deployment initiated, ${response.deploymentInitiate.deploymentTargets.length} files to upload.`,
|
33
|
-
|
34
|
+
logger
|
34
35
|
);
|
35
36
|
return response.deploymentInitiate;
|
36
37
|
} catch (error) {
|
@@ -3,7 +3,7 @@ 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
5
|
import { createTestConfig } from '../utils/test-helper.js';
|
6
|
-
import {
|
6
|
+
import { stderrLogger, Header } from '../utils/utils.js';
|
7
7
|
import { deploymentInitiate } from './deployment-initiate.js';
|
8
8
|
|
9
9
|
vi.mock("@shopify/cli-kit/node/api/graphql");
|
@@ -38,9 +38,13 @@ const testResponse = {
|
|
38
38
|
describe("DeploymentInitiate", () => {
|
39
39
|
test("should initiate a deployment with a buildId", async () => {
|
40
40
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(testResponse);
|
41
|
-
const initiateResponse = await deploymentInitiate(
|
42
|
-
|
43
|
-
|
41
|
+
const initiateResponse = await deploymentInitiate({
|
42
|
+
config: testConfig,
|
43
|
+
input: {
|
44
|
+
buildId: "build-1",
|
45
|
+
manifest: testManifest
|
46
|
+
},
|
47
|
+
logger: stderrLogger
|
44
48
|
});
|
45
49
|
expect(initiateResponse).toEqual(testResponse.deploymentInitiate);
|
46
50
|
expect(graphqlRequest).toHaveBeenCalledWith({
|
@@ -65,10 +69,14 @@ describe("DeploymentInitiate", () => {
|
|
65
69
|
});
|
66
70
|
test("should initiate a deployment with an environmentName", async () => {
|
67
71
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(testResponse);
|
68
|
-
const initiateResponse = await deploymentInitiate(
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
+
const initiateResponse = await deploymentInitiate({
|
73
|
+
config: testConfig,
|
74
|
+
input: {
|
75
|
+
buildId: void 0,
|
76
|
+
environment: { tag: "preview" },
|
77
|
+
manifest: testManifest
|
78
|
+
},
|
79
|
+
logger: stderrLogger
|
72
80
|
});
|
73
81
|
expect(initiateResponse).toEqual(testResponse.deploymentInitiate);
|
74
82
|
expect(graphqlRequest).toHaveBeenCalledWith({
|
@@ -108,7 +116,11 @@ describe("DeploymentInitiate", () => {
|
|
108
116
|
manifest: testManifest
|
109
117
|
};
|
110
118
|
await expect(
|
111
|
-
deploymentInitiate(
|
119
|
+
deploymentInitiate({
|
120
|
+
config: testConfig,
|
121
|
+
input: deploymentInitData,
|
122
|
+
logger: stderrLogger
|
123
|
+
})
|
112
124
|
).rejects.toThrow(
|
113
125
|
new AbortError(
|
114
126
|
`Failed to create deployment. ${response.deploymentInitiate.userErrors[0]?.message}`
|
@@ -127,7 +139,11 @@ describe("DeploymentInitiate", () => {
|
|
127
139
|
manifest: testManifest
|
128
140
|
};
|
129
141
|
await expect(
|
130
|
-
deploymentInitiate(
|
142
|
+
deploymentInitiate({
|
143
|
+
config: testConfig,
|
144
|
+
input: deploymentInitData,
|
145
|
+
logger: stderrLogger
|
146
|
+
})
|
131
147
|
).rejects.toThrow(
|
132
148
|
new AbortError(
|
133
149
|
"You are not authorized to perform this action. Please check your deployment token."
|
@@ -1,5 +1,5 @@
|
|
1
|
-
import {
|
1
|
+
import { DeploymentConfig, DeploymentManifestFile } from './types.js';
|
2
2
|
|
3
|
-
declare function getUploadFiles(config:
|
3
|
+
declare function getUploadFiles(config: DeploymentConfig): Promise<DeploymentManifestFile[]>;
|
4
4
|
|
5
5
|
export { getUploadFiles };
|
package/dist/deploy/index.d.ts
CHANGED
@@ -1,5 +1,12 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig, DeploymentHooks } from './types.js';
|
3
|
+
export { parseToken } from '../utils/utils.js';
|
2
4
|
|
3
|
-
|
5
|
+
interface CreateDeployOptions {
|
6
|
+
config: DeploymentConfig;
|
7
|
+
hooks?: DeploymentHooks;
|
8
|
+
logger?: Logger;
|
9
|
+
}
|
10
|
+
declare function createDeploy(options: CreateDeployOptions): Promise<string | undefined>;
|
4
11
|
|
5
|
-
export { createDeploy };
|
12
|
+
export { DeploymentConfig, DeploymentHooks, createDeploy };
|
package/dist/deploy/index.js
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
import { outputSuccess, outputInfo, outputWarn, consoleError } from '@shopify/cli-kit/node/output';
|
2
|
-
import {
|
2
|
+
import { stderrLogger, verifyConfig } from '../utils/utils.js';
|
3
|
+
export { parseToken } from '../utils/utils.js';
|
3
4
|
import { buildInitiate } from './build-initiate.js';
|
4
5
|
import { buildCancel } from './build-cancel.js';
|
5
6
|
import { getUploadFiles } from './get-upload-files.js';
|
@@ -10,32 +11,43 @@ import { uploadFiles } from './upload-files.js';
|
|
10
11
|
import { buildProject } from './build-project.js';
|
11
12
|
import { getMetadata, createLabels, getEnvironmentInput } from './metadata.js';
|
12
13
|
|
13
|
-
async function createDeploy(
|
14
|
+
async function createDeploy(options) {
|
15
|
+
const { config, hooks } = options;
|
16
|
+
const logger = options.logger ?? stderrLogger;
|
14
17
|
const build = {};
|
15
18
|
let buildCompleted;
|
16
19
|
let deployment;
|
17
20
|
try {
|
18
|
-
const metadata = await getMetadata(config);
|
21
|
+
const metadata = await getMetadata(config, logger);
|
19
22
|
const labels = createLabels(metadata);
|
20
23
|
const environment = getEnvironmentInput(config, metadata);
|
21
24
|
if (!config.workerOnly && !config.skipBuild) {
|
22
|
-
const buildInitiateResponse = await buildInitiate(
|
25
|
+
const buildInitiateResponse = await buildInitiate({
|
23
26
|
config,
|
24
27
|
environment,
|
25
|
-
labels
|
26
|
-
|
28
|
+
labels,
|
29
|
+
logger
|
30
|
+
});
|
27
31
|
build.id = buildInitiateResponse.build.id;
|
28
32
|
build.assetPath = buildInitiateResponse.build.assetPath;
|
29
33
|
}
|
30
34
|
if (!config.skipBuild) {
|
31
|
-
await buildProject(
|
35
|
+
await buildProject({
|
36
|
+
config,
|
37
|
+
assetPath: build.assetPath,
|
38
|
+
hooks
|
39
|
+
});
|
32
40
|
verifyConfig({ config, performedBuild: true });
|
33
41
|
}
|
34
42
|
buildCompleted = true;
|
35
43
|
const manifest = await getUploadFiles(config);
|
36
44
|
const deploymentInitiateInput = build.id ? { buildId: build.id, manifest } : { environment, manifest, labels };
|
37
|
-
deployment = await deploymentInitiate(
|
38
|
-
|
45
|
+
deployment = await deploymentInitiate({
|
46
|
+
config,
|
47
|
+
input: deploymentInitiateInput,
|
48
|
+
logger
|
49
|
+
});
|
50
|
+
await uploadFiles({ config, targets: deployment.deploymentTargets, logger });
|
39
51
|
const deploymentCompleteOp = await deploymentComplete(
|
40
52
|
config,
|
41
53
|
deployment.deployment.id
|
@@ -44,45 +56,50 @@ async function createDeploy(config) {
|
|
44
56
|
outputSuccess(
|
45
57
|
`Deployment complete.
|
46
58
|
${urlMessage} preview URL: ${deploymentCompleteOp.deployment.url}`,
|
47
|
-
|
59
|
+
logger
|
48
60
|
);
|
49
61
|
if (metadata.name !== "none") {
|
50
62
|
outputInfo(deploymentCompleteOp.deployment.url);
|
51
63
|
}
|
64
|
+
return deploymentCompleteOp.deployment.url;
|
52
65
|
} catch (error) {
|
53
66
|
if (!(error instanceof Error)) {
|
54
67
|
console.error("Unknown error", error);
|
55
|
-
return;
|
68
|
+
return Promise.reject(new Error("Unknown error"));
|
56
69
|
}
|
57
70
|
if (build.id && !buildCompleted) {
|
58
71
|
outputWarn(
|
59
72
|
`Build failed with: ${error.message}, cancelling build.`,
|
60
|
-
|
73
|
+
logger
|
61
74
|
);
|
62
|
-
await buildCancel(
|
75
|
+
await buildCancel({
|
76
|
+
config,
|
77
|
+
buildId: build.id,
|
78
|
+
reason: error.message,
|
79
|
+
logger
|
80
|
+
}).catch((err) => {
|
63
81
|
if (err instanceof Error) {
|
64
|
-
outputWarn(`Failed to cancel build: ${err.message}`,
|
82
|
+
outputWarn(`Failed to cancel build: ${err.message}`, logger);
|
65
83
|
}
|
66
84
|
});
|
67
85
|
} else if (deployment?.deployment.id) {
|
68
86
|
outputWarn(
|
69
87
|
`Deployment failed with: ${error.message}, cancelling deployment.`,
|
70
|
-
|
88
|
+
logger
|
71
89
|
);
|
72
|
-
await deploymentCancel(
|
90
|
+
await deploymentCancel({
|
73
91
|
config,
|
74
|
-
deployment.deployment.id,
|
75
|
-
DeploymentCancelReason.Failed
|
76
|
-
|
92
|
+
deploymentId: deployment.deployment.id,
|
93
|
+
reason: DeploymentCancelReason.Failed,
|
94
|
+
logger
|
95
|
+
}).catch((err) => {
|
77
96
|
if (err instanceof Error) {
|
78
|
-
outputWarn(
|
79
|
-
`Failed to cancel deployment: ${err.message}`,
|
80
|
-
stderrLogger
|
81
|
-
);
|
97
|
+
outputWarn(`Failed to cancel deployment: ${err.message}`, logger);
|
82
98
|
}
|
83
99
|
});
|
84
100
|
}
|
85
101
|
consoleError(error.message);
|
102
|
+
return Promise.reject(error);
|
86
103
|
}
|
87
104
|
}
|
88
105
|
|
@@ -1,11 +1,12 @@
|
|
1
1
|
import { CIMetadata } from '@shopify/cli-kit/node/context/local';
|
2
|
-
import {
|
2
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
3
|
+
import { DeploymentConfig, EnvironmentInput } from './types.js';
|
3
4
|
|
4
5
|
type Metadata = CIMetadata & {
|
5
6
|
name: string;
|
6
7
|
};
|
7
|
-
declare function getMetadata(config:
|
8
|
-
declare function getEnvironmentInput(config:
|
8
|
+
declare function getMetadata(config: DeploymentConfig, logger: Logger): Promise<Metadata>;
|
9
|
+
declare function getEnvironmentInput(config: DeploymentConfig, metadata: CIMetadata): EnvironmentInput | undefined;
|
9
10
|
declare function createLabels(metadata: Metadata): string[];
|
10
11
|
|
11
12
|
export { createLabels, getEnvironmentInput, getMetadata };
|
package/dist/deploy/metadata.js
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
import { ciPlatform } from '@shopify/cli-kit/node/context/local';
|
2
2
|
import { getLatestGitCommit } from '@shopify/cli-kit/node/git';
|
3
3
|
import { outputWarn } from '@shopify/cli-kit/node/output';
|
4
|
-
import {
|
4
|
+
import { maxLabelLength } from '../utils/utils.js';
|
5
5
|
|
6
|
-
async function getMetadata(config) {
|
6
|
+
async function getMetadata(config, logger) {
|
7
7
|
const ciInfo = ciPlatform();
|
8
8
|
let metadata = {};
|
9
9
|
if (ciInfo.isCI && ciInfo.name !== "unknown") {
|
@@ -19,7 +19,7 @@ async function getMetadata(config) {
|
|
19
19
|
commitMessage: gitCommit.message
|
20
20
|
};
|
21
21
|
} catch (error) {
|
22
|
-
outputWarn("No CI metadata loaded from environment",
|
22
|
+
outputWarn("No CI metadata loaded from environment", logger);
|
23
23
|
}
|
24
24
|
}
|
25
25
|
return {
|
@@ -1,7 +1,7 @@
|
|
1
1
|
import { getLatestGitCommit } from '@shopify/cli-kit/node/git';
|
2
2
|
import { ciPlatform } from '@shopify/cli-kit/node/context/local';
|
3
3
|
import { vi, describe, test, expect } from 'vitest';
|
4
|
-
import { maxLabelLength } from '../utils/utils.js';
|
4
|
+
import { stderrLogger, maxLabelLength } from '../utils/utils.js';
|
5
5
|
import { createTestConfig } from '../utils/test-helper.js';
|
6
6
|
import { getMetadata, getEnvironmentInput, createLabels } from './metadata.js';
|
7
7
|
|
@@ -19,7 +19,7 @@ describe("getMetadata", () => {
|
|
19
19
|
}
|
20
20
|
});
|
21
21
|
const testConfig = createTestConfig("/tmp/deploymentRoot/");
|
22
|
-
const metadataResult = await getMetadata(testConfig);
|
22
|
+
const metadataResult = await getMetadata(testConfig, stderrLogger);
|
23
23
|
expect(metadataResult.actor).toBe("circle_actor");
|
24
24
|
expect(metadataResult.commitSha).toBe("circle_sha");
|
25
25
|
expect(metadataResult.name).toBe("circle");
|
@@ -41,7 +41,7 @@ describe("getMetadata", () => {
|
|
41
41
|
version: "custom_version",
|
42
42
|
url: "custom_url"
|
43
43
|
};
|
44
|
-
const metadataResult = await getMetadata(testConfig);
|
44
|
+
const metadataResult = await getMetadata(testConfig, stderrLogger);
|
45
45
|
expect(metadataResult.actor).toBe("custom_user");
|
46
46
|
expect(metadataResult.commitSha).toBe("custom_version");
|
47
47
|
expect(metadataResult.name).toBe("circle");
|
@@ -61,7 +61,7 @@ describe("getMetadata", () => {
|
|
61
61
|
body: "gh_body"
|
62
62
|
});
|
63
63
|
const testConfig = createTestConfig("/tmp/deploymentRoot/");
|
64
|
-
const metadataResult = await getMetadata(testConfig);
|
64
|
+
const metadataResult = await getMetadata(testConfig, stderrLogger);
|
65
65
|
expect(metadataResult.actor).toBe("gh_author");
|
66
66
|
expect(metadataResult.commitSha).toBe("gh_hash");
|
67
67
|
expect(metadataResult.name).toBe("none");
|
package/dist/deploy/types.d.ts
CHANGED
@@ -5,9 +5,17 @@ interface Build {
|
|
5
5
|
interface ClientError extends Error {
|
6
6
|
statusCode: number;
|
7
7
|
}
|
8
|
-
interface
|
8
|
+
interface DeploymentHooks {
|
9
|
+
onBuildStart?: () => void;
|
10
|
+
onBuildComplete?: () => void;
|
11
|
+
onBuildError?: (error: Error) => void;
|
12
|
+
onUploadFilesStart?: () => void;
|
13
|
+
onUploadFilesComplete?: () => void;
|
14
|
+
}
|
15
|
+
interface DeploymentConfig {
|
9
16
|
assetsDir?: string;
|
10
17
|
buildCommand: string;
|
18
|
+
buildOutput: boolean;
|
11
19
|
deploymentToken: DeploymentToken;
|
12
20
|
deploymentUrl: string;
|
13
21
|
environmentTag?: string;
|
@@ -50,4 +58,4 @@ interface OxygenError {
|
|
50
58
|
message: string;
|
51
59
|
}
|
52
60
|
|
53
|
-
export { Build, ClientError,
|
61
|
+
export { Build, ClientError, DeploymentConfig, DeploymentHooks, DeploymentManifestFile, DeploymentToken, EnvironmentInput, FileType, OxygenError };
|
@@ -1,6 +1,13 @@
|
|
1
|
-
import {
|
1
|
+
import { Logger } from '@shopify/cli-kit/node/output';
|
2
|
+
import { DeploymentConfig, DeploymentHooks } from './types.js';
|
2
3
|
import { DeploymentTargetResponse } from './graphql/deployment-initiate.js';
|
3
4
|
|
4
|
-
|
5
|
+
interface UploadFilesOptions {
|
6
|
+
config: DeploymentConfig;
|
7
|
+
hooks?: DeploymentHooks;
|
8
|
+
logger: Logger;
|
9
|
+
targets: DeploymentTargetResponse[];
|
10
|
+
}
|
11
|
+
declare function uploadFiles(options: UploadFilesOptions): Promise<void>;
|
5
12
|
|
6
13
|
export { uploadFiles };
|
@@ -3,14 +3,17 @@ import { createFileReadStream } from '@shopify/cli-kit/node/fs';
|
|
3
3
|
import { outputInfo, outputCompleted } from '@shopify/cli-kit/node/output';
|
4
4
|
import { joinPath } from '@shopify/cli-kit/node/path';
|
5
5
|
import { mapLimit } from 'async';
|
6
|
-
import {
|
6
|
+
import { deployDefaults } from '../utils/utils.js';
|
7
7
|
|
8
|
-
async function uploadFiles(
|
9
|
-
|
8
|
+
async function uploadFiles(options) {
|
9
|
+
const { config, logger, targets, hooks } = options;
|
10
|
+
outputInfo(`Uploading ${targets.length} files...`, logger);
|
11
|
+
hooks?.onUploadFilesStart?.();
|
10
12
|
return mapLimit(targets, 6, async (target) => {
|
11
13
|
await uploadFile(config, target);
|
12
14
|
}).then(() => {
|
13
|
-
|
15
|
+
hooks?.onUploadFilesComplete?.();
|
16
|
+
outputCompleted(`Files uploaded successfully`, logger);
|
14
17
|
});
|
15
18
|
}
|
16
19
|
async function uploadFile(config, target) {
|
@@ -3,7 +3,7 @@ import { fetch } from '@shopify/cli-kit/node/http';
|
|
3
3
|
import { vi, describe, beforeEach, it, expect } from 'vitest';
|
4
4
|
import { Response } from 'node-fetch';
|
5
5
|
import { createTestConfig } from '../utils/test-helper.js';
|
6
|
-
import { deployDefaults } from '../utils/utils.js';
|
6
|
+
import { stderrLogger, deployDefaults } from '../utils/utils.js';
|
7
7
|
import { uploadFiles } from './upload-files.js';
|
8
8
|
|
9
9
|
class NamedReadable extends Readable {
|
@@ -29,22 +29,16 @@ vi.mock("@shopify/cli-kit/node/fs", () => {
|
|
29
29
|
})
|
30
30
|
};
|
31
31
|
});
|
32
|
-
vi.mock("fs", () => {
|
33
|
-
return {
|
34
|
-
createReadStream: vi.fn(() => {
|
35
|
-
const readable = new NamedReadable();
|
36
|
-
readable.push("dummy");
|
37
|
-
readable.emit("end");
|
38
|
-
return readable;
|
39
|
-
})
|
40
|
-
};
|
41
|
-
});
|
42
32
|
const testConfig = createTestConfig("/tmp/deploymentRoot");
|
43
33
|
describe("UploadFiles", () => {
|
44
34
|
beforeEach(() => {
|
45
35
|
vi.mocked(fetch).mockReset();
|
46
36
|
});
|
47
37
|
it("Performs a form upload", async () => {
|
38
|
+
const hooks = {
|
39
|
+
onUploadFilesStart: vi.fn(),
|
40
|
+
onUploadFilesComplete: vi.fn()
|
41
|
+
};
|
48
42
|
const response = new Response();
|
49
43
|
vi.mocked(fetch).mockResolvedValueOnce(response);
|
50
44
|
const testWorkerUpload = [
|
@@ -56,7 +50,12 @@ describe("UploadFiles", () => {
|
|
56
50
|
parameters: [{ name: "someName", value: "someValue" }]
|
57
51
|
}
|
58
52
|
];
|
59
|
-
await uploadFiles(
|
53
|
+
await uploadFiles({
|
54
|
+
config: testConfig,
|
55
|
+
targets: testWorkerUpload,
|
56
|
+
logger: stderrLogger,
|
57
|
+
hooks
|
58
|
+
});
|
60
59
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(1);
|
61
60
|
expect(vi.mocked(fetch)).toHaveBeenCalledWith(
|
62
61
|
"https://storage.googleapis.com/the-bucket/",
|
@@ -73,6 +72,8 @@ describe("UploadFiles", () => {
|
|
73
72
|
})
|
74
73
|
})
|
75
74
|
);
|
75
|
+
expect(hooks.onUploadFilesStart).toBeCalled();
|
76
|
+
expect(hooks.onUploadFilesComplete).toBeCalled();
|
76
77
|
});
|
77
78
|
it("Retries a failed form upload until the max upload attempts then throws", async () => {
|
78
79
|
vi.mocked(fetch).mockRejectedValue(new Error("some error"));
|
@@ -85,9 +86,13 @@ describe("UploadFiles", () => {
|
|
85
86
|
parameters: [{ name: "someName", value: "someValue" }]
|
86
87
|
}
|
87
88
|
];
|
88
|
-
await expect(
|
89
|
-
|
90
|
-
|
89
|
+
await expect(
|
90
|
+
uploadFiles({
|
91
|
+
config: testConfig,
|
92
|
+
targets: testWorkerUpload,
|
93
|
+
logger: stderrLogger
|
94
|
+
})
|
95
|
+
).rejects.toThrow("Failed to upload file index.js");
|
91
96
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(
|
92
97
|
Number(deployDefaults.maxUploadAttempts) + 1
|
93
98
|
);
|
@@ -108,7 +113,11 @@ describe("UploadFiles", () => {
|
|
108
113
|
parameters: null
|
109
114
|
}
|
110
115
|
];
|
111
|
-
await uploadFiles(
|
116
|
+
await uploadFiles({
|
117
|
+
config: testConfig,
|
118
|
+
targets: testWorkerUpload,
|
119
|
+
logger: stderrLogger
|
120
|
+
});
|
112
121
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(2);
|
113
122
|
const secondCall = vi.mocked(fetch).mock.calls[1];
|
114
123
|
expect(secondCall[0]).toBe("https://upload-it-here.com/");
|
@@ -145,7 +154,11 @@ describe("UploadFiles", () => {
|
|
145
154
|
parameters: null
|
146
155
|
}
|
147
156
|
];
|
148
|
-
await uploadFiles(
|
157
|
+
await uploadFiles({
|
158
|
+
config: testConfig,
|
159
|
+
targets: testWorkerUpload,
|
160
|
+
logger: stderrLogger
|
161
|
+
});
|
149
162
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(4);
|
150
163
|
const statusCall = vi.mocked(fetch).mock.calls[2];
|
151
164
|
expect(statusCall[0]).toBe("https://upload-it-here.com/");
|
@@ -183,7 +196,13 @@ describe("UploadFiles", () => {
|
|
183
196
|
parameters: null
|
184
197
|
}
|
185
198
|
];
|
186
|
-
await expect(
|
199
|
+
await expect(
|
200
|
+
uploadFiles({
|
201
|
+
config: testConfig,
|
202
|
+
targets: testWorkerUpload,
|
203
|
+
logger: stderrLogger
|
204
|
+
})
|
205
|
+
).rejects.toThrow(
|
187
206
|
`Failed to upload file index.js after ${deployDefaults.maxResumabeUploadAttempts} attempts`
|
188
207
|
);
|
189
208
|
expect(vi.mocked(fetch)).toHaveBeenCalledTimes(
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {
|
1
|
+
import { DeploymentConfig } from '../deploy/types.js';
|
2
2
|
|
3
3
|
declare const testToken: {
|
4
4
|
accessToken: string;
|
@@ -9,6 +9,6 @@ declare const testToken: {
|
|
9
9
|
namespace: string;
|
10
10
|
namespaceId: string;
|
11
11
|
};
|
12
|
-
declare function createTestConfig(rootFolder: string):
|
12
|
+
declare function createTestConfig(rootFolder: string): DeploymentConfig;
|
13
13
|
|
14
14
|
export { createTestConfig, testToken };
|
@@ -13,6 +13,7 @@ function createTestConfig(rootFolder) {
|
|
13
13
|
return {
|
14
14
|
assetsDir: "/assets/",
|
15
15
|
buildCommand: String(deployDefaults.buildCommandDefault),
|
16
|
+
buildOutput: true,
|
16
17
|
deploymentToken: testToken,
|
17
18
|
environmentTag: "environment",
|
18
19
|
deploymentUrl: "https://localhost:3000",
|
package/dist/utils/utils.d.ts
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
import {
|
1
|
+
import { DeploymentConfig, ClientError, DeploymentToken } from '../deploy/types.js';
|
2
2
|
|
3
3
|
declare const deployDefaults: {
|
4
4
|
[key: string]: string | number;
|
5
5
|
};
|
6
6
|
declare function errorHandler(error: any): void;
|
7
|
-
declare function getBuildCommandFromLockFile(config:
|
7
|
+
declare function getBuildCommandFromLockFile(config: DeploymentConfig): string;
|
8
8
|
declare enum Header {
|
9
9
|
OxygenNamespaceHandle = "X-Oxygen-Namespace-Handle"
|
10
10
|
}
|
@@ -13,7 +13,7 @@ declare function stderrLogger(log: string): void;
|
|
13
13
|
declare const maxLabelLength = 90;
|
14
14
|
declare function parseToken(inputToken: string): DeploymentToken;
|
15
15
|
interface VerifyConfigParams {
|
16
|
-
config:
|
16
|
+
config: DeploymentConfig;
|
17
17
|
performedBuild?: boolean;
|
18
18
|
}
|
19
19
|
declare function verifyConfig({ config, performedBuild, }: VerifyConfigParams): Promise<void>;
|
package/dist/utils/utils.js
CHANGED
@@ -72,11 +72,6 @@ function stderrLogger(log) {
|
|
72
72
|
}
|
73
73
|
const maxLabelLength = 90;
|
74
74
|
function parseToken(inputToken) {
|
75
|
-
if (!inputToken) {
|
76
|
-
throw new Error(
|
77
|
-
"No deployment token provided. Use the --token flag to set a deployment token."
|
78
|
-
);
|
79
|
-
}
|
80
75
|
try {
|
81
76
|
const decodedToken = Buffer.from(inputToken, "base64").toString("utf-8");
|
82
77
|
const rawToken = JSON.parse(decodedToken);
|
package/oclif.manifest.json
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": "1.
|
2
|
+
"version": "1.5.0",
|
3
3
|
"commands": {
|
4
4
|
"oxygen:deploy": {
|
5
5
|
"id": "oxygen:deploy",
|
@@ -16,7 +16,7 @@
|
|
16
16
|
"type": "option",
|
17
17
|
"char": "t",
|
18
18
|
"description": "Oxygen deployment token",
|
19
|
-
"required":
|
19
|
+
"required": true,
|
20
20
|
"multiple": false
|
21
21
|
},
|
22
22
|
"path": {
|
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.5.0",
|
9
9
|
"type": "module",
|
10
10
|
"scripts": {
|
11
11
|
"build": "tsup --clean --config ./tsup.config.ts && oclif manifest",
|
@@ -31,7 +31,7 @@
|
|
31
31
|
"/oclif.manifest.json"
|
32
32
|
],
|
33
33
|
"dependencies": {
|
34
|
-
"@oclif/core": "2.8.
|
34
|
+
"@oclif/core": "2.8.11",
|
35
35
|
"@shopify/cli-kit": "^3.46.5",
|
36
36
|
"async": "^3.2.4"
|
37
37
|
},
|
@@ -45,7 +45,7 @@
|
|
45
45
|
"eslint": "^8.43.0",
|
46
46
|
"node-fetch": "^3.3.1",
|
47
47
|
"oclif": "^3",
|
48
|
-
"tsup": "^
|
48
|
+
"tsup": "^7.1.0",
|
49
49
|
"typescript": "^5.1.3",
|
50
50
|
"vite": "^4.3.9",
|
51
51
|
"vitest": "^0.32.2"
|