@olivervea/pipelines 2.0.0-beta.27 → 2.0.0-beta.28
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/package.json +1 -1
- package/src/describe/config-schema.ts +98 -0
- package/src/describe/context.ts +182 -0
- package/src/describe/describe.ts +37 -851
- package/src/describe/failure-handlers.ts +34 -0
- package/src/describe/schemas.ts +71 -0
- package/src/describe/stages.ts +165 -0
- package/src/describe/step.ts +395 -0
- package/src/describe/triggers.ts +72 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { STEP_NAME } from '../core/steps.ts';
|
|
2
|
+
import type { TriggerNode } from '../builder/pipeline.ts';
|
|
3
|
+
import type { TriggerT } from './manifest-schema.ts';
|
|
4
|
+
import type { DescribeContext } from './context.ts';
|
|
5
|
+
|
|
6
|
+
export function describeTriggers(
|
|
7
|
+
ctx: DescribeContext,
|
|
8
|
+
triggers: readonly TriggerNode[],
|
|
9
|
+
): TriggerT[] {
|
|
10
|
+
const names = new Set<string>();
|
|
11
|
+
return triggers.map((t) => {
|
|
12
|
+
if (names.has(t.name))
|
|
13
|
+
ctx.problems.push(
|
|
14
|
+
`duplicate trigger '${t.name}'${t.kind === 'push' ? ' (onPush may be used once)' : ' (give each onPoll and onWebhook a distinct name)'}`,
|
|
15
|
+
);
|
|
16
|
+
names.add(t.name);
|
|
17
|
+
if (t.kind === 'push') return { kind: 'push', name: 'push' };
|
|
18
|
+
if (t.kind === 'webhook') return describeWebhook(ctx, t);
|
|
19
|
+
return describePoll(ctx, t);
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function describeWebhook(
|
|
24
|
+
ctx: DescribeContext,
|
|
25
|
+
t: Extract<TriggerNode, { kind: 'webhook' }>,
|
|
26
|
+
): TriggerT {
|
|
27
|
+
if (!STEP_NAME.test(t.name))
|
|
28
|
+
ctx.problems.push(`webhook trigger name '${t.name}' must be lower-case kebab`);
|
|
29
|
+
const secret = ctx.useSecret(t.verify.secret, `webhook '${t.name}'`);
|
|
30
|
+
if (t.verify.scheme === 'bearer')
|
|
31
|
+
return { kind: 'webhook', name: t.name, verify: { scheme: 'bearer', secret } };
|
|
32
|
+
if (!t.verify.header)
|
|
33
|
+
ctx.problems.push(`webhook '${t.name}': the signature header must not be empty`);
|
|
34
|
+
return {
|
|
35
|
+
kind: 'webhook',
|
|
36
|
+
name: t.name,
|
|
37
|
+
verify: {
|
|
38
|
+
scheme: 'hmac-sha256',
|
|
39
|
+
secret,
|
|
40
|
+
header: t.verify.header,
|
|
41
|
+
prefix: t.verify.prefix,
|
|
42
|
+
},
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function describePoll(
|
|
47
|
+
ctx: DescribeContext,
|
|
48
|
+
t: Extract<TriggerNode, { kind: 'poll' }>,
|
|
49
|
+
): TriggerT {
|
|
50
|
+
const problems = ctx.problems;
|
|
51
|
+
if (!STEP_NAME.test(t.name))
|
|
52
|
+
problems.push(`poll trigger name '${t.name}' must be lower-case kebab`);
|
|
53
|
+
if (!(Number.isInteger(t.intervalSeconds) && t.intervalSeconds > 0))
|
|
54
|
+
problems.push(`poll '${t.name}': intervalSeconds must be a positive integer`);
|
|
55
|
+
const declared = new Set(t.secrets.map((s) => ctx.useSecret(s, `poll '${t.name}'`)));
|
|
56
|
+
for (const [h, v] of Object.entries(t.headers)) {
|
|
57
|
+
for (const m of v.matchAll(/\$SECRET:([A-Za-z0-9_]+)/g))
|
|
58
|
+
if (!declared.has(m[1]!))
|
|
59
|
+
problems.push(
|
|
60
|
+
`poll '${t.name}': header '${h}' references secret '${m[1]}', which is not in the poll's secrets`,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
kind: 'poll',
|
|
65
|
+
name: t.name,
|
|
66
|
+
url: t.url,
|
|
67
|
+
headers: { ...t.headers },
|
|
68
|
+
secrets: [...declared].sort(),
|
|
69
|
+
valuePath: t.valuePath,
|
|
70
|
+
intervalSeconds: t.intervalSeconds,
|
|
71
|
+
};
|
|
72
|
+
}
|