1package gitlabci
2
3import (
4 "net"
5 "list"
6 "strings"
7 "struct"
8 "time"
9 "regexp"
10)
11
12#Pipeline: {
13 @jsonschema(schema="http://json-schema.org/draft-07/schema#")
14 @jsonschema(id="https://gitlab.com/.gitlab-ci.yml")
15 "$schema"?: net.AbsURL
16 "spec"?: close({"inputs"?: #configInputs})
17 "image"?: #image
18 "services"?: #services
19 "before_script"?: #before_script
20 "after_script"?: #after_script
21 "variables"?: #globalVariables
22 "cache"?: #cache
23 "!reference"?: #."!reference"
24 "default"?: close({
25 "after_script"?: #after_script
26 "artifacts"?: #artifacts
27 "before_script"?: #before_script
28 "hooks"?: #hooks
29 "cache"?: #cache
30 "image"?: #image
31 "interruptible"?: #interruptible
32 "id_tokens"?: #id_tokens
33 "identity"?: #identity
34 "retry"?: #retry
35 "services"?: #services
36 "tags"?: #tags
37 "timeout"?: #timeout
38 "!reference"?: #."!reference"
39 })
40 "stages"?: list.UniqueItems() & list.MinItems(1) & [...matchN(>=1, [string, [...string]])]
41 "include"?: matchN(1, [#include_item, [...#include_item]])
42 "pages"?: #job
43 "workflow"?: {
44 "name"?: #workflowName
45 "auto_cancel"?: #workflowAutoCancel
46 "rules"?: [...matchN(>=1, [{...}, list.MinItems(1) & [...string]]) &
47 ([...] | close({
48 "if"?: #if
49 "changes"?: #changes
50 "exists"?: #exists
51 "variables"?: #rulesVariables
52 "when"?: "always" | "never"
53 "auto_cancel"?: #workflowAutoCancel
54 }))]
55 ...
56 }
57
58 {[=~"^[.]"]: matchN(>=1, [#job_template, _])}
59 {[!~"^[.]" &
60 !~"^(\\$schema|spec|image|services|before_script|after_script|variables|cache|!reference|default|stages|include|pages|workflow)$"]: #job}
61
62 #: "!reference": [...strings.MinRunes(1)]
63
64 #after_script: #optional_script
65
66 #allow_failure: matchN(1, [
67 bool,
68 close({"exit_codes"!: int}), close({"exit_codes"!: list.MinItems(1) & list.UniqueItems() & [...int]}),
69 ])
70
71 #artifacts: null | close({
72 "paths"?: list.MinItems(1) & [...string]
73 "exclude"?: list.MinItems(1) & [...string]
74 "expose_as"?: string
75 "name"?: string
76 "untracked"?: bool
77 "when"?: "on_success" | "on_failure" | "always"
78 "access"?: "none" | "developer" | "maintainer" | "all"
79 "expire_in"?: string
80 "reports"?: close({
81 // Path to JSON file with accessibility report.
82 "accessibility"?: string
83
84 // Path to JSON file with annotations report.
85 "annotations"?: string
86
87 // Path for file(s) that should be parsed as JUnit XML result
88 "junit"?: matchN(1, [string, list.MinItems(1) & [...string]])
89
90 // Path to a single file with browser performance metric report(s).
91 "browser_performance"?: string
92
93 // Used to collect coverage reports from the job.
94 "coverage_report"?: null | {
95 // Code coverage format used by the test framework.
96 "coverage_format"?: "cobertura" | "jacoco"
97
98 // Path to the coverage report file that should be parsed.
99 "path"?: strings.MinRunes(1)
100 ...
101 }
102 "codequality"?: #string_file_list
103 "dotenv"?: #string_file_list
104 "lsif"?: #string_file_list
105 "sast"?: #string_file_list
106 "dependency_scanning"?: #string_file_list
107 "container_scanning"?: #string_file_list
108 "dast"?: #string_file_list
109 "license_management"?: #string_file_list
110 "license_scanning"?: #string_file_list
111 "requirements"?: #string_file_list
112 "secret_detection"?: #string_file_list
113 "metrics"?: #string_file_list
114 "terraform"?: #string_file_list
115 "cyclonedx"?: #string_file_list
116 "sarif"?: #string_file_list
117 "load_performance"?: #string_file_list
118 "repository_xray"?: #string_file_list
119 })
120 })
121
122 #baseInput: {
123 "type"?: "array" | "boolean" | "number" | "string"
124 "description"?: strings.MaxRunes(1024)
125 "options"?: [...bool | number | string]
126 "regex"?: string
127 "default"?: _
128 ...
129 }
130
131 #before_script: #optional_script
132
133 #cache: matchN(1, [#cache_item, [...#cache_item]])
134
135 #cache_item: {
136 "key"?: matchN(1, [
137 =~"^[^/]*[^./][^/]*$",
138 {
139 "files"?: list.MinItems(1) & list.MaxItems(2) & [...string]
140 "files_commits"?: list.MinItems(1) & list.MaxItems(2) & [...string]
141 "prefix"?: string
142 ...
143 }
144 ])
145 "paths"?: [...string]
146 "policy"?: =~"pull-push|pull|push|\\$\\w{1,255}"
147 "unprotect"?: bool
148 "untracked"?: bool
149 "when"?: "on_success" | "on_failure" | "always"
150 "fallback_keys"?: list.MaxItems(5) & [...string]
151 ...
152 }
153
154 #changes: matchN(>=1, [
155 matchN(1, [{
156 "paths"!: _
157 ...
158 }, {
159 "regexp"!: _
160 ...
161 }]) & close({
162 // List of file paths.
163 "paths"?: [...string]
164
165 // Ref for comparing changes.
166 "compare_to"?: string
167
168 // Regular expression to match against changed file paths.
169 "regexp"?: strings.MaxRunes(255)
170 }),
171 [...string]
172 ])
173
174 #configInputs: {
175 {
176 [=~".*"]: matchN(1, [
177 matchN(3, [
178 #baseInput,
179 null | bool | number | string | [...] | {
180 "rules"?: [...{...}]
181 ...
182 },
183 matchN(5, [matchIf(
184 null | bool | number | string | [...] | {
185 "type"!: "string"
186 ...
187 },
188 null | bool | number | string | [...] | {
189 "default"?: null | string
190 ...
191 },
192 _
193 ), matchIf(
194 null | bool | number | string | [...] | {
195 "type"!: "number"
196 ...
197 },
198 null | bool | number | string | [...] | {
199 "default"?: null | number
200 ...
201 },
202 _
203 ), matchIf(
204 null | bool | number | string | [...] | {
205 "type"!: "boolean"
206 ...
207 },
208 null | bool | number | string | [...] | {
209 "default"?: null | bool
210 ...
211 },
212 _
213 ), matchIf(
214 null | bool | number | string | [...] | {
215 "type"!: "array"
216 ...
217 },
218 null | bool | number | string | [...] | {
219 "default"?: null | [...]
220 ...
221 },
222 _
223 ), matchIf(
224 matchN(0, [null | bool | number | string | [...] | {
225 "type"!: _
226 ...
227 }]),
228 null | bool | number | string | [...] | {
229 "default"?: null | string
230 ...
231 },
232 _
233 )])
234 ]),
235 null
236 ])
237 }
238 ...
239 }
240
241 #exists: matchN(>=1, [
242 [...string],
243 matchN(1, [{
244 "paths"!: _
245 ...
246 }, {
247 "regexp"!: _
248 ...
249 }]) & close({
250 // List of file paths.
251 "paths"?: [...string]
252
253 // Path of the project to search in.
254 "project"?: string
255
256 // Regular expression to match against file paths in the repository.
257 "regexp"?: strings.MaxRunes(255)
258 }),
259 matchN(1, [{
260 "paths"!: _
261 ...
262 }, {
263 "regexp"!: _
264 ...
265 }]) & close({
266 // List of file paths.
267 "paths"?: [...string]
268
269 // Path of the project to search in.
270 "project"!: string
271
272 // Ref of the project to search in.
273 "ref"?: string
274
275 // Regular expression to match against file paths in the repository.
276 "regexp"?: strings.MaxRunes(255)
277 })
278 ])
279
280 #filter: matchN(1, [
281 null,
282 #filter_refs,
283 close({
284 "refs"?: #filter_refs
285
286 // Filter job based on if Kubernetes integration is active.
287 "kubernetes"?: "active"
288 "variables"?: [...string]
289
290 // Filter job creation based on files that were modified in a git push.
291 "changes"?: [...string]
292 })
293 ])
294
295 // Filter job by different keywords that determine origin or state, or by
296 // supplying string/regex to check against branch/tag names.
297 #filter_refs: [
298 ...matchN(>=1, [
299 matchN(1, ["branches", "tags", "api", "external", "pipelines", "pushes", "schedules", "triggers", "web"]),
300 string
301 ])
302 ]
303
304 #globalVariables: {
305 {
306 [=~".*"]: matchN(1, [
307 bool | number | string,
308 close({
309 "value"?: string
310 "options"?: list.MinItems(1) & list.UniqueItems() & [...string]
311 "description"?: string
312 "expand"?: bool
313 })
314 ])
315 }
316 ...
317 }
318
319 #hooks: close({"pre_get_sources_script"?: #optional_script})
320
321 #id_tokens: {
322 {[=~".*"]: close({"aud"!: matchN(1, [string, list.MinItems(1) & list.UniqueItems() & [...string]])})}
323 ...
324 }
325
326 #identity: "google_cloud"
327
328 #if: string
329
330 #image: matchN(1, [strings.MinRunes(
331 1,
332 ), close({
333 // Full name of the image that should be used. It should contain the Registry part if needed.
334 "name"!: strings.MinRunes(1)
335
336 // Command or script that should be executed as the container's entrypoint. It
337 // will be translated to Docker's --entrypoint option while creating the
338 // container. The syntax is similar to Dockerfile's ENTRYPOINT directive, where
339 // each shell token is a separate string in the array.
340 "entrypoint"?: list.MinItems(1)
341 "docker"?: close({
342 // Image architecture to pull.
343 "platform"?: strings.MinRunes(1)
344
345 // Username or UID to use for the container.
346 "user"?: strings.MinRunes(1) & strings.MaxRunes(255)
347 })
348 "kubernetes"?: close({
349 // Username or UID to use for the container. It also supports the UID:GID format.
350 "user"?: int | strings.MinRunes(1) & strings.MaxRunes(255)
351 })
352 "pull_policy"?: matchN(1, [
353 "always" | "never" | "if-not-present",
354 list.MinItems(1) & list.UniqueItems() & [..."always" | "never" | "if-not-present"],
355 ])
356 })])
357
358 #includeRules: null | [...matchN(>=1, [
359 close({
360 "if"?: #if
361 "changes"?: #changes
362 "exists"?: #exists
363 "when"?: matchN(1, ["never" | "always", null])
364 }), strings.MinRunes(1),
365 list.MinItems(1) & [...string]
366 ])]
367
368 #include_item: matchN(1, [
369 matchN(>=1, [=~"^https?://", matchN(0, [null | bool | number | =~"^\\w+://" | [...] | {...}]) & string]) &
370 net.URL &
371 =~"\\w\\.ya?ml$",
372 close({
373 // Relative path from local repository root (`/`) to the `yaml`/`yml` file
374 // template. The file must be on the same branch, and does not work across git
375 // submodules.
376 "local"!: net.URL & =~"\\.ya?ml$"
377 "rules"?: #includeRules
378 "inputs"?: #inputs
379 }), close({
380 // Path to the project, e.g. `group/project`, or `group/sub-group/project`
381 // [Learn more](https://docs.gitlab.com/ci/yaml/#includeproject).
382 "project"!: =~"(?:\\S/\\S|\\$\\S+)"
383
384 // Branch/Tag/Commit-hash for the target project.
385 "ref"?: string
386 "file"!: matchN(1, [=~"\\.ya?ml$", [...=~"\\.ya?ml$"]])
387 "rules"?: #includeRules
388 "inputs"?: #inputs
389 }), close({
390 // Use a `.gitlab-ci.yml` template as a base, e.g. `Nodejs.gitlab-ci.yml`.
391 "template"!: net.URL & =~"\\.ya?ml$"
392 "rules"?: #includeRules
393 "inputs"?: #inputs
394 }), close({
395 // Local path to component directory or full path to external component directory.
396 "component"!: net.URL
397 "rules"?: #includeRules
398 "inputs"?: #inputs
399 }), close({
400 // URL to a `yaml`/`yml` template file using HTTP/HTTPS.
401 "remote"!: net.URL & =~"^https?://.+\\.ya?ml$"
402
403 // SHA256 integrity hash of the remote file content.
404 "integrity"?: =~"^sha256-[A-Za-z0-9+/]{43}=$"
405 "rules"?: #includeRules
406 "inputs"?: #inputs
407 })
408 ])
409
410 #inputs: close({
411
412 {[=~"^[a-zA-Z0-9_-]+$"]: matchN(1, [
413 strings.MaxRunes(1024),
414 number,
415 bool,
416 [...matchN(1, [string, number, bool, {...}, [...null | bool | number | string | [...] | {...}]])], {...},
417 null
418 ])}})
419
420 #interruptible: bool
421
422 #job: #job_template
423
424 #jobInputs: struct.MaxFields(50) & {
425 {
426 [=~".*"]: matchN(3, [
427 #baseInput,
428 null | bool | number | string | [...] | {
429 "default"!: _
430 ...
431 },
432 matchN(5, [matchIf(
433 null | bool | number | string | [...] | {
434 "type"!: "string"
435 ...
436 },
437 null | bool | number | string | [...] | {
438 "default"?: string
439 ...
440 },
441 _
442 ), matchIf(
443 null | bool | number | string | [...] | {
444 "type"!: "number"
445 ...
446 },
447 null | bool | number | string | [...] | {
448 "default"?: number
449 ...
450 },
451 _
452 ), matchIf(
453 null | bool | number | string | [...] | {
454 "type"!: "boolean"
455 ...
456 },
457 null | bool | number | string | [...] | {
458 "default"?: bool
459 ...
460 },
461 _
462 ), matchIf(
463 null | bool | number | string | [...] | {
464 "type"!: "array"
465 ...
466 },
467 null | bool | number | string | [...] | {
468 "default"?: [...]
469 ...
470 },
471 _
472 ), matchIf(
473 matchN(0, [null | bool | number | string | [...] | {
474 "type"!: _
475 ...
476 }]),
477 null | bool | number | string | [...] | {
478 "default"?: string
479 ...
480 },
481 _
482 )])
483 ])
484 }
485 ...
486 }
487
488 #jobVariables: {
489 {
490 [=~".*"]: matchN(1, [
491 bool | number | string,
492 close({
493 "value"?: string
494 "expand"?: bool
495 })
496 ])
497 }
498 ...
499 }
500
501 #job_template: matchN(1, [{
502 "when"!: "delayed"
503 "start_in"!: _
504 ...
505 }, {
506 "when"?: matchN(0, ["delayed"])
507 ...
508 }]) & close({
509 "image"?: #image
510 "services"?: #services
511 "before_script"?: #before_script
512 "after_script"?: #after_script
513 "hooks"?: #hooks
514 "rules"?: #rules
515 "variables"?: #jobVariables
516 "cache"?: #cache
517 "id_tokens"?: #id_tokens
518 "identity"?: #identity
519 "inputs"?: #jobInputs
520 "secrets"?: #secrets
521 "script"?: #script
522 "run"?: #steps
523
524 // Define what stage the job will run in.
525 "stage"?: matchN(>=1, [strings.MinRunes(1), list.MinItems(1) & [...string]])
526 "only"?: #filter
527
528 // The name of one or more jobs to inherit configuration from.
529 "extends"?: matchN(1, [string, list.MinItems(1) & [...string]])
530
531 // The list of jobs in previous stages whose sole completion is needed to start the current job.
532 "needs"?: [...matchN(1, [
533 string,
534 close({
535 "job"!: string
536 "artifacts"?: bool
537 "optional"?: bool
538 "parallel"?: #parallel_matrix
539 }), close({
540 "pipeline"!: string
541 "job"!: string
542 "artifacts"?: bool
543 "parallel"?: #parallel_matrix
544 }), close({
545 "job"!: string
546 "project"!: string
547 "ref"!: string
548 "artifacts"?: bool
549 "parallel"?: #parallel_matrix
550 }),
551 #."!reference"
552 ])]
553 "except"?: #filter
554 "tags"?: #tags
555 "allow_failure"?: #allow_failure
556 "timeout"?: #timeout
557 "when"?: #when
558 "start_in"?: #start_in
559 "manual_confirmation"?: string
560
561 // Specify a list of job names from earlier stages from which artifacts should
562 // be loaded. By default, all previous artifacts are passed. Use an empty array
563 // to skip downloading artifacts.
564 "dependencies"?: [...string]
565 "artifacts"?: #artifacts
566
567 // Used to associate environment metadata with a deploy. Environment can have a
568 // name and URL attached to it, and will be displayed under /environments under
569 // the project.
570 "environment"?: matchN(1, [
571 string,
572 close({
573 // The name of the environment, e.g. 'qa', 'staging', 'production'.
574 "name"!: strings.MinRunes(1)
575
576 // When set, this will expose buttons in various places for the current
577 // environment in GitLab, that will take you to the defined URL.
578 "url"?: net.AbsURL & =~"^(https?://.+|\\$[A-Za-z]+)"
579
580 // The name of a job to execute when the environment is about to be stopped.
581 "on_stop"?: string
582
583 // Specifies what this job will do. 'start' (default) indicates the job will
584 // start the deployment. 'prepare'/'verify'/'access' indicates this will not
585 // affect the deployment. 'stop' indicates this will stop the deployment.
586 "action"?: "start" | "prepare" | "stop" | "verify" | "access"
587
588 // The amount of time it should take before GitLab will automatically stop the
589 // environment. Supports a wide variety of formats, e.g. '1 week', '3 mins 4
590 // sec', '2 hrs 20 min', '2h20min', '6 mos 1 day', '47 yrs 6 mos and 4d', '3
591 // weeks and 2 days'.
592 "auto_stop_in"?: string
593
594 // Used to configure the kubernetes deployment for this environment. This is
595 // currently not supported for kubernetes clusters that are managed by GitLab.
596 "kubernetes"?: {
597 // Specifies the GitLab Agent for Kubernetes. The format is `path/to/agent/project:agent-name`.
598 "agent"?: string
599
600 // Deprecated. Use `dashboard.namespace` instead. The kubernetes namespace where
601 // this environment's dashboard should be deployed to.
602 "namespace"?: strings.MinRunes(1)
603
604 // Deprecated. Use `dashboard.flux_resource_path` instead. The Flux resource
605 // path to associate with this environment. This must be the full resource
606 // path. For example,
607 // 'helm.toolkit.fluxcd.io/v2/namespaces/gitlab-agent/helmreleases/gitlab-agent'.
608 "flux_resource_path"?: string
609
610 // Used to configure the managed resources for this environment.
611 "managed_resources"?: {
612 // Indicates whether the managed resources are enabled for this environment.
613 "enabled"?: bool
614 ...
615 }
616
617 // Used to configure the dashboard for this environment.
618 "dashboard"?: {
619 // The kubernetes namespace where the dashboard for this environment should be deployed to.
620 "namespace"?: strings.MinRunes(1)
621
622 // The Flux resource path to associate with this environment. This must be the
623 // full resource path. For example,
624 // 'helm.toolkit.fluxcd.io/v2/namespaces/gitlab-agent/helmreleases/gitlab-agent'.
625 "flux_resource_path"?: string
626 ...
627 }
628 ...
629 }
630
631 // Explicitly specifies the tier of the deployment environment if non-standard
632 // environment name is used.
633 "deployment_tier"?: string
634 })
635 ])
636
637 // Indicates that the job creates a Release.
638 "release"?: close({
639 // The tag_name must be specified. It can refer to an existing Git tag or can be
640 // specified by the user.
641 "tag_name"!: strings.MinRunes(1)
642
643 // Message to use if creating a new annotated tag.
644 "tag_message"?: string
645
646 // Specifies the longer description of the Release.
647 "description"!: strings.MinRunes(1)
648
649 // The Release name. If omitted, it is populated with the value of release: tag_name.
650 "name"?: string
651
652 // If the release: tag_name doesn’t exist yet, the release is created from ref.
653 // ref can be a commit SHA, another tag name, or a branch name.
654 "ref"?: string
655
656 // The title of each milestone the release is associated with.
657 "milestones"?: [...string]
658
659 // The date and time when the release is ready. Defaults to the current date and
660 // time if not defined. Should be enclosed in quotes and expressed in ISO 8601
661 // format.
662 "released_at"?: time.Time &
663 =~"^(?:[1-9]\\d{3}-(?:(?:0[1-9]|1[0-2])-(?:0[1-9]|1\\d|2[0-8])|(?:0[13-9]|1[0-2])-(?:29|30)|(?:0[13578]|1[02])-31)|(?:[1-9]\\d(?:0[48]|[2468][048]|[13579][26])|(?:[2468][048]|[13579][26])00)-02-29)T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:Z|[+-][01]\\d:[0-5]\\d)$"
664 "assets"?: close({
665 // Include asset links in the release.
666 "links"!: list.MinItems(1) & [...close({
667 // The name of the link.
668 "name"!: strings.MinRunes(1)
669
670 // The URL to download a file.
671 "url"!: strings.MinRunes(1)
672
673 // The redirect link to the url.
674 "filepath"?: string
675
676 // The content kind of what users can download via url.
677 "link_type"?: "runbook" | "package" | "image" | "other"
678 })]
679 })
680 })
681
682 // Must be a regular expression, optionally but recommended to be quoted, and
683 // must be surrounded with '/'. Example: '/Code coverage: \d+\.\d+/'
684 "coverage"?: regexp.Valid & =~"^/.+/$"
685 "retry"?: #retry
686 "parallel"?: #parallel
687 "interruptible"?: #interruptible
688
689 // Limit job concurrency. Can be used to ensure that the Runner will not run
690 // certain jobs simultaneously.
691 "resource_group"?: string
692 "trigger"?: matchN(1, [
693 close({
694 // Path to the project, e.g. `group/project`, or `group/sub-group/project`.
695 "project"!: =~"(?:\\S/\\S|\\$\\S+)"
696
697 // The branch name that a downstream pipeline will use
698 "branch"?: string
699
700 // You can mirror or depend on the pipeline status from the triggered pipeline
701 // to the source bridge job by using strategy: `depend` or `mirror`
702 "strategy"?: "depend" | "mirror"
703 "inputs"?: #inputs
704
705 // Specify what to forward to the downstream pipeline.
706 "forward"?: close({
707 // Variables defined in the trigger job are passed to downstream pipelines.
708 "yaml_variables"?: bool
709
710 // Variables added for manual pipeline runs and scheduled pipelines are passed
711 // to downstream pipelines.
712 "pipeline_variables"?: bool
713 })
714 branch?: _
715 if branch != _|_ {
716 "project"!: _
717 }
718 {}
719 }), close({
720 "include"?: matchN(1, [
721 net.URL & =~"\\.ya?ml$",
722 list.MaxItems(3) & [...matchN(1, [close({
723 // Relative path from local repository root (`/`) to the local YAML file to
724 // define the pipeline configuration.
725 "local"!: net.URL & =~"\\.ya?ml$"
726 "inputs"?: #inputs
727 }), close({
728 // Name of the template YAML file to use in the pipeline configuration.
729 "template"!: net.URL & =~"\\.ya?ml$"
730 "inputs"?: #inputs
731 }), close({
732 // Relative path to the generated YAML file which is extracted from the
733 // artifacts and used as the configuration for triggering the child pipeline.
734 "artifact"!: net.URL & =~"\\.ya?ml$"
735
736 // Job name which generates the artifact
737 "job"!: string
738 "inputs"?: #inputs
739 }), close({
740 // Path to another private project under the same GitLab instance, like
741 // `group/project` or `group/sub-group/project`.
742 "project"!: =~"(?:\\S/\\S|\\$\\S+)"
743
744 // Branch/Tag/Commit hash for the target project.
745 "ref"?: strings.MinRunes(1)
746
747 // Relative path from repository root (`/`) to the pipeline configuration YAML file.
748 "file"!: net.URL & =~"\\.ya?ml$"
749 "inputs"?: #inputs
750 }), close({
751 // Local path to component directory or full path to external component directory.
752 "component"!: net.URL
753 "inputs"?: #inputs
754 }), close({
755 // URL to a `yaml`/`yml` template file using HTTP/HTTPS.
756 "remote"!: net.URL & =~"^https?://.+\\.ya?ml$"
757 "inputs"?: #inputs
758 })])]
759 ])
760
761 // You can mirror or depend on the pipeline status from the triggered pipeline
762 // to the source bridge job by using strategy: `depend` or `mirror`
763 "strategy"?: "depend" | "mirror"
764
765 // Specify what to forward to the downstream pipeline.
766 "forward"?: close({
767 // Variables defined in the trigger job are passed to downstream pipelines.
768 "yaml_variables"?: bool
769
770 // Variables added for manual pipeline runs and scheduled pipelines are passed
771 // to downstream pipelines.
772 "pipeline_variables"?: bool
773 })
774 }),
775 =~"(?:\\S/\\S|\\$\\S+)"
776 ])
777 "inherit"?: close({
778 "default"?: matchN(1, [
779 bool,
780 [
781 ..."after_script" |
782 "artifacts" |
783 "before_script" |
784 "cache" |
785 "image" |
786 "interruptible" |
787 "retry" |
788 "services" |
789 "tags" |
790 "timeout"
791 ],
792 ])
793 "variables"?: matchN(1, [bool, [...string]])
794 })
795
796 // Deprecated. Use `pages.publish` instead. A path to a directory that contains
797 // the files to be published with Pages.
798 "publish"?: string
799 "pages"?: matchN(1, [
800 close({
801 "path_prefix"?: string
802 "expire_in"?: string
803 "publish"?: string
804 }),
805 bool
806 ])
807 })
808
809 #optional_script: matchN(1, [string, [...matchN(>=1, [string, [...string]])]])
810
811 // Splits up a single job into multiple that run in parallel. Provides
812 // `CI_NODE_INDEX` and `CI_NODE_TOTAL` environment variables to the jobs.
813 #parallel: matchN(1, [
814 int & >=1 & <=200,
815 close({
816 // Defines different variables for jobs that are running in parallel.
817 "matrix"!: list.MaxItems(200) & [...{[string]: number | string | [...]}]
818 })
819 ])
820
821 // Use the `needs:parallel:matrix` keyword to specify parallelized jobs needed
822 // to be completed for the job to run. [Learn
823 // More](https://docs.gitlab.com/ci/yaml/#needsparallelmatrix)
824 #parallel_matrix: close({
825 // Defines different variables for jobs that are running in parallel.
826 "matrix"!: list.MaxItems(200) & [...{[string]: number | string | [...]}]
827 })
828
829 #retry: matchN(1, [
830 #retry_max,
831 close({
832 "max"?: #retry_max
833 "when"?: matchN(1, [#retry_errors, [...#retry_errors]])
834 "exit_codes"?: matchN(1, [list.MinItems(1) & list.UniqueItems() & [...int], int])
835 })
836 ])
837
838 #retry_errors: matchN(1, [
839 "always",
840 "unknown_failure",
841 "script_failure",
842 "api_failure",
843 "stuck_or_timeout_failure",
844 "stuck_pending_with_matching_runners",
845 "stuck_pending_no_matching_runners",
846 "no_updates_running",
847 "no_updates_canceling",
848 "runner_system_failure",
849 "runner_configuration_error",
850 "runner_external_dependency_failure",
851 "runner_interrupted",
852 "runner_unsupported",
853 "stale_schedule",
854 "job_execution_timeout",
855 "server_timeout_running",
856 "server_timeout_canceling",
857 "archived_failure",
858 "unmet_prerequisites",
859 "scheduler_failure",
860 "data_integrity_failure",
861 ])
862
863 // The number of times the job will be retried if it fails. Defaults to 0 and
864 // can max be retried 2 times (3 times total).
865 #retry_max: int & >=0 & <=2
866
867 #rules: null | [...matchN(>=1, [
868 close({
869 "if"?: #if
870 "changes"?: #changes
871 "exists"?: #exists
872 "variables"?: #rulesVariables
873 "when"?: #when
874 "start_in"?: #start_in
875 "allow_failure"?: #allow_failure
876 "needs"?: #rulesNeeds
877 "interruptible"?: #interruptible
878 }), strings.MinRunes(1),
879 list.MinItems(1) & [...string]
880 ])]
881
882 #rulesNeeds: [...matchN(1, [
883 string,
884 close({
885 // Name of a job that is defined in the pipeline.
886 "job"!: strings.MinRunes(1)
887
888 // Download artifacts of the job in needs.
889 "artifacts"?: bool
890
891 // Whether the job needs to be present in the pipeline to run ahead of the current job.
892 "optional"?: bool
893 })
894 ])]
895
896 #rulesVariables: {
897 {[=~".*"]: bool | number | string}
898 ...
899 }
900
901 #script: matchN(1, [strings.MinRunes(1), list.MinItems(1) & [...matchN(>=1, [string, [...string]])]])
902
903 #secrets: {
904 {
905 [=~".*"]: matchN(>=1, [{
906 "vault"!: _
907 ...
908 }, {
909 "azure_key_vault"!: _
910 ...
911 }, {
912 "gcp_secret_manager"!: _
913 ...
914 }, {
915 "aws_secrets_manager"!: _
916 ...
917 }, {
918 "gitlab_secrets_manager"!: _
919 ...
920 }]) & close({
921 "vault"?: matchN(1, [
922 string,
923 close({
924 "engine"!: {
925 "name"!: string
926 "path"!: string
927 ...
928 }
929 "path"!: string
930 "field"!: string
931 })
932 ])
933 "gcp_secret_manager"?: close({
934 "name"!: string
935 "version"?: matchN(1, [string, int])
936 })
937 "azure_key_vault"?: close({
938 "name"!: string
939 "version"?: string
940 })
941 "aws_secrets_manager"?: matchN(1, [
942 string,
943 close({
944 // The ARN or name of the secret to retrieve. To retrieve a secret from another
945 // account, you must use an ARN.
946 "secret_id"!: string
947
948 // The unique identifier of the version of the secret to retrieve. If you
949 // include both this parameter and VersionStage, the two parameters must refer
950 // to the same secret version. If you don't specify either a VersionStage or
951 // VersionId, Secrets Manager returns the AWSCURRENT version.
952 "version_id"?: string
953
954 // The staging label of the version of the secret to retrieve. If you include
955 // both this parameter and VersionStage, the two parameters must refer to the
956 // same secret version. If you don't specify either a VersionStage or
957 // VersionId, Secrets Manager returns the AWSCURRENT version.
958 "version_stage"?: string
959
960 // The AWS region where the secret is stored. Use this to override the region
961 // for a specific secret. Defaults to AWS_REGION variable.
962 "region"?: string
963
964 // The ARN of the IAM role to assume before retrieving the secret. Use this to
965 // override the ARN. Defaults to AWS_ROLE_ARN variable.
966 "role_arn"?: string
967
968 // The name of the session to use when assuming the role. Use this to override
969 // the session name. Defaults to AWS_ROLE_SESSION_NAME variable.
970 "role_session_name"?: string
971
972 // The name of the field to retrieve from the secret. If not specified, the
973 // entire secret is retrieved.
974 "field"?: string
975 })
976 ])
977 "gitlab_secrets_manager"?: close({
978 // Name of the secret. Only letters, digits, and underscores are allowed.
979 "name"!: =~"^[a-zA-Z0-9_]+$"
980
981 // Source of the secret. Defaults to the current project if not given. For
982 // fetching a secret from a group, provide group/<full_path_of_the_group>
983 "source"?: string
984 })
985 "file"?: bool
986
987 // Specifies the JWT variable that should be used to authenticate with the secret provider.
988 "token"?: string
989 gcp_secret_manager?: _
990 if gcp_secret_manager != _|_ {
991 "token"!: _
992 }
993 {}
994 })
995 }
996 ...
997 }
998
999 #services: [...matchN(1, [strings.MinRunes(
1000 1,
1001 ), close({
1002 // Full name of the image that should be used. It should contain the Registry part if needed.
1003 "name"!: strings.MinRunes(1)
1004 "entrypoint"?: list.MinItems(1) & [...string]
1005 "docker"?: close({
1006 // Image architecture to pull.
1007 "platform"?: strings.MinRunes(1)
1008
1009 // Username or UID to use for the container.
1010 "user"?: strings.MinRunes(1) & strings.MaxRunes(255)
1011 })
1012 "kubernetes"?: close({
1013 // Username or UID to use for the container. It also supports the UID:GID format.
1014 "user"?: int | strings.MinRunes(1) & strings.MaxRunes(255)
1015 })
1016 "pull_policy"?: matchN(1, [
1017 "always" | "never" | "if-not-present",
1018 list.MinItems(1) & list.UniqueItems() & [..."always" | "never" | "if-not-present"],
1019 ])
1020 "command"?: #script
1021 "alias"?: strings.MinRunes(1)
1022 "variables"?: #jobVariables
1023 })])]
1024
1025 #start_in: strings.MinRunes(1)
1026
1027 // Any of these function use cases are valid.
1028 #step: matchN(1, [
1029 matchN(1, [
1030 matchN(0, [null | bool | number | string | [...] | {
1031 "func"!: _
1032 ...
1033 }]) & {
1034 "step"!: _
1035 ...
1036 },
1037 matchN(0, [null | bool | number | string | [...] | {
1038 "step"!: _
1039 ...
1040 }]) & {
1041 "func"!: _
1042 ...
1043 }
1044 ]) & close({
1045 "name"!: #stepName
1046 "env"?: #stepNamedStrings
1047 "inputs"?: #stepNamedValues
1048 "step"?: #stepFuncReference
1049 "func"?: #stepFuncReference
1050 }),
1051 close({
1052 "name"!: #stepName
1053 "env"?: #stepNamedStrings
1054 "script"!: strings.MinRunes(1)
1055 })
1056 ])
1057
1058 #stepFuncReference: matchN(1, [string, #stepGitReference, #stepOciReference])
1059
1060 // GitReference is a reference to a function in a Git repository.
1061 #stepGitReference: close({
1062 "git"!: close({
1063 "url"!: string
1064 "dir"?: string
1065 "rev"!: string
1066 "file"?: string
1067 })
1068 })
1069
1070 #stepName: =~"^[a-zA-Z_][a-zA-Z0-9_]*$"
1071
1072 #stepNamedStrings: close({
1073
1074 {[=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]: string}})
1075
1076 #stepNamedValues: close({
1077
1078 {[=~"^[a-zA-Z_][a-zA-Z0-9_]*$"]: _}})
1079
1080 // OCIReference is a reference to a function hosted in an OCI repository.
1081 #stepOciReference: close({
1082 "oci"!: close({
1083 // The <host>[:<port>] of the container registry server.
1084 "registry"!: string
1085
1086 // A path within the registry containing related OCI images. Typically the
1087 // namespace, project, and image name.
1088 "repository"!: string
1089
1090 // A pointer to the image manifest hosted in the OCI repository.
1091 "tag"!: string
1092
1093 // A directory inside the OCI image where the function can be found.
1094 "dir"?: string
1095
1096 // The name of the file that defines the function, defaults to func.yml.
1097 "file"?: string
1098 })
1099 })
1100
1101 #steps: [...#step]
1102
1103 #string_file_list: matchN(1, [string, [...string]])
1104
1105 #tags: list.MinItems(1) & [...matchN(>=1, [strings.MinRunes(1), list.MinItems(1) & [...string]])]
1106
1107 #timeout: strings.MinRunes(1)
1108
1109 #when: "on_success" | "on_failure" | "always" | "never" | "manual" | "delayed"
1110
1111 // Define the rules for when pipeline should be automatically cancelled.
1112 #workflowAutoCancel: close({
1113 "on_job_failure"?: "none" | "all"
1114 "on_new_commit"?: "conservative" | "interruptible" | "none"
1115 })
1116
1117 #workflowName: strings.MinRunes(1) & strings.MaxRunes(255)
1118}