feat(runbooks): runbook execution engine + pup workflows PoC#146
Draft
platinummonkey wants to merge 4 commits intomainfrom
Draft
feat(runbooks): runbook execution engine + pup workflows PoC#146platinummonkey wants to merge 4 commits intomainfrom
platinummonkey wants to merge 4 commits intomainfrom
Conversation
Implements the runbooks PoC as specified:
- `pup runbooks list/describe/run/validate/import` — execute YAML
runbooks from ~/.config/pup/runbooks/ with {{ VAR }} templating,
sequential step execution, poll loops, and confirm gates
- `pup workflows run/instances list/get` — trigger Datadog Workflows
and poll to completion via raw REST (POST/GET /api/v2/workflows/...)
New files:
- src/runbooks/mod.rs — Runbook, Step, VarDef, PollConfig types
- src/runbooks/template.rs — {{ VAR }} and | default: "x" rendering
- src/runbooks/loader.rs — scan runbooks dir, load/import by name
- src/runbooks/engine.rs — sequential executor with polling, confirm,
on_failure handling, variable capture
- src/commands/runbooks.rs — list/describe/run/validate/import CLI
- src/commands/workflows.rs — trigger + watch, instances list/get
- docs/examples/runbooks/ — deploy-service, incident-triage,
maintenance-window reference templates
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…hints Each step now shows: - Header: ► Step N/M · <name> · <kind> [HH:MM:SS] with command preview - Labeled sections: ── stdout ── and ── stderr ── blocks wrapping output - Footer: ✓/✗/⊘ <elapsed> · next: step N/M — <name> (<kind>) - Summary line with total elapsed time and pass/fail count Shell steps surface non-empty stderr even on success so warnings from curl, grep, etc. aren't silently dropped. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Remove RULE constant and all long separator lines - Timestamps now show full UTC date+time: 2026-03-02 18:11:01 UTC - Step header: [N/M] <name> (<kind>) <timestamp> - Output labeled with indented "stdout:" / "stderr:" markers - Summary line: ✓/⚠ done <name> N/M steps <elapsed> <timestamp> Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
…ch = "wasm32"))] Neither feature is compatible with wasm targets: - loader.rs uses std::fs and reqwest::Client::new() - engine.rs uses tokio::process::Command and chrono::Utc - both require dirs-based config path resolution (native-only) Gated items: - mod runbooks; in main.rs - pub mod runbooks/workflows; in commands/mod.rs - Commands::Runbooks/Workflows variants and their subcommand enums - dispatch arms in main_inner() Verified: native build, wasm32-wasip2 (wasi feature), and wasm32-unknown-unknown --lib (browser feature) all pass. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Proof-of-concept implementation of the runbook execution engine proposed in #143 (discussion). Adds two new command groups —
pup runbooksandpup workflows— with no new dependencies.What's included
pup runbooksYAML runbooks live in
~/.config/pup/runbooks/. Each file defines sequential steps that mixpupcommands, shell tools, Datadog Workflow triggers, HTTP calls, and interactive confirm gates.Example runbook (
~/.config/pup/runbooks/hello.yaml):Output while running:
pup workflowsRaw REST access to the Datadog Workflows API (not covered by the typed SDK client):
--watchpolls every 15 s until terminal state, printing elapsed time and status to stderr. Without--watch, agent mode includes awatch_commandmetadata hint.Step kinds
puppupbinary with--output json; supportspoll:loopsshellsh -c "..."with template rendering; surfaces stderr even on successdatadog-workflowwatch_commandhint in agent modeconfirm[y/N]; bypassed by--yes/ agent modehttpclient::raw_get/raw_postControl flow
{{ VAR }}and{{ VAR | default: "x" }}template substitution in all string fieldson_failure: warn | confirm | failper stepwhen: always | on_successto run cleanup steps after failureoptional: trueto swallow errors silentlycapture: VAR_NAMEto pipe step stdout into a variable for later stepspoll: { interval, timeout, until }with conditions:empty,status == X,value < N,decreasingReference runbooks
Three annotated examples in
docs/examples/runbooks/:deploy-service.yaml— SLO check → incident gate → DD Workflow trigger → monitor poll → Slack notifyincident-triage.yaml— fetch incident → search logs → check monitors → auto-mitigation workflow → shell diagnosticsmaintenance-window.yaml— create downtime (capture ID) → drain → metric poll → confirm → delete downtimeNot in this PoC
Platform support
pup runbooksandpup workflowsare native-only and excluded from all wasm builds via#[cfg(not(target_arch = "wasm32"))]. They rely on capabilities that wasm targets don't provide:tokio::process::Commandstd::fs+dirschrono::Utc(step timestamps)client::raw_post/raw_getThe gating covers every touch point — the
mod runbooksdeclaration, bothpub modentries incommands/mod.rs, theCommands::RunbooksandCommands::Workflowsenum variants, the three subcommand enums, and the dispatch arms inmain_inner(). All three build targets pass cleanly:cargo build(native) ✓cargo check --target wasm32-wasip2 --features wasi✓cargo check --target wasm32-unknown-unknown --lib --features browser✓Testing
All existing tests pass (
cargo test,cargo clippy -- -D warnings,cargo fmt --check).Discussion: #143
🤖 Generated with Claude Code