cue.dev/x/gitlab@v0.4.0

gitlabci/schema.cue raw

  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}