Skip to content

Pipeline components

Every Airframe repository builds its pipeline from the platform’s components, shared building blocks kept in the control-plane repository, rather than from jobs of its own. This page lists each component a repository may include, the jobs it adds and what it needs to run, then the jobs the platform injects into pipelines whatever their files say, so you can read any repository’s pipeline and know where each job comes from.

A component is included as gitlab.com/projectairframe/control-plane/<name>@<commit>, at a full commit, which the command airframe pin writes; the policy pack warns on a branch, a tag or a short commit. It takes inputs, never variables. A product’s pipeline file is rendered by the golden path’s template, and the policy pack denies a product file that includes anything but eight of these components or declares a job that deploys (enforced). The policy rules page lists those rules.

Jobs run on one of two runners: the untrusted runner, which holds no credential and runs anything a merge request brings, and the trusted runner, which runs only on a protected main and obtains identities through workload identity federation. The glossary explains both.

The tables describe release 2026.10.01-1, whose control-plane commit is c53c0bc. A row marked designed is a component the contracts name that is not built.

tf-apply

Jobs
plan:<name>, or plan-after:<name> for a root that plans after other roots' applies; policy:<name>; apply:<name>; run-job:<name> when the root runs a job after its apply; and drift:<name> on the scheduled pipeline.
Inputs a repository sets
One include per Terraform root: name, root, root_kind, identity, state_bucket, state_prefix and environment. A product's file also sets lifecycle, extra_changes, run_job, run_job_after and, for production, after. Platform roots may set reads_catalog, plan_after, plan_late, secret_env, smoke, drift_only and forget_projects.
What it needs
The trusted runner, a protected main, and the root's identity in the root's environment. The plan, policy and apply jobs run on main only, when the root's files changed.
Source
control-plane templates/tf-apply/template.yml, docs/pipeline.md; golden-path template/.gitlab-ci.yml.jinja

drift-report

Jobs
drift:report, on the scheduled pipeline, after the drift jobs.
Inputs a repository sets
None in practice: every input has a default.
What it needs
The trusted runner; the audit identity, in the environment platform/audit; the audit account's GitLab token, read from Secret Manager in the job; and a schedule on main that a maintainer creates.
Source
control-plane templates/drift-report/template.yml, docs/pipeline.md

image-build

Jobs
build:request, on main.
Inputs a repository sets
wait_minutes and gate_url. The identity, environment and registry inputs are retired and ignored.
What it needs
The untrusted runner and the job's token for the gate, with no cloud identity. The trusted builder built the commit at the approval, or builds it now at the job's request.
Source
control-plane templates/image-build/template.yml

promote-artifact

Jobs
deploy:promote, on main, after build:request.
Inputs a repository sets
wait_minutes and gate_url. Its former inputs are accepted and ignored.
What it needs
No credential: it asks the gate, and the executor copies the image by digest into the production registry as the artifact promoter. The production apply waits for it.
Source
control-plane templates/promote-artifact/template.yml, docs/pipeline.md

catalog-publish

Jobs
validate:fragment on merge requests; release:catalog on main.
Inputs a repository sets
kind, path, identity and environment; a platform repository also sets name.
What it needs
validate:fragment: the untrusted runner, no credential. release:catalog: the trusted runner and the repository's own identity, for a product its production apply identity in the environment prod.
Source
control-plane templates/catalog-publish/template.yml, docs/pipeline.md

reconcile

Jobs
<name>:reconcile, by convention edge:reconcile and grafana:reconcile, on main after the applies.
Inputs a repository sets
name, repository (landing-zone or operations), after and changes.
What it needs
The job's token for the gate, which starts the platform repository's main pipeline with the platform's own trigger token. No cloud identity.
Source
control-plane templates/reconcile/template.yml

progress

Jobs
progress:track, in the catalog's main pipeline after a merge that changed a product file.
Inputs a repository sets
None in practice; only the catalog includes it.
What it needs
The untrusted runner and the job's token for the gate, which writes the note on the merged merge request. It follows the merge for up to three hours.
Source
control-plane templates/progress/template.yml; catalog .gitlab-ci.yml

validate

Jobs
validate:terraform, validate:tofu, validate:tflint, validate:policy and validate:catalog.
Inputs a repository sets
A platform repository sets terraform_roots, root_kind and, in the catalog, catalog_lint. A product sets nothing: the product policy injects it.
What it needs
The untrusted runner, no credential and public images only.
Source
control-plane templates/validate/template.yml, docs/pipeline.md

build-test

Jobs
build:test-node, build:test-python with build:web-python, or build:test-java, chosen by the stack's files; then build:quality.
Inputs a repository sets
None: it is injected into every product pipeline and never included.
What it needs
The untrusted runner and no credential. The coverage and findings thresholds come from the product's quality in the catalog.
Source
control-plane templates/build-test/template.yml, docs/pipeline.md

A product’s rendered file includes image-build, promote-artifact, four tf-apply includes for prod, sandbox, np and grafana, drift-report, catalog-publish, and reconcile twice. A platform repository with Terraform roots includes validate and one tf-apply per root it applies; most also include drift-report and catalog-publish, and those that build images image-build and promote-artifact.

GitLab policies kept in the security-policies repository add these jobs to pipelines. A repository’s own file cannot remove or replace an injected job (enforced by GitLab’s pipeline execution policies), so a team sets nothing here.

gate:integrity

Where it runs
Every pipeline of every repository in the group but security-policies, in the stage before all others.
What it does
Asks the gate for its verdict on the pipeline's commit and fails when the verdict is fail, when the address is empty or when the gate cannot be reached. The address is the job's own, and the policy refuses variable overrides, so no project, group or pipeline variable reaches the job. The gate also fails a pipeline pinned to a revoked release.
What it needs
One token whose audience is the gate. It checks out no code.
Source
security-policies templates/airframe.yml, .gitlab/security-policies/policy.yml

validate:injected

Where it runs
Every pipeline in the group but security-policies', on merge requests and on main.
What it does
Marks the validation stage as present; the components run the checks.
What it needs
Nothing.
Source
security-policies templates/airframe.yml

The product checks

Where it runs
Every pipeline of a repository in the journey groups, where the products are.
What it does
The validate component on the roots infra/prod, infra/np, infra/sandbox, infra/grafana and infra/eph, with the policy pack, and the build-test component.
What it needs
The untrusted runner and no credential.
Source
security-policies templates/product.yml, .gitlab/security-policies/policy.yml

Secret detection, dependency scanning and SAST

Where it runs
Every merge request pipeline in the group, and a daily scan of every default branch.
What it does
GitLab's own scanners. Their findings appear on the merge request and block nothing yet.
What it needs
Nothing from the repository: the scan execution policy defines the jobs.
Source
security-policies .gitlab/security-policies/policy.yml

Named in the contracts, not components today

Section titled “Named in the contracts, not components today”

deploy-cloud-rundesigned

Jobs
deploy:sandbox, deploy:prod, deploy:canary, deploy:shift-<pct> and deploy:rollback
Today
Not built. The tf-apply applies deploy each image by digest, and criticality 1's canary order is designed.
Source
landing-zone docs/contracts.md 5.1, docs/adaptations.md

security-scandesigned

Jobs
verify:dependencies, verify:container and verify:licences
Today
Not built as a component. GitLab's scanners arrive through the scan execution policy, and the trusted builder scans each image it builds.
Source
landing-zone docs/contracts.md 5.1; control-plane docs/pipeline.md

pact-publish, pact-can-i-deploydesigned

Jobs
verify:pact-publish and deploy:can-i-deploy
Today
Not built: no contract broker runs.
Source
landing-zone docs/contracts.md 5.1

releasedesigned

Jobs
release:tag
Today
Not built.
Source
landing-zone docs/contracts.md 5.1

opsdesigned

Jobs
ops:restart, ops:scale, ops:rollback and six more operational jobs
Today
Not built.
Source
landing-zone docs/contracts.md 5.1

renovatedesigned

Jobs
ops:renovate, on a schedule
Today
Not built.
Source
landing-zone docs/contracts.md 5.1

tf-plan, cost-estimate, preview-env, destroy-on-close

Jobs
The plans at approval, their price, a preview and its destroy
Today
Built as the executor's runs, which the gate starts. A repository includes none of them.
Source
landing-zone docs/contracts.md 5.1, 5.3; control-plane executor/

The contracts give some jobs older names, such as deploy:apply-<root>. The tables use the names the components define.

Where it lives

In the control-plane repository:

In the security-policies repository:

MIT license. Copyright Airframe contributors.

This site describes platform release 2026.10.20-1.