Reusable steps
Compose operations from shared step files with uses: and with: instead of copying blocks between runbooks.
Step Composition (uses:)
SAMARITAN supports inline step composition using the uses: directive — inspired by GitHub Actions. Point at a file, and all its steps expand inline at that position. No registration, no IDs to remember.
steps:
- uses: ./tasks/database-backup.yaml # all steps from file expand here
- uses: ./tasks/health-checks.yaml # same file, with variables
with:
ENDPOINT: ${ENDPOINT}
TIMEOUT: 60
- uses: ./tasks/health-checks.yaml # same file again, different vars
with:
TIMEOUT: 120File Sources
uses: accepts local paths, HTTPS URLs, or GitHub shorthands:
steps:
# Local file (relative to this operation)
- uses: ./templates/health-checks.yaml
with: { ENDPOINT: https://api.example.com }
# HTTPS URL
- uses: https://raw.githubusercontent.com/org/repo/main/templates/deploy.yaml
with: { SERVICE: my-app }
# GitHub shorthand github:owner/repo//path@ref
- uses: github:org/ops-templates//health-checks.yaml@v2.1.0
with: { NAMESPACE: production }Writing Reusable Step Files
Step files can be a bare step array or a full operation file:
# tasks/health-checks.yaml — bare step array
- name: Check API Health
type: automatic
command: curl -f ${ENDPOINT}/health
timeout: ${TIMEOUT}
- name: Verify Database
type: automatic
command: kubectl exec ${SERVICE_NAME} -- nc -zv ${DB_HOST} 5432# tasks/k8s-deploy.yaml — full operation format (steps: field is extracted)
name: Kubernetes Deployment Steps
version: 1.0.0
common_variables:
REPLICAS: 2 # default — overridable via with:
steps:
- name: Apply Manifests
type: automatic
command: kubectl apply -f k8s/${SERVICE_NAME}.yaml -n ${NAMESPACE}
- name: Wait for Rollout
type: automatic
command: kubectl rollout status deployment/${SERVICE_NAME} -n ${NAMESPACE}Complete Example
name: Microservice Deployment
version: 2.0.0
environments:
- name: staging
variables:
ENDPOINT: https://staging.api.example.com
DB_HOST: staging-db
SERVICE_NAME: my-service
NAMESPACE: staging
- name: production
variables:
ENDPOINT: https://api.example.com
DB_HOST: prod-db
SERVICE_NAME: my-service
NAMESPACE: production
steps:
# Pre-deployment health checks
- uses: ./tasks/health-checks.yaml
with:
ENDPOINT: ${ENDPOINT}
DB_HOST: ${DB_HOST}
SERVICE_NAME: ${SERVICE_NAME}
TIMEOUT: 60
- name: Deploy Application
type: manual
instruction: Deploy the app
# Post-deployment health checks (same file, stricter timeout)
- uses: ./tasks/health-checks.yaml
with:
ENDPOINT: ${ENDPOINT}
DB_HOST: ${DB_HOST}
SERVICE_NAME: ${SERVICE_NAME}
TIMEOUT: 120How it works:
- File is loaded (local, HTTPS, or GitHub)
- Steps are extracted (from bare array or
steps:field) ${VAR}placeholders are substituted with values fromwith:- Steps expand inline at the
uses:position - Generated manuals show the fully expanded, substituted steps
Variable substitution:
- All plain
${VAR}placeholders must be satisfied bywith:orcommon_variablesdefaults - Shell parameter expansions (
${POD:?},${REGION:-us-east-1},${PATH##*/}, … — any name that isn't a plain identifier) are not template variables: they're never required inwith:and pass through to the shell untouched, so fail-fast bash guards for shell-local variables keep working inside reused files - Type-preserving:
timeout: ${TIMEOUT}withTIMEOUT: 60→timeout: 60(number, not string) - Omit
with:entirely if the file has no${VAR}placeholders
Block-scoped pre-flight
Generated manuals group steps into Pre-Flight / Flight / Post-Flight phases. A reused file can carry its own phase: preflight checks (e.g. a migration block that verifies the DB is reachable before migrating). Those checks stay local to the reused block — they render right before that block's steps in the Flight phase, not hoisted into the operation's top-level Pre-Flight section. The operation's own top-level phase: preflight steps still group into the global Pre-Flight section as usual. This is automatic; no extra configuration is needed. (A reused block whose steps are all preflight does group into the top-level Pre-Flight section, since it is purely a set of checks.)
See examples/scoped-preflight.yaml (+ examples/templates/db-migration.yaml).
Example files:
examples/templates/health-checks.yaml— service health verificationexamples/templates/kubernetes-deployment.yaml— K8s deployment workflowexamples/templates/notifications.yaml— team notification stepsexamples/templates/db-migration.yaml— migration block with local pre-flightexamples/templates/fail-fast-restart.yaml— shell${VAR:?}guards inside a reused file
See examples/deployment-with-templates.yaml for a complete example, and examples/uses-with-shell-guards.yaml for mixing template variables with shell parameter-expansion guards.
Reusable Step Files
# operation.yaml
name: Complex Deployment
version: 2.0.0
steps:
# Expand all database steps inline
- uses: ./lib/database-steps.yaml
- name: Custom Step
type: manual
instruction: |
Execute custom logic:
```bash
echo "Custom logic"
```
# Expand all monitoring steps inline
- uses: ./lib/monitoring-steps.yaml