From Make
Translate a Makefile of phony targets into an OrchStep workflow - targets, prerequisites, variables, .PHONY, and make -j.
If you use make as a command runner - a Makefile full of .PHONY targets
like build, test, deploy - OrchStep is a direct, friendlier replacement.
You keep the same mental model (named commands that run shell) and lose the
parts everyone trips over: tab-sensitive recipes, .PHONY bookkeeping, and
Bash-only portability.
The 30-second version
make -> orchstep run # default task
make build -> orchstep run build
make ci -> orchstep run ci
make deploy ENV=prod V=2.1 -> orchstep run deploy --var environment=prod --var version=2.1How the concepts map
| Make | OrchStep |
|---|---|
A target (build:) | A task (build: under tasks:) |
| A recipe line (tab + shell) | A step: func: shell with do: |
Prerequisites (ci: test build) | Steps that call task: test / task: build |
VAR ?= x and $(VAR) | defaults: plus {{ vars.VAR }} |
make build VAR=x | orchstep run build --var var=x |
.PHONY: build | Nothing - tasks are never file targets |
make -j2 a b | A parallel: block |
@echo (silent) | --log-level / --output |
Side by side
VERSION ?= 1.0.0
ENV ?= staging
.PHONY: build test deploy ci
build:
echo "building v$(VERSION)"
test:
echo "running tests"
deploy:
echo "deploying v$(VERSION) to $(ENV)"
ci: test buildname: app
desc: Build, test, and deploy the app
defaults:
version: "1.0.0"
environment: "staging"
tasks:
build:
steps:
- name: compile
func: shell
do: echo "building v{{ vars.version }}"
test:
steps:
- name: unit
func: shell
do: echo "running tests"
deploy:
steps:
- name: ship
func: shell
do: echo "deploying v{{ vars.version }} to {{ vars.environment }}"
ci: # "prerequisites" become task calls
steps:
- name: run_test
task: test
- name: run_build
task: buildRun it
orchstep run ci
orchstep run deploy --var environment=production --var version=2.1.0$ orchstep run deploy --var environment=production --var version=2.1.0
$ echo "deploying v2.1.0 to production"
deploying v2.1.0 to production
Result: successNote that make deploy ENV=prod (positional-ish VAR=value) becomes the
explicit, named --var environment=prod. List everything with
orchstep list-tasks.
Running targets in parallel
make -j2 lint test becomes a parallel: block - clearer, and it works the
same on every OS:
tasks:
check:
steps:
- name: fan_out
parallel:
- name: lint
func: shell
do: echo "linting"
- name: test
func: shell
do: echo "testing"Gotchas worth knowing
- No tabs. OrchStep is YAML - the single most common Makefile error (spaces where a tab belongs) simply cannot happen.
- No
.PHONY. Tasks are never confused with files on disk, so there is nothing to declare. envis reserved. Don't name a variableenv- that namespace is for environment variables ({{ env.PATH }}). Useenvironment(the loader will stop you with a clear error otherwise).- Make as a build system is different. If you actually rely on file-target
timestamps and automatic variables (
$@,$<) for incremental builds, that is a build graph, not a command runner - keep Make for it and call it from a step (do: make dist/app). For the.PHONYcommand-runner case (the common one), OrchStep is the better home.
Migrate one target at a time
A step is just shell, so you can wrap an old target while you convert the rest:
tasks:
build:
steps:
- name: legacy
func: shell
do: make -f Makefile.old buildWhat you gain
orchstep run --dry-runpreviews the whole chain (includingci->test/build).- The same file runs on Windows without
makeinstalled. - Steps pass typed outputs instead of echoing strings.
- Shared targets can become versioned modules.
Where to go next
- Composing Tasks - how
task:calls pass parameters. - Task Files - split a big Makefile's worth of targets across files.
- CLI Reference - every flag for
orchstep run.