OrchShell: dotenv++ for applications
OrchShell (orchstep do) runs any command or script with your environment's application config — structured per-env vars and dotenv — no orchstep.yml required.
OrchShell
OrchShell is orchstep do pointed at a folder of environment files. It's
dotenv++ for applications: dotenv hands your process flat KEY=value strings;
OrchShell additionally hands your commands structured application config —
whole objects, per environment, layered by group — and then runs them.
No orchstep.yml. No task. Just environment files and a command.
orchstep do --env prod-eu 'helm upgrade checkout ./chart \
--set image={{ env.REGISTRY }}/checkout:{{ vars.version }} \
--set replicas={{ vars.replicas }} \
--set resources.cpu={{ vars.resources.cpu }} \
--set ingress.host={{ vars.ingress.host }}'A project with no orchstep.yml
OrchShell discovers a conventional environments/ directory (rich application
vars) and the dotenv files declared in orchstep_config.yml (primitive env vars):
# Always loaded. Values can be whole OBJECTS, not just strings.
app_name: checkout
version: "1.4.2"
replicas: 1
resources:
cpu: "250m"
memory: 256Mi
ingress:
host: localhost
tls: falseThere is no orchstep.yml in that folder. OrchShell builds the context from the
files it finds.
How the layering works
Environment files merge hierarchically by name. Asking for prod-eu loads:
defaults.yml -> prod.yml (group) -> prod-eu.yml (environment)Later files win; objects replace (they don't deep-merge). So for --env prod-eu:
| Variable | Resolved value | From |
|---|---|---|
vars.app_name | checkout | defaults |
vars.version | 1.4.2 | defaults |
vars.replicas | 6 | prod (group) |
vars.resources.cpu | 2 | prod (group) |
vars.ingress.host | eu.checkout.example.com | prod-eu |
vars.region | eu-west-1 | prod-eu |
env.REGISTRY | registry.example.com | common.env (via orchstep_config.yml) |
Why this beats plain dotenv
dotenv/direnv give you export KEY=value — flat strings only. To pass an
application a structure (resources: {cpu, memory}) you'd flatten it into a
dozen RESOURCES_CPU=… variables and reassemble them downstream.
OrchShell keeps the structure. Your command references {{ vars.resources.cpu }}
and {{ vars.ingress.host }} directly, with real per-environment layering — and
still gets the flat env vars ($REGISTRY) from the declared dotenv for free. It's
the config layer your apps actually want, available to anything you can run in a
shell.
Profile dotenv files — declared in orchstep_config.yml
The classic layered dotenv pattern — a shared file, a per-profile file, and an
optional local-secrets file — is declared once in orchstep_config.yml's
dotenv: list (shown in the file tree above), not passed on the CLI:
# orchstep_config.yml
dotenv:
- common.env # shared by every profile (always)
- "deploy_{{ vars.environment }}.env" # the selected profile
- "secrets.local.env?" # local-only, git-ignored, optional (?)--env dev loads deploy_dev.env; --env prod loads deploy_prod.env. The ?
suffix skips a file that isn't there.
Two things make this work:
- It loads after
--env. The config'sdotenv:is applied once the environment is selected, so a path keyed on the selection (deploy_{{ vars.environment }}.env) resolves. (A workflow's owndotenv:loads earlier, before--env, so use the config for profile selection.) - It's declared, not magic. OrchStep does not auto-load a stray
.envfrom the current directory — loading only what a committed config file declares is a trust boundary, so a directory you didn't write can't slip env vars (like a poisonedPATH) into the commands you run.
Use it
# One-off, against an environment:
orchstep do --env prod-eu 'echo deploying to {{ vars.ingress.host }}'
# A whole script (or make it executable with the shebang above):
./deploy
# Preview the expansion without running it:
orchstep do --env prod-us --render 'kubectl scale --replicas={{ vars.replicas }} deploy/checkout'
# Interactive — drop into a shell where the config is already loaded:
orchstep do --env prod-eu
# orchstep> echo {{ vars.region }} -> {{ vars.ingress.host }}
# eu-west-1 -> eu.checkout.example.comSee also
- Ad-hoc Commands — the full
orchstep doreference (all input modes, REPL, exit codes). - Environments — the hierarchical external-file format in depth.