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