BLOG/TEAM CI/CD
THEME
TEAM CI/CD

Pin the engine version with required:

A workflow that uses a feature your teammate's orchstep doesn't have fails in a confusing place. Declare the minimum engine version once, and an out-of-date binary fails fast with a clear message instead.

Jun 30, 2026 OrchStep Team 5 minROLE: DevOps EngineerSCALE: Any

You add a workflow that leans on a feature shipped in a recent orchstep release. It runs clean on your machine. Then a teammate pulls main, runs the same task on a binary from three months ago, and gets a parse error two steps deep — or worse, a silently different result. The CI runner, pinned to whatever was cached, does something else again.

Nothing here is an OrchStep-specific problem. It's the same drift Terraform solved with required_version, package.json solved with engines, and go.mod solved with the go directive: the artifact should declare the toolchain it needs, and the toolchain should refuse to guess.

OrchStep has the same gate. It's one block.

The one block

orchstep.yml
name: deploy
# Declare the minimum engine this workflow needs.
required:
  orchstep: ">=0.10.0"
defaults:
  target: staging
tasks:
  deploy:
    steps:
      - name: build
        func: shell
        do: echo "building for {{ vars.target }}"

required is its own top-level block — deliberately not under config:. Behavior settings can be loaded from a machine-level file; a version requirement has to travel with the committed workflow, so it lives at the top with name: and tasks:. It's optional. A workflow with no required runs on whatever engine you have, exactly like today.

What happens on a mismatch

If the running engine doesn't satisfy the constraint, the run fails before executing anything — no half-applied side effects:

$ orchstep run deploy
Error: failed to load workflow: workflow requires orchstep >=99.0.0,
but this engine is v0.11.0; upgrade orchstep, or pass
--ignore-version-check (env ORCHSTEP_IGNORE_VERSION_CHECK=1) to override

That message is the whole point. Instead of a cryptic failure on the line that uses the new feature, you get the actual reason and the actual fix.

The escape hatch

Sometimes you know better — you're testing against a pre-release, or you've read the changelog and the gap doesn't touch the path you're running. Two equivalent overrides downgrade the hard error to a warning and run anyway:

orchstep run deploy --ignore-version-check
# or, for CI env config:
ORCHSTEP_IGNORE_VERSION_CHECK=1 orchstep run deploy
⚠️  workflow requires orchstep >=99.0.0, but this engine is v0.11.0;
... (continuing due to --ignore-version-check)
Workflow: deploy
...

It's a deliberate, visible decision in the logs — not a flag you set once and forget.

Constraint syntax

Standard semver, the same grammar as module versions:

ConstraintMatches
>=0.10.00.10.0 and up
^1.2.01.2.0 up to <2.0.0
~1.2.01.2.0 up to <1.3.0
>=1.2.0 <2.0.0a bounded range
1.2.0exactly 1.2.0

Test the gate without a second install

You don't need an old binary lying around to prove the gate works. ORCHSTEP_VERSION_OVERRIDE sets the version used for the check, so you can answer "would this run on 0.9?" in one command:

# Pretend this engine is 0.9.0 against a >=0.10.0 requirement
ORCHSTEP_VERSION_OVERRIDE=0.9.0 orchstep run deploy
# Error: ... requires orchstep >=0.10.0, but this engine is 0.9.0; ...

Flip the number above the floor and the same command runs clean. It's a real, useful check to drop into a test that guards your minimum.

Modules require an engine too

A module declares the same required block in its orchstep-module.yml. Pull a module built for a newer engine into an older one and it fails clearly at load time. In a workflow → modules → nested-modules chain there's nothing to resolve — there's one engine, so OrchStep checks it against every requirement in the chain and the most restrictive one wins.

One thing to know: a locally-built, unstamped engine reports its version as dev and skips the check entirely. There's nothing meaningful to compare a dev build against, so it never blocks your inner loop.

What you gained

Without required:With required:
Failure surfaces deep in a step, off the real causeFails at load, with the version and the fix
"Works on my machine" version driftFloor travels with the committed workflow
Override is editing the workflow--ignore-version-check, logged and visible
No way to test the floorORCHSTEP_VERSION_OVERRIDE simulates any engine

Where this is not the answer

required: pins a floor, not an exact build, and it doesn't pin the modules you pull — version your module sources for that. If your whole team installs orchstep from the same lockfile or container image already, the gate is a cheap belt-and-suspenders rather than a fix for an active problem. Add it anyway: it costs three lines and pays off the first time a stale binary would have lied to you.

Where to go next

Add required: to the workflow you're most afraid a teammate will run on the wrong binary. orchstep lint will tell you the moment the block is malformed.

#CI-CD#VERSIONING#REPRODUCIBILITY#TEAMS
Try it in two minutes — one binary, no signup.
curl -fsSL https://orchstep.dev/install.sh | sh

RELATED — TEAM CI/CD