feat(wfe-yaml): add YAML workflow definitions with shell executor
Concourse-CI-inspired YAML format for defining workflows. Compiles
to standard WorkflowDefinition + step factories.
Features:
- Schema parsing with serde_yaml (YamlWorkflow, YamlStep, StepConfig)
- ((var.path)) interpolation from config maps at load time
- YAML anchors (&anchor/*alias) fully supported
- Validation at load time (no runtime surprises)
- Shell executor: runs commands via tokio::process, captures stdout,
parses ##wfe[output name=value] annotations for structured outputs
- Compiler: sequential wiring, parallel blocks, on_failure/on_success/
ensure hooks, error behavior mapping
- Public API: load_workflow(), load_workflow_from_str()
- 23 tests (schema, interpolation, compiler, e2e)
2026-03-25 21:32:00 +00:00
|
|
|
use std::collections::HashMap;
|
|
|
|
|
|
|
|
|
|
use serde::Deserialize;
|
|
|
|
|
|
2026-03-26 17:21:20 +00:00
|
|
|
/// A condition in YAML that determines whether a step executes.
|
|
|
|
|
///
|
|
|
|
|
/// Uses `#[serde(untagged)]` so serde tries each variant in order.
|
|
|
|
|
/// A comparison has a `field:` key; a combinator has `all:/any:/none:/one_of:/not:`.
|
|
|
|
|
/// Comparison is listed first because it is more specific (requires `field`).
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
#[serde(untagged)]
|
|
|
|
|
pub enum YamlCondition {
|
|
|
|
|
/// Leaf comparison (has a `field:` key).
|
|
|
|
|
Comparison(Box<YamlComparison>),
|
|
|
|
|
/// Combinator with sub-conditions.
|
|
|
|
|
Combinator(YamlCombinator),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A combinator condition containing sub-conditions.
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
pub struct YamlCombinator {
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub all: Option<Vec<YamlCondition>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub any: Option<Vec<YamlCondition>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub none: Option<Vec<YamlCondition>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub one_of: Option<Vec<YamlCondition>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub not: Option<Box<YamlCondition>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// A leaf comparison condition that compares a field value.
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
pub struct YamlComparison {
|
|
|
|
|
pub field: String,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub equals: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub not_equals: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub gt: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub gte: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub lt: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub lte: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub contains: Option<serde_yaml::Value>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub is_null: Option<bool>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub is_not_null: Option<bool>,
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-26 14:14:15 +00:00
|
|
|
/// Top-level YAML file structure supporting both single and multi-workflow files.
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
pub struct YamlWorkflowFile {
|
|
|
|
|
/// Single workflow (backward compatible).
|
|
|
|
|
pub workflow: Option<WorkflowSpec>,
|
|
|
|
|
/// Multiple workflows in one file.
|
|
|
|
|
pub workflows: Option<Vec<WorkflowSpec>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Legacy single-workflow top-level structure. Kept for backward compatibility
|
|
|
|
|
/// with code that deserializes `YamlWorkflow` directly.
|
feat(wfe-yaml): add YAML workflow definitions with shell executor
Concourse-CI-inspired YAML format for defining workflows. Compiles
to standard WorkflowDefinition + step factories.
Features:
- Schema parsing with serde_yaml (YamlWorkflow, YamlStep, StepConfig)
- ((var.path)) interpolation from config maps at load time
- YAML anchors (&anchor/*alias) fully supported
- Validation at load time (no runtime surprises)
- Shell executor: runs commands via tokio::process, captures stdout,
parses ##wfe[output name=value] annotations for structured outputs
- Compiler: sequential wiring, parallel blocks, on_failure/on_success/
ensure hooks, error behavior mapping
- Public API: load_workflow(), load_workflow_from_str()
- 23 tests (schema, interpolation, compiler, e2e)
2026-03-25 21:32:00 +00:00
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
pub struct YamlWorkflow {
|
|
|
|
|
pub workflow: WorkflowSpec,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
pub struct WorkflowSpec {
|
|
|
|
|
pub id: String,
|
|
|
|
|
pub version: u32,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub description: Option<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub error_behavior: Option<YamlErrorBehavior>,
|
|
|
|
|
pub steps: Vec<YamlStep>,
|
2026-03-26 14:14:15 +00:00
|
|
|
/// Typed input schema: { field_name: type_string }.
|
|
|
|
|
/// Example: `"repo_url": "string"`, `"tags": "list<string>"`.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub inputs: HashMap<String, String>,
|
|
|
|
|
/// Typed output schema: { field_name: type_string }.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub outputs: HashMap<String, String>,
|
feat(wfe-yaml): add YAML workflow definitions with shell executor
Concourse-CI-inspired YAML format for defining workflows. Compiles
to standard WorkflowDefinition + step factories.
Features:
- Schema parsing with serde_yaml (YamlWorkflow, YamlStep, StepConfig)
- ((var.path)) interpolation from config maps at load time
- YAML anchors (&anchor/*alias) fully supported
- Validation at load time (no runtime surprises)
- Shell executor: runs commands via tokio::process, captures stdout,
parses ##wfe[output name=value] annotations for structured outputs
- Compiler: sequential wiring, parallel blocks, on_failure/on_success/
ensure hooks, error behavior mapping
- Public API: load_workflow(), load_workflow_from_str()
- 23 tests (schema, interpolation, compiler, e2e)
2026-03-25 21:32:00 +00:00
|
|
|
/// Allow unknown top-level keys (e.g. `_templates`) for YAML anchors.
|
|
|
|
|
#[serde(flatten)]
|
|
|
|
|
pub _extra: HashMap<String, serde_yaml::Value>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
pub struct YamlStep {
|
|
|
|
|
pub name: String,
|
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
|
pub step_type: Option<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub config: Option<StepConfig>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub inputs: Vec<DataRef>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub outputs: Vec<DataRef>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub parallel: Option<Vec<YamlStep>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub error_behavior: Option<YamlErrorBehavior>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub on_success: Option<Box<YamlStep>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub on_failure: Option<Box<YamlStep>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub ensure: Option<Box<YamlStep>>,
|
2026-03-26 17:21:20 +00:00
|
|
|
/// Optional condition that must be true for this step to execute.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub when: Option<YamlCondition>,
|
feat(wfe-yaml): add YAML workflow definitions with shell executor
Concourse-CI-inspired YAML format for defining workflows. Compiles
to standard WorkflowDefinition + step factories.
Features:
- Schema parsing with serde_yaml (YamlWorkflow, YamlStep, StepConfig)
- ((var.path)) interpolation from config maps at load time
- YAML anchors (&anchor/*alias) fully supported
- Validation at load time (no runtime surprises)
- Shell executor: runs commands via tokio::process, captures stdout,
parses ##wfe[output name=value] annotations for structured outputs
- Compiler: sequential wiring, parallel blocks, on_failure/on_success/
ensure hooks, error behavior mapping
- Public API: load_workflow(), load_workflow_from_str()
- 23 tests (schema, interpolation, compiler, e2e)
2026-03-25 21:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
pub struct StepConfig {
|
|
|
|
|
pub run: Option<String>,
|
|
|
|
|
pub file: Option<String>,
|
|
|
|
|
pub script: Option<String>,
|
|
|
|
|
pub shell: Option<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub env: HashMap<String, String>,
|
|
|
|
|
pub timeout: Option<String>,
|
|
|
|
|
pub working_dir: Option<String>,
|
2026-03-25 22:32:07 +00:00
|
|
|
#[serde(default)]
|
|
|
|
|
pub permissions: Option<DenoPermissionsYaml>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub modules: Vec<String>,
|
feat(wfe-buildkit, wfe-containerd): add container executor crates
Standalone workspace crates for BuildKit image building and containerd
container execution. Config types, YAML schema integration, compiler
dispatch, validation rules, and mock-based unit tests.
Current implementation shells out to buildctl/nerdctl — will be
replaced with proper gRPC clients (buildkit-client, containerd protos)
in a follow-up. Config types, YAML integration, and test infrastructure
are stable and reusable.
wfe-buildkit: 60 tests, 97.9% library coverage
wfe-containerd: 61 tests, 97.8% library coverage
447 total workspace tests.
2026-03-26 10:28:53 +00:00
|
|
|
// BuildKit fields
|
|
|
|
|
pub dockerfile: Option<String>,
|
|
|
|
|
pub context: Option<String>,
|
|
|
|
|
pub target: Option<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub tags: Vec<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub build_args: HashMap<String, String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub cache_from: Vec<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub cache_to: Vec<String>,
|
|
|
|
|
pub push: Option<bool>,
|
|
|
|
|
pub buildkit_addr: Option<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub tls: Option<TlsConfigYaml>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub registry_auth: Option<HashMap<String, RegistryAuthYaml>>,
|
|
|
|
|
// Containerd fields
|
|
|
|
|
pub image: Option<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub command: Option<Vec<String>>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub volumes: Vec<VolumeMountYaml>,
|
|
|
|
|
pub user: Option<String>,
|
|
|
|
|
pub network: Option<String>,
|
|
|
|
|
pub memory: Option<String>,
|
|
|
|
|
pub cpu: Option<String>,
|
|
|
|
|
pub pull: Option<String>,
|
|
|
|
|
pub containerd_addr: Option<String>,
|
|
|
|
|
/// CLI binary name for containerd steps: "nerdctl" (default) or "docker".
|
|
|
|
|
pub cli: Option<String>,
|
feat(wfe-yaml): wire rustlang step types and containerd integration tests
Add rustlang feature flag to wfe-yaml with support for all cargo and
rustup step types (15 total), including cargo-doc-mdx.
Schema additions: output_dir, package, features, all_features,
no_default_features, release, profile, toolchain, extra_args,
components, targets, default_toolchain fields on StepConfig.
Integration tests for compiling all step types from YAML, and
containerd-based end-to-end tests for running Rust toolchain
inside containers from bare Debian images.
2026-03-29 16:57:50 +01:00
|
|
|
// Cargo fields
|
|
|
|
|
/// Target package for cargo steps (`-p`).
|
|
|
|
|
pub package: Option<String>,
|
|
|
|
|
/// Features to enable for cargo steps.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub features: Vec<String>,
|
|
|
|
|
/// Enable all features for cargo steps.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub all_features: Option<bool>,
|
|
|
|
|
/// Disable default features for cargo steps.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub no_default_features: Option<bool>,
|
|
|
|
|
/// Build in release mode for cargo steps.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub release: Option<bool>,
|
|
|
|
|
/// Build profile for cargo steps (`--profile`).
|
|
|
|
|
pub profile: Option<String>,
|
|
|
|
|
/// Rust toolchain override for cargo steps (e.g. "nightly").
|
|
|
|
|
pub toolchain: Option<String>,
|
|
|
|
|
/// Additional arguments for cargo/rustup steps.
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub extra_args: Vec<String>,
|
|
|
|
|
/// Output directory for generated files (e.g., MDX docs).
|
|
|
|
|
pub output_dir: Option<String>,
|
|
|
|
|
// Rustup fields
|
|
|
|
|
/// Components to add for rustup steps (e.g. ["clippy", "rustfmt"]).
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub components: Vec<String>,
|
|
|
|
|
/// Compilation targets to add for rustup steps (e.g. ["wasm32-unknown-unknown"]).
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub targets: Vec<String>,
|
|
|
|
|
/// Default toolchain for rust-install steps.
|
|
|
|
|
pub default_toolchain: Option<String>,
|
2026-03-26 14:14:15 +00:00
|
|
|
// Workflow (sub-workflow) fields
|
|
|
|
|
/// Child workflow ID (for `type: workflow` steps).
|
|
|
|
|
#[serde(rename = "workflow")]
|
|
|
|
|
pub child_workflow: Option<String>,
|
|
|
|
|
/// Child workflow version (for `type: workflow` steps).
|
|
|
|
|
#[serde(rename = "workflow_version")]
|
|
|
|
|
pub child_version: Option<u32>,
|
2026-03-25 22:32:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// YAML-level permission configuration for Deno steps.
|
|
|
|
|
#[derive(Debug, Deserialize, Clone, Default)]
|
|
|
|
|
pub struct DenoPermissionsYaml {
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub net: Vec<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub read: Vec<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub write: Vec<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub env: Vec<String>,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub run: bool,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub dynamic_import: bool,
|
feat(wfe-yaml): add YAML workflow definitions with shell executor
Concourse-CI-inspired YAML format for defining workflows. Compiles
to standard WorkflowDefinition + step factories.
Features:
- Schema parsing with serde_yaml (YamlWorkflow, YamlStep, StepConfig)
- ((var.path)) interpolation from config maps at load time
- YAML anchors (&anchor/*alias) fully supported
- Validation at load time (no runtime surprises)
- Shell executor: runs commands via tokio::process, captures stdout,
parses ##wfe[output name=value] annotations for structured outputs
- Compiler: sequential wiring, parallel blocks, on_failure/on_success/
ensure hooks, error behavior mapping
- Public API: load_workflow(), load_workflow_from_str()
- 23 tests (schema, interpolation, compiler, e2e)
2026-03-25 21:32:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
pub struct DataRef {
|
|
|
|
|
pub name: String,
|
|
|
|
|
pub path: Option<String>,
|
|
|
|
|
pub json_path: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
feat(wfe-buildkit, wfe-containerd): add container executor crates
Standalone workspace crates for BuildKit image building and containerd
container execution. Config types, YAML schema integration, compiler
dispatch, validation rules, and mock-based unit tests.
Current implementation shells out to buildctl/nerdctl — will be
replaced with proper gRPC clients (buildkit-client, containerd protos)
in a follow-up. Config types, YAML integration, and test infrastructure
are stable and reusable.
wfe-buildkit: 60 tests, 97.9% library coverage
wfe-containerd: 61 tests, 97.8% library coverage
447 total workspace tests.
2026-03-26 10:28:53 +00:00
|
|
|
/// YAML-level TLS configuration for BuildKit steps.
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
pub struct TlsConfigYaml {
|
|
|
|
|
pub ca: Option<String>,
|
|
|
|
|
pub cert: Option<String>,
|
|
|
|
|
pub key: Option<String>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// YAML-level registry auth configuration for BuildKit steps.
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
pub struct RegistryAuthYaml {
|
|
|
|
|
pub username: String,
|
|
|
|
|
pub password: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// YAML-level volume mount configuration for containerd steps.
|
|
|
|
|
#[derive(Debug, Deserialize, Clone)]
|
|
|
|
|
pub struct VolumeMountYaml {
|
|
|
|
|
pub source: String,
|
|
|
|
|
pub target: String,
|
|
|
|
|
#[serde(default)]
|
|
|
|
|
pub readonly: bool,
|
|
|
|
|
}
|
|
|
|
|
|
feat(wfe-yaml): add YAML workflow definitions with shell executor
Concourse-CI-inspired YAML format for defining workflows. Compiles
to standard WorkflowDefinition + step factories.
Features:
- Schema parsing with serde_yaml (YamlWorkflow, YamlStep, StepConfig)
- ((var.path)) interpolation from config maps at load time
- YAML anchors (&anchor/*alias) fully supported
- Validation at load time (no runtime surprises)
- Shell executor: runs commands via tokio::process, captures stdout,
parses ##wfe[output name=value] annotations for structured outputs
- Compiler: sequential wiring, parallel blocks, on_failure/on_success/
ensure hooks, error behavior mapping
- Public API: load_workflow(), load_workflow_from_str()
- 23 tests (schema, interpolation, compiler, e2e)
2026-03-25 21:32:00 +00:00
|
|
|
#[derive(Debug, Deserialize)]
|
|
|
|
|
pub struct YamlErrorBehavior {
|
|
|
|
|
#[serde(rename = "type")]
|
|
|
|
|
pub behavior_type: String,
|
|
|
|
|
pub interval: Option<String>,
|
|
|
|
|
pub max_retries: Option<u32>,
|
|
|
|
|
}
|