@shopify/oxygen-cli 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/deploy/build-cancel.js +2 -2
- package/dist/deploy/build-initiate.js +3 -2
- package/dist/deploy/build-initiate.test.js +3 -2
- package/dist/deploy/build-project.js +2 -6
- package/dist/deploy/build-project.test.js +3 -1
- package/dist/deploy/deployment-cancel.js +2 -2
- package/dist/deploy/deployment-initiate.js +3 -2
- package/dist/deploy/deployment-initiate.test.js +9 -5
- package/dist/deploy/index.js +18 -7
- package/dist/deploy/metadata.js +3 -3
- package/dist/deploy/metadata.test.js +1 -1
- package/dist/deploy/upload-files.js +3 -3
- package/dist/utils/utils.d.ts +2 -1
- package/dist/utils/utils.js +13 -4
- package/dist/utils/utils.test.js +8 -4
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
@@ -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, errorHandler } from '../utils/utils.js';
|
4
|
+
import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
|
5
5
|
import { BuildCancelQuery } from './graphql/build-cancel.js';
|
6
6
|
|
7
7
|
async function buildCancel(config, buildId, reason) {
|
@@ -25,7 +25,7 @@ async function buildCancel(config, buildId, reason) {
|
|
25
25
|
`Failed to cancel build: ${response.buildCancel.userErrors[0]?.message}`
|
26
26
|
);
|
27
27
|
}
|
28
|
-
outputInfo(`Build with id ${buildId} cancelled
|
28
|
+
outputInfo(`Build with id ${buildId} cancelled.`, stderrLogger);
|
29
29
|
return response.buildCancel;
|
30
30
|
} catch (error) {
|
31
31
|
errorHandler(error);
|
@@ -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 { outputCompleted } from '@shopify/cli-kit/node/output';
|
4
|
-
import { Header, errorHandler } from '../utils/utils.js';
|
4
|
+
import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
|
5
5
|
import { BuildInitiateQuery } from './graphql/build-initiate.js';
|
6
6
|
|
7
7
|
async function buildInitiate(config, environment, labels = []) {
|
@@ -26,7 +26,8 @@ async function buildInitiate(config, environment, labels = []) {
|
|
26
26
|
);
|
27
27
|
}
|
28
28
|
outputCompleted(
|
29
|
-
`Build initiated successfully with id ${response.buildInitiate.build.id}
|
29
|
+
`Build initiated successfully with id ${response.buildInitiate.build.id}.`,
|
30
|
+
stderrLogger
|
30
31
|
);
|
31
32
|
return response.buildInitiate;
|
32
33
|
} 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 { Header } from '../utils/utils.js';
|
5
|
+
import { Header, stderrLogger } from '../utils/utils.js';
|
6
6
|
import { createTestConfig } from '../utils/test-helper.js';
|
7
7
|
import { buildInitiate } from './build-initiate.js';
|
8
8
|
|
@@ -39,7 +39,8 @@ describe("BuildInitiate", () => {
|
|
39
39
|
}
|
40
40
|
});
|
41
41
|
expect(outputCompleted).toHaveBeenCalledWith(
|
42
|
-
"Build initiated successfully with id build-1."
|
42
|
+
"Build initiated successfully with id build-1.",
|
43
|
+
stderrLogger
|
43
44
|
);
|
44
45
|
});
|
45
46
|
test("should throw AbortError when build initiation fails due to user errors", async () => {
|
@@ -4,7 +4,7 @@ async function buildProject(config, assetPath) {
|
|
4
4
|
const assetPathEnvironment = assetPath ? { HYDROGEN_ASSET_BASE_URL: assetPath } : {};
|
5
5
|
await new Promise((resolve, reject) => {
|
6
6
|
const buildCommand = spawn(config.buildCommand, [], {
|
7
|
-
stdio: "inherit",
|
7
|
+
stdio: ["inherit", "pipe", "inherit"],
|
8
8
|
env: {
|
9
9
|
// eslint-disable-next-line no-process-env
|
10
10
|
...process.env,
|
@@ -13,11 +13,7 @@ async function buildProject(config, assetPath) {
|
|
13
13
|
cwd: config.rootPath,
|
14
14
|
shell: true
|
15
15
|
});
|
16
|
-
|
17
|
-
buildCommand.stdout.on("data", (data) => {
|
18
|
-
console.log(`stdout: ${data}`);
|
19
|
-
});
|
20
|
-
}
|
16
|
+
buildCommand.stdout.pipe(process.stderr);
|
21
17
|
buildCommand.on("close", (code) => {
|
22
18
|
if (code !== 0) {
|
23
19
|
reject(code);
|
@@ -10,6 +10,8 @@ vi.mock("child_process", () => {
|
|
10
10
|
return {
|
11
11
|
stdout: {
|
12
12
|
on: () => {
|
13
|
+
},
|
14
|
+
pipe: () => {
|
13
15
|
}
|
14
16
|
},
|
15
17
|
on: (event, callback) => {
|
@@ -32,7 +34,7 @@ test("BuildProject builds the project successfully", async () => {
|
|
32
34
|
expect(spawn).toBeCalledWith("npm run build", [], {
|
33
35
|
cwd: "rootFolder",
|
34
36
|
shell: true,
|
35
|
-
stdio: "inherit",
|
37
|
+
stdio: ["inherit", "pipe", "inherit"],
|
36
38
|
env: {
|
37
39
|
// eslint-disable-next-line no-process-env
|
38
40
|
...process.env,
|
@@ -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, errorHandler } from '../utils/utils.js';
|
4
|
+
import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
|
5
5
|
import { DeploymentCancelQuery } from './graphql/deployment-cancel.js';
|
6
6
|
|
7
7
|
async function deploymentCancel(config, deploymentId, reason) {
|
@@ -25,7 +25,7 @@ async function deploymentCancel(config, deploymentId, reason) {
|
|
25
25
|
`Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
|
26
26
|
);
|
27
27
|
}
|
28
|
-
outputInfo(`Deployment with id ${deploymentId} cancelled
|
28
|
+
outputInfo(`Deployment with id ${deploymentId} cancelled.`, stderrLogger);
|
29
29
|
return response.deploymentCancel;
|
30
30
|
} catch (error) {
|
31
31
|
errorHandler(error);
|
@@ -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 { outputCompleted } from '@shopify/cli-kit/node/output';
|
4
|
-
import { Header, errorHandler } from '../utils/utils.js';
|
4
|
+
import { Header, stderrLogger, errorHandler } from '../utils/utils.js';
|
5
5
|
import { DeploymentInitiateQuery } from './graphql/deployment-initiate.js';
|
6
6
|
|
7
7
|
async function deploymentInitiate(config, input) {
|
@@ -29,7 +29,8 @@ async function deploymentInitiate(config, input) {
|
|
29
29
|
);
|
30
30
|
}
|
31
31
|
outputCompleted(
|
32
|
-
`Deployment initiated, ${response.deploymentInitiate.deploymentTargets.length} files to upload
|
32
|
+
`Deployment initiated, ${response.deploymentInitiate.deploymentTargets.length} files to upload.`,
|
33
|
+
stderrLogger
|
33
34
|
);
|
34
35
|
return response.deploymentInitiate;
|
35
36
|
} 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 { Header } from '../utils/utils.js';
|
6
|
+
import { Header, stderrLogger } from '../utils/utils.js';
|
7
7
|
import { deploymentInitiate } from './deployment-initiate.js';
|
8
8
|
|
9
9
|
vi.mock("@shopify/cli-kit/node/api/graphql");
|
@@ -51,14 +51,16 @@ describe("DeploymentInitiate", () => {
|
|
51
51
|
variables: {
|
52
52
|
buildId: "build-1",
|
53
53
|
environment: void 0,
|
54
|
-
files: testManifest
|
54
|
+
files: testManifest,
|
55
|
+
isPrivate: true
|
55
56
|
},
|
56
57
|
addedHeaders: {
|
57
58
|
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
58
59
|
}
|
59
60
|
});
|
60
61
|
expect(outputCompleted).toHaveBeenCalledWith(
|
61
|
-
`Deployment initiated, ${testManifest.length} files to upload
|
62
|
+
`Deployment initiated, ${testManifest.length} files to upload.`,
|
63
|
+
stderrLogger
|
62
64
|
);
|
63
65
|
});
|
64
66
|
test("should initiate a deployment with an environmentName", async () => {
|
@@ -77,14 +79,16 @@ describe("DeploymentInitiate", () => {
|
|
77
79
|
variables: {
|
78
80
|
buildId: void 0,
|
79
81
|
environment: { tag: "preview" },
|
80
|
-
files: testManifest
|
82
|
+
files: testManifest,
|
83
|
+
isPrivate: true
|
81
84
|
},
|
82
85
|
addedHeaders: {
|
83
86
|
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
84
87
|
}
|
85
88
|
});
|
86
89
|
expect(outputCompleted).toHaveBeenCalledWith(
|
87
|
-
`Deployment initiated, ${testManifest.length} files to upload
|
90
|
+
`Deployment initiated, ${testManifest.length} files to upload.`,
|
91
|
+
stderrLogger
|
88
92
|
);
|
89
93
|
});
|
90
94
|
test("should throw AbortError when deployment initiation fails due to user errors", async () => {
|
package/dist/deploy/index.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
import { outputSuccess, outputWarn, consoleError } from '@shopify/cli-kit/node/output';
|
2
|
-
import { verifyConfig } from '../utils/utils.js';
|
1
|
+
import { outputSuccess, outputInfo, outputWarn, consoleError } from '@shopify/cli-kit/node/output';
|
2
|
+
import { verifyConfig, stderrLogger } from '../utils/utils.js';
|
3
3
|
import { buildInitiate } from './build-initiate.js';
|
4
4
|
import { buildCancel } from './build-cancel.js';
|
5
5
|
import { getUploadFiles } from './get-upload-files.js';
|
@@ -43,28 +43,39 @@ async function createDeploy(config) {
|
|
43
43
|
const urlMessage = config.publicDeployment ? "Public" : "Private";
|
44
44
|
outputSuccess(
|
45
45
|
`Deployment complete.
|
46
|
-
${urlMessage} preview URL: ${deploymentCompleteOp.deployment.url}
|
46
|
+
${urlMessage} preview URL: ${deploymentCompleteOp.deployment.url}`,
|
47
|
+
stderrLogger
|
47
48
|
);
|
49
|
+
if (metadata.name !== "none") {
|
50
|
+
outputInfo(deploymentCompleteOp.deployment.url);
|
51
|
+
}
|
48
52
|
} catch (error) {
|
49
53
|
if (!(error instanceof Error)) {
|
50
54
|
console.error("Unknown error", error);
|
51
55
|
return;
|
52
56
|
}
|
53
57
|
if (build.id && !buildCompleted) {
|
54
|
-
outputWarn(
|
58
|
+
outputWarn(
|
59
|
+
`Build failed with: ${error.message}, cancelling build.`,
|
60
|
+
stderrLogger
|
61
|
+
);
|
55
62
|
await buildCancel(config, build.id, error.message).catch((err) => {
|
56
63
|
if (err instanceof Error) {
|
57
|
-
outputWarn(`Failed to cancel build: ${err.message}
|
64
|
+
outputWarn(`Failed to cancel build: ${err.message}`, stderrLogger);
|
58
65
|
}
|
59
66
|
});
|
60
67
|
} else if (deployment?.deployment.id) {
|
61
68
|
outputWarn(
|
62
|
-
`Deployment failed with: ${error.message}, cancelling deployment
|
69
|
+
`Deployment failed with: ${error.message}, cancelling deployment.`,
|
70
|
+
stderrLogger
|
63
71
|
);
|
64
72
|
await deploymentCancel(config, deployment.deployment.id, "failed").catch(
|
65
73
|
(err) => {
|
66
74
|
if (err instanceof Error) {
|
67
|
-
outputWarn(
|
75
|
+
outputWarn(
|
76
|
+
`Failed to cancel deployment: ${err.message}`,
|
77
|
+
stderrLogger
|
78
|
+
);
|
68
79
|
}
|
69
80
|
}
|
70
81
|
);
|
package/dist/deploy/metadata.js
CHANGED
@@ -1,7 +1,7 @@
|
|
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 { maxLabelLength } from '../utils/utils.js';
|
4
|
+
import { stderrLogger, maxLabelLength } from '../utils/utils.js';
|
5
5
|
|
6
6
|
async function getMetadata(config) {
|
7
7
|
const ciInfo = ciPlatform();
|
@@ -19,11 +19,11 @@ 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", stderrLogger);
|
23
23
|
}
|
24
24
|
}
|
25
25
|
return {
|
26
|
-
name: ciInfo.isCI ? ciInfo.name : "
|
26
|
+
name: ciInfo.isCI ? ciInfo.name : "none",
|
27
27
|
...metadata,
|
28
28
|
actor: config.metadata.user ?? metadata.actor,
|
29
29
|
commitSha: config.metadata.version ?? metadata.commitSha,
|
@@ -64,7 +64,7 @@ describe("getMetadata", () => {
|
|
64
64
|
const metadataResult = await getMetadata(testConfig);
|
65
65
|
expect(metadataResult.actor).toBe("gh_author");
|
66
66
|
expect(metadataResult.commitSha).toBe("gh_hash");
|
67
|
-
expect(metadataResult.name).toBe("
|
67
|
+
expect(metadataResult.name).toBe("none");
|
68
68
|
expect(metadataResult.url).toBe(void 0);
|
69
69
|
});
|
70
70
|
});
|
@@ -3,14 +3,14 @@ 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 { deployDefaults } from '../utils/utils.js';
|
6
|
+
import { stderrLogger, deployDefaults } from '../utils/utils.js';
|
7
7
|
|
8
8
|
async function uploadFiles(config, targets) {
|
9
|
-
outputInfo(`Uploading ${targets.length} files
|
9
|
+
outputInfo(`Uploading ${targets.length} files...`, stderrLogger);
|
10
10
|
return mapLimit(targets, 6, async (target) => {
|
11
11
|
await uploadFile(config, target);
|
12
12
|
}).then(() => {
|
13
|
-
outputCompleted(`Files uploaded successfully
|
13
|
+
outputCompleted(`Files uploaded successfully`, stderrLogger);
|
14
14
|
});
|
15
15
|
}
|
16
16
|
async function uploadFile(config, target) {
|
package/dist/utils/utils.d.ts
CHANGED
@@ -9,6 +9,7 @@ declare enum Header {
|
|
9
9
|
OxygenNamespaceHandle = "X-Oxygen-Namespace-Handle"
|
10
10
|
}
|
11
11
|
declare function isClientError(error: unknown): error is ClientError;
|
12
|
+
declare function stderrLogger(log: string): void;
|
12
13
|
declare const maxLabelLength = 90;
|
13
14
|
declare function parseToken(inputToken: string): DeploymentToken;
|
14
15
|
interface VerifyConfigParams {
|
@@ -17,4 +18,4 @@ interface VerifyConfigParams {
|
|
17
18
|
}
|
18
19
|
declare function verifyConfig({ config, performedBuild, }: VerifyConfigParams): Promise<void>;
|
19
20
|
|
20
|
-
export { Header, deployDefaults, errorHandler, getBuildCommandFromLockFile, isClientError, maxLabelLength, parseToken, verifyConfig };
|
21
|
+
export { Header, deployDefaults, errorHandler, getBuildCommandFromLockFile, isClientError, maxLabelLength, parseToken, stderrLogger, verifyConfig };
|
package/dist/utils/utils.js
CHANGED
@@ -43,13 +43,17 @@ function getBuildCommandFromLockFile(config) {
|
|
43
43
|
}
|
44
44
|
if (foundLockFiles.length > 1) {
|
45
45
|
const lockFilesList = foundLockFiles.map(({ lockFileName }) => lockFileName).join(", ");
|
46
|
-
outputWarn(
|
46
|
+
outputWarn(
|
47
|
+
`Warning: Multiple lock files found: (${lockFilesList}).`,
|
48
|
+
stderrLogger
|
49
|
+
);
|
47
50
|
}
|
48
51
|
if (foundLockFiles.length > 0) {
|
49
52
|
const { lockFileName, buildCommand } = foundLockFiles[0];
|
50
53
|
const infoMsg = foundLockFiles.length > 1 ? "" : `Found: ${lockFileName}. `;
|
51
54
|
outputInfo(
|
52
|
-
`${infoMsg}Assuming "${buildCommand}" as build command. Use the buildCommand flag to override
|
55
|
+
`${infoMsg}Assuming "${buildCommand}" as build command. Use the buildCommand flag to override.`,
|
56
|
+
stderrLogger
|
53
57
|
);
|
54
58
|
return buildCommand;
|
55
59
|
}
|
@@ -62,6 +66,10 @@ var Header = /* @__PURE__ */ ((Header2) => {
|
|
62
66
|
function isClientError(error) {
|
63
67
|
return typeof error === "object" && error !== null && "statusCode" in error;
|
64
68
|
}
|
69
|
+
function stderrLogger(log) {
|
70
|
+
process.stderr.write(`${log}
|
71
|
+
`);
|
72
|
+
}
|
65
73
|
const maxLabelLength = 90;
|
66
74
|
function parseToken(inputToken) {
|
67
75
|
try {
|
@@ -100,7 +108,8 @@ async function checkPath(path, pathType) {
|
|
100
108
|
if (!await fileExists(path)) {
|
101
109
|
if (pathType === "assets") {
|
102
110
|
outputWarn(
|
103
|
-
`Use the "workerOnly" flag to perform a worker-only deployment
|
111
|
+
`Use the "workerOnly" flag to perform a worker-only deployment.`,
|
112
|
+
stderrLogger
|
104
113
|
);
|
105
114
|
}
|
106
115
|
throw new Error(`Path not found: ${path}`);
|
@@ -123,4 +132,4 @@ function convertKeysToCamelCase(obj) {
|
|
123
132
|
return obj;
|
124
133
|
}
|
125
134
|
|
126
|
-
export { Header, deployDefaults, errorHandler, getBuildCommandFromLockFile, isClientError, maxLabelLength, parseToken, verifyConfig };
|
135
|
+
export { Header, deployDefaults, errorHandler, getBuildCommandFromLockFile, isClientError, maxLabelLength, parseToken, stderrLogger, verifyConfig };
|
package/dist/utils/utils.test.js
CHANGED
@@ -29,7 +29,8 @@ describe("getBuildCommandFromLockfile", () => {
|
|
29
29
|
const buildCommand = utils.getBuildCommandFromLockFile(testConfig);
|
30
30
|
expect(buildCommand).toBe("pnpm run build");
|
31
31
|
expect(outputInfo).toHaveBeenCalledWith(
|
32
|
-
'Found: pnpm-lock.yaml. Assuming "pnpm run build" as build command. Use the buildCommand flag to override.'
|
32
|
+
'Found: pnpm-lock.yaml. Assuming "pnpm run build" as build command. Use the buildCommand flag to override.',
|
33
|
+
utils.stderrLogger
|
33
34
|
);
|
34
35
|
});
|
35
36
|
test("getBuildCommandFromLockfile the first build command and warns when multiple lockfiles are found", async () => {
|
@@ -37,10 +38,12 @@ describe("getBuildCommandFromLockfile", () => {
|
|
37
38
|
const buildCommand = utils.getBuildCommandFromLockFile(testConfig);
|
38
39
|
expect(buildCommand).toBe("pnpm run build");
|
39
40
|
expect(outputInfo).toHaveBeenCalledWith(
|
40
|
-
'Assuming "pnpm run build" as build command. Use the buildCommand flag to override.'
|
41
|
+
'Assuming "pnpm run build" as build command. Use the buildCommand flag to override.',
|
42
|
+
utils.stderrLogger
|
41
43
|
);
|
42
44
|
expect(outputWarn).toHaveBeenCalledWith(
|
43
|
-
"Warning: Multiple lock files found: (pnpm-lock.yaml, yarn.lock)."
|
45
|
+
"Warning: Multiple lock files found: (pnpm-lock.yaml, yarn.lock).",
|
46
|
+
utils.stderrLogger
|
44
47
|
);
|
45
48
|
});
|
46
49
|
});
|
@@ -94,7 +97,8 @@ describe("verifyConfig", () => {
|
|
94
97
|
)
|
95
98
|
);
|
96
99
|
expect(outputWarn).toHaveBeenCalledWith(
|
97
|
-
`Use the "workerOnly" flag to perform a worker-only deployment
|
100
|
+
`Use the "workerOnly" flag to perform a worker-only deployment.`,
|
101
|
+
utils.stderrLogger
|
98
102
|
);
|
99
103
|
});
|
100
104
|
test("verifyConfig throws when the workerDir cannot be resolved after a build", async () => {
|
package/oclif.manifest.json
CHANGED