@olivervea/pipelines 0.0.0-stage → 2.0.0-beta.10

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.
Files changed (54) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +467 -2
  3. package/manifest.schema.json +674 -0
  4. package/package.json +60 -4
  5. package/src/assets.d.ts +10 -0
  6. package/src/build/build.ts +127 -0
  7. package/src/build/cli.ts +52 -0
  8. package/src/build/elf.ts +35 -0
  9. package/src/build/hashes.ts +96 -0
  10. package/src/build/project.ts +107 -0
  11. package/src/builder/pipeline.ts +373 -0
  12. package/src/builder/refs.ts +26 -0
  13. package/src/core/brands.ts +15 -0
  14. package/src/core/config-refs.ts +77 -0
  15. package/src/core/config.ts +147 -0
  16. package/src/core/handlers.ts +50 -0
  17. package/src/core/models.ts +69 -0
  18. package/src/core/origin.ts +20 -0
  19. package/src/core/secrets.ts +13 -0
  20. package/src/core/steps.ts +138 -0
  21. package/src/core/types.ts +6 -0
  22. package/src/core/webhooks.ts +30 -0
  23. package/src/ctx/files.ts +161 -0
  24. package/src/ctx/index.ts +122 -0
  25. package/src/ctx/sh.ts +197 -0
  26. package/src/ctx/types.ts +116 -0
  27. package/src/describe/describe.ts +565 -0
  28. package/src/describe/manifest-schema.ts +179 -0
  29. package/src/describe/mapper-source.ts +238 -0
  30. package/src/describe/record.ts +107 -0
  31. package/src/dev/cli.ts +87 -0
  32. package/src/harness/env.ts +58 -0
  33. package/src/harness/execute.ts +97 -0
  34. package/src/harness/exit.ts +19 -0
  35. package/src/harness/index.ts +9 -0
  36. package/src/harness/main.ts +270 -0
  37. package/src/harness/result.ts +75 -0
  38. package/src/harness/validate.ts +92 -0
  39. package/src/index.ts +15 -0
  40. package/src/library/checks.ts +23 -0
  41. package/src/library/compose-deploy.ts +96 -0
  42. package/src/library/github-source.ts +100 -0
  43. package/src/library/helm-deploy-ssh.ts +358 -0
  44. package/src/library/helm-deploy.ts +271 -0
  45. package/src/library/http-health.ts +34 -0
  46. package/src/library/image-build.ts +418 -0
  47. package/src/library/index.ts +18 -0
  48. package/src/library/models.ts +79 -0
  49. package/src/library/ssh.ts +50 -0
  50. package/src/testing/index.ts +82 -0
  51. package/src/util/canonical.ts +19 -0
  52. package/src/util/handler-hash.ts +22 -0
  53. package/src/util/hash.ts +22 -0
  54. package/src/util/tar.ts +167 -0
@@ -0,0 +1,674 @@
1
+ {
2
+ "$defs": {
3
+ "InputType": {
4
+ "anyOf": [
5
+ {
6
+ "additionalProperties": false,
7
+ "properties": {
8
+ "model": {
9
+ "description": "Model name (key of `models`).",
10
+ "pattern": "^[A-Za-z][A-Za-z0-9_]*$",
11
+ "type": "string"
12
+ },
13
+ "optional": {
14
+ "description": "optional(Model): may be absent because its producer was skipped.",
15
+ "type": "boolean"
16
+ }
17
+ },
18
+ "required": [
19
+ "model",
20
+ "optional"
21
+ ],
22
+ "type": "object"
23
+ },
24
+ {
25
+ "additionalProperties": false,
26
+ "properties": {
27
+ "schema": {
28
+ "$ref": "#/$defs/ModelSchemas",
29
+ "description": "A plain (unnamed) zod schema. Such inputs always have an explicit mapping."
30
+ }
31
+ },
32
+ "required": [
33
+ "schema"
34
+ ],
35
+ "type": "object"
36
+ }
37
+ ]
38
+ },
39
+ "Json": {
40
+ "$ref": "#/$defs/__schema0",
41
+ "description": "Any JSON value."
42
+ },
43
+ "Manifest": {
44
+ "additionalProperties": false,
45
+ "properties": {
46
+ "apiVersion": {
47
+ "const": "2.0",
48
+ "type": "string"
49
+ },
50
+ "config": {
51
+ "description": "Config entries used by steps, sorted by name (omitted when none). Fields of kind secretRef ({secret: NAME}) name a secret.",
52
+ "items": {
53
+ "additionalProperties": false,
54
+ "properties": {
55
+ "description": {
56
+ "type": "string"
57
+ },
58
+ "name": {
59
+ "description": "Config entry name; a key of the pipeline's config document.",
60
+ "pattern": "^[a-z][a-zA-Z0-9]*$",
61
+ "type": "string"
62
+ },
63
+ "required": {
64
+ "description": "False when the schema accepts a missing value (optional, or a default).",
65
+ "type": "boolean"
66
+ },
67
+ "schema": {
68
+ "additionalProperties": {},
69
+ "description": "z.input view: validates the config document's value for this entry (defaults listed).",
70
+ "propertyNames": {
71
+ "type": "string"
72
+ },
73
+ "type": "object"
74
+ }
75
+ },
76
+ "required": [
77
+ "name",
78
+ "description",
79
+ "required",
80
+ "schema"
81
+ ],
82
+ "type": "object"
83
+ },
84
+ "type": "array"
85
+ },
86
+ "description": {
87
+ "type": "string"
88
+ },
89
+ "failureHandlers": {
90
+ "items": {
91
+ "additionalProperties": false,
92
+ "properties": {
93
+ "step": {
94
+ "$ref": "#/$defs/Step",
95
+ "description": "The handler step. Not part of any stage; its inputs are all FailureContext ({ref: 'failure'})."
96
+ },
97
+ "steps": {
98
+ "anyOf": [
99
+ {
100
+ "items": {
101
+ "description": "Step name: lower-case kebab, 1-63 chars. The step's identity.",
102
+ "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
103
+ "type": "string"
104
+ },
105
+ "type": "array"
106
+ },
107
+ {
108
+ "type": "null"
109
+ }
110
+ ],
111
+ "description": "Steps whose failure triggers the handler (null = any step)."
112
+ }
113
+ },
114
+ "required": [
115
+ "step",
116
+ "steps"
117
+ ],
118
+ "type": "object"
119
+ },
120
+ "type": "array"
121
+ },
122
+ "harness": {
123
+ "additionalProperties": false,
124
+ "description": "Harness identity. Already folded into every handlerHash.",
125
+ "properties": {
126
+ "bun": {
127
+ "description": "Bun runtime version compiled into the binary.",
128
+ "type": "string"
129
+ },
130
+ "sdk": {
131
+ "description": "@olivervea/pipelines package version.",
132
+ "type": "string"
133
+ },
134
+ "sdkHash": {
135
+ "description": "Hash of the SDK runtime sources + zod version.",
136
+ "pattern": "^sha256:[0-9a-f]{64}$",
137
+ "type": "string"
138
+ }
139
+ },
140
+ "required": [
141
+ "bun",
142
+ "sdk",
143
+ "sdkHash"
144
+ ],
145
+ "type": "object"
146
+ },
147
+ "input": {
148
+ "description": "Pipeline input model.",
149
+ "pattern": "^[A-Za-z][A-Za-z0-9_]*$",
150
+ "type": "string"
151
+ },
152
+ "models": {
153
+ "additionalProperties": {
154
+ "$ref": "#/$defs/ModelSchemas"
155
+ },
156
+ "description": "Every model referenced by the pipeline (input, step inputs/outputs).",
157
+ "propertyNames": {
158
+ "description": "Model name (key of `models`).",
159
+ "pattern": "^[A-Za-z][A-Za-z0-9_]*$",
160
+ "type": "string"
161
+ },
162
+ "type": "object"
163
+ },
164
+ "name": {
165
+ "minLength": 1,
166
+ "type": "string"
167
+ },
168
+ "secrets": {
169
+ "description": "All declared secrets (steps + poll triggers), sorted by name.",
170
+ "items": {
171
+ "additionalProperties": false,
172
+ "properties": {
173
+ "description": {
174
+ "type": "string"
175
+ },
176
+ "name": {
177
+ "description": "Secret name; also the env var name in the step container.",
178
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
179
+ "type": "string"
180
+ }
181
+ },
182
+ "required": [
183
+ "name",
184
+ "description"
185
+ ],
186
+ "type": "object"
187
+ },
188
+ "type": "array"
189
+ },
190
+ "stages": {
191
+ "items": {
192
+ "$ref": "#/$defs/Stage"
193
+ },
194
+ "type": "array"
195
+ },
196
+ "triggers": {
197
+ "items": {
198
+ "$ref": "#/$defs/Trigger"
199
+ },
200
+ "type": "array"
201
+ }
202
+ },
203
+ "required": [
204
+ "apiVersion",
205
+ "name",
206
+ "input",
207
+ "harness",
208
+ "models",
209
+ "secrets",
210
+ "triggers",
211
+ "stages",
212
+ "failureHandlers"
213
+ ],
214
+ "title": "Olve.Pipelines v2 manifest",
215
+ "type": "object"
216
+ },
217
+ "Mapping": {
218
+ "anyOf": [
219
+ {
220
+ "additionalProperties": false,
221
+ "description": "Value taken from the run pool. A ref whose root step was skipped yields no value (only allowed for optional inputs).",
222
+ "properties": {
223
+ "ref": {
224
+ "description": "'<root>' or '<root>.<field>.<field>…'. Root: 'input' (pipeline input), a step name (that step's output) or 'failure' (FailureContext, failure handlers only).",
225
+ "pattern": "^(?:input|failure|[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)(?:\\.[^.]+)*$",
226
+ "type": "string"
227
+ }
228
+ },
229
+ "required": [
230
+ "ref"
231
+ ],
232
+ "type": "object"
233
+ },
234
+ {
235
+ "additionalProperties": false,
236
+ "description": "A JSON constant.",
237
+ "properties": {
238
+ "const": {
239
+ "$ref": "#/$defs/Json"
240
+ }
241
+ },
242
+ "required": [
243
+ "const"
244
+ ],
245
+ "type": "object"
246
+ },
247
+ {
248
+ "additionalProperties": {
249
+ "$ref": "#/$defs/Mapping"
250
+ },
251
+ "description": "An object built field by field. Discrimination: an object whose only key is 'ref' (string value) is a ref, whose only key is 'const' is a constant, anything else is a nested object (describe never emits a nested object whose only key is 'ref' or 'const').",
252
+ "propertyNames": {
253
+ "type": "string"
254
+ },
255
+ "type": "object"
256
+ }
257
+ ]
258
+ },
259
+ "ModelSchemas": {
260
+ "additionalProperties": false,
261
+ "properties": {
262
+ "input": {
263
+ "additionalProperties": {},
264
+ "description": "z.input view (defaults make fields optional; `default` values are listed). Present only when it differs from `output`.",
265
+ "propertyNames": {
266
+ "type": "string"
267
+ },
268
+ "type": "object"
269
+ },
270
+ "output": {
271
+ "additionalProperties": {},
272
+ "description": "z.output view: validates step outputs, trigger results and the pool. Every object has additionalProperties: false.",
273
+ "propertyNames": {
274
+ "type": "string"
275
+ },
276
+ "type": "object"
277
+ }
278
+ },
279
+ "required": [
280
+ "output"
281
+ ],
282
+ "type": "object"
283
+ },
284
+ "Stage": {
285
+ "anyOf": [
286
+ {
287
+ "additionalProperties": false,
288
+ "properties": {
289
+ "steps": {
290
+ "description": "Steps run in parallel; the stage is a barrier.",
291
+ "items": {
292
+ "$ref": "#/$defs/Step"
293
+ },
294
+ "minItems": 1,
295
+ "type": "array"
296
+ }
297
+ },
298
+ "required": [
299
+ "steps"
300
+ ],
301
+ "type": "object"
302
+ },
303
+ {
304
+ "additionalProperties": false,
305
+ "properties": {
306
+ "stages": {
307
+ "items": {
308
+ "$ref": "#/$defs/Stage"
309
+ },
310
+ "type": "array"
311
+ },
312
+ "when": {
313
+ "additionalProperties": {
314
+ "items": {
315
+ "type": [
316
+ "string",
317
+ "number",
318
+ "boolean"
319
+ ]
320
+ },
321
+ "minItems": 1,
322
+ "type": "array"
323
+ },
324
+ "description": "Pipeline-input field → accepted values (all fields must match). Empty object = always.",
325
+ "propertyNames": {
326
+ "type": "string"
327
+ },
328
+ "type": "object"
329
+ }
330
+ },
331
+ "required": [
332
+ "when",
333
+ "stages"
334
+ ],
335
+ "type": "object"
336
+ },
337
+ {
338
+ "additionalProperties": false,
339
+ "properties": {
340
+ "cases": {
341
+ "additionalProperties": {
342
+ "items": {
343
+ "$ref": "#/$defs/Stage"
344
+ },
345
+ "type": "array"
346
+ },
347
+ "description": "Discriminator value → stages. Exactly one case runs; a step name may repeat across cases, nowhere else.",
348
+ "propertyNames": {
349
+ "type": "string"
350
+ },
351
+ "type": "object"
352
+ },
353
+ "discriminator": {
354
+ "description": "The union's literal field whose value names the case.",
355
+ "minLength": 1,
356
+ "type": "string"
357
+ },
358
+ "select": {
359
+ "description": "Config reference (`<entry>.<field>…`) to a discriminated union; the run's config snapshot picks the case.",
360
+ "minLength": 1,
361
+ "type": "string"
362
+ }
363
+ },
364
+ "required": [
365
+ "select",
366
+ "discriminator",
367
+ "cases"
368
+ ],
369
+ "type": "object"
370
+ }
371
+ ]
372
+ },
373
+ "Step": {
374
+ "additionalProperties": false,
375
+ "properties": {
376
+ "clusterAccess": {
377
+ "const": true,
378
+ "description": "The step pod gets the instance's step ServiceAccount token (Kubernetes:StepServiceAccount), if the instance grants one. Omitted = no token.",
379
+ "type": "boolean"
380
+ },
381
+ "config": {
382
+ "additionalProperties": {
383
+ "$ref": "#/$defs/Json"
384
+ },
385
+ "description": "The step's settings (display only; already covered by handlerHash). A config reference is recorded as {\"$config\": \"<entry>.<field>…\"}; the entry is in configEntries.",
386
+ "propertyNames": {
387
+ "type": "string"
388
+ },
389
+ "type": "object"
390
+ },
391
+ "configEntries": {
392
+ "description": "Config entries the step receives (sorted; omitted when none). The service delivers them in input.json under '$config'.",
393
+ "items": {
394
+ "description": "Config entry name; a key of the pipeline's config document.",
395
+ "pattern": "^[a-z][a-zA-Z0-9]*$",
396
+ "type": "string"
397
+ },
398
+ "type": "array"
399
+ },
400
+ "description": {
401
+ "description": "What the step does, shown in the UI (may be empty).",
402
+ "type": "string"
403
+ },
404
+ "handlerHash": {
405
+ "description": "Implementation identity: handler bundle (contract files excluded) + harness (bun + sdkHash); for a step that carries its implementation kind + config + harness + the hash of the code of its kind.",
406
+ "pattern": "^sha256:[0-9a-f]{64}$",
407
+ "type": "string"
408
+ },
409
+ "image": {
410
+ "description": "Container image the step runs in.",
411
+ "minLength": 1,
412
+ "type": "string"
413
+ },
414
+ "input": {
415
+ "additionalProperties": {
416
+ "$ref": "#/$defs/Mapping"
417
+ },
418
+ "description": "How the service assembles input.json: one mapping per input key (same keys as inputTypes).",
419
+ "propertyNames": {
420
+ "type": "string"
421
+ },
422
+ "type": "object"
423
+ },
424
+ "inputTypes": {
425
+ "additionalProperties": {
426
+ "$ref": "#/$defs/InputType"
427
+ },
428
+ "description": "Declared input entries, keyed like input.json.",
429
+ "propertyNames": {
430
+ "type": "string"
431
+ },
432
+ "type": "object"
433
+ },
434
+ "kind": {
435
+ "description": "'custom' = the handler is a handlers/*.ts file; any other kind is a step that carries its implementation (an SDK or package step). A label: the service accepts any kind.",
436
+ "minLength": 1,
437
+ "type": "string"
438
+ },
439
+ "name": {
440
+ "description": "Step name: lower-case kebab, 1-63 chars. The step's identity.",
441
+ "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
442
+ "type": "string"
443
+ },
444
+ "output": {
445
+ "anyOf": [
446
+ {
447
+ "description": "Model name (key of `models`).",
448
+ "pattern": "^[A-Za-z][A-Za-z0-9_]*$",
449
+ "type": "string"
450
+ },
451
+ {
452
+ "type": "null"
453
+ }
454
+ ],
455
+ "description": "Output model, or null if the step produces no output."
456
+ },
457
+ "retries": {
458
+ "maximum": 9007199254740991,
459
+ "minimum": 0,
460
+ "type": "integer"
461
+ },
462
+ "secrets": {
463
+ "description": "Declared secrets (sorted). Mount exactly these, as env vars of the same name.",
464
+ "items": {
465
+ "description": "Secret name; also the env var name in the step container.",
466
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
467
+ "type": "string"
468
+ },
469
+ "type": "array"
470
+ },
471
+ "timeoutSeconds": {
472
+ "exclusiveMinimum": 0,
473
+ "maximum": 9007199254740991,
474
+ "type": "integer"
475
+ }
476
+ },
477
+ "required": [
478
+ "name",
479
+ "description",
480
+ "kind",
481
+ "image",
482
+ "inputTypes",
483
+ "input",
484
+ "output",
485
+ "secrets",
486
+ "handlerHash"
487
+ ],
488
+ "type": "object"
489
+ },
490
+ "Trigger": {
491
+ "oneOf": [
492
+ {
493
+ "additionalProperties": false,
494
+ "description": "GitHub push. Event = the webhook payload.",
495
+ "properties": {
496
+ "kind": {
497
+ "const": "push",
498
+ "type": "string"
499
+ },
500
+ "name": {
501
+ "const": "push",
502
+ "type": "string"
503
+ }
504
+ },
505
+ "required": [
506
+ "kind",
507
+ "name"
508
+ ],
509
+ "type": "object"
510
+ },
511
+ {
512
+ "additionalProperties": false,
513
+ "description": "Background poller.",
514
+ "properties": {
515
+ "headers": {
516
+ "additionalProperties": {
517
+ "type": "string"
518
+ },
519
+ "description": "Values may contain '$SECRET:NAME' (NAME ∈ secrets).",
520
+ "propertyNames": {
521
+ "type": "string"
522
+ },
523
+ "type": "object"
524
+ },
525
+ "intervalSeconds": {
526
+ "exclusiveMinimum": 0,
527
+ "maximum": 9007199254740991,
528
+ "type": "integer"
529
+ },
530
+ "kind": {
531
+ "const": "poll",
532
+ "type": "string"
533
+ },
534
+ "name": {
535
+ "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
536
+ "type": "string"
537
+ },
538
+ "secrets": {
539
+ "items": {
540
+ "description": "Secret name; also the env var name in the step container.",
541
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
542
+ "type": "string"
543
+ },
544
+ "type": "array"
545
+ },
546
+ "url": {
547
+ "type": "string"
548
+ },
549
+ "valuePath": {
550
+ "description": "Dot path into the JSON response; a change triggers map-trigger with {\"value\": <string>}.",
551
+ "type": "string"
552
+ }
553
+ },
554
+ "required": [
555
+ "kind",
556
+ "name",
557
+ "url",
558
+ "headers",
559
+ "secrets",
560
+ "valuePath",
561
+ "intervalSeconds"
562
+ ],
563
+ "type": "object"
564
+ },
565
+ {
566
+ "additionalProperties": false,
567
+ "description": "Inbound HTTP delivery to /api/hooks/<pipeline id>/<name>. Event = {headers, body}; a null mapping ignores it.",
568
+ "properties": {
569
+ "kind": {
570
+ "const": "webhook",
571
+ "type": "string"
572
+ },
573
+ "name": {
574
+ "pattern": "^[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?$",
575
+ "type": "string"
576
+ },
577
+ "verify": {
578
+ "oneOf": [
579
+ {
580
+ "additionalProperties": false,
581
+ "properties": {
582
+ "header": {
583
+ "minLength": 1,
584
+ "type": "string"
585
+ },
586
+ "prefix": {
587
+ "description": "Text before the hex digest in the header, e.g. 'sha256='.",
588
+ "type": "string"
589
+ },
590
+ "scheme": {
591
+ "const": "hmac-sha256",
592
+ "type": "string"
593
+ },
594
+ "secret": {
595
+ "description": "Secret name; also the env var name in the step container.",
596
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
597
+ "type": "string"
598
+ }
599
+ },
600
+ "required": [
601
+ "scheme",
602
+ "secret",
603
+ "header",
604
+ "prefix"
605
+ ],
606
+ "type": "object"
607
+ },
608
+ {
609
+ "additionalProperties": false,
610
+ "properties": {
611
+ "scheme": {
612
+ "const": "bearer",
613
+ "type": "string"
614
+ },
615
+ "secret": {
616
+ "description": "Secret name; also the env var name in the step container.",
617
+ "pattern": "^[A-Z_][A-Z0-9_]*$",
618
+ "type": "string"
619
+ }
620
+ },
621
+ "required": [
622
+ "scheme",
623
+ "secret"
624
+ ],
625
+ "type": "object"
626
+ }
627
+ ]
628
+ }
629
+ },
630
+ "required": [
631
+ "kind",
632
+ "name",
633
+ "verify"
634
+ ],
635
+ "type": "object"
636
+ }
637
+ ]
638
+ },
639
+ "__schema0": {
640
+ "anyOf": [
641
+ {
642
+ "type": "string"
643
+ },
644
+ {
645
+ "type": "number"
646
+ },
647
+ {
648
+ "type": "boolean"
649
+ },
650
+ {
651
+ "type": "null"
652
+ },
653
+ {
654
+ "items": {
655
+ "$ref": "#/$defs/__schema0"
656
+ },
657
+ "type": "array"
658
+ },
659
+ {
660
+ "additionalProperties": {
661
+ "$ref": "#/$defs/__schema0"
662
+ },
663
+ "propertyNames": {
664
+ "type": "string"
665
+ },
666
+ "type": "object"
667
+ }
668
+ ]
669
+ }
670
+ },
671
+ "$id": "https://olve.dev/schemas/pipelines/manifest-2.0.json",
672
+ "$ref": "#/$defs/Manifest",
673
+ "$schema": "https://json-schema.org/draft/2020-12/schema"
674
+ }