OrchStep for open-source maintainers
Maintainers run the same release and triage steps over and over, usually from memory at 11pm. Here's how to put the project's rituals in one file contributors can run too.
Maintaining an open-source project is mostly remembering things. The exact order to cut a release. Which checks have to pass before you merge. The five commands a new contributor needs before their first PR will even build. None of it is hard. All of it lives in your head, in a RELEASING.md that's three versions out of date, and in the muscle memory you don't have at 11pm when someone's blocking PR is finally green.
The fix isn't a bigger CI config. It's putting the project's rituals in one file that you, your co-maintainers, and your contributors all run the same way — locally and in CI.
What automation looks like for a maintainer
You don't have a platform team. You have you, maybe two co-maintainers, and a CI bill of zero dollars. Automation that fits that means:
- One file in the repo that documents and runs the project's rituals.
- The same commands a contributor runs locally and CI runs on a PR — so "works on my machine" stops being a category of bug.
- Releases that are a single command, not a checklist you hope you didn't skip a step in.
- No new service to maintain. You have enough to maintain.
Where OrchStep fits
OrchStep is a single binary that wraps your existing commands — go test, npm run build, git tag — in named tasks with retries, assertions, and rollback. A contributor downloads one binary and runs the exact gate CI runs. No more "why does CI fail when it passed for me."
Here's a maintainer kit: the PR gate and the release ritual in one file.
name: maintainer-kit
defaults:
version: "1.4.0"
branch: main
tasks:
# orchstep run pr-gate — the same checks a contributor runs locally
pr-gate:
steps:
- name: lint
func: shell
do: echo "linting changed files"
- name: test
func: shell
do: echo "running unit + integration tests"
retry:
max_attempts: 2
interval: "1s"
backoff_rate: 2.0
- name: verify
func: assert
args:
condition: '{{ eq vars.branch "main" }}'
message: "release checks only run against main"
# orchstep run release --var version=1.5.0
release:
steps:
- name: changelog
func: shell
do: echo "generating changelog for v{{ vars.version }}"
outputs:
tag: "v{{ vars.version }}"
- name: tag
func: shell
do: echo "tagging {{ steps.changelog.tag }}"
- name: publish
func: shell
do: echo "publishing {{ steps.changelog.tag }} to the registry"
retry:
max_attempts: 3
interval: "2s"
backoff_rate: 2.0
catch:
- name: announce-failure
func: shell
do: echo "release {{ steps.changelog.tag }} failed, opening issue"The pr-gate task is the contract: if it passes locally, it passes in CI, because it is what CI runs. The release task turns "did I remember to tag before publishing?" into a single command where the order is the file.
Three workflows worth stealing
1. The one-command release. orchstep run release --var version=1.5.0 generates the changelog, captures the tag as an output, tags, and publishes — with a retry: around the flaky publish step and a catch: that opens a failure issue instead of leaving you with a half-published release. The version is a variable, so cutting 1.5.1 is a flag, not an edit. See Variables & Outputs.
2. The contributor-runnable gate. Put pr-gate in your CONTRIBUTING guide as the command. A first-time contributor runs orchstep run pr-gate, sees exactly what the bots will see, and submits a green PR. Your CI calls the same task — the workflow refuses to hang waiting on input in a pipeline, so it's safe there. See Running in CI.
3. The "preview the release" dry-run. Before you tag anything public, orchstep run release --var version=1.5.0 --dry-run prints the resolved plan — the tag it would cut, the steps in order — and executes nothing. Cheap insurance against a fat-fingered version. See Previewing with Dry Run.
What you gained
| Concern | The old way | OrchStep |
|---|---|---|
| Release steps | RELEASING.md, run by hand | orchstep run release |
| Version bump | edit several files | --var version=1.5.0 |
| Flaky publish | re-run, hope | retry: + catch: opens an issue |
| "Works on my machine" | CI-only checks | contributors run the same pr-gate |
| Onboarding a contributor | a wiki page | one binary, one command |
| Release safety | cross fingers | --dry-run first |
OrchStep doesn't replace GitHub Actions — your release task runs inside it, identically to how it runs on your laptop. If your project is small enough that one Makefile target covers releases, keep the Makefile. Once the release ritual has more than a couple of ordered steps with retries and a rollback, a workflow file is the thing you'll actually keep up to date.
Where to go next
- Quick Start — your first workflow in two minutes
- Running in CI — the same task locally and on every PR
- Error Handling — retry, catch, finally, timeouts
- The assert function — guard release steps with explicit conditions
Tired of running your release from memory? Put the ritual in one file and let a contributor run the gate too.
curl -fsSL https://orchstep.dev/install.sh | sh