1package buildkite
2
3import (
4 "strings"
5 "list"
6 "struct"
7 "regexp"
8)
9
10// JSON schema for Buildkite pipeline configuration files
11#Pipeline: {
12 @jsonschema(schema="http://json-schema.org/draft-07/schema#")
13 env?: #env
14 agents?: #agents
15 notify?: #buildNotify
16 image?: #image
17 secrets?: #secrets
18 priority?: #priority
19
20 // Configure git checkout behavior. Pipeline-level values are inherited by each
21 // step unless that step overrides the same key. ssh_secret is step-level only
22 // and is not valid here
23 checkout?: #checkout & {
24 ssh_secret?: error("disallowed")
25 ...
26 }
27 steps!: #pipelineSteps
28
29 #agents: matchN(1, [#agentsObject, #agentsList])
30
31 // Query rules to target specific agents in k=v format
32 #agentsList: [...string]
33
34 // Query rules to target specific agents
35 #agentsObject: {...}
36
37 // Whether to proceed with this step and further steps if a step named in the
38 // depends_on attribute fails
39 #allowDependencyFailure: true | false | "true" | "false"
40
41 // A list of teams that are permitted to unblock this step, whose values are a
42 // list of one or more team slugs or IDs
43 #allowedTeams: matchN(>=1, [string, [...string]])
44
45 #automaticRetry: close({
46 // The exit status number that will cause this job to retry
47 exit_status?: matchN(>=1, ["*", int, [...int]])
48
49 // The number of times this job can be retried
50 limit?: int & >=0 & <=10
51
52 // The exit signal, if any, that may be retried
53 signal?: string
54
55 // The exit signal reason, if any, that may be retried
56 signal_reason?: "*" |
57 "none" |
58 "agent_incompatible" |
59 "agent_refused" |
60 "agent_stop" |
61 "cancel" |
62 "process_run_error" |
63 "signature_rejected" |
64 "stack_error"
65 })
66
67 #automaticRetryList: [...#automaticRetry]
68
69 #blockStep: close({
70 allow_dependency_failure?: #allowDependencyFailure
71
72 // The label of the block step
73 block?: _#defs."/definitions/blockStep/properties/block"
74
75 // The state that the build is set to when the build is blocked by this block step
76 blocked_state?: "passed" | "failed" | "running"
77 branches?: #branches
78 depends_on?: #dependsOn
79 fields?: #fields
80 if?: #if
81 key?: _#defs."/definitions/blockStep/properties/key"
82 identifier?: _#defs."/definitions/blockStep/properties/key"
83 id?: _#defs."/definitions/blockStep/properties/key"
84 label?: _#defs."/definitions/blockStep/properties/block"
85 name?: _#defs."/definitions/blockStep/properties/block"
86 prompt?: #prompt
87 allowed_teams?: #allowedTeams
88 type?: "block"
89 })
90
91 // Which branches will include this step in their builds
92 #branches: matchN(>=1, [string, [...string]])
93
94 // Array of notification options for this step
95 #buildNotify: [
96 ...matchN(1, [
97 #notifySimple,
98 #notifyEmail,
99 #notifyBasecamp,
100 #notifySlack,
101 #notifyWebhook,
102 #notifyPagerduty,
103 #notifyGithubCommitStatus,
104 #notifyGithubCheck,
105 ])
106 ]
107
108 // The paths for the caches to be used in the step
109 #cache: matchN(>=1, [
110 string,
111 [...string], {
112 paths!: [...string]
113 size?: =~"^\\d+g$"
114 name?: string
115 ...
116 }
117 ])
118
119 // Whether to cancel the job as soon as the build is marked as failing
120 #cancelOnBuildFailing: true | false | "true" | "false"
121
122 // Configure git checkout behavior. Pipeline-level values are inherited by each
123 // step unless that step overrides the same key
124 #checkout: close({
125 // Number of commits to fetch when performing a shallow clone; omit for full history
126 depth?: int & >=1 | =~"^[1-9][0-9]*$"
127
128 // Skip the git checkout phase. An explicit null is treated as unset
129 skip?: true | false | "true" | "false" | null
130
131 // Initialize, sync, update, and clean submodules recursively as part of
132 // checkout. An explicit null is treated as unset
133 submodules?: true | false | "true" | "false" | null
134
135 // Verify the checked-out commit is on the expected branch; strict fails the job
136 // on a definitive mismatch, warn only logs
137 commit_verification?: "strict" | "warn"
138
139 // Custom flags passed to git commands during checkout. Flag strings are passed
140 // to git verbatim and are not sanitized; do not interpolate untrusted input.
141 // See the agent documentation for precedence and defaults:
142 // https://buildkite.com/docs/agent/v3/configuration
143 flags?: close({
144 // Flags for the git clone command
145 clone?: string
146
147 // Flags for the git fetch command
148 fetch?: string
149
150 // Flags for the git checkout command
151 checkout?: string
152
153 // Flags for the git clean command
154 clean?: string
155 })
156
157 // Name of an SSH private key secret from Buildkite Secrets to use for git
158 // clone/fetch operations. The name must start with a letter, contain only
159 // letters, numbers, and underscores, and must not start with `buildkite` or
160 // `bk` (case-insensitive).
161 ssh_secret?: matchN(0, [
162 null | bool | number | =~"^([Bb][Uu][Ii][Ll][Dd][Kk][Ii][Tt][Ee]|[Bb][Kk])" | [...] | {...}
163 ]) &
164 strings.MinRunes(1) &
165 strings.MaxRunes(255) &
166 =~"^[A-Za-z][A-Za-z0-9_]*$"
167
168 // Whether to install Git LFS and fetch LFS objects after checkout. An explicit
169 // null is treated as unset
170 lfs?: true | false | "true" | "false" | null
171
172 // Check out only the specified paths in git cone mode; requires git 2.27+ on the agent
173 sparse?: close({
174 // Repository-relative directory paths within the worktree, as one path or a
175 // list of paths; cone mode includes each directory recursively, not file globs
176 paths!: matchN(>=1, [#checkoutSparsePath, list.MinItems(1) & list.UniqueItems() & [...#checkoutSparsePath]])
177 })
178 })
179
180 #checkoutSparsePath: matchN(0, [
181 null |
182 bool |
183 number |
184 =~"^[-\\t\\n\\v\\f\\r \u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]|[\\t\\n\\v\\f\\r \u0085\u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000]$" |
185 [...] |
186 {...}
187 ]) &
188 =~"^[^,\\t\\n\\v\\f\\r]+$"
189
190 #commandStep: close({
191 agents?: #agents
192 allow_dependency_failure?: #allowDependencyFailure
193
194 // The glob path/s of artifacts to upload once this step has finished running
195 artifact_paths?: matchN(>=1, [string, [...string]])
196 branches?: #branches
197 cache?: #cache
198 cancel_on_build_failing?: #cancelOnBuildFailing
199 checkout?: #checkout
200 command?: #commandStepCommand
201 commands?: #commandStepCommand
202
203 // The maximum number of jobs created from this step that are allowed to run at
204 // the same time. If you use this attribute, you must also define
205 // concurrency_group.
206 concurrency?: int
207
208 // A unique name for the concurrency group that you are creating with the concurrency attribute
209 concurrency_group?: string
210
211 // Control command order, allowed values are 'ordered' (default) and 'eager'. If
212 // you use this attribute, you must also define concurrency_group and
213 // concurrency.
214 concurrency_method?: "ordered" | "eager"
215 depends_on?: #dependsOn
216 env?: #env
217 if?: #if
218 if_changed?: #ifChanged
219 key?: _#defs."/definitions/commandStep/properties/key"
220 identifier?: _#defs."/definitions/commandStep/properties/key"
221 id?: _#defs."/definitions/commandStep/properties/key"
222 image?: #image
223 label?: _#defs."/definitions/commandStep/properties/label"
224
225 // The signature of the command step, generally injected by agents at pipeline upload
226 signature?: {
227 // The algorithm used to generate the signature
228 algorithm?: string
229
230 // The signature value, a JWS compact signature with a detached body
231 value?: string
232
233 // The fields that were signed to form the signature value
234 signed_fields?: [...string]
235 ...
236 }
237 matrix?: #matrix
238 name?: _#defs."/definitions/commandStep/properties/label"
239 notify?: #commandStepNotify
240
241 // The number of parallel jobs that will be created based on this step
242 parallelism?: int
243 plugins?: #plugins
244 soft_fail?: #softFail
245
246 // The conditions for retrying this step.
247 retry?: close({
248 automatic?: #commandStepAutomaticRetry
249 manual?: #commandStepManualRetry
250 })
251 skip?: #skip
252
253 // The number of minutes to time out a job
254 timeout_in_minutes?: int & >=1
255 type?: "script" | "command" | "commands"
256 priority?: #priority
257 secrets?: #secrets
258 })
259
260 // Whether to allow a job to retry automatically. If set to true, the retry
261 // conditions are set to the default value.
262 #commandStepAutomaticRetry: matchN(>=1, [true | false | "true" | "false", #automaticRetry, #automaticRetryList])
263
264 // The commands to run on the agent
265 #commandStepCommand: matchN(>=1, [[...string], string])
266
267 // Whether to allow a job to be retried manually
268 #commandStepManualRetry: matchN(>=1, [true | false | "true" | "false", #commandStepManualRetryObject])
269
270 #commandStepManualRetryObject: close({
271 // Whether or not this job can be retried manually
272 allowed?: true | false | "true" | "false"
273
274 // Whether or not this job can be retried after it has passed
275 permit_on_passed?: true | false | "true" | "false"
276
277 // A string that will be displayed in a tooltip on the Retry button in
278 // Buildkite. This will only be displayed if the allowed attribute is set to
279 // false.
280 reason?: string
281 })
282
283 // Array of notification options for this step
284 #commandStepNotify: [
285 ...matchN(1, [#notifySimple, #notifyBasecamp, #notifySlack, #notifyGithubCommitStatus, #notifyGithubCheck])
286 ]
287
288 // The step keys for a step to depend on
289 #dependsOn: matchN(>=1, [null, string, #dependsOnList])
290
291 #dependsOnList: [...matchN(>=1, [
292 string,
293 close({
294 step?: string
295 allow_failure?: true | false | "true" | "false"
296 })
297 ])]
298
299 // Environment variables for this step
300 #env: {...}
301
302 // A list of input fields required to be filled out before unblocking the step
303 #fields: [...matchN(1, [#textField, #selectField])]
304
305 #groupStep: close({
306 depends_on?: #dependsOn
307
308 // The name to give to this group of steps
309 group!: _#defs."/definitions/groupStep/properties/group"
310 if?: #if
311 if_changed?: #ifChanged
312 key?: _#defs."/definitions/groupStep/properties/key"
313 identifier?: _#defs."/definitions/groupStep/properties/key"
314 id?: _#defs."/definitions/groupStep/properties/key"
315 label?: _#defs."/definitions/groupStep/properties/group"
316 name?: _#defs."/definitions/groupStep/properties/group"
317 allow_dependency_failure?: #allowDependencyFailure
318 notify?: #buildNotify
319 skip?: #skip
320 steps!: #groupSteps
321 })
322
323 // A list of steps
324 #groupSteps: list.MinItems(1) & [
325 ...matchN(>=1, [
326 #blockStep,
327 #nestedBlockStep,
328 #stringBlockStep,
329 #inputStep,
330 #nestedInputStep,
331 #stringInputStep,
332 #commandStep,
333 #nestedCommandStep,
334 #waitStep,
335 #nestedWaitStep,
336 #stringWaitStep,
337 #triggerStep,
338 #nestedTriggerStep,
339 ])
340 ]
341
342 // A boolean expression that omits the step when false
343 #if: string
344
345 // Agent-applied attribute: A glob pattern that omits the step from a build if
346 // it does not match any files changed in the build. Can be a single pattern,
347 // list of patterns, or an object with include/exclude attributes.
348 #ifChanged: matchN(1, [
349 string,
350 [...string], close({
351 // Pattern or list of patterns to include
352 include!: matchN(1, [string, [...string]])
353
354 // Pattern or list of patterns to exclude
355 exclude?: matchN(1, [string, [...string]])
356 })
357 ])
358
359 // (Kubernetes stack only) The container image to use for this pipeline or step
360 #image: string
361
362 #inputStep: close({
363 allow_dependency_failure?: #allowDependencyFailure
364
365 // The label of the input step
366 input?: _#defs."/definitions/inputStep/properties/input"
367 branches?: #branches
368 depends_on?: #dependsOn
369 fields?: #fields
370
371 // The state that the build is set to when the build is blocked by this input step
372 blocked_state?: "passed" | "failed" | "running"
373 if?: #if
374 key?: _#defs."/definitions/inputStep/properties/key"
375 identifier?: _#defs."/definitions/inputStep/properties/key"
376 id?: _#defs."/definitions/inputStep/properties/key"
377 label?: _#defs."/definitions/inputStep/properties/input"
378 name?: _#defs."/definitions/inputStep/properties/input"
379 prompt?: #prompt
380 allowed_teams?: #allowedTeams
381 type?: "input"
382 })
383
384 // A unique identifier for a step, must not resemble a UUID
385 #key: matchN(0, [
386 null |
387 bool |
388 number |
389 =~"^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" |
390 [...] |
391 {...}
392 ]) &
393 strings.MaxRunes(100) &
394 =~"^[a-zA-Z0-9_\\-:${}.,]+$"
395
396 // The label that will be displayed in the pipeline visualisation in Buildkite. Supports emoji.
397 #label: string
398
399 #matrix: matchN(1, [#matrixElementList, #matrixObject])
400
401 // An adjustment to a Build Matrix
402 #matrixAdjustments: {
403 with!: matchN(1, [#matrixElementList, #matrixAdjustmentsWithObject])
404 skip?: #skip
405 soft_fail?: #softFail
406 ...
407 }
408
409 // Specification of a new or existing Build Matrix combination
410 #matrixAdjustmentsWithObject: {...} & {[string]: string}
411
412 #matrixElement: matchN(1, [string, int, bool])
413
414 // List of elements for single-dimension Build Matrix
415 #matrixElementList: [...#matrixElement]
416
417 // Configuration for multi-dimension Build Matrix
418 #matrixObject: {
419 setup!: #matrixSetup
420
421 // List of Build Matrix adjustments
422 adjustments?: [...#matrixAdjustments]
423 ...
424 }
425
426 #matrixSetup: matchN(1, [#matrixElementList, {[=~"^[a-zA-Z0-9_]+$"]: _} & {[string]: [...#matrixElement]}])
427
428 #nestedBlockStep: close({block?: #blockStep})
429
430 #nestedCommandStep: close({
431 command?: #commandStep
432 commands?: #commandStep
433 script?: #commandStep
434 })
435
436 #nestedInputStep: close({input?: #inputStep})
437
438 #nestedTriggerStep: close({trigger?: #triggerStep})
439
440 #nestedWaitStep: close({
441 wait?: #waitStep
442 waiter?: #waitStep
443 })
444
445 #notifyBasecamp: close({
446 basecamp_campfire?: string
447 if?: #if
448 })
449
450 #notifyEmail: close({
451 email?: string
452 if?: #if
453 })
454
455 #notifyGithubCheck: close({
456 github_check?: close({
457 // The name of the GitHub check
458 name?: string
459 output?: close({
460 // The title of the GitHub check's output
461 title?: string
462
463 // The summary of the GitHub check's output
464 summary?: string
465
466 // The details of the GitHub check's output. Supports Markdown
467 text?: string
468 annotations?: [...close({
469 // The path of the file to add an annotation to, relative to the repository root
470 path!: string
471
472 // The start line of the annotation
473 start_line!: int
474
475 // The end line of the annotation
476 end_line!: int
477
478 // The start column of the annotation. Only valid when start_line and end_line are equal
479 start_column?: int
480
481 // The end column of the annotation. Only valid when start_line and end_line are equal
482 end_column?: int
483
484 // The level of the annotation
485 annotation_level!: "notice" | "warning" | "failure"
486
487 // The message for the annotation
488 message!: string
489
490 // The title for the annotation
491 title?: string
492
493 // Additional details for the annotation, displayed alongside the message
494 raw_details?: string
495 })]
496 })
497 })
498 if?: #if
499 })
500
501 #notifyGithubCommitStatus: close({
502 github_commit_status?: close({
503 // GitHub commit status name
504 context?: string
505 })
506 if?: #if
507 })
508
509 #notifyPagerduty: close({
510 pagerduty_change_event?: string
511 if?: #if
512 })
513
514 #notifySimple: "github_check" | "github_commit_status"
515
516 #notifySlack: close({
517 slack?: matchN(1, [=~"^[^ \\t\\n\\v\\f\\r]+$", #notifySlackObject])
518 if?: #if
519 })
520
521 #notifySlackObject: {
522 channels!: list.MinItems(1) & [...=~"^[^ \\t\\n\\v\\f\\r]+$"]
523 message?: string
524 ...
525 }
526
527 #notifyWebhook: close({
528 webhook?: string
529 if?: #if
530 })
531
532 // A list of steps
533 #pipelineSteps: [
534 ...matchN(>=1, [
535 #blockStep,
536 #nestedBlockStep,
537 #stringBlockStep,
538 #inputStep,
539 #nestedInputStep,
540 #stringInputStep,
541 #commandStep,
542 #nestedCommandStep,
543 #waitStep,
544 #nestedWaitStep,
545 #stringWaitStep,
546 #triggerStep,
547 #nestedTriggerStep,
548 #groupStep,
549 ])
550 ]
551
552 #plugins: matchN(>=1, [#pluginsList, #pluginsObject])
553
554 // Array of plugins for this step
555 #pluginsList: [...matchN(1, [string, struct.MaxFields(1)])]
556
557 // A map of plugins for this step. Deprecated: please use the array syntax.
558 #pluginsObject: {...}
559
560 // Priority of all jobs in the pipeline, higher priorities are assigned to
561 // agents. When set pipeline-wide, it applies to all steps that do not have
562 // their own priority key set.
563 #priority: int
564
565 // The instructional message displayed in the dialog box when the unblock step is activated
566 #prompt: string
567
568 // A list of secret names or a mapping of environment variable names to secret
569 // names to be made available to the build or step
570 #secrets: matchN(>=1, [[...string], {[string]: string}])
571
572 #selectField: close({
573 // The text input name
574 select?: string
575
576 // The meta-data key that stores the field's input
577 key!: =~"^[a-zA-Z0-9-_]+$"
578
579 // The value of the option(s) that will be pre-selected in the dropdown
580 default?: matchN(1, [string, [...string]])
581
582 // The explanatory text that is shown after the label
583 hint?: string
584
585 // Whether more than one option may be selected
586 multiple?: true | false | "true" | "false"
587 options!: list.MinItems(1) & [...#selectFieldOption]
588
589 // Whether the field is required for form submission
590 required?: true | false | "true" | "false"
591 })
592
593 #selectFieldOption: close({
594 // The text displayed on the select list item
595 label!: string
596
597 // The value to be stored as meta-data
598 value!: string
599
600 // The text displayed directly under the select field’s label
601 hint?: string
602
603 // Whether the field is required for form submission
604 required?: true | false | "true" | "false"
605 })
606
607 // Whether this step should be skipped. Passing a string provides a reason for skipping this command
608 #skip: matchN(>=1, [bool, strings.MaxRunes(70)])
609
610 // The conditions for marking the step as a soft-fail.
611 #softFail: matchN(>=1, [true | false | "true" | "false", #softFailList])
612
613 #softFailList: [...#softFailObject]
614
615 #softFailObject: {
616 // The exit status number that will cause this job to soft-fail
617 exit_status?: matchN(>=1, ["*", int])
618 ...
619 }
620
621 // Pauses the execution of a build and waits on a user to unblock it
622 #stringBlockStep: "block"
623
624 // Pauses the execution of a build and waits on a user to unblock it
625 #stringInputStep: "input"
626
627 // Waits for previous steps to pass before continuing
628 #stringWaitStep: "wait" | "waiter"
629
630 #textField: close({
631 // The text input name
632 text?: string
633
634 // The meta-data key that stores the field's input
635 key!: =~"^[a-zA-Z0-9-_]+$"
636
637 // The explanatory text that is shown after the label
638 hint?: string
639
640 // The format must be a regular expression implicitly anchored to the beginning
641 // and end of the input and is functionally equivalent to the HTML5 pattern
642 // attribute.
643 format?: regexp.Valid
644
645 // Whether the field is required for form submission
646 required?: true | false | "true" | "false"
647
648 // The value that is pre-filled in the text field
649 default?: string
650 })
651
652 #triggerStep: close({
653 allow_dependency_failure?: #allowDependencyFailure
654
655 // Whether to continue the build without waiting for the triggered step to complete
656 async?: true | false | "true" | "false"
657 branches?: #branches
658
659 // Properties of the build that will be created when the step is triggered
660 build?: close({
661 // The branch for the build
662 branch?: string
663
664 // The commit hash for the build
665 commit?: string
666 env?: #env
667
668 // The message for the build (supports emoji)
669 message?: string
670
671 // Meta-data for the build
672 meta_data?: {...}
673 })
674 depends_on?: #dependsOn
675 if?: #if
676 if_changed?: #ifChanged
677 key?: _#defs."/definitions/triggerStep/properties/key"
678 identifier?: _#defs."/definitions/triggerStep/properties/key"
679 id?: _#defs."/definitions/triggerStep/properties/key"
680 label?: _#defs."/definitions/triggerStep/properties/label"
681 name?: _#defs."/definitions/triggerStep/properties/label"
682 type?: "trigger"
683
684 // The slug of the pipeline to create a build
685 trigger!: string
686 skip?: #skip
687 soft_fail?: #softFail
688 })
689
690 #waitStep: close({
691 allow_dependency_failure?: #allowDependencyFailure
692 branches?: #branches
693
694 // Continue to the next steps, even if the previous group of steps fail
695 continue_on_failure?: true | false | "true" | "false"
696 depends_on?: #dependsOn
697 if?: #if
698 key?: _#defs."/definitions/waitStep/properties/key"
699 label?: _#defs."/definitions/waitStep/properties/wait"
700 name?: _#defs."/definitions/waitStep/properties/wait"
701 identifier?: _#defs."/definitions/waitStep/properties/key"
702 id?: _#defs."/definitions/waitStep/properties/key"
703 type?: "wait" | "waiter"
704
705 // Waits for previous steps to pass before continuing
706 wait?: _#defs."/definitions/waitStep/properties/wait"
707 })
708
709 // The label of the block step
710 _#defs: "/definitions/blockStep/properties/block": string
711
712 _#defs: "/definitions/blockStep/properties/key": #key
713
714 _#defs: "/definitions/commandStep/properties/key": #key
715
716 _#defs: "/definitions/commandStep/properties/label": #label
717
718 // The name to give to this group of steps
719 _#defs: "/definitions/groupStep/properties/group": null | string
720
721 _#defs: "/definitions/groupStep/properties/key": #key
722
723 // The label of the input step
724 _#defs: "/definitions/inputStep/properties/input": string
725
726 _#defs: "/definitions/inputStep/properties/key": #key
727
728 _#defs: "/definitions/triggerStep/properties/key": #key
729
730 _#defs: "/definitions/triggerStep/properties/label": #label
731
732 _#defs: "/definitions/waitStep/properties/key": #key
733
734 // Waits for previous steps to pass before continuing
735 _#defs: "/definitions/waitStep/properties/wait": null | string
736 ...
737}