Skip to content

CI configuration reference

Forge reads pipeline configuration from .gitlab-ci.yml at the root of the repository. The syntax is compatible with GitLab CI/CD, but only the subset below is supported. Configuration that uses anything else is rejected by lint with the line and column, not ignored.

The configuration is pinned to the commit that the pipeline runs on.

Keyword Support
stages Stage order. The implicit .pre and .post stages run first and last.
default Defaults for image, before_script, tags and timeout.
workflow:rules Decide whether a pipeline is created.
include local files at the pipeline’s commit; files of other repositories in the same Orbit project (project, file, ref as a branch, tag or commit, pinned when the pipeline is created); CI/CD components with inputs. Nested up to 10 levels and 50 files.
spec:inputs Typed, defaulted inputs for included files and for web runs. Unknown inputs are refused.
extends Several parents, deep merge, up to 11 levels.
!reference Up to 10 levels.
YAML anchors, aliases and merge keys Bounded to 20,000 expanded nodes. Hidden jobs (names starting with .) work as templates.
variables Plain global, job, workflow-rule and job-rule variables with $VAR references. Names such as CI_*, FORGE_*, DOCKER_* and PATH are refused. Project and schedule secrets take precedence.

Components are included with an address of this shape, and live in the same Orbit project:

.gitlab-ci.yml
include:
- component: $CI_SERVER_FQDN/<repository>/<component>@<version>
inputs:
stage: test

The component file is templates/<name>.yml or templates/<name>/template.yml. <version> can be a tag, a branch, a commit or ~latest (the highest release tag; pre-release tags are ignored).

Keyword Support
image Job or global. Also image: {name, pull_policy}, subject to the runner’s allowlist of pull policies.
script, before_script Supported.
tags Match runner tags.
needs Job names, or {job, artifacts, optional}. optional: true drops a need on a job that rules leave out. artifacts: false stops artifacts and dotenv variables reaching the job.
dependencies Selects exactly which earlier jobs’ artifacts a job receives ([] for none).
when on_success, on_failure, always, manual and delayed with start_in (up to one week).
allow_failure Boolean, or {exit_codes: [...]} to allow only those exit codes.
retry 0 to 2, or {max, when, exit_codes}. Deployment and resource-group jobs never retry automatically.
timeout Up to 24 hours. Durations accept forms such as 90, 15m, 1h 30m, 1 hour 30 minutes and 2 days.
parallel parallel: N and parallel: matrix, up to 50 instances. A job that needs a parallel job waits for all its instances.
rules if (operators ==, !=, =~, !~ with RE2 regexes such as /.../i, null, &&, ||, parentheses), changes, exists, variables, plus when and allow_failure on a rule.
resource_group A static key. Jobs of a group are serialised.
environment See below.
release tag_name, tag_message, name, description, ref, released_at and assets.links.
id_tokens RS256 JWTs for reaching cloud providers without long-lived keys.
trigger Child and multi-project pipelines, see below.

environment supports a name and url (http or https, up to 512 characters, no credentials; it may use $CI_ENVIRONMENT_SLUG, $CI_ENVIRONMENT_NAME and the commit variables), deployment_tier, on_stop, auto_stop_in (from one minute to one year, or never) and action (start, prepare, verify, access, stop). A dynamic name such as review/$CI_COMMIT_REF_SLUG must start with a static segment, so a branch name can never create a top-level environment such as production. Runners that offer environmentV1 set CI_ENVIRONMENT_NAME, CI_ENVIRONMENT_SLUG, CI_ENVIRONMENT_ACTION, CI_ENVIRONMENT_URL and CI_ENVIRONMENT_TIER in the job. Details: Environments and deployments.

Keyword Support
artifacts:paths, when, expire_in, name, exclude, expose_as Supported. name may use variables.
artifacts:reports junit (globs), dotenv (up to five files, at most 20 variables and 5 KiB, reserved names refused) and coverage (a regex read from the job log).
cache Up to four caches per job; key (with variables or key:files, up to two files) and prefix, paths, policy (pull, push, pull-push), when, fallback_keys, unprotect; also default:cache. Keys get a -protected or -non_protected suffix, so jobs on unprotected refs never read or replace a protected ref’s cache.

Limits: an archive holds up to 1000 entries and 64 MiB expanded (32 MiB compressed). Project quotas default to 512 MiB and 1000 unpurged archives and are configurable. Caches are evicted above a per-repository quota (1 GiB by default) and removed when unused for 14 days by default. Symlink and device entries are rejected. Optional S3-compatible object storage can hold artifacts and caches.

trigger jobs never reach a runner.

  • Child pipelines: trigger:include starts a child from up to three included files at the parent commit, or from a file produced by an earlier job’s artifact (a dynamic child pipeline).
  • Multi-project pipelines: trigger:project (a repository slug, or PROJECTKEY/slug for another Orbit project) with an optional branch.
  • strategy: depend mirrors the downstream result into the trigger job, and forward:yaml_variables (on by default) passes the trigger job’s variables.
  • Downstream pipelines run as the user who triggered the parent, who needs write access to the target project. Nesting stops at two levels, and a pipeline creates at most 20 downstream pipelines. CI_PIPELINE_SOURCE is parent_pipeline or pipeline.
Trigger Notes
Branch push, tag push, merge request Each is opt-in per project. [skip ci] or [ci skip] in the commit message and git push -o ci.skip skip them.
Schedules Branch and protected-tag targets, five-field cron with JAN-DEC and SUN-SAT names and @hourly to @yearly shortcuts, IANA time zones, typed inputs, encrypted schedule variables.
API and webhook triggers Owner-scoped trigger tokens and HMAC-signed webhooks, with exact allowed refs, expiry and once-only display of the secret.
Web run Manual run, with typed spec:inputs.

Forge rejects these, so a copied GitLab file fails lint rather than behaving differently:

  • after_script
  • services (service containers) and image:entrypoint
  • remote includes and GitLab template includes
  • includes or components from other Orbit projects (multi-project triggers may cross projects)
  • needs:pipeline, needs:project and rules:needs
  • interruptible and automatic cancellation of redundant pipelines
  • cache:untracked
  • secrets: (use id_tokens to reach external secret providers)
  • trigger:include:inputs and forward:pipeline_variables
  • ci.variable and ci.input push options (rejected)

Other differences: log output is not streamed live (the job log refreshes while the pipeline page polls), and only JUnit, dotenv and coverage reports are collected, besides the security reports.