The Deploy Train
The Deploy Train: lint -> test -> build -> canary -> ship, where a red gate stops the train and everything behind it reports CANCELED, not skipped-and-shrugged. Run it twice: healthy train, then a canary failure. The second run is why deploy pipelines exist.
Testing & Verification
Round 6
DHH
exit 0
bundle exec ruby examples/deploy_train.rb
a real captured run
monday's deploy: lint green test green build green canary green ship green announce green train status: completed friday's deploy: lint green test green build green canary RED - error rate 4.2% exceeds 1% threshold ship CANCELED (never left the yard) announce CANCELED (never left the yard) train status: partial_failure friday's verdict is precise: the train is :partial_failure (a gate went RED), and the cars behind it are CANCELED, not silently skipped. failure outranks cancellation in the status - the headline is WHY the train stopped, the manifest shows what never shipped.
source
# frozen_string_literal: true # The Deploy Train: lint -> test -> build -> canary -> ship, where a # red gate stops the train and everything behind it reports CANCELED, # not skipped-and-shrugged. Run it twice: healthy train, then a canary # failure. The second run is why deploy pipelines exist. # # bundle exec ruby examples/deploy_train.rb # # Runs offline; the canary's health is scripted. require class="s">"bundler/setup" require class="s">"agentic" Agentic.logger.level = class="y">:fatal # the failure is the demo, not news STATIONS = %w[lint test build canary ship announce].freeze def run_train(canary_healthy:) orchestrator = nil hooks = { after_task_failure: ->(task_id:, task:, failure:, duration:) { # A red gate stops the whole train - no half-shipped releases orchestrator.cancel_plan } } orchestrator = Agentic:class="y">:PlanOrchestrator.new( concurrency_limit: 1, lifecycle_hooks: hooks, retry_policy: {max_retries: 0, retryable_errors: []} ) previous = nil tasks = STATIONS.to_h do |station| task = Agentic:class="y">:Task.new( description: station, agent_spec: {class="s">"name" => station, class="s">"instructions" => class="s">"run the gate"} ) orchestrator.add_task(task, previous ? [previous] : [], agent: ->(t) { sleep(0.01) if t.description == class="s">"canary" && !canary_healthy raise class="s">"error rate 4.2% exceeds 1% threshold" end class="y">:green }) previous = task [station, task] end result = orchestrator.execute_plan [result, tasks] end def print_train(label, result, tasks) puts label tasks.each do |station, task| task_result = result.results[task.id] status = if task_result.nil? class="s">"CANCELED (never left the yard)" elsif task_result.successful? class="s">"green" elsif task_result.canceled? class="s">"CANCELED" else class="s">"RED - #{task_result.failure.message}" end puts format(class="s">" %-9s %s", station, status) end puts format(class="s">" train status: %s", result.status) puts end healthy, healthy_tasks = run_train(canary_healthy: true) print_train(class="s">"monday's deploy:", healthy, healthy_tasks) broken, broken_tasks = run_train(canary_healthy: false) print_train(class="s">"friday's deploy:", broken, broken_tasks) puts class="s">"friday's verdict is precise: the train is class="y">:partial_failure (a gate" puts class="s">"went RED), and the cars behind it are CANCELED, not silently" puts class="s">"skipped. failure outranks cancellation in the status - the headline" puts class="s">"is WHY the train stopped, the manifest shows what never shipped."