Skip to main content
A workflow is a YAML file listing the steps a runner executes. Each step is a bash script. Steps run in order, in one workspace that holds the workflow’s files.

About YAML syntax for workflows

  • Workflows live at .bento/workflow/workflow.yml in the repository (VCS workflows) or in the uploaded file set (local workflows).
  • The runner parses the file with yaml.safe_load. Bentra itself only checks that the file exists and is a YAML mapping before a version can be cut. Everything else is validated by the runner when a run starts.
  • Local workflow file sets are limited to 256 KB per file, 2 MB in total, 100 files, and a path depth of 10.
  • Bentra workflows are not GitHub Actions. There is no on, jobs, runs-on, needs, uses, or ${{ }} expression syntax. Triggers, approvals, schedules, and runner selection are configured in the Bentra UI. See Configured outside the YAML.

Example: a complete workflow


name

Optional. The workflow’s display name, shown in runner logs. Defaults to Unnamed.

description

Optional. Free-text documentation. The runner ignores it.

version

Optional. The syntax version, by convention "2.0", which is what the starter template uses. The runner ignores it.

tools

Optional. Pins tool versions for the whole run. The versions are installed during the “Set up job” phase, before any step runs. If a requested version can’t be installed, the run fails.

tools.terraform_version

A string. The Terraform version to install and select with tfenv, for example "1.7.5". If omitted, the runner image’s default is used.

tools.opentofu_version

A string. The OpenTofu version to install and select with tofuenv. If omitted, the runner image’s default is used.

steps

Required. The list of steps to execute. If steps is missing or is not a list, the run fails. Items that are not mappings are skipped with a warning. A run in which no step executes fails. Steps run one at a time, in order. By default the first failing step stops the run.

steps[*].name

Optional. The step’s name, shown in the run view and logs. At most 255 characters. Defaults to Unnamed step.

steps[*].run

Required in practice. The bash script to execute. It runs as:
  • -e: the step fails on the first failing command.
  • -o pipefail: a failure anywhere in a pipeline fails the step.
  • The working directory is the workspace root, which contains the workflow’s files plus bento.env and bento_inputs.json.
  • Each step gets a fresh shell. Variables exported in one step are not visible to later steps. To pass data between steps, write it to a file in the workspace.
  • A step with an empty or missing run is marked skipped.

steps[*].continue_on_error

Optional. Boolean, default false. When true, later steps still run if this step fails. The run as a whole is still reported as failed.
A step timeout always stops the run, even with continue_on_error: true.

steps[*].tools

Optional. Switches the tool version from this step onward. It takes the same keys as the top-level tools: terraform_version and opentofu_version.
The version is not reset after the step. Later steps keep using it until another step sets a different version.

steps[*].retry

Not supported yetretry (both top-level and per step) is accepted in the YAML and appears in some older examples, but the runner doesn’t apply it. A failing step is not retried.

outputs

Optional. Declares data the run publishes.
Datasets need runner 0.7.0+. Only job-type workflows can declare outputs; request workflows are rejected.

outputs.datasets.<name>

Declares a dataset: a small table that the run publishes and other jobs and views can read.
  • The name must match ^[a-z][a-z0-9_-]*$ and be at most 64 characters.
  • A job can declare at most 10 datasets.
  • The declaration is checked when the run is planned, and an invalid declaration fails the run before any step executes.
  • A dataset the job previously declared but no longer declares is marked retired.

outputs.datasets.<name>.columns

Required. A non-empty list of unique column names. Each name is at most 64 characters, and there can be at most 20 columns.

outputs.datasets.<name>.max_rows

Optional. An integer from 1 to 1000. Default 1000.

outputs.datasets.<name>.description

Optional. A string.

outputs.datasets.<name>.allow_empty

Optional. Boolean, default false. By default, publishing zero rows is rejected when the current version of the dataset has rows. This guards against wiping out data by accident. Set it to true if an empty result is legitimate.

Writing a dataset

Steps write each dataset to $BENTRA_DATASETS/<name>.json as a JSON array of objects. After the steps succeed, an automatic Publish datasets step uploads the files. Each object is one row, and these rules apply:
  • Keys must be declared columns. A missing column becomes null.
  • Values must be scalars: string, number, boolean, or null.
  • All datasets in a run must total at most 1 MB.
  • Every declared dataset must be written.
Only successful runs publish. A new version is created only when the data has changed.
A step with continue_on_error: true that fails still makes the run fail, so a job whose datasets matter shouldn’t rely on it: the datasets won’t be published. Handle expected errors inside the script instead.

inputs

Optional. Declares other jobs’ datasets this workflow reads. Both job and request workflows can declare inputs.

inputs.datasets

A non-empty list of {job, dataset} entries. job is the slug of the job that publishes the dataset.
  • The workflow needs a read grant on each job (the job’s Data sharing settings), and the job must have published the dataset. Otherwise the run fails before any step executes.
  • Before the first step, the runner downloads the current version of each dataset to $BENTRA_INPUTS/<job>/<dataset>.json, as a JSON array of row objects (the same shape a job writes to $BENTRA_DATASETS). The version it loaded is printed in the setup log.
  • The version each run read is recorded on the attempt.

Inputs and environment variables

There is no templating language. Values reach your steps as environment variables and as files in the workspace.

Form inputs

Each field in the submitted form becomes an environment variable named after the field id in upper case:

Variables and secrets

Variables and secrets from the workflow’s variable collections are injected as upper-cased environment variables. They override a form input with the same name.

System variables

The runner’s own credentials (BENTRA_RUNNER_TOKEN, and anything prefixed OPENBAO_, BAO_, or VAULT_) are removed from the step environment.

Files in the workspace

Both files are written before each step:
  • bento.env: a sourceable bash file with the form inputs and the BENTO_* variables. Other secrets are not included. A form input that a secret overrides is written with the secret’s value.
  • bento_inputs.json: the submitted form data as typed JSON. Lists stay lists and tags stay objects.

Reporting checks

A step can report a check (a pass/fail annotation shown on the run) by printing a line to stdout:
  • status is required and must be one of passed, failed, warning, or info.
  • name defaults to Check.
  • Any other key=value pairs are attached as details.
  • To use a literal comma inside a value, write %2C. To use a literal ::, write %3A%3A.
  • A failed check fails the step, even if the script exits 0.

Timeouts and implicit setup

  • Step timeout: 300 s by default. This is set by the runner’s STEP_TIMEOUT environment variable, not in the YAML.
  • Run timeout: 1800 s by default, set by the runner’s EXECUTION_TIMEOUT.
  • Dependency install: before your steps, the runner adds an “Install Python dependencies” step (pip install -r requirements.txt) if requirements.txt exists in the workspace root, and an “Install Node.js dependencies” step (npm install --production) if package.json exists. If either fails, the run stops.

Configured outside the YAML

These settings are made in the Bentra UI or API rather than in workflow.yml: Published workflow versions are immutable snapshots of these files, taken when the version is cut.