@synergenius/flow-weaver 0.17.3 → 0.17.4
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/dist/chevrotain-parser/trigger-cancel-parser.js +6 -0
- package/dist/cli/commands/export.js +11 -1
- package/dist/cli/flow-weaver.mjs +57 -10
- package/dist/deployment/targets/base.d.ts +2 -0
- package/dist/export/index.d.ts +2 -0
- package/dist/export/index.js +2 -0
- package/dist/extensions/cicd/base-target.js +5 -5
- package/dist/extensions/cicd/tag-handler.js +16 -0
- package/dist/extensions/cicd/templates/cicd-multi-env.js +8 -0
- package/dist/extensions/cicd/templates/cicd-test-deploy.js +7 -0
- package/dist/generated-version.d.ts +1 -1
- package/dist/generated-version.js +1 -1
- package/docs/reference/jsdoc-grammar.md +5 -1
- package/package.json +1 -1
|
@@ -156,6 +156,12 @@ export function parseTriggerLine(input, warnings) {
|
|
|
156
156
|
return null;
|
|
157
157
|
}
|
|
158
158
|
const result = visitorInstance.visit(cst);
|
|
159
|
+
// Empty result means the parser consumed @trigger but found no event=/cron= assignments.
|
|
160
|
+
// Return null so the caller can delegate to domain-specific handlers (e.g. CI/CD triggers
|
|
161
|
+
// like @trigger push, @trigger pull_request, etc.)
|
|
162
|
+
if (!result.event && !result.cron) {
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
159
165
|
// Validate cron expression
|
|
160
166
|
if (result.cron && !CRON_REGEX.test(result.cron)) {
|
|
161
167
|
warnings.push(`Invalid cron expression: "${result.cron}". Expected 5 fields (minute hour day month weekday).`);
|
|
@@ -103,7 +103,9 @@ export async function exportCommand(input, options) {
|
|
|
103
103
|
logger.section('Handler Preview');
|
|
104
104
|
const handlerFile = result.files.find((f) => f.path.endsWith('handler.ts') ||
|
|
105
105
|
f.path.endsWith(`${result.workflow}.ts`) ||
|
|
106
|
-
f.path.endsWith('index.ts')
|
|
106
|
+
f.path.endsWith('index.ts') ||
|
|
107
|
+
f.path.endsWith('.yml') ||
|
|
108
|
+
f.path.endsWith('.yaml'));
|
|
107
109
|
if (handlerFile) {
|
|
108
110
|
// Show first 40 lines of handler
|
|
109
111
|
const lines = handlerFile.content.split('\n');
|
|
@@ -114,6 +116,14 @@ export async function exportCommand(input, options) {
|
|
|
114
116
|
}
|
|
115
117
|
}
|
|
116
118
|
}
|
|
119
|
+
// Show warnings about unsupported annotations
|
|
120
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
121
|
+
logger.newline();
|
|
122
|
+
logger.section('Warnings');
|
|
123
|
+
for (const warning of result.warnings) {
|
|
124
|
+
logger.warn(warning);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
117
127
|
// Get deploy instructions from the target
|
|
118
128
|
logger.newline();
|
|
119
129
|
logger.section('Next Steps');
|
package/dist/cli/flow-weaver.mjs
CHANGED
|
@@ -17061,6 +17061,9 @@ function parseTriggerLine(input, warnings) {
|
|
|
17061
17061
|
return null;
|
|
17062
17062
|
}
|
|
17063
17063
|
const result = visitorInstance8.visit(cst);
|
|
17064
|
+
if (!result.event && !result.cron) {
|
|
17065
|
+
return null;
|
|
17066
|
+
}
|
|
17064
17067
|
if (result.cron && !CRON_REGEX.test(result.cron)) {
|
|
17065
17068
|
warnings.push(`Invalid cron expression: "${result.cron}". Expected 5 fields (minute hour day month weekday).`);
|
|
17066
17069
|
}
|
|
@@ -25611,7 +25614,7 @@ var VERSION2;
|
|
|
25611
25614
|
var init_generated_version = __esm({
|
|
25612
25615
|
"src/generated-version.ts"() {
|
|
25613
25616
|
"use strict";
|
|
25614
|
-
VERSION2 = "0.17.
|
|
25617
|
+
VERSION2 = "0.17.4";
|
|
25615
25618
|
}
|
|
25616
25619
|
});
|
|
25617
25620
|
|
|
@@ -71463,7 +71466,7 @@ var init_base_target = __esm({
|
|
|
71463
71466
|
},
|
|
71464
71467
|
"slack-notify": {
|
|
71465
71468
|
githubAction: "slackapi/slack-github-action@v1",
|
|
71466
|
-
gitlabScript: [
|
|
71469
|
+
gitlabScript: [`curl -X POST -H 'Content-type: application/json' --data '{"text":"Pipeline complete"}' $SLACK_WEBHOOK_URL`],
|
|
71467
71470
|
label: "Send Slack notification"
|
|
71468
71471
|
},
|
|
71469
71472
|
"health-check": {
|
|
@@ -71575,11 +71578,10 @@ var init_base_target = __esm({
|
|
|
71575
71578
|
const stages = ast.options?.cicd?.stages;
|
|
71576
71579
|
if (stages && stages.length > 0) {
|
|
71577
71580
|
const depthMap = this.computeJobDepths(jobs);
|
|
71578
|
-
for (const
|
|
71579
|
-
|
|
71580
|
-
if (job && !job.stage) {
|
|
71581
|
+
for (const job of jobs) {
|
|
71582
|
+
if (!job.stage) {
|
|
71581
71583
|
for (const s of stages) {
|
|
71582
|
-
if (
|
|
71584
|
+
if (job.id === s.name || job.id.startsWith(s.name + "-") || job.id.startsWith(s.name + "_")) {
|
|
71583
71585
|
job.stage = s.name;
|
|
71584
71586
|
break;
|
|
71585
71587
|
}
|
|
@@ -73354,6 +73356,18 @@ function parseJob(text, d, warnings) {
|
|
|
73354
73356
|
jc.rules = jc.rules || [];
|
|
73355
73357
|
jc.rules.push({ if: value2 });
|
|
73356
73358
|
break;
|
|
73359
|
+
case "when": {
|
|
73360
|
+
jc.rules = jc.rules || [];
|
|
73361
|
+
if (jc.rules.length === 0) jc.rules.push({});
|
|
73362
|
+
jc.rules[jc.rules.length - 1].when = value2;
|
|
73363
|
+
break;
|
|
73364
|
+
}
|
|
73365
|
+
case "changes": {
|
|
73366
|
+
jc.rules = jc.rules || [];
|
|
73367
|
+
if (jc.rules.length === 0) jc.rules.push({});
|
|
73368
|
+
jc.rules[jc.rules.length - 1].changes = value2.split(",").map((s) => s.trim()).filter(Boolean);
|
|
73369
|
+
break;
|
|
73370
|
+
}
|
|
73357
73371
|
case "reports": {
|
|
73358
73372
|
jc.reports = jc.reports || [];
|
|
73359
73373
|
for (const pair of value2.split(",")) {
|
|
@@ -73794,6 +73808,18 @@ function deploySsh(sshKey: string = ''): { result: string } { return { result: '
|
|
|
73794
73808
|
*/
|
|
73795
73809
|
function deployS3(accessKey: string = '', secretKey: string = ''): { result: string } { return { result: 'deployed' }; }
|
|
73796
73810
|
` : "";
|
|
73811
|
+
const stageAnnotations = hasDeploy ? ` * @stage test
|
|
73812
|
+
* @stage build
|
|
73813
|
+
* @stage deploy
|
|
73814
|
+
` : ` * @stage test
|
|
73815
|
+
* @stage build
|
|
73816
|
+
`;
|
|
73817
|
+
const jobAnnotations = hasDeploy ? ` * @job test retry=1
|
|
73818
|
+
* @job build timeout="10m"
|
|
73819
|
+
* @job deploy allow_failure=false
|
|
73820
|
+
` : ` * @job test retry=1
|
|
73821
|
+
* @job build timeout="10m"
|
|
73822
|
+
`;
|
|
73797
73823
|
return `/** @flowWeaver nodeType
|
|
73798
73824
|
* @expression
|
|
73799
73825
|
* @label Checkout code
|
|
@@ -73832,6 +73858,7 @@ ${deployStub}
|
|
|
73832
73858
|
* @secret NPM_TOKEN - npm auth token${deploySecret}
|
|
73833
73859
|
* @cache npm key="package-lock.json"
|
|
73834
73860
|
*
|
|
73861
|
+
${stageAnnotations}${jobAnnotations} *
|
|
73835
73862
|
* @node co checkout [job: "test"] [position: 270 0]
|
|
73836
73863
|
* @node setup setupNode [job: "test"] [position: 540 0]
|
|
73837
73864
|
* @node install npmInstall [job: "test"] [position: 810 0]
|
|
@@ -73996,6 +74023,15 @@ var cicdMultiEnvTemplate = {
|
|
|
73996
74023
|
const name = opts.workflowName || "multiEnvPipeline";
|
|
73997
74024
|
const envs = (opts.config?.environments || "staging,production").split(",").map((e) => e.trim());
|
|
73998
74025
|
const envAnnotations = envs.map((env) => ` * @environment ${env} url="https://${env}.example.com"`).join("\n");
|
|
74026
|
+
const stageAnnotations = ` * @stage test
|
|
74027
|
+
* @stage build
|
|
74028
|
+
* @stage deploy
|
|
74029
|
+
`;
|
|
74030
|
+
const jobAnnotations = [
|
|
74031
|
+
` * @job test retry=1`,
|
|
74032
|
+
` * @job build timeout="10m"`,
|
|
74033
|
+
...envs.map((env) => ` * @job deploy-${env} allow_failure=${env === "staging" ? "true" : "false"}`)
|
|
74034
|
+
].join("\n");
|
|
73999
74035
|
let x = 270;
|
|
74000
74036
|
const nodeAnnotations = [];
|
|
74001
74037
|
const pathParts = ["Start"];
|
|
@@ -74048,6 +74084,8 @@ ${envAnnotations}
|
|
|
74048
74084
|
* @cache npm key="package-lock.json"
|
|
74049
74085
|
* @artifact dist path="dist/" retention=3
|
|
74050
74086
|
*
|
|
74087
|
+
${stageAnnotations}${jobAnnotations}
|
|
74088
|
+
*
|
|
74051
74089
|
${nodeAnnotations.join("\n")}
|
|
74052
74090
|
*
|
|
74053
74091
|
* @path ${pathParts.join(" -> ")}
|
|
@@ -107919,7 +107957,8 @@ async function exportSingleWorkflowViaRegistry(target, inputPath, outputDir, isD
|
|
|
107919
107957
|
target: options.target,
|
|
107920
107958
|
files,
|
|
107921
107959
|
workflow: workflow.name,
|
|
107922
|
-
description: workflow.description
|
|
107960
|
+
description: workflow.description,
|
|
107961
|
+
warnings: artifacts.warnings
|
|
107923
107962
|
};
|
|
107924
107963
|
}
|
|
107925
107964
|
async function exportMultiWorkflowViaRegistry(target, inputPath, outputDir, isDryRun, options) {
|
|
@@ -107981,7 +108020,8 @@ async function exportMultiWorkflowViaRegistry(target, inputPath, outputDir, isDr
|
|
|
107981
108020
|
target: options.target,
|
|
107982
108021
|
files,
|
|
107983
108022
|
workflow: serviceName,
|
|
107984
|
-
workflows: selectedWorkflows.map((w) => w.name)
|
|
108023
|
+
workflows: selectedWorkflows.map((w) => w.name),
|
|
108024
|
+
warnings: artifacts.warnings
|
|
107985
108025
|
};
|
|
107986
108026
|
}
|
|
107987
108027
|
async function compileToOutput(inputPath, functionName, outputDir, production) {
|
|
@@ -108070,7 +108110,7 @@ async function exportCommand(input, options) {
|
|
|
108070
108110
|
logger.newline();
|
|
108071
108111
|
logger.section("Handler Preview");
|
|
108072
108112
|
const handlerFile = result.files.find(
|
|
108073
|
-
(f) => f.path.endsWith("handler.ts") || f.path.endsWith(`${result.workflow}.ts`) || f.path.endsWith("index.ts")
|
|
108113
|
+
(f) => f.path.endsWith("handler.ts") || f.path.endsWith(`${result.workflow}.ts`) || f.path.endsWith("index.ts") || f.path.endsWith(".yml") || f.path.endsWith(".yaml")
|
|
108074
108114
|
);
|
|
108075
108115
|
if (handlerFile) {
|
|
108076
108116
|
const lines = handlerFile.content.split("\n");
|
|
@@ -108081,6 +108121,13 @@ async function exportCommand(input, options) {
|
|
|
108081
108121
|
}
|
|
108082
108122
|
}
|
|
108083
108123
|
}
|
|
108124
|
+
if (result.warnings && result.warnings.length > 0) {
|
|
108125
|
+
logger.newline();
|
|
108126
|
+
logger.section("Warnings");
|
|
108127
|
+
for (const warning of result.warnings) {
|
|
108128
|
+
logger.warn(warning);
|
|
108129
|
+
}
|
|
108130
|
+
}
|
|
108084
108131
|
logger.newline();
|
|
108085
108132
|
logger.section("Next Steps");
|
|
108086
108133
|
const { createTargetRegistry: createTargetRegistry2 } = await Promise.resolve().then(() => (init_deployment(), deployment_exports));
|
|
@@ -109257,7 +109304,7 @@ function displayInstalledPackage(pkg) {
|
|
|
109257
109304
|
|
|
109258
109305
|
// src/cli/index.ts
|
|
109259
109306
|
init_error_utils();
|
|
109260
|
-
var version2 = true ? "0.17.
|
|
109307
|
+
var version2 = true ? "0.17.4" : "0.0.0-dev";
|
|
109261
109308
|
var program2 = new Command();
|
|
109262
109309
|
program2.name("flow-weaver").description("Flow Weaver Annotations - Compile and validate workflow files").option("-v, --version", "Output the current version").option("--no-color", "Disable colors").option("--color", "Force colors").on("option:version", () => {
|
|
109263
109310
|
logger.banner(version2);
|
package/dist/export/index.d.ts
CHANGED
package/dist/export/index.js
CHANGED
|
@@ -112,6 +112,7 @@ async function exportSingleWorkflowViaRegistry(target, inputPath, outputDir, isD
|
|
|
112
112
|
files,
|
|
113
113
|
workflow: workflow.name,
|
|
114
114
|
description: workflow.description,
|
|
115
|
+
warnings: artifacts.warnings,
|
|
115
116
|
};
|
|
116
117
|
}
|
|
117
118
|
/**
|
|
@@ -177,6 +178,7 @@ async function exportMultiWorkflowViaRegistry(target, inputPath, outputDir, isDr
|
|
|
177
178
|
files,
|
|
178
179
|
workflow: serviceName,
|
|
179
180
|
workflows: selectedWorkflows.map((w) => w.name),
|
|
181
|
+
warnings: artifacts.warnings,
|
|
180
182
|
};
|
|
181
183
|
}
|
|
182
184
|
/**
|
|
@@ -79,7 +79,7 @@ export const NODE_ACTION_MAP = {
|
|
|
79
79
|
},
|
|
80
80
|
'slack-notify': {
|
|
81
81
|
githubAction: 'slackapi/slack-github-action@v1',
|
|
82
|
-
gitlabScript: [
|
|
82
|
+
gitlabScript: ["curl -X POST -H 'Content-type: application/json' --data '{\"text\":\"Pipeline complete\"}' $SLACK_WEBHOOK_URL"],
|
|
83
83
|
label: 'Send Slack notification',
|
|
84
84
|
},
|
|
85
85
|
'health-check': {
|
|
@@ -224,11 +224,11 @@ export class BaseCICDTarget extends BaseExportTarget {
|
|
|
224
224
|
const stages = ast.options?.cicd?.stages;
|
|
225
225
|
if (stages && stages.length > 0) {
|
|
226
226
|
const depthMap = this.computeJobDepths(jobs);
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (
|
|
227
|
+
// Match ALL jobs by name prefix to stages, not just configured ones
|
|
228
|
+
for (const job of jobs) {
|
|
229
|
+
if (!job.stage) {
|
|
230
230
|
for (const s of stages) {
|
|
231
|
-
if (
|
|
231
|
+
if (job.id === s.name || job.id.startsWith(s.name + '-') || job.id.startsWith(s.name + '_')) {
|
|
232
232
|
job.stage = s.name;
|
|
233
233
|
break;
|
|
234
234
|
}
|
|
@@ -326,6 +326,22 @@ function parseJob(text, d, warnings) {
|
|
|
326
326
|
jc.rules = jc.rules || [];
|
|
327
327
|
jc.rules.push({ if: value });
|
|
328
328
|
break;
|
|
329
|
+
case 'when': {
|
|
330
|
+
// Modifier: sets `when` on the last rule, or creates a standalone rule
|
|
331
|
+
jc.rules = jc.rules || [];
|
|
332
|
+
if (jc.rules.length === 0)
|
|
333
|
+
jc.rules.push({});
|
|
334
|
+
jc.rules[jc.rules.length - 1].when = value;
|
|
335
|
+
break;
|
|
336
|
+
}
|
|
337
|
+
case 'changes': {
|
|
338
|
+
// Modifier: sets `changes` on the last rule
|
|
339
|
+
jc.rules = jc.rules || [];
|
|
340
|
+
if (jc.rules.length === 0)
|
|
341
|
+
jc.rules.push({});
|
|
342
|
+
jc.rules[jc.rules.length - 1].changes = value.split(',').map(s => s.trim()).filter(Boolean);
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
329
345
|
case 'reports': {
|
|
330
346
|
jc.reports = jc.reports || [];
|
|
331
347
|
for (const pair of value.split(',')) {
|
|
@@ -35,6 +35,12 @@ export const cicdMultiEnvTemplate = {
|
|
|
35
35
|
const envAnnotations = envs
|
|
36
36
|
.map((env) => ` * @environment ${env} url="https://${env}.example.com"`)
|
|
37
37
|
.join('\n');
|
|
38
|
+
const stageAnnotations = ` * @stage test\n * @stage build\n * @stage deploy\n`;
|
|
39
|
+
const jobAnnotations = [
|
|
40
|
+
` * @job test retry=1`,
|
|
41
|
+
` * @job build timeout="10m"`,
|
|
42
|
+
...envs.map((env) => ` * @job deploy-${env} allow_failure=${env === 'staging' ? 'true' : 'false'}`),
|
|
43
|
+
].join('\n');
|
|
38
44
|
let x = 270;
|
|
39
45
|
const nodeAnnotations = [];
|
|
40
46
|
const pathParts = ['Start'];
|
|
@@ -89,6 +95,8 @@ ${envAnnotations}
|
|
|
89
95
|
* @cache npm key="package-lock.json"
|
|
90
96
|
* @artifact dist path="dist/" retention=3
|
|
91
97
|
*
|
|
98
|
+
${stageAnnotations}${jobAnnotations}
|
|
99
|
+
*
|
|
92
100
|
${nodeAnnotations.join('\n')}
|
|
93
101
|
*
|
|
94
102
|
* @path ${pathParts.join(' -> ')}
|
|
@@ -78,6 +78,12 @@ function deploySsh(sshKey: string = ''): { result: string } { return { result: '
|
|
|
78
78
|
function deployS3(accessKey: string = '', secretKey: string = ''): { result: string } { return { result: 'deployed' }; }
|
|
79
79
|
`
|
|
80
80
|
: '';
|
|
81
|
+
const stageAnnotations = hasDeploy
|
|
82
|
+
? ` * @stage test\n * @stage build\n * @stage deploy\n`
|
|
83
|
+
: ` * @stage test\n * @stage build\n`;
|
|
84
|
+
const jobAnnotations = hasDeploy
|
|
85
|
+
? ` * @job test retry=1\n * @job build timeout="10m"\n * @job deploy allow_failure=false\n`
|
|
86
|
+
: ` * @job test retry=1\n * @job build timeout="10m"\n`;
|
|
81
87
|
return `/** @flowWeaver nodeType
|
|
82
88
|
* @expression
|
|
83
89
|
* @label Checkout code
|
|
@@ -116,6 +122,7 @@ ${deployStub}
|
|
|
116
122
|
* @secret NPM_TOKEN - npm auth token${deploySecret}
|
|
117
123
|
* @cache npm key="package-lock.json"
|
|
118
124
|
*
|
|
125
|
+
${stageAnnotations}${jobAnnotations} *
|
|
119
126
|
* @node co checkout [job: "test"] [position: 270 0]
|
|
120
127
|
* @node setup setupNode [job: "test"] [position: 540 0]
|
|
121
128
|
* @node install npmInstall [job: "test"] [position: 810 0]
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const VERSION = "0.17.
|
|
1
|
+
export declare const VERSION = "0.17.4";
|
|
2
2
|
//# sourceMappingURL=generated-version.d.ts.map
|
|
@@ -572,7 +572,9 @@ Configures per-job settings. The name must match a `[job: "name"]` attribute use
|
|
|
572
572
|
jobTag ::= "@job" IDENTIFIER { IDENTIFIER "=" ( STRING | IDENTIFIER | INTEGER ) }
|
|
573
573
|
```
|
|
574
574
|
|
|
575
|
-
Recognized keys: `retry` (number), `allow_failure` (boolean), `timeout` (string), `runner` (string), `tags` (comma-list), `coverage` (string), `reports` (comma-list of type=path), `rules` (string), `extends` (string), `before_script` (comma-list), `variables` (comma-list of KEY=VALUE).
|
|
575
|
+
Recognized keys: `retry` (number), `allow_failure` (boolean), `timeout` (string), `runner` (string), `tags` (comma-list), `coverage` (string), `reports` (comma-list of type=path), `rules` (string), `when` (rule modifier), `changes` (rule modifier, comma-list), `extends` (string), `before_script` (comma-list), `variables` (comma-list of KEY=VALUE).
|
|
576
|
+
|
|
577
|
+
The `when` and `changes` keys are rule modifiers: they apply to the most recently declared `rules` entry for that job. If no `rules` entry exists yet, one is created automatically.
|
|
576
578
|
|
|
577
579
|
**Examples:**
|
|
578
580
|
|
|
@@ -580,6 +582,8 @@ Recognized keys: `retry` (number), `allow_failure` (boolean), `timeout` (string)
|
|
|
580
582
|
@job build retry=2 timeout="10m"
|
|
581
583
|
@job test-unit coverage='/Coverage: (\d+)%/' reports="junit=test-results.xml"
|
|
582
584
|
@job deploy allow_failure=true rules="$CI_COMMIT_BRANCH == main"
|
|
585
|
+
@job deploy rules="$CI_COMMIT_BRANCH == main" when=manual
|
|
586
|
+
@job deploy rules="$CI_COMMIT_TAG" changes="src/**,lib/**"
|
|
583
587
|
@job lint tags="docker,linux" extends=".base-lint"
|
|
584
588
|
```
|
|
585
589
|
|
package/package.json
CHANGED