Skip to content

Workflows

Workflows define which steps run and in what order.

Defining Workflows

workflows:
default:
description: "Standard project setup"
steps: [deps, db, assets]
ci:
steps: [deps, test, lint]
reset:
steps: [db_drop, db_create, db_migrate, db_seed]

description is optional and shown in bivvy list to help teammates pick the right workflow.

Running Workflows

Terminal window
bivvy
Terminal window
bivvy run ci
Terminal window
bivvy run reset

Step Dependencies

Use depends_on to ensure steps run in order:

steps:
tools:
template: mise-tools
deps:
template: yarn-install
depends_on: [tools]
db:
template: postgres-install
depends_on: [tools]
assets:
command: "yarn build"
depends_on: [deps]
workflows:
default:
steps: [tools, deps, db, assets]

Bivvy resolves dependencies automatically. Steps without dependencies between each other can run concurrently when parallel execution is enabled — see Parallel Execution.

Before/After Hooks

Run commands before or after a step:

steps:
db_migrate:
command: "rails db:migrate"
before:
- "echo 'Starting migration...'"
after:
- "rails db:seed"

Skipping Steps

Skip steps from the command line:

Terminal window
bivvy --skip deps
Terminal window
bivvy --only db,assets

Skip Behavior

When you skip a step with --skip, Bivvy needs to decide what to do with steps that depend on it. The --skip-behavior flag controls this:

Terminal window
bivvy run --skip deps --skip-behavior skip_with_dependents
ValueEffect
skip_with_dependentsSkip the listed step and every step that depends on it (default)
skip_onlySkip only the listed step; let dependents try to run
run_anywaySkip the listed step but run all dependents normally

This option is CLI-only — it is not configured in YAML.

Workflow Environment Variables

A workflow can declare environment variables that apply to every step it runs:

workflows:
ci:
steps: [deps, test]
env:
CI: "true"
RAILS_ENV: test
env_file: .env.ci

env_file is loaded relative to the project root. Values in env: win over env_file. Workflow-level values override settings.env: / settings.env_file: from the project-wide settings, and step-level env: / env_file: override workflow-level values. Shell-exported variables (FOO=bar bivvy run) win over all of them — see Environment Variable Precedence.

Workflow Settings

Override interactive behavior for a specific workflow with the settings: block. The only supported field is non_interactive:

workflows:
ci:
steps: [deps, test]
settings:
non_interactive: true

Setting non_interactive: true forces the workflow into the same mode as bivvy run --non-interactive — no prompts, all interactive choices use their defaults. This is useful for workflows that should never prompt, even when run from a developer’s machine.

Workflow-Level Auto-Run

Override the auto-run setting for every step in a workflow with auto_run_steps. Individual step overrides still take precedence:

workflows:
release:
description: "Cut a release"
steps: [build, test, tag, publish]
auto_run_steps: false # prompt before each step in this workflow

auto_run_steps: true makes the workflow auto-run every step; auto_run_steps: false prompts before each one. See Auto-Run and the Decision Engine.

Per-Step Overrides

A workflow can override a small set of behavior flags on individual steps without redefining the step itself. Use the overrides: map, keyed by step name:

workflows:
release:
steps: [build, test, publish]
overrides:
publish:
auto_run: false # always prompt before publish in this workflow
prompt_on_rerun: true
rerun_window: "0" # never trust a previous successful run

Supported override fields:

FieldDescription
auto_runOverride the step’s auto-run flag for this workflow
prompt_on_rerunOverride whether re-runs prompt
rerun_windowOverride the step’s rerun window

Forcing Steps in a Workflow

Workflows can opt specific steps — or every step — out of check evaluation, the same way --force and --force-all do on the CLI. Useful when a workflow exists specifically to refresh state (a fresh-start workflow that always reinstalls, a migrate workflow that should never trust the satisfaction cache, etc.).

Force specific steps every time the workflow runs:

workflows:
partial-refresh:
steps: [install, build, migrate]
force: [migrate]

Force every step in the workflow:

workflows:
fresh-start:
steps: [install, build, migrate]
force_all: true

Force is monotonic — workflow-level directives are unioned with CLI flags and step-level force: true. Any source can opt a step in; nothing turns force off. Preconditions are still never bypassed. See Forcing Re-run for the full matrix.

Portable Workflow Files

A file at .bivvy/workflows/<name>.yml can carry its own step definitions and variables alongside the workflow declaration. Drop one of these into a project and bivvy run <name> works end-to-end — no need to split steps across multiple files.

.bivvy/workflows/release-prepare.yml
description: "Prepare a release branch"
vars:
current_version:
command: "bin/rails runner 'puts MyApp::VERSION'"
steps:
fetch-working:
title: "Fetch working branch"
command: "git fetch origin ${working_branch}"
finalize-changelog:
title: "Finalize changelog"
command: "bundle exec rake reissue:finalize"
depends_on: [fetch-working]
workflow:
steps:
- fetch-working
- finalize-changelog
env_file: .bivvy/release.env

The workflow: block is the workflow declaration itself (ordering, env, force directives) — exactly the same shape as inline workflows under workflows: in .bivvy/config.yml. The file’s top-level steps: and vars: blocks are bundled with this workflow but can be overridden by the project file or .bivvy/config.local.yml.

Resolution Order

When bivvy run <name> executes, configuration merges in this order (later overrides earlier):

  1. Remote extends: URLs
  2. ~/.bivvy/config.yml
  3. .bivvy/config.yml
  4. .bivvy/steps/*.yml
  5. .bivvy/workflows/<the-named-one>.yml
  6. .bivvy/config.local.yml

Only the workflow file matching the requested name participates — sibling workflow files are not parsed, so a malformed neighbor cannot break a run of an unrelated workflow.

Legacy Workflow Files

Files written in the legacy shape (description + steps: as an ordered list of names, no workflow: block) continue to work unchanged. The new format is detected by the presence of a top-level workflow: mapping.