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.
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
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 overrideThat 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:
| Constraint | Matches |
|---|---|
>=0.10.0 | 0.10.0 and up |
^1.2.0 | 1.2.0 up to <2.0.0 |
~1.2.0 | 1.2.0 up to <1.3.0 |
>=1.2.0 <2.0.0 | a bounded range |
1.2.0 | exactly 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 cause | Fails at load, with the version and the fix |
| "Works on my machine" version drift | Floor travels with the committed workflow |
| Override is editing the workflow | --ignore-version-check, logged and visible |
| No way to test the floor | ORCHSTEP_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
- Engine Version — the full reference, including module chains
- Editor Support — the JSON Schema autocompletes
required.orchstep - Continuous Integration — wiring OrchStep into CI
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.
curl -fsSL https://orchstep.dev/install.sh | sh