BLOG/BY COMPANY SIZE
THEME
BY COMPANY SIZE

OrchStep for early startups

Your first three engineers are shipping faster than they can document. Here's how one orchstep.yml runs the same locally and in CI, so the deploy works the same on a laptop as in the pipeline.

Apr 6, 2026 OrchStep Team 7 minROLE: AnySCALE: Startup

The first few engineers at a startup move fast and write almost nothing down. The deploy lives in one person's head and a GitHub Actions YAML that's slowly diverging from what they actually run on their laptop. Someone pushes a fix, CI does something subtly different from local, and you lose an afternoon to "works on my machine, fails in the pipeline."

At this stage you don't need a platform team or a golden path. You need one description of how the app is built and shipped — one that runs the same way whether a human types it or CI does. That's the gap OrchStep fills for an early team: the same orchstep.yml is your local command and your CI step.

What automation looks like at this stage

You have CI now (probably GitHub Actions), but it's a second, parallel definition of your build. Local has a Makefile or a deploy.sh; CI has YAML that reimplements the same steps with different env handling. Two sources of truth means two things to keep in sync, and they never stay in sync.

The fix isn't more CI — it's making CI call the same workflow you call locally. Your pipeline shrinks to "install orchstep, run the task." Everything else lives in one file every engineer can read and run.

Two workflows: CI and deploy

Split the work into a ci task (what every push must pass) and a deploy task that reuses it. The deploy gates on the target, so the same definition handles a staging push and a guarded production release.

ORCHSTEP.YML
name: app
defaults:
  version: "0.2.0"
  target: staging
tasks:
  ci:
    steps:
      - name: lint
        func: shell
        do: echo "linting"
      - name: test
        func: shell
        do: echo "running tests"
  deploy:
    steps:
      - name: ci
        task: ci                # CI runs first, every time
      - name: release
        func: shell
        do: echo "deploying {{ vars.version }} to {{ vars.target }}"
        catch:
          - name: rollback
            func: shell
            do: echo "rolling back {{ vars.target }}"
      - name: gate
        if: '{{ eq vars.target "production" }}'
        then:
          - name: smoke
            func: shell
            do: echo "running smoke tests in production"
        else:
          - name: note
            func: shell
            do: echo "staging deploy complete"
HOW EACH SIDE RUNS IT
# A laptop, mid-afternoon
orchstep run ci
orchstep run deploy --var version=0.3.1

# The exact same task, in CI
orchstep run deploy \
  --var version=$GIT_TAG \
  --var target=production

# Preview the prod path without shipping
orchstep run deploy --var target=production --dry-run

The important part is what doesn't change between those two columns. CI doesn't reimplement lint, test, and release in pipeline YAML — it installs the binary and runs the same task your engineers run by hand. The gate means production automatically gets a smoke test that staging skips, and the catch: rolls back without a hand-rolled ||. One file, and the laptop and the pipeline finally agree.

Why this scales with the team

When engineer number four joins, onboarding is "clone the repo, run orchstep menu." They see every task with single-key hotkeys, run the inner loop, and ship to staging the same day — without a Notion page that's already stale. The workflow is the documentation, and because CI runs it too, it can't rot without the pipeline going red.

orchstep menu

What you gained

ConcernTwo definitions (local + CI)One orchstep.yml
Build defined inMakefile and pipeline YAMLone file both call
"Works locally, fails in CI"constantsame task runs both places
Production safetyhope someone remembersif: gate adds a smoke test
Rollback|| after the deploy commandcatch: block
Onboardinga stale wiki pageorchstep menu
Preview a risky deploypush and watch--dry-run prints the plan

Where OrchStep is not the answer

If your whole pipeline is genuinely "run the tests, deploy on green" and your CI vendor's YAML expresses that cleanly, you may not need this yet. OrchStep earns its keep the moment local and CI start to diverge, or the moment you want a command an engineer can run on a laptop and trust in the pipeline. Don't adopt it to look like a bigger company than you are.

Where to go next

The same orchstep.yml your engineers run by hand is the one CI runs. Start with orchstep init and point your pipeline at the task.

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

RELATED — BY COMPANY SIZE