Skip to main content
Each example is a complete file. Copy one, change the names, and validate it before you commit:
For one stage per language, see Starter pipelines. For every key, see the pipeline.yaml reference.

A Go service that builds once

Tests run on every pull request and push. The image is built, scanned and gated on both, and published only on push. A merge publishes the image the pull request already tested instead of rebuilding it.
  • test_results turns the JSON report into the run’s Tests section, with flaky tests detected from retries. The report is also listed under artifacts, which is what uploads it.
  • promote_from is a protected section, so it takes effect once an administrator approves the definition on main.

A monorepo that tests only what changed

A pnpm web app and a Go API in one repository. Each test stage follows its own dependency graph, so a change to a shared Go library runs the API tests and skips the web tests. A change to a shared pnpm package does the opposite.
  • The -web and -api suffixes tie each build to its component, so publish-web can only ever re-tag the web image. The application has to record components named web and api (in .ankra/ankra.yaml, or from its analysis). Otherwise ankra pipeline validate warns that both builds would publish to one repository.
  • when.paths on each build skips that component’s whole chain (build, scan, gate, publish) when nothing of it changed. affected: on the test stages goes deeper than paths: it follows imports.
  • Check the plan before you push: ankra pipeline validate --changed-file libs/auth/token.go.

A Python API with Postgres and a version matrix

The tests run against a real Postgres sidecar on three Python versions, side by side.
  • network: services lets the stage reach its sidecar by name. It is a protected tier, so it applies after an administrator approves the definition.
  • The matrix value is part of the cache key, so each Python version keeps its own wheels.

A repository with no application

A library, a docs site or a platform repository needs tests, not a deploy. Connect it as a bare repository, and the pipeline needs no build or publish at all.
lint and test start together. A scan without a build scans the source tree.

A nightly suite and a manual dispatch

Pull requests run the fast tests. A schedule runs the slow end-to-end suite every weekday night, and anyone can dispatch it by hand against a chosen environment.
Dispatch it by hand:
  • stages on the schedule names exactly what the nightly runs, checkout included. A re-run of a red nightly repeats the nightly, not the whole pipeline.
  • Cron fields are numeric only (1-5, not MON-FRI).
  • on_failure stages run after the main stages, and only when one of them failed. Here it keeps the Playwright traces of a red night. A failed run already raises pipeline_run_failed, which your notification rules send to Slack or Teams.

A tagged release

A push of a v* tag builds, scans and gates, then publishes with a moving latest tag and a numbered version tag beside the usual sha- tag.
Each extra tag is a manifest re-tag of the one gate-approved digest. No layer is pushed again. A registry that refuses a tag, for example through a tag-immutability rule, fails the step and names the tag, so a latest that did not move never reads as published.

A matrix across operating systems and architectures

runs_on places one leg per architecture on matching nodes of your CI cluster.
runs_on is a protected section, and the organisation’s pipeline policy decides which node selectors a pipeline may ask for. Your CI cluster needs nodes of each architecture.