Executable Runbooks (DevOps)
Automated deployment workflows with dependency management
Recipe 3: Executable Runbooks (DevOps)
Goal: Define an automated server health check and deployment workflow with dependency management, error handling, and rollback capabilities.
Runbook Benefits
Executable runbooks capture DevOps procedures as code, making them testable, version-controlled, and consistently executable. No more copy-pasting commands from wiki pages!
Create the Runbook
Create deployment-runbook.md:
---
runbook:
name: Production Deployment
version: 1.0.0
author: DevOps Team
---
# Production Deployment Runbook
This runbook automates the deployment process with health checks.
## Pre-Flight Checks
```bash check-git-status --descr "Verify clean git working directory"
#!/usr/bin/env -S bash
set -e
if [ -n "$(git status --porcelain)" ]; then
echo "ERROR: Working directory is not clean"
git status --short
exit 1
fi
echo "OK: Git working directory is clean"
```
```bash check-tests --descr "Run test suite" --dep check-git-status
#!/usr/bin/env -S bash
set -e
echo "Running test suite..."
npm test
if [ $? -eq 0 ]; then
echo "OK: All tests passed"
else
echo "ERROR: Tests failed"
exit 1
fi
```
## Build Phase
```bash build-app --descr "Build production artifacts" --dep check-tests
#!/usr/bin/env -S bash
set -e
echo "Building production artifacts..."
npm run build
echo "OK: Build completed successfully"
ls -la dist/
```
## Health Check
```bash health-check --descr "Verify server health"
#!/usr/bin/env -S bash
set -e
SERVER_URL="${SERVER_URL:-http://localhost:3000}"
echo "Checking server health at $SERVER_URL..."
response=$(curl -s -o /dev/null -w "%{http_code}" "$SERVER_URL/health")
if [ "$response" = "200" ]; then
echo "OK: Server is healthy (HTTP $response)"
else
echo "ERROR: Server health check failed (HTTP $response)"
exit 1
fi
```
## Deployment
```bash deploy --descr "Deploy to production" --dep build-app,health-check
#!/usr/bin/env -S bash
set -e
echo "Deploying to production..."
# Example: Deploy to server
rsync -avz --delete dist/ user@server:/var/www/app/
echo "Restarting application..."
ssh user@server 'systemctl restart app'
echo "OK: Deployment completed"
```
## Post-Deployment Verification
```bash verify-deployment --descr "Verify deployment success" --dep deploy
#!/usr/bin/env -S bash
set -e
echo "Verifying deployment..."
sleep 10 # Wait for app to start
response=$(curl -s -o /dev/null -w "%{http_code}" "http://production-server/health")
if [ "$response" = "200" ]; then
echo "OK: Deployment verified successfully"
else
echo "ERROR: Post-deployment verification failed"
exit 1
fi
```
## Rollback (Manual)
```bash rollback --descr "Rollback to previous version"
#!/usr/bin/env -S bash
set -e
echo "Rolling back to previous version..."
ssh user@server 'cd /var/www/app && git checkout HEAD~1 && systemctl restart app'
echo "Rollback completed"
```Dependency Graph
The --dep flag creates a dependency graph, ensuring tasks run in the correct order. Spry automatically builds and executes the DAG.
Visualize the Execution Plan
Before running, view the task dependency graph:
# List all tasks and their dependencies
spry rb ls deployment-runbook.md
# Visualize the DAG
spry rb run deployment-runbook.md --visualize plainExample Output:
Execution Plan:
Layer 0: check-git-status, health-check
Layer 1: check-tests
Layer 2: build-app
Layer 3: deploy
Layer 4: verify-deploymentExecute the Runbook
Run the complete deployment pipeline:
# Execute all tasks in dependency order
spry rb run deployment-runbook.md --verbose richThis runs the entire pipeline with rich progress output, stopping on any error.
# Run only the deploy task (and its dependencies)
spry rb task deploy deployment-runbook.mdThis executes only deploy and any tasks it depends on.
# Execute with concise summary
spry rb run deployment-runbook.md --summarizeShows a summary of task execution with success/failure indicators.
Handle Failures and Rollback
If deployment fails, execute the rollback task:
# Manual rollback
spry rb task rollback deployment-runbook.mdError Handling
All tasks use set -e to fail fast on errors. The runbook stops at the first failure, preventing partial deployments and making it safe to retry.
Advanced Runbook Patterns
Multi-Environment Deployments
Use environment variables to target different environments:
# Development
ENV=dev spry rb run deployment-runbook.md
# Staging
ENV=staging spry rb run deployment-runbook.md
# Production
ENV=production spry rb run deployment-runbook.mdIn your runbook:
SERVER_URL="${SERVER_URL:-http://${ENV:-dev}.example.com}"Send Notifications
Add notification tasks for Slack, email, or PagerDuty:
#!/usr/bin/env -S bash
# Notify on deployment completion
curl -X POST https://hooks.slack.com/services/YOUR/WEBHOOK/URL \
-H 'Content-Type: application/json' \
-d "{\"text\":\"Deployment completed successfully to ${ENV}\"}"Manual Approval Gates
Add interactive approval steps:
#!/usr/bin/env -S bash
echo "About to deploy to PRODUCTION"
echo "Type 'yes' to continue:"
read confirmation
if [ "$confirmation" != "yes" ]; then
echo "Deployment cancelled"
exit 1
fiHow is this guide?
Last updated on