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