@contrail/cli 3.5.3-alpha.cc8f6c0 → 3.5.3-alpha.d91b702
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 +11 -5
- package/dist/commands/workflow-templates/export.d.ts +3 -2
- package/dist/commands/workflow-templates/export.js +112 -30
- package/dist/helpers/workflow-templates/helper.d.ts +1 -0
- package/dist/helpers/workflow-templates/helper.js +26 -3
- package/oclif.manifest.json +15 -5
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ $ npm install -g @contrail/cli
|
|
|
17
17
|
$ contrail COMMAND
|
|
18
18
|
running command...
|
|
19
19
|
$ contrail (--version)
|
|
20
|
-
@contrail/cli/3.5.3-alpha.
|
|
20
|
+
@contrail/cli/3.5.3-alpha.d91b702 linux-x64 node-v24.16.0
|
|
21
21
|
$ contrail --help [COMMAND]
|
|
22
22
|
USAGE
|
|
23
23
|
$ contrail COMMAND
|
|
@@ -1611,25 +1611,31 @@ EXAMPLES
|
|
|
1611
1611
|
|
|
1612
1612
|
## `contrail workflow-templates export`
|
|
1613
1613
|
|
|
1614
|
-
Export all workflows in the org.
|
|
1614
|
+
Export all workflows in the org. By default exports one file per app to the current directory.
|
|
1615
1615
|
|
|
1616
1616
|
```
|
|
1617
1617
|
USAGE
|
|
1618
|
-
$ contrail workflow-templates export [-l error|warn|info|debug] [-e true|false] [-f <value>] [
|
|
1618
|
+
$ contrail workflow-templates export [-l error|warn|info|debug] [-e true|false] [-f <value>] [-d <value>]
|
|
1619
|
+
[--overwrite]
|
|
1619
1620
|
|
|
1620
1621
|
FLAGS
|
|
1622
|
+
-d, --dir=<value> [default: .] Directory to write per-app workflow files
|
|
1621
1623
|
-e, --alwaysConfirmEnv=<option> [default: true] The Environment variables
|
|
1622
1624
|
<options: true|false>
|
|
1623
|
-
-f, --outFile=<value>
|
|
1625
|
+
-f, --outFile=<value> Export all workflows to a single file at this path (overrides per-app export)
|
|
1624
1626
|
-l, --logLevel=<option> The Log Level
|
|
1625
1627
|
<options: error|warn|info|debug>
|
|
1626
1628
|
--overwrite Replaces existing files if they exist
|
|
1627
1629
|
|
|
1628
1630
|
DESCRIPTION
|
|
1629
|
-
Export all workflows in the org.
|
|
1631
|
+
Export all workflows in the org. By default exports one file per app to the current directory.
|
|
1630
1632
|
|
|
1631
1633
|
EXAMPLES
|
|
1632
1634
|
$ contrail workflow-templates export
|
|
1635
|
+
|
|
1636
|
+
$ contrail workflow-templates export --dir ./workflows
|
|
1637
|
+
|
|
1638
|
+
$ contrail workflow-templates export --outFile workflows.yml
|
|
1633
1639
|
```
|
|
1634
1640
|
|
|
1635
1641
|
## `contrail workflow-templates list`
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
import { BaseCommand } from '../../basecommand';
|
|
2
|
-
export declare const DEFAULT_FILE_LOCATION = "workflows.yml";
|
|
3
2
|
export default class ExportWorkflows extends BaseCommand {
|
|
4
3
|
static description: string;
|
|
5
4
|
static examples: string[];
|
|
6
5
|
static flags: {
|
|
7
6
|
outFile: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
7
|
+
dir: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
8
8
|
overwrite: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
|
|
9
9
|
alwaysConfirmEnv: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
10
10
|
logLevel: import("@oclif/core/lib/interfaces").OptionFlag<string, import("@oclif/core/lib/interfaces/parser").CustomOptions>;
|
|
11
11
|
};
|
|
12
12
|
run(): Promise<void>;
|
|
13
13
|
}
|
|
14
|
-
export declare function
|
|
14
|
+
export declare function exportWorkflowsByApp(outputDir: string, overwrite: boolean): Promise<void>;
|
|
15
|
+
export declare function exportWorkflowsToFile(fileLocation: string, overwrite: boolean): Promise<void>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.exportWorkflowsToFile = exports.exportWorkflowsByApp = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
@@ -11,22 +11,29 @@ const js_yaml_1 = tslib_1.__importDefault(require("js-yaml"));
|
|
|
11
11
|
const core_1 = require("@oclif/core");
|
|
12
12
|
const file_helpers_1 = require("../../helpers/file-helpers");
|
|
13
13
|
const event_workflow_templates_1 = require("../../api/event-workflow-templates");
|
|
14
|
+
const schedules_1 = require("../../api/schedules");
|
|
15
|
+
const apps_1 = require("../../api/apps");
|
|
14
16
|
const helper_1 = require("../../helpers/workflow-templates/helper");
|
|
15
17
|
const basecommand_1 = require("../../basecommand");
|
|
16
|
-
exports.DEFAULT_FILE_LOCATION = 'workflows.yml';
|
|
17
18
|
class ExportWorkflows extends basecommand_1.BaseCommand {
|
|
18
|
-
static description = 'Export all workflows in the org.';
|
|
19
|
+
static description = 'Export all workflows in the org. By default exports one file per app to the current directory.';
|
|
19
20
|
static examples = [
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
'$ contrail workflow-templates export',
|
|
22
|
+
'$ contrail workflow-templates export --dir ./workflows',
|
|
23
|
+
'$ contrail workflow-templates export --outFile workflows.yml',
|
|
22
24
|
];
|
|
23
25
|
static flags = {
|
|
24
26
|
...basecommand_1.BaseCommand.baseFlags,
|
|
25
27
|
outFile: core_1.Flags.string({
|
|
26
28
|
char: 'f',
|
|
27
|
-
description: '
|
|
29
|
+
description: 'Export all workflows to a single file at this path (overrides per-app export)',
|
|
28
30
|
required: false,
|
|
29
|
-
|
|
31
|
+
}),
|
|
32
|
+
dir: core_1.Flags.string({
|
|
33
|
+
char: 'd',
|
|
34
|
+
description: 'Directory to write per-app workflow files',
|
|
35
|
+
required: false,
|
|
36
|
+
default: '.',
|
|
30
37
|
}),
|
|
31
38
|
overwrite: core_1.Flags.boolean({
|
|
32
39
|
description: 'Replaces existing files if they exist',
|
|
@@ -38,7 +45,12 @@ class ExportWorkflows extends basecommand_1.BaseCommand {
|
|
|
38
45
|
try {
|
|
39
46
|
await (0, login_1.authUser)();
|
|
40
47
|
this.log(`${chalk_1.default.blue.bold('START')} Getting Workflows.`);
|
|
41
|
-
|
|
48
|
+
if (this.flags.outFile) {
|
|
49
|
+
await exportWorkflowsToFile(this.flags.outFile, this.flags.overwrite);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
await exportWorkflowsByApp(this.flags.dir ?? '.', this.flags.overwrite);
|
|
53
|
+
}
|
|
42
54
|
this.log(`${chalk_1.default.yellow.bold('WORKFLOWS')} Done`);
|
|
43
55
|
}
|
|
44
56
|
catch (e) {
|
|
@@ -49,31 +61,101 @@ class ExportWorkflows extends basecommand_1.BaseCommand {
|
|
|
49
61
|
}
|
|
50
62
|
}
|
|
51
63
|
exports.default = ExportWorkflows;
|
|
52
|
-
async function
|
|
53
|
-
const allWorkflowsInOrg = await
|
|
64
|
+
async function exportWorkflowsByApp(outputDir, overwrite) {
|
|
65
|
+
const [allWorkflowsInOrg, allSchedules, installedApps] = await Promise.all([
|
|
66
|
+
(0, event_workflow_templates_1.getExistingWorkflowTemplates)(),
|
|
67
|
+
(0, schedules_1.getExistingSchedules)(),
|
|
68
|
+
(0, apps_1.getInstalledApps)(),
|
|
69
|
+
]);
|
|
70
|
+
const appIdToIdentifier = new Map(installedApps
|
|
71
|
+
.filter((appOrg) => appOrg.appId && appOrg.app?.identifier)
|
|
72
|
+
.map((appOrg) => [appOrg.appId, appOrg.app.identifier]));
|
|
73
|
+
const workflowsByApp = new Map();
|
|
74
|
+
const unassigned = [];
|
|
75
|
+
for (const workflow of allWorkflowsInOrg) {
|
|
76
|
+
let appIdentifier = workflow.supportingAppId
|
|
77
|
+
? appIdToIdentifier.get(workflow.supportingAppId)
|
|
78
|
+
: undefined;
|
|
79
|
+
// If no supportingAppId, try to extract app identifier from workflow identifier
|
|
80
|
+
// Format: @{appIdentifier}@{randomId}:{workflowName}
|
|
81
|
+
if (!appIdentifier && workflow.identifier) {
|
|
82
|
+
const match = workflow.identifier.match(/^@([^@]+)@/);
|
|
83
|
+
if (match) {
|
|
84
|
+
// Keep the @ prefix in the appIdentifier
|
|
85
|
+
appIdentifier = `@${match[1]}`;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (appIdentifier) {
|
|
89
|
+
if (!workflowsByApp.has(appIdentifier)) {
|
|
90
|
+
workflowsByApp.set(appIdentifier, []);
|
|
91
|
+
}
|
|
92
|
+
const workflows = workflowsByApp.get(appIdentifier);
|
|
93
|
+
if (workflows) {
|
|
94
|
+
workflows.push(workflow);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
unassigned.push(workflow);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const resolvedDir = path.resolve(process.cwd(), outputDir);
|
|
102
|
+
for (const [appIdentifier, workflows] of workflowsByApp.entries()) {
|
|
103
|
+
const exportObj = { appIdentifier, workflows: [] };
|
|
104
|
+
for (const workflow of workflows) {
|
|
105
|
+
exportObj.workflows.push(await buildExportWorkflow(workflow, allSchedules));
|
|
106
|
+
}
|
|
107
|
+
const safeAppIdentifier = appIdentifier.replace(/[\\/]/g, '-');
|
|
108
|
+
const filePath = path.join(resolvedDir, `workflows-${safeAppIdentifier}.yml`);
|
|
109
|
+
await writeYamlFile(exportObj, filePath, overwrite);
|
|
110
|
+
console.log(`${chalk_1.default.green('EXPORTED')} ${filePath}`);
|
|
111
|
+
}
|
|
112
|
+
if (unassigned.length > 0) {
|
|
113
|
+
const unassignedObj = { workflows: [] };
|
|
114
|
+
for (const workflow of unassigned) {
|
|
115
|
+
unassignedObj.workflows.push(await buildExportWorkflow(workflow, allSchedules));
|
|
116
|
+
}
|
|
117
|
+
const unassignedFilePath = path.join(resolvedDir, 'workflows-unassigned.yml');
|
|
118
|
+
await writeYamlFile(unassignedObj, unassignedFilePath, overwrite);
|
|
119
|
+
console.log(`${chalk_1.default.yellow('EXPORTED')} ${unassignedFilePath} (unassigned workflows)`);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.exportWorkflowsByApp = exportWorkflowsByApp;
|
|
123
|
+
async function exportWorkflowsToFile(fileLocation, overwrite) {
|
|
124
|
+
const [allWorkflowsInOrg, allSchedules] = await Promise.all([
|
|
125
|
+
(0, event_workflow_templates_1.getExistingWorkflowTemplates)(),
|
|
126
|
+
(0, schedules_1.getExistingSchedules)(),
|
|
127
|
+
]);
|
|
54
128
|
const workflowsObj = { workflows: [] };
|
|
55
129
|
for (const workflow of allWorkflowsInOrg) {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
130
|
+
workflowsObj.workflows.push(await buildExportWorkflow(workflow, allSchedules));
|
|
131
|
+
}
|
|
132
|
+
const pathToWrite = path.resolve(process.cwd(), fileLocation);
|
|
133
|
+
await writeYamlFile(workflowsObj, pathToWrite, overwrite);
|
|
134
|
+
}
|
|
135
|
+
exports.exportWorkflowsToFile = exportWorkflowsToFile;
|
|
136
|
+
async function buildExportWorkflow(workflow, allSchedules) {
|
|
137
|
+
const exportWorkflow = lodash_1.default.pick(workflow, [
|
|
138
|
+
'identifier',
|
|
139
|
+
'name',
|
|
140
|
+
'triggerKey',
|
|
141
|
+
'isActive',
|
|
142
|
+
'messageGroup',
|
|
143
|
+
'dynamicMessageGroupId',
|
|
144
|
+
'parallelWorkerCount',
|
|
145
|
+
'workflowDefinition',
|
|
146
|
+
]);
|
|
147
|
+
const schedules = allSchedules.filter((s) => s.ownerReference === `event-workflow-template:${workflow.id}`);
|
|
148
|
+
if (schedules.length > 0) {
|
|
149
|
+
exportWorkflow.crons = schedules.map((s) => ({ name: s.name, cron: s.cron }));
|
|
67
150
|
}
|
|
68
|
-
await
|
|
151
|
+
await (0, helper_1.populateActionIdentifiers)(exportWorkflow);
|
|
152
|
+
(0, helper_1.extractShortActionKeys)(exportWorkflow);
|
|
153
|
+
return exportWorkflow;
|
|
69
154
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const CURRENT_DIR = process.cwd();
|
|
74
|
-
const pathToWrite = path.resolve(path.join(CURRENT_DIR, fileLocation));
|
|
75
|
-
if (fs_1.default.existsSync(pathToWrite)) {
|
|
76
|
-
await (0, file_helpers_1.safeFileOverwrite)(pathToWrite, overwrite);
|
|
155
|
+
async function writeYamlFile(data, absolutePath, overwrite) {
|
|
156
|
+
if (fs_1.default.existsSync(absolutePath)) {
|
|
157
|
+
await (0, file_helpers_1.safeFileOverwrite)(absolutePath, overwrite);
|
|
77
158
|
}
|
|
78
|
-
fs_1.default.
|
|
159
|
+
fs_1.default.mkdirSync(path.dirname(absolutePath), { recursive: true });
|
|
160
|
+
fs_1.default.writeFileSync(absolutePath, js_yaml_1.default.dump(data), 'utf8');
|
|
79
161
|
}
|
|
@@ -18,3 +18,4 @@ export declare class WorkflowTemplateDeployer {
|
|
|
18
18
|
export declare function deleteWorkflowTemplates(): Promise<void>;
|
|
19
19
|
export declare function localDeployWorkflowTemplate(saveFileLocation: string): Promise<void>;
|
|
20
20
|
export declare function populateActionIdentifiers(workflowTemplate: WorkflowTemplate): Promise<void>;
|
|
21
|
+
export declare function extractShortActionKeys(workflowTemplate: WorkflowTemplate): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.populateActionIdentifiers = exports.localDeployWorkflowTemplate = exports.deleteWorkflowTemplates = exports.WorkflowTemplateDeployer = exports.getActionByIdentifier = exports.getWorkflowTemplateIdentifier = exports.LocalWorkflowTemplateDeployer = void 0;
|
|
3
|
+
exports.extractShortActionKeys = exports.populateActionIdentifiers = exports.localDeployWorkflowTemplate = exports.deleteWorkflowTemplates = exports.WorkflowTemplateDeployer = exports.getActionByIdentifier = exports.getWorkflowTemplateIdentifier = exports.LocalWorkflowTemplateDeployer = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const util_1 = require("@contrail/util");
|
|
6
6
|
const chalk_1 = tslib_1.__importDefault(require("chalk"));
|
|
@@ -44,6 +44,8 @@ class LocalWorkflowTemplateDeployer {
|
|
|
44
44
|
isActive: workflowTemplate.isActive,
|
|
45
45
|
supportingAppId: workflowTemplate.supportingAppId,
|
|
46
46
|
messageGroupId: workflowTemplate.messageGroupId,
|
|
47
|
+
messageGroup: workflowTemplate.messageGroup,
|
|
48
|
+
dynamicMessageGroupId: workflowTemplate.dynamicMessageGroupId,
|
|
47
49
|
parallelWorkerCount: workflowTemplate.parallelWorkerCount,
|
|
48
50
|
};
|
|
49
51
|
const newWorkflowTemplate = await (0, event_workflow_templates_1.createWorkflowTemplate)(newObject);
|
|
@@ -55,8 +57,11 @@ class LocalWorkflowTemplateDeployer {
|
|
|
55
57
|
}
|
|
56
58
|
async populateActionIds(workflowTemplate, workflowKey, appIdentifier) {
|
|
57
59
|
const installedApps = await (0, apps_1.getInstalledApps)();
|
|
58
|
-
const appOrg = installedApps.find((x) => x.app
|
|
60
|
+
const appOrg = installedApps.find((x) => x.app?.identifier === appIdentifier);
|
|
59
61
|
logger_1.default.info('workflow template:', JSON.stringify(workflowTemplate, null, 2));
|
|
62
|
+
if (!appOrg) {
|
|
63
|
+
throw new Error(`Could not find installed app with identifier "${appIdentifier}". Make sure the app is installed in this org before importing workflows.`);
|
|
64
|
+
}
|
|
60
65
|
if (!workflowTemplate?.workflowDefinition?.paths) {
|
|
61
66
|
return;
|
|
62
67
|
}
|
|
@@ -86,7 +91,7 @@ class LocalWorkflowTemplateDeployer {
|
|
|
86
91
|
}
|
|
87
92
|
}
|
|
88
93
|
async createWorkflowSchedule(workflowTemplate, workflowId) {
|
|
89
|
-
if (!workflowTemplate?.crons?.length
|
|
94
|
+
if (!workflowTemplate?.crons?.length) {
|
|
90
95
|
return;
|
|
91
96
|
}
|
|
92
97
|
const crons = [];
|
|
@@ -283,3 +288,21 @@ async function populateActionIdentifiers(workflowTemplate) {
|
|
|
283
288
|
}
|
|
284
289
|
}
|
|
285
290
|
exports.populateActionIdentifiers = populateActionIdentifiers;
|
|
291
|
+
function extractShortActionKeys(workflowTemplate) {
|
|
292
|
+
if (!workflowTemplate?.workflowDefinition?.paths) {
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
for (const wfPath of workflowTemplate.workflowDefinition.paths) {
|
|
296
|
+
if (!wfPath?.actionDefinitionConfigs) {
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
for (const actionConfig of wfPath.actionDefinitionConfigs) {
|
|
300
|
+
if (actionConfig.action?.includes(':')) {
|
|
301
|
+
// Full identifier format: "app-id@version:action-name" -> "action-name"
|
|
302
|
+
actionConfig.action = actionConfig.action.split(':').pop();
|
|
303
|
+
}
|
|
304
|
+
delete actionConfig.identifier;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
exports.extractShortActionKeys = extractShortActionKeys;
|
package/oclif.manifest.json
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"version": "3.5.3-alpha.
|
|
2
|
+
"version": "3.5.3-alpha.d91b702",
|
|
3
3
|
"commands": {
|
|
4
4
|
"app:create": {
|
|
5
5
|
"id": "app:create",
|
|
@@ -2956,14 +2956,16 @@
|
|
|
2956
2956
|
},
|
|
2957
2957
|
"workflow-templates:export": {
|
|
2958
2958
|
"id": "workflow-templates:export",
|
|
2959
|
-
"description": "Export all workflows in the org.",
|
|
2959
|
+
"description": "Export all workflows in the org. By default exports one file per app to the current directory.",
|
|
2960
2960
|
"strict": true,
|
|
2961
2961
|
"pluginName": "@contrail/cli",
|
|
2962
2962
|
"pluginAlias": "@contrail/cli",
|
|
2963
2963
|
"pluginType": "core",
|
|
2964
2964
|
"aliases": [],
|
|
2965
2965
|
"examples": [
|
|
2966
|
-
"$ contrail workflow-templates export
|
|
2966
|
+
"$ contrail workflow-templates export",
|
|
2967
|
+
"$ contrail workflow-templates export --dir ./workflows",
|
|
2968
|
+
"$ contrail workflow-templates export --outFile workflows.yml"
|
|
2967
2969
|
],
|
|
2968
2970
|
"flags": {
|
|
2969
2971
|
"logLevel": {
|
|
@@ -2997,10 +2999,18 @@
|
|
|
2997
2999
|
"name": "outFile",
|
|
2998
3000
|
"type": "option",
|
|
2999
3001
|
"char": "f",
|
|
3000
|
-
"description": "
|
|
3002
|
+
"description": "Export all workflows to a single file at this path (overrides per-app export)",
|
|
3003
|
+
"required": false,
|
|
3004
|
+
"multiple": false
|
|
3005
|
+
},
|
|
3006
|
+
"dir": {
|
|
3007
|
+
"name": "dir",
|
|
3008
|
+
"type": "option",
|
|
3009
|
+
"char": "d",
|
|
3010
|
+
"description": "Directory to write per-app workflow files",
|
|
3001
3011
|
"required": false,
|
|
3002
3012
|
"multiple": false,
|
|
3003
|
-
"default": "
|
|
3013
|
+
"default": "."
|
|
3004
3014
|
},
|
|
3005
3015
|
"overwrite": {
|
|
3006
3016
|
"name": "overwrite",
|