@mittwald/cli 1.11.2 → 1.13.1-beta.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/bin/dev.js +0 -0
- package/dist/commands/app/copy.d.ts +1 -0
- package/dist/commands/app/copy.js +6 -1
- package/dist/commands/app/create/node.d.ts +1 -1
- package/dist/commands/app/create/php-worker.d.ts +1 -1
- package/dist/commands/app/create/php.d.ts +1 -1
- package/dist/commands/app/create/python.d.ts +1 -1
- package/dist/commands/app/create/static.d.ts +1 -1
- package/dist/commands/app/dependency/update.js +4 -6
- package/dist/commands/app/dependency/versions.js +3 -3
- package/dist/commands/app/install/contao.d.ts +1 -1
- package/dist/commands/app/install/joomla.d.ts +1 -1
- package/dist/commands/app/install/matomo.d.ts +1 -1
- package/dist/commands/app/install/nextcloud.d.ts +1 -1
- package/dist/commands/app/install/shopware5.d.ts +1 -1
- package/dist/commands/app/install/shopware6.d.ts +1 -1
- package/dist/commands/app/install/typo3.d.ts +1 -1
- package/dist/commands/app/install/wordpress.d.ts +1 -1
- package/dist/commands/app/open.d.ts +3 -0
- package/dist/commands/app/open.js +35 -9
- package/dist/commands/container/logs.d.ts +1 -0
- package/dist/commands/container/logs.js +8 -0
- package/dist/commands/container/port-forward.js +2 -2
- package/dist/commands/container/run.d.ts +9 -0
- package/dist/commands/container/run.js +42 -4
- package/dist/commands/container/update.js +2 -2
- package/dist/commands/context/get.js +1 -0
- package/dist/commands/database/mysql/create.d.ts +1 -1
- package/dist/commands/database/mysql/create.js +3 -2
- package/dist/commands/ddev/init.js +2 -1
- package/dist/commands/org/invite/list-own.d.ts +1 -0
- package/dist/commands/org/membership/list-own.d.ts +1 -0
- package/dist/commands/project/create.js +12 -3
- package/dist/commands/stack/deploy.d.ts +2 -0
- package/dist/commands/stack/deploy.js +49 -6
- package/dist/lib/context/FlagSetBuilder.d.ts +1 -0
- package/dist/lib/context/FlagSetBuilder.js +7 -1
- package/dist/lib/intellij/config.test.js +9 -2
- package/dist/lib/resources/app/Installer.d.ts +1 -1
- package/dist/lib/resources/app/Installer.js +14 -1
- package/dist/lib/resources/app/flags.d.ts +3 -1
- package/dist/lib/resources/app/flags.js +12 -0
- package/dist/lib/resources/app/install.d.ts +1 -0
- package/dist/lib/resources/app/install.js +1 -0
- package/dist/lib/resources/app/versions.d.ts +7 -1
- package/dist/lib/resources/app/versions.js +35 -2
- package/dist/lib/resources/container/containerconfig.js +7 -1
- package/dist/lib/resources/container/containerconfig.test.d.ts +1 -0
- package/dist/lib/resources/container/containerconfig.test.js +25 -0
- package/dist/lib/resources/database/mysql/flags.js +1 -1
- package/dist/lib/resources/stack/env.d.ts +10 -0
- package/dist/lib/resources/stack/env.js +22 -0
- package/dist/lib/resources/stack/flags.js +16 -1
- package/dist/lib/resources/stack/template-loader.d.ts +18 -0
- package/dist/lib/resources/stack/template-loader.js +94 -0
- package/dist/lib/resources/stack/template-loader.test.d.ts +1 -0
- package/dist/lib/resources/stack/template-loader.test.js +125 -0
- package/dist/lib/units/PortMapping.d.ts +2 -0
- package/dist/lib/units/PortMapping.js +21 -6
- package/dist/lib/units/PortMapping.test.js +10 -0
- package/package.json +13 -9
- package/dist/commands/cronjob/execution/abort.d.ts +0 -18
- package/dist/commands/cronjob/execution/abort.js +0 -41
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, jest, } from "@jest/globals";
|
|
2
|
+
import { validateTemplateName, templateNameToRepoName, buildGitHubRawUrl, fetchTemplateFile, loadStackFromTemplate, TemplateFileNotFoundError, GitHubRateLimitError, TemplateNetworkError, } from "./template-loader.js";
|
|
3
|
+
import axios from "axios";
|
|
4
|
+
describe("validateTemplateName", () => {
|
|
5
|
+
it("should accept valid template names", () => {
|
|
6
|
+
expect(() => validateTemplateName("mittwald/n8n")).not.toThrow();
|
|
7
|
+
expect(() => validateTemplateName("owner/name")).not.toThrow();
|
|
8
|
+
expect(() => validateTemplateName("my-org/my-app")).not.toThrow();
|
|
9
|
+
expect(() => validateTemplateName("org_name/app_name")).not.toThrow();
|
|
10
|
+
});
|
|
11
|
+
it("should reject invalid template names", () => {
|
|
12
|
+
expect(() => validateTemplateName("")).toThrow(/Invalid template name/);
|
|
13
|
+
expect(() => validateTemplateName("noSlash")).toThrow(/Invalid template name/);
|
|
14
|
+
expect(() => validateTemplateName("too/many/slashes")).toThrow(/Invalid template name/);
|
|
15
|
+
expect(() => validateTemplateName("/missingOwner")).toThrow(/Invalid template name/);
|
|
16
|
+
expect(() => validateTemplateName("missingName/")).toThrow(/Invalid template name/);
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe("templateNameToRepoName", () => {
|
|
20
|
+
it("should convert template name to repository name", () => {
|
|
21
|
+
expect(templateNameToRepoName("mittwald/n8n")).toBe("mittwald/stack-template-n8n");
|
|
22
|
+
expect(templateNameToRepoName("owner/app")).toBe("owner/stack-template-app");
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
describe("buildGitHubRawUrl", () => {
|
|
26
|
+
it("should build correct GitHub raw URL", () => {
|
|
27
|
+
expect(buildGitHubRawUrl("mittwald/n8n", "docker-compose.yml")).toBe("https://raw.githubusercontent.com/mittwald/stack-template-n8n/main/docker-compose.yml");
|
|
28
|
+
expect(buildGitHubRawUrl("owner/app", ".env")).toBe("https://raw.githubusercontent.com/owner/stack-template-app/main/.env");
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
describe("fetchTemplateFile", () => {
|
|
32
|
+
let axiosGetSpy;
|
|
33
|
+
let axiosIsAxiosErrorSpy;
|
|
34
|
+
beforeEach(() => {
|
|
35
|
+
axiosGetSpy = jest.spyOn(axios, "get");
|
|
36
|
+
axiosIsAxiosErrorSpy = jest.spyOn(axios, "isAxiosError");
|
|
37
|
+
});
|
|
38
|
+
afterEach(() => {
|
|
39
|
+
jest.restoreAllMocks();
|
|
40
|
+
});
|
|
41
|
+
it("should fetch file successfully", async () => {
|
|
42
|
+
const mockData = "file content";
|
|
43
|
+
axiosGetSpy.mockResolvedValue({ data: mockData });
|
|
44
|
+
const result = await fetchTemplateFile("https://raw.githubusercontent.com/mittwald/stack-template-n8n/main/docker-compose.yml");
|
|
45
|
+
expect(result).toBe(mockData);
|
|
46
|
+
expect(axiosGetSpy).toHaveBeenCalledWith("https://raw.githubusercontent.com/mittwald/stack-template-n8n/main/docker-compose.yml", { responseType: "text", timeout: 10000 });
|
|
47
|
+
});
|
|
48
|
+
it("should handle 404 errors", async () => {
|
|
49
|
+
axiosGetSpy.mockRejectedValue({
|
|
50
|
+
isAxiosError: true,
|
|
51
|
+
response: { status: 404 },
|
|
52
|
+
});
|
|
53
|
+
axiosIsAxiosErrorSpy.mockReturnValue(true);
|
|
54
|
+
await expect(fetchTemplateFile("https://example.com/missing.yml")).rejects.toThrow(TemplateFileNotFoundError);
|
|
55
|
+
});
|
|
56
|
+
it("should handle 403 rate limit errors", async () => {
|
|
57
|
+
axiosGetSpy.mockRejectedValue({
|
|
58
|
+
isAxiosError: true,
|
|
59
|
+
response: { status: 403 },
|
|
60
|
+
});
|
|
61
|
+
axiosIsAxiosErrorSpy.mockReturnValue(true);
|
|
62
|
+
await expect(fetchTemplateFile("https://example.com/file.yml")).rejects.toThrow(GitHubRateLimitError);
|
|
63
|
+
});
|
|
64
|
+
it("should handle timeout errors", async () => {
|
|
65
|
+
axiosGetSpy.mockRejectedValue({
|
|
66
|
+
isAxiosError: true,
|
|
67
|
+
code: "ETIMEDOUT",
|
|
68
|
+
});
|
|
69
|
+
axiosIsAxiosErrorSpy.mockReturnValue(true);
|
|
70
|
+
await expect(fetchTemplateFile("https://example.com/file.yml")).rejects.toThrow(TemplateNetworkError);
|
|
71
|
+
});
|
|
72
|
+
it("should handle network errors", async () => {
|
|
73
|
+
axiosGetSpy.mockRejectedValue({
|
|
74
|
+
isAxiosError: true,
|
|
75
|
+
code: "ECONNREFUSED",
|
|
76
|
+
});
|
|
77
|
+
axiosIsAxiosErrorSpy.mockReturnValue(true);
|
|
78
|
+
await expect(fetchTemplateFile("https://example.com/file.yml")).rejects.toThrow(TemplateNetworkError);
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("loadStackFromTemplate", () => {
|
|
82
|
+
let axiosGetSpy;
|
|
83
|
+
let axiosIsAxiosErrorSpy;
|
|
84
|
+
beforeEach(() => {
|
|
85
|
+
axiosGetSpy = jest.spyOn(axios, "get");
|
|
86
|
+
axiosIsAxiosErrorSpy = jest.spyOn(axios, "isAxiosError");
|
|
87
|
+
});
|
|
88
|
+
afterEach(() => {
|
|
89
|
+
jest.restoreAllMocks();
|
|
90
|
+
});
|
|
91
|
+
it("should load both docker-compose.yml and .env", async () => {
|
|
92
|
+
const composeContent = "version: '3'\nservices:\n app:\n image: nginx";
|
|
93
|
+
const envContent = "FOO=bar\nBAZ=qux";
|
|
94
|
+
axiosGetSpy
|
|
95
|
+
.mockResolvedValueOnce({ data: composeContent })
|
|
96
|
+
.mockResolvedValueOnce({ data: envContent });
|
|
97
|
+
const result = await loadStackFromTemplate("mittwald/n8n");
|
|
98
|
+
expect(result.composeYaml).toBe(composeContent);
|
|
99
|
+
expect(result.envContent).toBe(envContent);
|
|
100
|
+
});
|
|
101
|
+
it("should handle missing .env file gracefully", async () => {
|
|
102
|
+
const composeContent = "version: '3'\nservices:\n app:\n image: nginx";
|
|
103
|
+
axiosGetSpy.mockResolvedValueOnce({ data: composeContent });
|
|
104
|
+
axiosGetSpy.mockRejectedValueOnce({
|
|
105
|
+
isAxiosError: true,
|
|
106
|
+
response: { status: 404 },
|
|
107
|
+
});
|
|
108
|
+
axiosIsAxiosErrorSpy.mockReturnValue(true);
|
|
109
|
+
const result = await loadStackFromTemplate("mittwald/n8n");
|
|
110
|
+
expect(result.composeYaml).toBe(composeContent);
|
|
111
|
+
expect(result.envContent).toBeNull();
|
|
112
|
+
});
|
|
113
|
+
it("should throw error if docker-compose.yml is missing", async () => {
|
|
114
|
+
axiosGetSpy.mockRejectedValue({
|
|
115
|
+
isAxiosError: true,
|
|
116
|
+
response: { status: 404 },
|
|
117
|
+
});
|
|
118
|
+
axiosIsAxiosErrorSpy.mockReturnValue(true);
|
|
119
|
+
await expect(loadStackFromTemplate("mittwald/n8n")).rejects.toThrow(/Template 'mittwald\/n8n' not found/);
|
|
120
|
+
});
|
|
121
|
+
it("should validate template name before fetching", async () => {
|
|
122
|
+
await expect(loadStackFromTemplate("invalid")).rejects.toThrow(/Invalid template name/);
|
|
123
|
+
expect(axiosGetSpy).not.toHaveBeenCalled();
|
|
124
|
+
});
|
|
125
|
+
});
|
|
@@ -4,6 +4,8 @@ export default class PortMapping {
|
|
|
4
4
|
readonly remotePort: number;
|
|
5
5
|
constructor(localPort: number, remotePort: number);
|
|
6
6
|
private static validatePort;
|
|
7
|
+
private static isValidPortString;
|
|
8
|
+
private static parseAndValidatePort;
|
|
7
9
|
static arg: import("@oclif/core/interfaces").ArgDefinition<PortMapping, Record<string, unknown>>;
|
|
8
10
|
/** @param str Port and protocol; example: `8080/tcp` */
|
|
9
11
|
static fromPortAndProtocol(str: string): PortMapping;
|
|
@@ -10,6 +10,19 @@ export default class PortMapping {
|
|
|
10
10
|
static validatePort(port) {
|
|
11
11
|
return !isNaN(port) && port > 0 && port <= 65535;
|
|
12
12
|
}
|
|
13
|
+
static isValidPortString(str) {
|
|
14
|
+
return /^\d+$/.test(str);
|
|
15
|
+
}
|
|
16
|
+
static parseAndValidatePort(str) {
|
|
17
|
+
if (!PortMapping.isValidPortString(str)) {
|
|
18
|
+
throw new Error("Invalid port number. Ports must be between 1 and 65535.");
|
|
19
|
+
}
|
|
20
|
+
const portNum = parseInt(str);
|
|
21
|
+
if (!PortMapping.validatePort(portNum)) {
|
|
22
|
+
throw new Error("Invalid port number. Ports must be between 1 and 65535.");
|
|
23
|
+
}
|
|
24
|
+
return portNum;
|
|
25
|
+
}
|
|
13
26
|
static arg = Args.custom({
|
|
14
27
|
parse: async (input) => PortMapping.fromString(input),
|
|
15
28
|
});
|
|
@@ -26,13 +39,15 @@ export default class PortMapping {
|
|
|
26
39
|
return new PortMapping(portNum, portNum);
|
|
27
40
|
}
|
|
28
41
|
static fromString(str) {
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
throw new Error("Invalid port number. Ports must be between 1 and 65535.");
|
|
42
|
+
const parts = str.split(":");
|
|
43
|
+
// If only one part, use it for both local and remote port
|
|
44
|
+
if (parts.length === 1) {
|
|
45
|
+
const portNum = PortMapping.parseAndValidatePort(parts[0]);
|
|
46
|
+
return new PortMapping(portNum, portNum);
|
|
35
47
|
}
|
|
48
|
+
const [localPort, remotePort] = parts;
|
|
49
|
+
const localPortNum = PortMapping.parseAndValidatePort(localPort);
|
|
50
|
+
const remotePortNum = PortMapping.parseAndValidatePort(remotePort);
|
|
36
51
|
return new PortMapping(localPortNum, remotePortNum);
|
|
37
52
|
}
|
|
38
53
|
}
|
|
@@ -7,6 +7,12 @@ describe("PortMapping", () => {
|
|
|
7
7
|
expect(result.localPort).toBe(8080);
|
|
8
8
|
expect(result.remotePort).toBe(9090);
|
|
9
9
|
});
|
|
10
|
+
// Test: Successfully parse single integer as identical local and remote port
|
|
11
|
+
it("should correctly parse single integer to identical ports", () => {
|
|
12
|
+
const result = PortMapping.fromString("8080");
|
|
13
|
+
expect(result.localPort).toBe(8080);
|
|
14
|
+
expect(result.remotePort).toBe(8080);
|
|
15
|
+
});
|
|
10
16
|
// Test: Throws an error for invalid local port
|
|
11
17
|
it("should throw an error for invalid local port", () => {
|
|
12
18
|
expect(() => PortMapping.fromString("100000:8080")).toThrow("Invalid port number. Ports must be between 1 and 65535.");
|
|
@@ -19,6 +25,10 @@ describe("PortMapping", () => {
|
|
|
19
25
|
it("should throw an error for invalid string format", () => {
|
|
20
26
|
expect(() => PortMapping.fromString("8080-9090")).toThrow("Invalid port number. Ports must be between 1 and 65535.");
|
|
21
27
|
});
|
|
28
|
+
// Test: Throws an error for invalid single port
|
|
29
|
+
it("should throw an error for invalid single port", () => {
|
|
30
|
+
expect(() => PortMapping.fromString("100000")).toThrow("Invalid port number. Ports must be between 1 and 65535.");
|
|
31
|
+
});
|
|
22
32
|
// Test: Successfully assign local and remote ports via constructor
|
|
23
33
|
it("should correctly initialize PortMapping with valid ports", () => {
|
|
24
34
|
const portMapping = new PortMapping(3000, 4000);
|
package/package.json
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mittwald/cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.1-beta.6",
|
|
4
4
|
"description": "Hand-crafted CLI for the mittwald API",
|
|
5
5
|
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"url": "https://github.com/mittwald/cli"
|
|
8
|
+
},
|
|
6
9
|
"author": {
|
|
7
10
|
"name": "Mittwald CM Service GmbH & Co. KG",
|
|
8
11
|
"email": "opensource@mittwald.de"
|
|
@@ -16,12 +19,13 @@
|
|
|
16
19
|
},
|
|
17
20
|
"type": "module",
|
|
18
21
|
"engines": {
|
|
19
|
-
"node": ">=20.
|
|
22
|
+
"node": ">=20.7.0"
|
|
20
23
|
},
|
|
21
24
|
"scripts": {
|
|
22
25
|
"clean": "(rimraf --glob dist tsconfig.*.tsbuildinfo) | true",
|
|
23
26
|
"compile": "tsc --build tsconfig.json",
|
|
24
|
-
"format": "prettier --write
|
|
27
|
+
"format": "yarn format:prettier --write",
|
|
28
|
+
"format:prettier": "prettier $@ '**/*.{ts,tsx,yaml,yml,json,md,mdx}'",
|
|
25
29
|
"generate:readme": "oclif readme --multi --output-dir=docs < /dev/null",
|
|
26
30
|
"license-check": "yarn pnpify license-checker-rseidelsohn ",
|
|
27
31
|
"lint": "eslint . --cache",
|
|
@@ -31,7 +35,7 @@
|
|
|
31
35
|
"package:windows": "oclif pack win --targets=win32-x64,win32-x86",
|
|
32
36
|
"post:generate": "yarn run -T compile && yarn run -T compile:cjs",
|
|
33
37
|
"test": "yarn test:format && yarn test:licenses && yarn test:unit",
|
|
34
|
-
"test:format": "yarn lint && yarn format --check",
|
|
38
|
+
"test:format": "yarn lint && yarn format:prettier --check",
|
|
35
39
|
"test:licenses": "yarn license-check --summary --unknown --failOn 'UNLICENSED;UNKNOWN'",
|
|
36
40
|
"test:readme": "yarn generate:readme && git diff --exit-code README.md docs/*.md",
|
|
37
41
|
"test:unit": "NODE_NO_WARNINGS=1 yarn node --experimental-vm-modules $(yarn bin jest) ./src"
|
|
@@ -61,7 +65,7 @@
|
|
|
61
65
|
"js-yaml": "^4.1.0",
|
|
62
66
|
"marked": "^15.0.12",
|
|
63
67
|
"marked-terminal": "^7.3.0",
|
|
64
|
-
"open": "^
|
|
68
|
+
"open": "^11.0.0",
|
|
65
69
|
"parse-duration": "^2.0.1",
|
|
66
70
|
"pretty-bytes": "^7.0.0",
|
|
67
71
|
"react": "^19.1.1",
|
|
@@ -70,14 +74,14 @@
|
|
|
70
74
|
"shell-escape": "^0.2.0",
|
|
71
75
|
"slice-ansi": "^7.1.0",
|
|
72
76
|
"string-width": "^8.0.0",
|
|
73
|
-
"tempfile": "^
|
|
77
|
+
"tempfile": "^6.0.1",
|
|
74
78
|
"uuid": "^13.0.0"
|
|
75
79
|
},
|
|
76
80
|
"devDependencies": {
|
|
77
81
|
"@jest/globals": "^30.0.4",
|
|
78
82
|
"@oclif/test": "^4.0.4",
|
|
79
83
|
"@types/js-yaml": "^4.0.9",
|
|
80
|
-
"@types/node": "^
|
|
84
|
+
"@types/node": "^25.0.3",
|
|
81
85
|
"@types/react": "^19",
|
|
82
86
|
"@types/semver": "^7.5.0",
|
|
83
87
|
"@types/shell-escape": "^0.2.3",
|
|
@@ -88,7 +92,7 @@
|
|
|
88
92
|
"eslint-config-prettier": "^10.1.5",
|
|
89
93
|
"eslint-plugin-json": "^4.0.1",
|
|
90
94
|
"eslint-plugin-prettier": "^5.5.1",
|
|
91
|
-
"globals": "^
|
|
95
|
+
"globals": "^17.0.0",
|
|
92
96
|
"jest": "^30.0.4",
|
|
93
97
|
"license-checker-rseidelsohn": "^4.2.6",
|
|
94
98
|
"nock": "^14.0.0",
|
|
@@ -288,4 +292,4 @@
|
|
|
288
292
|
}
|
|
289
293
|
},
|
|
290
294
|
"packageManager": "yarn@3.6.1"
|
|
291
|
-
}
|
|
295
|
+
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { ExecRenderBaseCommand } from "../../../lib/basecommands/ExecRenderBaseCommand.js";
|
|
2
|
-
import { ReactNode } from "react";
|
|
3
|
-
type Result = {
|
|
4
|
-
executionId: string;
|
|
5
|
-
};
|
|
6
|
-
export declare class Abort extends ExecRenderBaseCommand<typeof Abort, Result> {
|
|
7
|
-
static summary: string;
|
|
8
|
-
static flags: {
|
|
9
|
-
quiet: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
10
|
-
};
|
|
11
|
-
static args: {
|
|
12
|
-
"cronjob-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
13
|
-
"execution-id": import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
14
|
-
};
|
|
15
|
-
protected exec(): Promise<Result>;
|
|
16
|
-
protected render({ executionId }: Result): ReactNode;
|
|
17
|
-
}
|
|
18
|
-
export {};
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { ExecRenderBaseCommand } from "../../../lib/basecommands/ExecRenderBaseCommand.js";
|
|
3
|
-
import { makeProcessRenderer, processFlags, } from "../../../rendering/process/process_flags.js";
|
|
4
|
-
import { Args } from "@oclif/core";
|
|
5
|
-
import { Success } from "../../../rendering/react/components/Success.js";
|
|
6
|
-
import { Value } from "../../../rendering/react/components/Value.js";
|
|
7
|
-
import assertSuccess from "../../../lib/apiutil/assert_success.js";
|
|
8
|
-
export class Abort extends ExecRenderBaseCommand {
|
|
9
|
-
static summary = "Abort a running cron job execution.";
|
|
10
|
-
static flags = {
|
|
11
|
-
...processFlags,
|
|
12
|
-
};
|
|
13
|
-
static args = {
|
|
14
|
-
"cronjob-id": Args.string({
|
|
15
|
-
description: "ID of the cronjob the execution belongs to",
|
|
16
|
-
required: true,
|
|
17
|
-
}),
|
|
18
|
-
"execution-id": Args.string({
|
|
19
|
-
required: true,
|
|
20
|
-
description: "ID of the cron job execution to abort",
|
|
21
|
-
}),
|
|
22
|
-
};
|
|
23
|
-
async exec() {
|
|
24
|
-
const p = makeProcessRenderer(this.flags, "Aborting a cron job execution");
|
|
25
|
-
const { "cronjob-id": cronjobId, "execution-id": executionId } = this.args;
|
|
26
|
-
await p.runStep("aborting cron job execution", async () => {
|
|
27
|
-
const r = await this.apiClient.cronjob.abortExecution({
|
|
28
|
-
cronjobId,
|
|
29
|
-
executionId,
|
|
30
|
-
});
|
|
31
|
-
assertSuccess(r);
|
|
32
|
-
});
|
|
33
|
-
p.complete(_jsxs(Success, { children: ["Execution ", _jsx(Value, { children: executionId }), " was successfully aborted."] }));
|
|
34
|
-
return { executionId };
|
|
35
|
-
}
|
|
36
|
-
render({ executionId }) {
|
|
37
|
-
if (this.flags.quiet) {
|
|
38
|
-
return executionId;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|