Skip to main content
CI is built into rbs. Workflows are declared in the RBS language — the same language as your build files — and executed by the rbs DAG engine: independent jobs run in parallel, needs edges order the rest, and every step benefits from the shared cache. There is no YAML dialect and no separate runner to install; the rbs binary that builds your workspace also runs its CI.

Defining a workflow

Declare workflows with ci_workflow() in a file named ci.rbs. rbs discovers every ci.rbs in the workspace (workflows can also live in WORKSPACE.rbs), so a monorepo can keep each service’s pipeline next to its code.
Jobs form a DAG: test waits for build, and jobs without edges between them run concurrently. A dependency cycle is rejected before anything runs.

Triggers

The on dict declares which events run the workflow:
  • push — filter with branches, branches_ignore, tags, tags_ignore, paths, paths_ignore. Glob patterns work ("v*", "release/**"). A workflow that only declares tags runs only on tag pushes; one that only declares branches runs only on branch pushes.
  • pull_request — filter with branches (the target branch), branches_ignore, types, paths, paths_ignore.
  • manual — runs only when invoked by name or with --event manual.
  • schedule{"cron": "0 6 * * *"}. rbs does not run a daemon; a schedule trigger matches when an external scheduler invokes rbs ci run --event schedule.
Path filters compare against the files changed since the base ref, so a docs-only push can skip a build workflow entirely.

Steps

Each job runs its steps in order. A step is one of four kinds: For target and affected_target steps, command selects the rbs verb: "build" (the default), "test", or "coverage". Steps also accept name, env, if, working_directory, timeout, and continue_on_error (a failing step with continue_on_error set does not fail the job).

Environment variables

Steps see your environment plus three layers of declared variables — workflow-level env, then job-level, then step-level, later layers overriding earlier ones. rbs adds the trigger context automatically:
  • CI_EVENT_TYPEpush, pull_request, manual, …
  • CI_REF — the fully-qualified ref (refs/heads/main, refs/tags/v1.2.0)
  • CI_BRANCH — the branch name
  • CI_PR_NUMBER — set for pull-request runs

Conditions

Jobs and steps take an if expression. The evaluated forms are always(), success(), failure(), cancelled(), and the literals true / false.
An if expression the engine does not recognize is treated as true — the job runs. Keep conditions to the supported forms.

Matrix jobs

A job with a matrix expands into one job per combination:
This produces four jobs, scheduled in parallel like any other independent jobs. Each expansion’s variable assignment is recorded in the run results and shown by rbs ci plan.

Running workflows

With no workflow name, every workflow whose triggers match the event runs. The trigger context comes from flags first and the workspace’s git state otherwise — --event, --branch, --tag, --ref (a fully-qualified ref decides branch vs tag), --base, and --pr. Useful flags on rbs ci run:
  • --workers N — parallel job slots (default 4)
  • --timeout 30m — overall workflow timeout
  • --fail-fast — stop at the first failing workflow (default on)
  • --json — emit run results as JSON
  • --remote host:port — run the jobs on a remote cluster (see below)

Inspecting workflows and runs

Run records persist in the workspace, so rbs ci status sees runs from earlier invocations; the most recent 50 are kept.

Planning without running

rbs ci plan resolves a trigger event into the exact job DAG it would execute and prints it as JSON on stdout — nothing runs, nothing is written:
Matrix jobs are expanded and needs edges are rewritten to the expanded names, so the output is the DAG that would actually be scheduled. This is the integration point for external schedulers and dashboards.

Affected-package detection

For monorepos, rbs can compute which packages the current change actually touches — directly and through the dependency graph:
Inside a workflow, an affected_target step applies this automatically: it finds every affected package defining the named target and runs just those, instead of the whole workspace.

Running CI on a cluster

If you run a remote build cluster (see Remote cache & execution), rbs ci run can fan the workflow’s jobs onto its workers instead of running them locally:
Each job is submitted to the cluster with its needs edges preserved as job dependencies. Workers check out the repository at the triggering commit, stream their logs back to your terminal, and any rbs commands inside the job’s steps automatically use the same cluster — so every job shares one cache.
Fleet CI submits jobs with the CI_* context variables, but secret values are never placed in job specs — a job spec can sit in the queue, and secrets do not belong there. See the secrets rule.