# WORKSHOP-BAKER CRATE KNOWLEDGE BASE ## OVERVIEW Primary crate — the only crate with a `[[bin]]` target. Contains the `workshop-baker` binary and `workshop_baker` library. Orchestrates the full CI/CD pipeline: prebake (env setup) → bake (script execution) → finalize (plugins, cleanup) → drain notification queue. ~69 .rs source files. ## STRUCTURE ``` src/ ├── main.rs # Entry: default(full pipeline) | bare(dev-only) | daemon(unimplemented) ├── lib.rs # Clap Cli/Commands/BareCommands — CLI structs in lib, not bin ├── error.rs # CliError enum (wraps stage errors, delegates exit_code) ├── bare.rs # Dev-only single-stage execution, ctx.privileged always false ├── utils.rs # Cross-cutting helpers ├── bake/ # Script parsing + DAG scheduling + execution │ ├── decorator.rs # @decorator(args) parsing, 81 tests — heaviest coverage in crate │ ├── parser.rs # Step/function extraction │ ├── schedule.rs # DAG build → topological sort │ ├── execute.rs # Per-step timeout/retry │ ├── builder.rs # Script assembly │ ├── trivial.rs # Trivial step detection (skip in dry-run) │ ├── constant.rs / error.rs / util.rs ├── prebake/ # Environment provisioning │ ├── config.rs # PrebakeConfig deserialization │ ├── stage.rs + stage/{bootstrap,depssystem,depsuser,environment,hook}.rs │ ├── env.rs + env/{container,firecracker,baremetal,custom}.rs # Builder dispatch │ ├── security.rs # Privilege/sandbox checks │ ├── event.rs # Event sender/receiver channel │ ├── types.rs + types/{memsize,cache,builderconfig,architecture}.rs │ ├── constant.rs / error.rs ├── finalize/ # Post-build hooks + plugins │ ├── config.rs # FinalizeConfig │ ├── stage.rs + stage/hook.rs │ ├── template.rs # Output templating (minijinja) │ ├── plugin.rs + plugin/{shell,dylib,rhai,internal}.rs │ │ └── plugin/internal/{dummy,mail,satori,webhook,insitenotify}.rs │ ├── types.rs + types/compression.rs │ ├── constant.rs / error.rs / event.rs ├── notify/ # Async notification dispatch │ ├── queue.rs # NotificationQueue — drain on pipeline complete │ ├── handler.rs / rule.rs / template.rs / types.rs / util.rs / error.rs └── types/ # Shared types — ZERO deps on stage modules ├── resource.rs # ResourceRegistry (populated pre-pipeline, consumed read-only) └── buildstatus.rs ``` ## WHERE TO LOOK | Task | Location | Notes | |------|----------|-------| | CLI args + subcommands | `src/lib.rs` | Cli, Commands(Bare/Daemon), BareCommands | | Pipeline orchestration | `src/main.rs` | worker_main(): prebake→bake→finalize→queue.drain() | | Decorator syntax | `src/bake/decorator.rs` | `# @decorator` or `# @decorator(args)`, line-by-line regex | | Build execution | `src/bake/execute.rs` | timeout, retry, exit code capture | | DAG scheduling | `src/bake/schedule.rs` | Uses workshop-schedule crate | | Docker builder | `src/prebake/env/container.rs` | Bollard-based, buildkit support | | Firecracker / Bare metal | `.../firecracker.rs`, `.../baremetal.rs` | MicroVM; needs PIPELINE_BAREMETAL_ELEVATE | | Plugin dispatch | `src/finalize/plugin.rs` | Dispatches shell / dylib(stub) / rhai(stub) / internal | | Notification queue | `src/notify/queue.rs` | Spawned early, drained after pipeline, retry support | | Error type | `src/error.rs` | CliError wraps PrebakeError/BakeError/FinalizeError/anyhow | | Dev bare mode | `src/bare.rs` | ctx.privileged=false always; do not extrapolate to production | ## DEPENDENCIES **Internal:** workshop-engine, workshop-schedule, workshop-getterurl, workshop-baker-params. **External:** bollard (Docker), clap (CLI), axum 0.7 (HTTP), lettre 0.11 (email), minijinja (templates), cgroups-rs (limits), privdrop. ## CONVENTIONS (CRATE-SPECIFIC) - **Lint overrides** (this crate only): `dead_code=allow`, `unreachable_code=allow`, `inherent_to_string=allow`, `non_canonical_partial_ord_impl=allow` - **CLI structs in lib.rs, not main.rs** — enables integration tests to import and construct Cli directly. - **Pipeline stages return `anyhow::Result<()>`** — stages propagate with `?`; only main.rs converts to CliError. - **ResourceRegistry pattern** — populated before pipeline stages, consumed read-only by stages. New resource types go in `types/resource.rs`. - **Notification queue fire-and-forget + drain** — notify tasks spawned early, send during pipeline, drain on completion. `NotificationQueue::drain()` must be called. - **Trivial step detection** — steps with no external deps can be marked trivial (`trivial.rs`), skipped in dry-run. ## ANTI-PATTERNS (THIS CRATE) - **Do NOT derive production behavior from bare mode** — ctx.privileged is hardcoded false. - **Do NOT add CLI args bypassing prebake→bake→finalize ordering** — the pipeline is linear. Parallelism lives in the DAG scheduler within bake. - **Do NOT import types/ from bake/, prebake/, or finalize/** — `types/` must have zero crate-internal deps. - **Do NOT add lint allows without justification** — the four existing overrides are intentional. - **Do NOT spawn blocking work on tokio runtime** — use `spawn_blocking` for CPU-heavy tasks. - **Decorator regex is line-by-line** — multi-line decorators need a parser rewrite, not a regex hack. - **Careful with `unimplemented!()`** — Daemon, Rhai/Dylib plugins, Custom builder are stubs. Prefer error over crash.