Advanced Features¶
Sloth Runner provides powerful advanced features for enterprise deployments using the Modern DSL pattern.
Table of Contents¶
- Conditional Execution
- Lifecycle Hooks
- Artifact Management
- Error Handling & Retries
- Parallel Execution
- Task Dependencies
- Asynchronous Tasks
- Distributed Execution
Conditional Execution¶
Control when tasks run using run_if and abort_if conditions.
Basic Conditional Execution¶
task("deploy_to_production")
:description("Deploy only in production environment")
:command(function(this, params)
log.info("Deploying to production...")
return true, "Deployment successful"
end)
:run_if(function(this, params)
return os.getenv("ENV") == "production"
end)
:build()
task("skip_tests")
:description("Skip tests if SKIP_TESTS is set")
:command(function(this, params)
exec.run("npm test")
return true, "Tests passed"
end)
:run_if(function(this, params)
return os.getenv("SKIP_TESTS") ~= "true"
end)
:build()
Abort Workflow on Condition¶
task("security_check")
:description("Abort workflow if security vulnerabilities found")
:command(function(this, params)
local result = exec.run("npm audit --json")
local vulnerabilities = json.decode(result.stdout)
return true, "Security check completed", { vulnerabilities = vulnerabilities }
end)
:abort_if(function(this, params)
local result = exec.run("npm audit")
return result.exit_code ~= 0
end)
:build()
Lifecycle Hooks¶
Execute custom logic at different stages of task execution.
Complete Lifecycle Example¶
task("deploy_with_hooks")
:description("Deployment with full lifecycle management")
:pre_hook(function(this, params)
log.info("Pre-deployment: Taking snapshot...")
exec.run("aws ec2 create-snapshot --volume-id vol-123")
return true, "Snapshot created"
end)
:command(function(this, params)
log.info("Deploying application...")
exec.run("kubectl apply -f deployment.yaml")
return true, "Application deployed"
end)
:post_hook(function(this, params)
log.info("Post-deployment: Running smoke tests...")
exec.run("./smoke-tests.sh")
return true, "Smoke tests passed"
end)
:on_success(function(this, params)
log.success("Deployment successful! Sending notification...")
exec.run("slack-notify 'Deployment successful'")
return true, "Notification sent"
end)
:on_failure(function(this, params, err)
log.error("Deployment failed: " .. err)
exec.run("slack-notify 'Deployment failed: " .. err .. "'")
exec.run("kubectl rollback deployment/myapp")
return false, "Rollback initiated"
end)
:on_timeout(function(this, params)
log.warn("Deployment timed out, rolling back...")
exec.run("kubectl rollback deployment/myapp")
return false, "Timeout rollback"
end)
:timeout("10m")
:build()
Multi-Stage Deployment with Hooks¶
task("blue_green_deployment")
:description("Blue-green deployment with validation")
:pre_hook(function(this, params)
log.info("Preparing green environment...")
exec.run("terraform apply -target=module.green")
return true, "Green environment ready"
end)
:command(function(this, params)
log.info("Deploying to green environment...")
exec.run("ansible-playbook deploy-green.yml")
return true, "Deployed to green"
end)
:post_hook(function(this, params)
log.info("Validating green environment...")
local result = exec.run("./health-check.sh green")
if result.exit_code == 0 then
log.info("Switching traffic to green...")
exec.run("./switch-traffic.sh green")
return true, "Traffic switched"
else
return false, "Health check failed"
end
end)
:on_success(function(this, params)
log.info("Decommissioning blue environment...")
exec.run("terraform destroy -target=module.blue")
return true, "Blue environment removed"
end)
:on_failure(function(this, params, err)
log.error("Deployment failed, cleaning up green...")
exec.run("terraform destroy -target=module.green")
return false, "Cleanup completed"
end)
:build()
Artifact Management¶
Share files between tasks using the artifact system.
Basic Artifact Workflow¶
local build_task = task("build")
:description("Build application and produce artifacts")
:command(function(this, params)
log.info("Building application...")
exec.run("go build -o myapp")
exec.run("tar czf myapp.tar.gz myapp")
return true, "Build successful"
end)
:artifacts({"myapp.tar.gz", "myapp"})
:build()
local test_task = task("test")
:description("Test using built artifacts")
:depends_on({"build"})
:consumes({"myapp"})
:command(function(this, params)
log.info("Running tests with artifact...")
exec.run("./myapp --version")
exec.run("go test ./...")
return true, "Tests passed"
end)
:build()
local deploy_task = task("deploy")
:description("Deploy using built artifacts")
:depends_on({"test"})
:consumes({"myapp.tar.gz"})
:command(function(this, params)
log.info("Deploying artifact...")
exec.run("scp myapp.tar.gz server:/opt/app/")
exec.run("ssh server 'cd /opt/app && tar xzf myapp.tar.gz'")
return true, "Deployment successful"
end)
:build()
workflow.define("ci_cd_pipeline")
:description("Complete CI/CD with artifact management")
:version("1.0.0")
:tasks({build_task, test_task, deploy_task})
Multi-Stage Artifact Pipeline¶
local compile_task = task("compile")
:description("Compile source code")
:command(function(this, params)
exec.run("gcc -o program main.c")
return true, "Compilation successful"
end)
:artifacts({"program"})
:build()
local package_task = task("package")
:description("Package compiled program")
:depends_on({"compile"})
:consumes({"program"})
:command(function(this, params)
exec.run("docker build -t myapp:latest .")
exec.run("docker save myapp:latest > myapp.tar")
return true, "Package created"
end)
:artifacts({"myapp.tar"})
:build()
local distribute_task = task("distribute")
:description("Distribute packaged application")
:depends_on({"package"})
:consumes({"myapp.tar"})
:command(function(this, params)
exec.run("aws s3 cp myapp.tar s3://artifacts/myapp/")
return true, "Distribution complete"
end)
:build()
workflow.define("artifact_pipeline")
:description("Multi-stage artifact pipeline")
:version("1.0.0")
:tasks({compile_task, package_task, distribute_task})
Error Handling & Retries¶
Implement robust error handling with automatic retries.
Retry Strategies¶
task("flaky_api_call")
:description("Call external API with exponential backoff")
:command(function(this, params)
local response = http.get("https://api.example.com/data")
if response.status ~= 200 then
return false, "API call failed with status " .. response.status
end
return true, "API call successful"
end)
:retries(5, "exponential")
:timeout("30s")
:build()
task("database_migration")
:description("Run database migration with fixed retry interval")
:command(function(this, params)
local result = exec.run("./migrate.sh")
return result.exit_code == 0, result.stdout
end)
:retries(3, "fixed")
:timeout("5m")
:build()
task("network_operation")
:description("Network operation with linear backoff")
:command(function(this, params)
exec.run("rsync -avz /data remote:/backup/")
return true, "Sync completed"
end)
:retries(3, "linear")
:build()
Error Recovery Workflow¶
local main_task = task("main_operation")
:description("Main operation with error recovery")
:command(function(this, params)
local result = exec.run("./critical-operation.sh")
if result.exit_code ~= 0 then
return false, "Operation failed: " .. result.stderr
end
return true, "Operation successful"
end)
:retries(3, "exponential")
:on_failure(function(this, params, err)
log.error("All retries exhausted, initiating recovery...")
exec.run("./recovery.sh")
return false, "Recovery initiated"
end)
:build()
workflow.define("resilient_workflow")
:description("Workflow with comprehensive error handling")
:version("1.0.0")
:tasks({main_task})
Parallel Execution¶
Execute multiple tasks concurrently for improved performance.
Parallel Task Groups¶
task("lint")
:description("Run linting")
:command(function(this, params)
exec.run("eslint .")
return true, "Linting complete"
end)
:build()
task("type_check")
:description("Run type checking")
:command(function(this, params)
exec.run("tsc --noEmit")
return true, "Type checking complete"
end)
:build()
task("unit_tests")
:description("Run unit tests")
:command(function(this, params)
exec.run("jest")
return true, "Unit tests complete"
end)
:build()
task("integration_tests")
:description("Run integration tests")
:command(function(this, params)
exec.run("npm run test:integration")
return true, "Integration tests complete"
end)
:build()
task("parallel_quality_checks")
:description("Run all quality checks in parallel")
:command(function(this, params)
local results, err = parallel({
{ name = "lint", command = "eslint ." },
{ name = "typecheck", command = "tsc --noEmit" },
{ name = "test", command = "jest" },
{ name = "audit", command = "npm audit" }
})
if err then
return false, "Some checks failed: " .. err
end
return true, "All checks passed"
end)
:build()
workflow.define("quality_pipeline")
:description("Parallel quality checks workflow")
:version("1.0.0")
:tasks({parallel_quality_checks})
Task Dependencies¶
Create complex dependency chains between tasks.
Linear Dependencies¶
local install = task("install")
:description("Install dependencies")
:command(function(this, params)
exec.run("npm install")
return true, "Dependencies installed"
end)
:build()
local build = task("build")
:description("Build application")
:depends_on({"install"})
:command(function(this, params)
exec.run("npm run build")
return true, "Build complete"
end)
:build()
local test = task("test")
:description("Run tests")
:depends_on({"build"})
:command(function(this, params)
exec.run("npm test")
return true, "Tests passed"
end)
:build()
local deploy = task("deploy")
:description("Deploy application")
:depends_on({"test"})
:command(function(this, params)
exec.run("./deploy.sh")
return true, "Deployment complete"
end)
:build()
workflow.define("linear_pipeline")
:description("Linear dependency pipeline")
:version("1.0.0")
:tasks({install, build, test, deploy})
Complex Dependencies¶
local setup_db = task("setup_db")
:description("Setup database")
:command(function(this, params)
exec.run("docker-compose up -d postgres")
return true, "Database ready"
end)
:build()
local setup_cache = task("setup_cache")
:description("Setup cache")
:command(function(this, params)
exec.run("docker-compose up -d redis")
return true, "Cache ready"
end)
:build()
local migrate = task("migrate")
:description("Run migrations")
:depends_on({"setup_db"})
:command(function(this, params)
exec.run("./migrate.sh")
return true, "Migrations complete"
end)
:build()
local seed = task("seed")
:description("Seed database")
:depends_on({"migrate"})
:command(function(this, params)
exec.run("./seed.sh")
return true, "Seeding complete"
end)
:build()
local start_app = task("start_app")
:description("Start application")
:depends_on({"seed", "setup_cache"})
:command(function(this, params)
exec.run("npm start")
return true, "Application started"
end)
:build()
workflow.define("complex_startup")
:description("Complex dependency workflow")
:version("1.0.0")
:tasks({setup_db, setup_cache, migrate, seed, start_app})
Asynchronous Tasks¶
Run tasks in the background without blocking workflow execution.
Background Tasks¶
task("monitoring")
:description("Start monitoring in background")
:command(function(this, params)
exec.run("./monitor.sh &")
return true, "Monitoring started"
end)
:async(true)
:build()
task("main_process")
:description("Main application process")
:command(function(this, params)
log.info("Starting main process...")
exec.run("./app")
return true, "Process complete"
end)
:build()
workflow.define("async_workflow")
:description("Workflow with async background tasks")
:version("1.0.0")
:tasks({
task("monitoring"):async(true):command(function(this, params)
exec.run("./monitor.sh")
return true, "Monitoring"
end):build(),
task("main_process"):command(function(this, params)
exec.run("./app")
return true, "Complete"
end):build()
})
Distributed Execution¶
Execute tasks across multiple agents in a distributed environment.
Agent-Targeted Tasks¶
task("deploy_web_servers")
:description("Deploy to web server agents")
:target_agent("web-*")
:command(function(this, params)
exec.run("systemctl restart nginx")
return true, "Web server restarted"
end)
:build()
task("backup_databases")
:description("Backup on database agents")
:target_agent("db-*")
:command(function(this, params)
exec.run("pg_dump mydb > /backup/mydb.sql")
return true, "Backup complete"
end)
:build()
task("update_monitoring")
:description("Update monitoring agents")
:target_agent("monitor-*")
:command(function(this, params)
exec.run("./update-prometheus.sh")
return true, "Monitoring updated"
end)
:build()
workflow.define("distributed_operations")
:description("Distributed multi-agent operations")
:version("1.0.0")
:tasks({deploy_web_servers, backup_databases, update_monitoring})
Tag-Based Execution¶
task("security_scan")
:description("Run security scan on production servers")
:target_tags({"production", "web"})
:command(function(this, params)
exec.run("trivy filesystem /")
return true, "Security scan complete"
end)
:build()
task("performance_test")
:description("Run performance tests on staging")
:target_tags({"staging", "app"})
:command(function(this, params)
exec.run("k6 run performance-test.js")
return true, "Performance test complete"
end)
:build()
workflow.define("environment_specific")
:description("Environment-specific distributed tasks")
:version("1.0.0")
:tasks({security_scan, performance_test})
Related Documentation¶
- AI Integration - Intelligent workflow optimization
- Distributed Agents - Multi-agent orchestration
- Web Dashboard - Visual management interface
- Advanced Scheduler - Cron-based scheduling
- Multi-Cloud Excellence - Cloud provider integration
- Stack Management - State and environment management
Getting Started¶
See Getting Started Guide for installation instructions.
More Examples¶
Check out Advanced Examples for complete end-to-end use cases.
English | Portuguรชs | ไธญๆ