@shopify/oxygen-cli 1.2.0 → 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +4 -4
- package/dist/commands/oxygen/deploy.js +3 -3
- 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.d.ts +6 -2
- package/dist/deploy/deployment-cancel.js +8 -3
- package/dist/deploy/deployment-cancel.test.js +13 -5
- package/dist/deploy/deployment-initiate.js +3 -2
- package/dist/deploy/deployment-initiate.test.js +9 -5
- package/dist/deploy/graphql/deployment-complete.d.ts +1 -2
- package/dist/deploy/graphql/deployment-complete.js +0 -1
- package/dist/deploy/graphql/deployment-initiate.d.ts +1 -2
- package/dist/deploy/graphql/deployment-initiate.js +0 -1
- package/dist/deploy/index.js +26 -13
- 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 +14 -5
- package/dist/utils/utils.test.js +8 -4
- package/oclif.manifest.json +4 -4
- package/package.json +8 -8
package/README.md
CHANGED
@@ -68,7 +68,7 @@ environment:
|
|
68
68
|
OXYGEN_DEPLOYMENT_TOKEN: ${YOUR_ENV_VARIABLE}
|
69
69
|
```
|
70
70
|
|
71
|
-
When run from a supported CI/CD environment, the tool will automatically retrieve metadata from relevant environment variables. Metadata describes the author making the deployment (user), the version (commit Sha) and the deployment URL (workflow URL).
|
71
|
+
When run from a supported CI/CD environment, the tool will automatically retrieve metadata from relevant environment variables. Metadata describes the author making the deployment (user), the version (commit Sha) and the deployment URL (workflow URL). This metadata will be saved and used to show details about the Oxygen deployment in the Hydrogen channel within the Shopify Admin.
|
72
72
|
|
73
73
|
The following environment variables are relevant, depending on your environment:
|
74
74
|
|
@@ -78,9 +78,9 @@ The following environment variables are relevant, depending on your environment:
|
|
78
78
|
| Version | BITBUCKET_COMMIT | CIRCLE_SHA1 | GITHUB_SHA | CI_COMMIT_SHA |
|
79
79
|
| URL | BITBUCKET_BUILD_URL | CIRCLE_BUILD_URL | `${GITHUB_SERVER_URL}${GITHUB_REPOSITORY}/actions/runs/${GITHUB_RUN_ID}` | CI_PROJECT_URL |
|
80
80
|
|
81
|
-
These values can be
|
81
|
+
These values can be overridden by the command line flags `metadataUser`, `metadataUrl` and `metadataVersion` respectively.
|
82
82
|
|
83
|
-
The tag
|
83
|
+
The environment tag to deploy to will be derived from the following variables:
|
84
84
|
|
85
85
|
| Service | Branch |
|
86
86
|
| ------- | ------ |
|
@@ -89,4 +89,4 @@ The tag of the environment to deploy to, will be derived from the following vari
|
|
89
89
|
| Github | GITHUB_REF_NAME |
|
90
90
|
| Gitlab | CI_COMMIT_REF_NAME |
|
91
91
|
|
92
|
-
The `environmentTag` command line option can be used to override this,
|
92
|
+
The `environmentTag` command line option can be used to override this. If not provided, or there is no environment with the specified tag, the deployment will be deployed to the default environment for the app (if one exists).
|
@@ -67,17 +67,17 @@ class Deploy extends Command {
|
|
67
67
|
default: false
|
68
68
|
}),
|
69
69
|
metadataUrl: Flags.string({
|
70
|
-
description: "URL that links to the deployment",
|
70
|
+
description: "URL that links to the deployment. Will be saved and displayed in the Shopify admin",
|
71
71
|
required: false,
|
72
72
|
env: "OXYGEN_METADATA_URL"
|
73
73
|
}),
|
74
74
|
metadataUser: Flags.string({
|
75
|
-
description: "User that initiated the deployment",
|
75
|
+
description: "User that initiated the deployment. Will be saved and displayed in the Shopify admin",
|
76
76
|
required: false,
|
77
77
|
env: "OXYGEN_METADATA_USER"
|
78
78
|
}),
|
79
79
|
metadataVersion: Flags.string({
|
80
|
-
description: "A version identifier for the deployment",
|
80
|
+
description: "A version identifier for the deployment. Will be saved and displayed in the Shopify admin",
|
81
81
|
required: false,
|
82
82
|
env: "OXYGEN_METADATA_VERSION"
|
83
83
|
})
|
@@ -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,6 +1,10 @@
|
|
1
1
|
import { DeployConfig } from './types.js';
|
2
2
|
import { DeploymentCancelResponse } from './graphql/deployment-cancel.js';
|
3
3
|
|
4
|
-
declare
|
4
|
+
declare enum DeploymentCancelReason {
|
5
|
+
Failed = "FAILED",
|
6
|
+
Cancelled = "CANCELLED"
|
7
|
+
}
|
8
|
+
declare function deploymentCancel(config: DeployConfig, deploymentId: string, reason: DeploymentCancelReason): Promise<DeploymentCancelResponse>;
|
5
9
|
|
6
|
-
export { deploymentCancel };
|
10
|
+
export { DeploymentCancelReason, deploymentCancel };
|
@@ -1,9 +1,14 @@
|
|
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
|
+
var DeploymentCancelReason = /* @__PURE__ */ ((DeploymentCancelReason2) => {
|
8
|
+
DeploymentCancelReason2["Failed"] = "FAILED";
|
9
|
+
DeploymentCancelReason2["Cancelled"] = "CANCELLED";
|
10
|
+
return DeploymentCancelReason2;
|
11
|
+
})(DeploymentCancelReason || {});
|
7
12
|
async function deploymentCancel(config, deploymentId, reason) {
|
8
13
|
const variables = {
|
9
14
|
deploymentId,
|
@@ -25,7 +30,7 @@ async function deploymentCancel(config, deploymentId, reason) {
|
|
25
30
|
`Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
|
26
31
|
);
|
27
32
|
}
|
28
|
-
outputInfo(`Deployment with id ${deploymentId} cancelled
|
33
|
+
outputInfo(`Deployment with id ${deploymentId} cancelled.`, stderrLogger);
|
29
34
|
return response.deploymentCancel;
|
30
35
|
} catch (error) {
|
31
36
|
errorHandler(error);
|
@@ -33,4 +38,4 @@ async function deploymentCancel(config, deploymentId, reason) {
|
|
33
38
|
}
|
34
39
|
}
|
35
40
|
|
36
|
-
export { deploymentCancel };
|
41
|
+
export { DeploymentCancelReason, deploymentCancel };
|
@@ -3,7 +3,7 @@ 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
5
|
import { Header } from '../utils/utils.js';
|
6
|
-
import { deploymentCancel } from './deployment-cancel.js';
|
6
|
+
import { deploymentCancel, DeploymentCancelReason } from './deployment-cancel.js';
|
7
7
|
|
8
8
|
vi.mock("@shopify/cli-kit/node/api/graphql");
|
9
9
|
vi.mock("@shopify/cli-kit/node/output");
|
@@ -22,7 +22,7 @@ describe("DeploymentComplete", () => {
|
|
22
22
|
const completeResponse = await deploymentCancel(
|
23
23
|
testConfig,
|
24
24
|
"deployment-1",
|
25
|
-
|
25
|
+
DeploymentCancelReason.Failed
|
26
26
|
);
|
27
27
|
expect(completeResponse).toEqual(response.deploymentCancel);
|
28
28
|
expect(graphqlRequest).toHaveBeenCalledWith({
|
@@ -32,7 +32,7 @@ describe("DeploymentComplete", () => {
|
|
32
32
|
token: testConfig.deploymentToken.accessToken,
|
33
33
|
variables: {
|
34
34
|
deploymentId: "deployment-1",
|
35
|
-
reason:
|
35
|
+
reason: DeploymentCancelReason.Failed
|
36
36
|
},
|
37
37
|
addedHeaders: {
|
38
38
|
[Header.OxygenNamespaceHandle]: `${testConfig.deploymentToken.namespace}`
|
@@ -51,7 +51,11 @@ describe("DeploymentComplete", () => {
|
|
51
51
|
};
|
52
52
|
vi.mocked(graphqlRequest).mockResolvedValueOnce(response);
|
53
53
|
await expect(
|
54
|
-
deploymentCancel(
|
54
|
+
deploymentCancel(
|
55
|
+
testConfig,
|
56
|
+
"deployment-1",
|
57
|
+
DeploymentCancelReason.Failed
|
58
|
+
)
|
55
59
|
).rejects.toThrow(
|
56
60
|
new AbortError(
|
57
61
|
`Failed to cancel deployment: ${response.deploymentCancel.userErrors[0]?.message}`
|
@@ -65,7 +69,11 @@ describe("DeploymentComplete", () => {
|
|
65
69
|
vi.mocked(graphqlRequest).mockRejectedValueOnce(error);
|
66
70
|
try {
|
67
71
|
await expect(
|
68
|
-
deploymentCancel(
|
72
|
+
deploymentCancel(
|
73
|
+
testConfig,
|
74
|
+
"deployment-1",
|
75
|
+
DeploymentCancelReason.Failed
|
76
|
+
)
|
69
77
|
).rejects.toThrow(
|
70
78
|
new AbortError(
|
71
79
|
"You are not authorized to perform this action. Please check your deployment token."
|
@@ -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 () => {
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { OxygenError } from '../types.js';
|
2
2
|
|
3
|
-
declare const DeploymentCompleteQuery = "\n mutation DeploymentComplete($deploymentId: ID!) {\n deploymentComplete(id: $deploymentId) {\n deployment {\n id\n
|
3
|
+
declare const DeploymentCompleteQuery = "\n mutation DeploymentComplete($deploymentId: ID!) {\n deploymentComplete(id: $deploymentId) {\n deployment {\n id\n url\n }\n userErrors {\n message\n }\n }\n }\n";
|
4
4
|
interface DeploymentCompleteQueryData {
|
5
5
|
deploymentComplete: DeploymentCompleteResponse;
|
6
6
|
}
|
@@ -10,7 +10,6 @@ interface DeploymentCompleteResponse {
|
|
10
10
|
}
|
11
11
|
interface Deployment {
|
12
12
|
id: string;
|
13
|
-
status: string;
|
14
13
|
url: string;
|
15
14
|
}
|
16
15
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { OxygenError } from '../types.js';
|
2
2
|
|
3
|
-
declare const DeploymentInitiateQuery = "\n mutation DeploymentInitiate($buildId: ID, $environment: EnvironmentSelectorInput, $labels: [String!], $files: [FileInput!]!, $isPrivate: Boolean) {\n deploymentInitiate(buildId: $buildId, environment: $environment, labels: $labels, files: $files, isPrivate: $isPrivate) {\n deployment {\n id\n
|
3
|
+
declare const DeploymentInitiateQuery = "\n mutation DeploymentInitiate($buildId: ID, $environment: EnvironmentSelectorInput, $labels: [String!], $files: [FileInput!]!, $isPrivate: Boolean) {\n deploymentInitiate(buildId: $buildId, environment: $environment, labels: $labels, files: $files, isPrivate: $isPrivate) {\n deployment {\n id\n }\n deploymentTargets {\n filePath\n fileSize\n uploadUrl\n fileType\n parameters {\n name\n value\n }\n }\n userErrors {\n message\n }\n }\n }\n";
|
4
4
|
interface DeploymentInitiateQueryData {
|
5
5
|
deploymentInitiate: DeploymentInitiateResponse;
|
6
6
|
}
|
@@ -18,7 +18,6 @@ interface DeploymentTargetResponse {
|
|
18
18
|
}
|
19
19
|
interface Deployment {
|
20
20
|
id: string;
|
21
|
-
status: string;
|
22
21
|
}
|
23
22
|
interface DeploymentInitiateParameters {
|
24
23
|
name: string;
|
package/dist/deploy/index.js
CHANGED
@@ -1,11 +1,11 @@
|
|
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';
|
6
6
|
import { deploymentInitiate } from './deployment-initiate.js';
|
7
7
|
import { deploymentComplete } from './deployment-complete.js';
|
8
|
-
import { deploymentCancel } from './deployment-cancel.js';
|
8
|
+
import { deploymentCancel, DeploymentCancelReason } from './deployment-cancel.js';
|
9
9
|
import { uploadFiles } from './upload-files.js';
|
10
10
|
import { buildProject } from './build-project.js';
|
11
11
|
import { getMetadata, createLabels, getEnvironmentInput } from './metadata.js';
|
@@ -43,31 +43,44 @@ 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
|
-
await deploymentCancel(
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
72
|
+
await deploymentCancel(
|
73
|
+
config,
|
74
|
+
deployment.deployment.id,
|
75
|
+
DeploymentCancelReason.Failed
|
76
|
+
).catch((err) => {
|
77
|
+
if (err instanceof Error) {
|
78
|
+
outputWarn(
|
79
|
+
`Failed to cancel deployment: ${err.message}`,
|
80
|
+
stderrLogger
|
81
|
+
);
|
69
82
|
}
|
70
|
-
);
|
83
|
+
});
|
71
84
|
}
|
72
85
|
consoleError(error.message);
|
73
86
|
}
|
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 {
|
@@ -91,7 +99,7 @@ async function verifyConfig({
|
|
91
99
|
for (const pathType of Object.keys(checkPaths)) {
|
92
100
|
await checkPath(checkPaths[pathType], pathType);
|
93
101
|
}
|
94
|
-
const addressRegex = /^
|
102
|
+
const addressRegex = /^https:\/\/(?:[\w-]+\.)*[\w-]+|^https:\/\/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/;
|
95
103
|
if (!addressRegex.test(config.deploymentUrl)) {
|
96
104
|
throw new Error(`Invalid deployment service URL: ${config.deploymentUrl}`);
|
97
105
|
}
|
@@ -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
@@ -1,5 +1,5 @@
|
|
1
1
|
{
|
2
|
-
"version": "1.
|
2
|
+
"version": "1.3.1",
|
3
3
|
"commands": {
|
4
4
|
"oxygen:deploy": {
|
5
5
|
"id": "oxygen:deploy",
|
@@ -90,21 +90,21 @@
|
|
90
90
|
"metadataUrl": {
|
91
91
|
"name": "metadataUrl",
|
92
92
|
"type": "option",
|
93
|
-
"description": "URL that links to the deployment",
|
93
|
+
"description": "URL that links to the deployment. Will be saved and displayed in the Shopify admin",
|
94
94
|
"required": false,
|
95
95
|
"multiple": false
|
96
96
|
},
|
97
97
|
"metadataUser": {
|
98
98
|
"name": "metadataUser",
|
99
99
|
"type": "option",
|
100
|
-
"description": "User that initiated the deployment",
|
100
|
+
"description": "User that initiated the deployment. Will be saved and displayed in the Shopify admin",
|
101
101
|
"required": false,
|
102
102
|
"multiple": false
|
103
103
|
},
|
104
104
|
"metadataVersion": {
|
105
105
|
"name": "metadataVersion",
|
106
106
|
"type": "option",
|
107
|
-
"description": "A version identifier for the deployment",
|
107
|
+
"description": "A version identifier for the deployment. Will be saved and displayed in the Shopify admin",
|
108
108
|
"required": false,
|
109
109
|
"multiple": false
|
110
110
|
}
|
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.3.1",
|
9
9
|
"type": "module",
|
10
10
|
"scripts": {
|
11
11
|
"build": "tsup --clean --config ./tsup.config.ts && oclif manifest",
|
@@ -13,7 +13,7 @@
|
|
13
13
|
"dev": "tsup --watch --config ./tsup.config.ts",
|
14
14
|
"typecheck": "tsc --noEmit",
|
15
15
|
"lint": "eslint --ext .js,.ts --max-warnings 0 src",
|
16
|
-
"lint:format": "npm run lint --fix",
|
16
|
+
"lint:format": "prettier --write \"**/*.*\" && npm run lint --fix",
|
17
17
|
"generate:manifest": "oclif manifest",
|
18
18
|
"prepack": "npm install && npm run build",
|
19
19
|
"release": "npm run build && npx changeset publish",
|
@@ -31,7 +31,7 @@
|
|
31
31
|
"/oclif.manifest.json"
|
32
32
|
],
|
33
33
|
"dependencies": {
|
34
|
-
"@oclif/core": "2.
|
34
|
+
"@oclif/core": "2.8.6",
|
35
35
|
"@shopify/cli-kit": "^3.46.0",
|
36
36
|
"async": "^3.2.4"
|
37
37
|
},
|
@@ -41,14 +41,14 @@
|
|
41
41
|
"@shopify/prettier-config": "^1.1.2",
|
42
42
|
"@types/async": "^3.2.18",
|
43
43
|
"@types/node": "^18.15.11",
|
44
|
-
"@types/prettier": "^2.7.
|
45
|
-
"eslint": "^8.
|
44
|
+
"@types/prettier": "^2.7.3",
|
45
|
+
"eslint": "^8.42.0",
|
46
46
|
"node-fetch": "^3.3.1",
|
47
47
|
"oclif": "^3",
|
48
48
|
"tsup": "^6.7.0",
|
49
|
-
"typescript": "^5.
|
50
|
-
"vite": "^4.
|
51
|
-
"vitest": "^0.
|
49
|
+
"typescript": "^5.1.3",
|
50
|
+
"vite": "^4.3.9",
|
51
|
+
"vitest": "^0.32.0"
|
52
52
|
},
|
53
53
|
"prettier": "@shopify/prettier-config",
|
54
54
|
"oclif": {
|