Composing Tasks
Tasks calling tasks - parameterized, reusable building blocks within one workflow
Steps can call tasks (task:), which makes tasks your unit of reuse inside
a workflow: define deploy_to_env once, call it three times with different
parameters.
Calling a task with parameters
name: promotion
defaults:
app_name: "checkout-service"
tasks:
deploy_to_env:
desc: "Deploy to one environment (parameterized)"
vars:
env_name: ""
replicas: "1"
steps:
- name: deploy
func: shell
do: echo "deploying {{ vars.app_name }} to {{ vars.env_name }} ({{ vars.replicas }} replicas)"
main:
steps:
- name: dev
task: deploy_to_env
vars:
env_name: "dev"
replicas: "1"
- name: staging
task: deploy_to_env
vars:
env_name: "staging"
replicas: "4"The calling step's vars: become the called task's parameters - same
precedence rules as everywhere else.
Transform: data shaping between tasks
When data needs reshaping between steps, transform runs JavaScript with
access to vars and steps:
- name: aggregate
func: transform
do: |
const regions = [
Number(steps.fetch_apac.orders),
Number(steps.fetch_emea.orders),
];
return { total: regions.reduce((a, b) => a + b, 0) };
- name: report
func: shell
do: 'echo "total orders: {{ steps.aggregate.total }}"'Two verified rules keep transform predictable:
- Transform code is not template-rendered -
{{ }}inside it passes through as literal text. - Since v0.8.0, transform sees the same merged
varsas templates (including--var). On older engines, stage runtime values through a previous step's outputs (JS always seessteps.*).
Parallel composition
Independent work runs concurrently in a parallel: block; every child's
outputs merge into the normal steps.* namespace afterwards (verified):
- name: build_all
parallel:
- name: build_frontend
func: shell
do: echo "frontend built"
outputs: { ok: "true" }
- name: build_backend
func: shell
do: echo "backend built"
outputs: { ok: "true" }
- name: package
func: shell
do: echo "fe={{ steps.build_frontend.ok }} be={{ steps.build_backend.ok }}"If any parallel child fails (and is not caught), the block fails.
Run it
orchstep runWhere to go next
Modules - the same idea across workflow boundaries: reusable, versioned units shared between projects and teams.