# Complete Workflow Example # This workflow demonstrates all features of the Attune workflow system ref: examples.complete_deployment_workflow label: "Complete Application Deployment Workflow" description: | A comprehensive example workflow that demonstrates: - Sequential and parallel execution - Conditional branching - Iteration and batching - Variable scoping and templating - Error handling and retry - Human-in-the-loop (inquiries) - Subworkflow invocation version: "1.0.0" # Input parameters accepted by this workflow parameters: app_name: type: string required: true description: "Name of the application to deploy" version: type: string required: true description: "Version to deploy" environment: type: string enum: [dev, staging, production] default: dev description: "Target environment" regions: type: array items: type: string default: ["us-east-1"] description: "AWS regions to deploy to" enable_canary: type: boolean default: false description: "Enable canary deployment" rollback_on_failure: type: boolean default: true description: "Automatically rollback on failure" # Output schema - what this workflow produces output: type: object properties: deployment_id: type: string status: type: string enum: [success, failed, rolled_back] deployed_version: type: string deployment_urls: type: array items: type: string duration_seconds: type: integer # Workflow-scoped variables vars: deployment_id: null start_time: null health_check_urls: [] failed_regions: [] successful_regions: [] canary_passed: false approval_granted: false rollback_initiated: false # Task execution graph tasks: # ============================================================================ # PHASE 1: VALIDATION & PREPARATION # ============================================================================ - name: start_workflow action: core.noop input: {} publish: - start_time: "{{ system.timestamp }}" on_success: validate_inputs - name: validate_inputs action: validation.validate_deployment_params input: app_name: "{{ parameters.app_name }}" version: "{{ parameters.version }}" environment: "{{ parameters.environment }}" regions: "{{ parameters.regions }}" retry: count: 2 delay: 5 on_success: check_environment_type on_failure: notify_validation_failed # Conditional: Production deployments require approval - name: check_environment_type action: core.noop input: {} decision: - when: "{{ parameters.environment == 'production' }}" next: require_production_approval - default: create_deployment_record # Human-in-the-loop: Require approval for production - name: require_production_approval action: core.inquiry input: prompt: | Approve production deployment? Application: {{ parameters.app_name }} Version: {{ parameters.version }} Regions: {{ parameters.regions | join(', ') }} schema: type: object properties: approved: type: boolean approver_notes: type: string assigned_to: "deployment-approvers" timeout: 3600 # 1 hour timeout publish: - approval_granted: "{{ task.require_production_approval.result.approved }}" decision: - when: "{{ workflow.approval_granted == true }}" next: create_deployment_record - default: cancel_deployment on_timeout: deployment_approval_timeout # ============================================================================ # PHASE 2: DEPLOYMENT PREPARATION # ============================================================================ - name: create_deployment_record action: deployments.create_record input: app_name: "{{ parameters.app_name }}" version: "{{ parameters.version }}" environment: "{{ parameters.environment }}" regions: "{{ parameters.regions }}" initiated_by: "{{ system.identity.login }}" publish: - deployment_id: "{{ task.create_deployment_record.result.id }}" on_success: parallel_pre_deployment_checks on_failure: notify_deployment_failed # Parallel execution: Run multiple checks concurrently - name: parallel_pre_deployment_checks type: parallel tasks: - name: check_docker_registry action: docker.check_registry_health input: registry: "{{ pack.config.docker_registry }}" - name: check_kubernetes_clusters action: kubernetes.check_clusters input: regions: "{{ parameters.regions }}" - name: check_database_migrations action: database.check_pending_migrations input: app_name: "{{ parameters.app_name }}" environment: "{{ parameters.environment }}" - name: verify_secrets action: secrets.verify_availability input: app_name: "{{ parameters.app_name }}" environment: "{{ parameters.environment }}" on_success: build_and_test on_failure: cleanup_failed_deployment # ============================================================================ # PHASE 3: BUILD & TEST # ============================================================================ - name: build_and_test action: ci.build_and_test input: app_name: "{{ parameters.app_name }}" version: "{{ parameters.version }}" registry: "{{ pack.config.docker_registry }}" run_tests: true timeout: 1800 # 30 minutes retry: count: 2 delay: 60 backoff: exponential on_success: push_container_image on_failure: notify_build_failed on_timeout: notify_build_timeout - name: push_container_image action: docker.push_image input: image: "{{ task.build_and_test.result.image_name }}" tag: "{{ parameters.version }}" registry: "{{ pack.config.docker_registry }}" on_success: check_canary_enabled on_failure: notify_push_failed # ============================================================================ # PHASE 4: CANARY DEPLOYMENT (CONDITIONAL) # ============================================================================ - name: check_canary_enabled action: core.noop input: {} decision: - when: "{{ parameters.enable_canary == true }}" next: deploy_canary - default: deploy_to_all_regions - name: deploy_canary action: kubernetes.deploy_canary input: app_name: "{{ parameters.app_name }}" image: "{{ task.build_and_test.result.image_uri }}" region: "{{ parameters.regions | first }}" traffic_percentage: 10 on_success: monitor_canary on_failure: handle_canary_failure - name: monitor_canary action: monitoring.analyze_canary input: app_name: "{{ parameters.app_name }}" duration: 300 # 5 minutes error_threshold: 0.01 publish: - canary_passed: "{{ task.monitor_canary.result.success }}" decision: - when: "{{ workflow.canary_passed == true }}" next: promote_canary - default: rollback_canary - name: promote_canary action: kubernetes.promote_canary input: app_name: "{{ parameters.app_name }}" region: "{{ parameters.regions | first }}" on_success: deploy_to_remaining_regions on_failure: rollback_canary - name: rollback_canary action: kubernetes.rollback_canary input: app_name: "{{ parameters.app_name }}" region: "{{ parameters.regions | first }}" publish: - rollback_initiated: true on_complete: notify_canary_failed # ============================================================================ # PHASE 5: MULTI-REGION DEPLOYMENT (WITH ITERATION) # ============================================================================ - name: deploy_to_all_regions action: kubernetes.deploy with_items: "{{ parameters.regions }}" input: app_name: "{{ parameters.app_name }}" image: "{{ task.build_and_test.result.image_uri }}" region: "{{ item }}" replicas: 3 environment: "{{ parameters.environment }}" retry: count: 2 delay: 30 publish: - health_check_urls: "{{ task.deploy_to_all_regions.results | map(attribute='health_url') | list }}" on_success: parallel_health_checks on_failure: handle_deployment_failures - name: deploy_to_remaining_regions action: kubernetes.deploy # Filter out first region (already has canary) with_items: "{{ parameters.regions | slice(start=1) }}" input: app_name: "{{ parameters.app_name }}" image: "{{ task.build_and_test.result.image_uri }}" region: "{{ item }}" replicas: 3 environment: "{{ parameters.environment }}" on_success: parallel_health_checks on_failure: handle_deployment_failures # ============================================================================ # PHASE 6: VERIFICATION # ============================================================================ - name: parallel_health_checks action: http.get with_items: "{{ workflow.health_check_urls }}" batch_size: 5 # Check 5 URLs at a time input: url: "{{ item }}" expected_status: 200 timeout: 30 retry: count: 10 delay: 10 backoff: linear on_success: run_smoke_tests on_failure: handle_health_check_failures - name: run_smoke_tests action: testing.run_smoke_tests input: app_name: "{{ parameters.app_name }}" environment: "{{ parameters.environment }}" base_urls: "{{ workflow.health_check_urls }}" timeout: 600 on_success: verify_metrics on_failure: handle_smoke_test_failures - name: verify_metrics action: monitoring.verify_deployment_metrics input: app_name: "{{ parameters.app_name }}" environment: "{{ parameters.environment }}" thresholds: error_rate: 0.01 latency_p99: 1000 cpu_usage: 80 on_success: update_load_balancer on_failure: handle_metrics_failures # ============================================================================ # PHASE 7: TRAFFIC ROUTING # ============================================================================ - name: update_load_balancer action: aws.update_load_balancer with_items: "{{ parameters.regions }}" input: app_name: "{{ parameters.app_name }}" region: "{{ item }}" target_version: "{{ parameters.version }}" on_success: finalize_deployment on_failure: handle_lb_update_failure # ============================================================================ # PHASE 8: FINALIZATION # ============================================================================ - name: finalize_deployment action: deployments.update_status input: deployment_id: "{{ workflow.deployment_id }}" status: "success" metadata: version: "{{ parameters.version }}" regions: "{{ parameters.regions }}" duration: "{{ system.timestamp - workflow.start_time }}" publish: - successful_regions: "{{ parameters.regions }}" on_success: post_deployment_tasks - name: post_deployment_tasks type: parallel tasks: - name: update_service_catalog action: catalog.update_service_version input: app_name: "{{ parameters.app_name }}" version: "{{ parameters.version }}" environment: "{{ parameters.environment }}" - name: trigger_integration_tests action: testing.trigger_integration_suite input: app_name: "{{ parameters.app_name }}" environment: "{{ parameters.environment }}" - name: update_documentation action: docs.update_deployment_history input: app_name: "{{ parameters.app_name }}" version: "{{ parameters.version }}" deployment_id: "{{ workflow.deployment_id }}" on_complete: notify_deployment_success # ============================================================================ # FAILURE HANDLERS # ============================================================================ - name: handle_deployment_failures action: deployments.analyze_failures input: deployment_id: "{{ workflow.deployment_id }}" failed_tasks: "{{ task.deploy_to_all_regions.failed_items }}" publish: - failed_regions: "{{ task.handle_deployment_failures.result.failed_regions }}" decision: - when: "{{ parameters.rollback_on_failure == true }}" next: rollback_all_regions - default: notify_partial_deployment - name: handle_health_check_failures action: diagnostics.analyze_health_failures input: deployment_id: "{{ workflow.deployment_id }}" failed_urls: "{{ task.parallel_health_checks.failed_items }}" decision: - when: "{{ parameters.rollback_on_failure == true }}" next: rollback_all_regions - default: notify_health_check_failures - name: handle_smoke_test_failures action: testing.capture_smoke_test_results input: deployment_id: "{{ workflow.deployment_id }}" results: "{{ task.run_smoke_tests.result }}" decision: - when: "{{ parameters.rollback_on_failure == true }}" next: rollback_all_regions - default: notify_smoke_test_failures - name: handle_metrics_failures action: monitoring.capture_metric_violations input: deployment_id: "{{ workflow.deployment_id }}" violations: "{{ task.verify_metrics.result.violations }}" decision: - when: "{{ parameters.rollback_on_failure == true }}" next: rollback_all_regions - default: notify_metrics_failures - name: handle_lb_update_failure action: aws.diagnose_lb_failure input: regions: "{{ parameters.regions }}" error: "{{ task.update_load_balancer.error }}" on_complete: rollback_all_regions # ============================================================================ # ROLLBACK PROCEDURES # ============================================================================ - name: rollback_all_regions action: kubernetes.rollback_deployment with_items: "{{ parameters.regions }}" input: app_name: "{{ parameters.app_name }}" region: "{{ item }}" target_version: "previous" publish: - rollback_initiated: true on_success: update_deployment_rolled_back on_failure: notify_rollback_failed - name: update_deployment_rolled_back action: deployments.update_status input: deployment_id: "{{ workflow.deployment_id }}" status: "rolled_back" metadata: reason: "deployment_failure" failed_regions: "{{ workflow.failed_regions }}" on_complete: notify_deployment_rolled_back # ============================================================================ # CANCELLATION HANDLERS # ============================================================================ - name: cancel_deployment action: deployments.update_status input: deployment_id: "{{ workflow.deployment_id }}" status: "cancelled" metadata: reason: "approval_denied" on_complete: notify_deployment_cancelled - name: deployment_approval_timeout action: deployments.update_status input: deployment_id: "{{ workflow.deployment_id }}" status: "cancelled" metadata: reason: "approval_timeout" on_complete: notify_approval_timeout - name: cleanup_failed_deployment action: deployments.cleanup_resources input: deployment_id: "{{ workflow.deployment_id }}" reason: "pre_deployment_checks_failed" on_complete: notify_deployment_failed # ============================================================================ # NOTIFICATION TASKS # ============================================================================ - name: notify_deployment_success action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | โœ… Deployment Successful Application: {{ parameters.app_name }} Version: {{ parameters.version }} Environment: {{ parameters.environment }} Regions: {{ workflow.successful_regions | join(', ') }} Duration: {{ system.timestamp - workflow.start_time }}s Deployment ID: {{ workflow.deployment_id }} metadata: severity: "info" deployment_id: "{{ workflow.deployment_id }}" - name: notify_deployment_failed action: notifications.send_multi_channel input: channels: ["slack", "email", "pagerduty"] message: | โŒ Deployment Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Environment: {{ parameters.environment }} Failed Regions: {{ workflow.failed_regions | join(', ') }} Deployment ID: {{ workflow.deployment_id }} metadata: severity: "error" deployment_id: "{{ workflow.deployment_id }}" - name: notify_deployment_rolled_back action: notifications.send_multi_channel input: channels: ["slack", "email", "pagerduty"] message: | โš ๏ธ Deployment Rolled Back Application: {{ parameters.app_name }} Version: {{ parameters.version }} Environment: {{ parameters.environment }} Rollback completed for all regions Deployment ID: {{ workflow.deployment_id }}" metadata: severity: "warning" deployment_id: "{{ workflow.deployment_id }}" - name: notify_deployment_cancelled action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | ๐Ÿšซ Deployment Cancelled Application: {{ parameters.app_name }} Version: {{ parameters.version }} Environment: {{ parameters.environment }} Reason: Approval denied metadata: severity: "info" - name: notify_approval_timeout action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | โฑ๏ธ Deployment Approval Timeout Application: {{ parameters.app_name }} Version: {{ parameters.version }} Environment: {{ parameters.environment }} No approval received within 1 hour metadata: severity: "warning" - name: notify_validation_failed action: notifications.send_multi_channel input: channels: ["slack"] message: | โš ๏ธ Deployment Validation Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Error: {{ task.validate_inputs.error.message }} metadata: severity: "warning" - name: notify_build_failed action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | ๐Ÿ”จ Build Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Error: {{ task.build_and_test.error.message }} metadata: severity: "error" - name: notify_build_timeout action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | โฑ๏ธ Build Timeout Application: {{ parameters.app_name }} Version: {{ parameters.version }} Build exceeded 30 minute timeout metadata: severity: "error" - name: notify_push_failed action: notifications.send_multi_channel input: channels: ["slack"] message: | ๐Ÿ“ฆ Container Push Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Error: {{ task.push_container_image.error.message }} metadata: severity: "error" - name: notify_canary_failed action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | ๐Ÿฆ Canary Deployment Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Canary has been rolled back Metrics: {{ task.monitor_canary.result }} metadata: severity: "warning" - name: notify_partial_deployment action: notifications.send_multi_channel input: channels: ["slack", "email", "pagerduty"] message: | โš ๏ธ Partial Deployment Application: {{ parameters.app_name }} Version: {{ parameters.version }} Successful Regions: {{ workflow.successful_regions | join(', ') }} Failed Regions: {{ workflow.failed_regions | join(', ') }} metadata: severity: "error" - name: notify_health_check_failures action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | ๐Ÿ’” Health Check Failures Application: {{ parameters.app_name }} Version: {{ parameters.version }} Failed URLs: {{ task.parallel_health_checks.failed_items | length }} metadata: severity: "error" - name: notify_smoke_test_failures action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | ๐Ÿงช Smoke Tests Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Results: {{ task.run_smoke_tests.result.summary }} metadata: severity: "error" - name: notify_metrics_failures action: notifications.send_multi_channel input: channels: ["slack", "email"] message: | ๐Ÿ“Š Metrics Verification Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Violations: {{ task.verify_metrics.result.violations | length }} metadata: severity: "error" - name: notify_rollback_failed action: notifications.send_multi_channel input: channels: ["slack", "email", "pagerduty"] message: | ๐Ÿšจ CRITICAL: Rollback Failed Application: {{ parameters.app_name }} Version: {{ parameters.version }} Manual intervention required! metadata: severity: "critical" # Workflow output mapping output_map: deployment_id: "{{ workflow.deployment_id }}" status: "{{ workflow.rollback_initiated ? 'rolled_back' : 'success' }}" deployed_version: "{{ parameters.version }}" deployment_urls: "{{ workflow.health_check_urls }}" duration_seconds: "{{ system.timestamp - workflow.start_time }}"