Lockfile & Supply Chain
How orchstep.lock pins modules to an immutable commit and content hash for reproducible, tamper-evident builds
Git tags are mutable - @company/deploy/v1.2.0 can be force-moved to different
bytes tomorrow. Every ecosystem that ships executable units solves this with a
lockfile (go.sum, package-lock.json, .terraform.lock.hcl, Cargo.lock).
OrchStep's is orchstep.lock.
What gets pinned
When OrchStep resolves a remote module, it records three things in
orchstep.lock:
modules:
deploy:
source: "@company/deploy"
version: 1.2.0 # resolved semver
tag: deploy/v1.2.0 # the git tag matched
commit: 8af4687c67c62d834860013a1004232509cd17ce # immutable commit SHA
hash: sha256:b50fe37b6526eb19283ecab0d59d96af... # content hash of the module- commit binds the module to an exact commit, not a movable tag.
- hash is a sha256 over the module's files (excluding
.git), so even a re-pointed commit or a tampered cache is detected.
How it behaves
-
First resolve writes the lock. Run a workflow with an unlocked remote module and OrchStep resolves the newest version your constraint allows, then writes
orchstep.locknext to yourorchstep.yml. Commit this file. -
Later runs are pinned and verified. With a lock present, OrchStep fetches the pinned commit (ignoring the tag entirely) and recomputes the content hash. A mismatch - the tag was force-moved, or the cache was tampered with - fails the run:
module 'deploy' failed integrity check: orchstep.lock expects sha256:b50f... but resolved content is sha256:1c9d... (the tag may have been force-moved or the cache tampered; run 'orchstep module update' if this change is intended)
Local-path modules (./mod, ../shared) are never locked - there's nothing
remote to pin.
Commands
| Command | What it does |
|---|---|
orchstep module lock | Write orchstep.lock for the workflow's modules. Keeps versions already pinned; fills in any missing ones. |
orchstep module update [name...] | Re-resolve modules to the newest version their constraint allows and re-pin commit + hash. Bumps everything, or just the named modules. |
orchstep module verify | Re-fetch every locked module at its pinned commit, recompute the hash, and exit non-zero on any drift. |
In CI
Treat orchstep.lock like any other lockfile: commit it, and gate builds with
module verify so a moved tag or tampered module fails the pipeline instead of
silently changing what runs.
steps:
- uses: orchstep/setup-orchstep@v1
- run: orchstep module verify # fails the build on supply-chain drift
- run: orchstep run deployTo forbid implicit lock writes in automation entirely, set
ORCHSTEP_LOCK_AUTOWRITE=false - resolves then require an up-to-date committed
lock instead of writing one.
Updating a module on purpose
orchstep module update deploy # bump 'deploy' to newest allowed, re-pin
git add orchstep.lock # review the commit/hash change in the diffBecause the change shows up as a commit + hash diff in orchstep.lock, a
reviewer can see exactly which bytes changed - the property a platform/security
team asks for.