Pipeline YAML
Complete specification for .gittan.yaml — every field, constraint, and default.
The .gittan.yaml file
in a repo’s root defines its pipeline. It is optional — repos without one
get their pipeline from matching org policies.
Top-level fields
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| steps | array | No | [] | Pipeline steps. Empty array means no repo override — policies apply. |
| gated | string[] | No | ["main"] | Branches where pushes are gated. A failing pipeline on a gated branch rejects the push. |
| depends | Dependency[] | No | — | Cross-repo dependencies for cascade pipelines. |
| notify | NotifyConfig | No | — | Notification channels for failures and review requests. |
| links | object | No | — | External links shown in the UI: docs, grafana, status, homepage. |
Step fields
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Unique identifier. 1–64 chars, lowercase alphanumeric and hyphens only (/^[a-z0-9-]+$/). |
| image | string | No | Container image for this step. Omit to use the detected default for the project type. |
| run | string | No | Shell command to execute. |
| use | string | No | Reference to a shared step by name. Resolves image, run, and defaults from the registry. |
| with | Record<string, string> | No | Parameters passed to a shared step. |
| env | Record<string, string> | No | Environment variables. Use ${{ secrets.NAME }} for secrets. |
| needs | string[] | No | Step names this step depends on. Defines the DAG — steps without dependencies run in parallel. |
| publish | object | No | Image publish config. Fields: image (required), dockerfile (default: Dockerfile). |
| only | string | No | Branch filter. Supports exact match, * (all branches), and trailing-star patterns (release/*). Publish steps without an explicit only default to main. |
| secrets | string[] | No | Secret names this step needs access to. Resolved from repo → team → org scope. |
| cache | string[] | No | Paths to cache between pipeline runs. Package manager stores (.pnpm-store, .npm, .cache/pip, .cache/uv) are shared org-wide; all other paths are repo-scoped. See cache behavior. |
| artifacts | string[] | No | Paths to persist as build artifacts. |
| services | array | No | Sidecar services. Each entry is a string (image name) or an object with image and optional env. |
| timeout | string | No | Max duration for the step. Default: 10m. |
| description | string | No | Human-readable purpose. Max 200 characters. |
Review step
A special step type that gates the pipeline on human code review. The step name must
be exactly review.
| Field | Type | Default | Description |
|---|---|---|---|
| name | literal | — | Must be review. |
| require | integer | 1 | Number of approvals required. Minimum 1. |
| from | string | writers | writers or admins. Who can approve. |
| autoAssign | string | blame | blame, round-robin, or none. Reviewer auto-assignment strategy. |
| needs | string[] | — | Steps that must pass before the review opens. |
| skipFor | string[] | — | Users who can skip review (e.g. bot accounts). |
Dependency object
Declares a cross-repo dependency for cascade pipelines. When the upstream repo pushes, a cascade run triggers in the downstream repo.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
| repo | string | Yes | — | Upstream repo name. |
| team | string | No | — | Team the upstream repo belongs to. Inferred if omitted. |
| cascade | boolean | No | true | Trigger a cascade run when the upstream pushes. |
| contractTest | boolean | No | true | Run contract tests between the repos. |
Notify config
notify:
onFailure:
- channel: team-slack
template: detailed
- channel: author
onReviewNeeded:
- channel: team-slack | Field | Type | Description |
|---|---|---|
| channel | string | team-slack, author, or webhook. |
| target | string | Optional. Webhook URL or specific channel for webhook notifications. |
| template | string | compact (default) or detailed. |
Resolution behavior
A repo’s final pipeline is not just its .gittan.yaml —
it is the union of steps from matching policies and the repo config:
- Enforce policies always contribute their steps when the match rule hits.
- Platform policies (secret-scan, dep-scan, policy-scan) each have their own blocking behavior — secret-scan and dep-scan (CRITICAL) block the push, policy-scan is advisory.
- Base steps come from the repo’s
.gittan.yamlif it defines steps, otherwise from matchingmode: defaultpolicies. - A
.gittan.yamlwith only metadata (depends,links, no steps) does not override default policies. - Publish steps without an explicit
onlygetonly: mainautomatically — feature-branch pushes never become production deploys. - Step name dedup: first occurrence wins. Enforce steps are placed first.
Publish config: .gittan.config.yaml
A separate file from .gittan.yaml.
Drop a .gittan.config.yaml in the repo root to override image publishing defaults.
| Field | Type | Default | Description |
|---|---|---|---|
| image | string | repo name | Override the published image name. |
| platform | string | native | Target platform for Docker builds (e.g. linux/arm64). |
Image tags
Published image tags must match the format YYYYMMDD-HHMMSS-sha (e.g. 20260612-143022-a1b2c3d).
The :latest tag is rejected.
See image pinning.
Full example
steps:
- name: install
run: pnpm install --frozen-lockfile
- name: test
run: pnpm test
needs: [install]
services:
- postgres:16
env:
DATABASE_URL: postgres://test:test@localhost:5432/test
- name: build
run: pnpm build
needs: [install]
- name: review
require: 1
from: writers
autoAssign: blame
needs: [test, build]
- name: publish
publish:
image: api
dockerfile: Dockerfile
needs: [review]
secrets: [NPM_TOKEN]
gated:
- main
- release/*
depends:
- repo: shared-types
cascade: true
notify:
onFailure:
- channel: team-slack
template: detailed
- channel: author
onReviewNeeded:
- channel: team-slack
links:
docs: https://docs.example.com
grafana: https://grafana.example.com/d/api