Files
honey-biscuit-workshop/workshop-baker/tests/finalize_pipeline_integration.rs
T
Catty Steve 2658d0ebfa feat(baker): add build status tracking and notification dispatch system
Add new `build_status` types module for tracking pipeline stage
execution
status across prebake, bake, and finalize phases. Introduce
`NotificationCore`
dispatcher that processes notification methods by priority groups with
fallback
on failure. Status files written to `/tmp/.hbwstatus` in JSON lines
format.
2026-04-22 18:45:22 +08:00

146 lines
4.4 KiB
Rust

//! Integration tests for the full finalize pipeline
//!
//! These tests verify the complete finalize workflow from YAML parsing
//! through hook execution, using real files and the public `finalize()` entry point.
use std::collections::HashMap;
use std::time::Duration;
use workshop_baker::engine::{ExecutionContext, ExecutionEvent};
use workshop_baker::finalize::finalize;
use workshop_baker::cli::Cli;
fn create_test_context() -> ExecutionContext {
ExecutionContext {
task_id: "test-finalize-1".to_string(),
pipeline_name: "test-pipeline".to_string(),
username: "testuser".to_string(),
working_dir: std::env::temp_dir(),
env_vars: HashMap::new(),
timeout: Some(Duration::from_secs(30)),
cgroup_path: None,
shell: "bash".to_string(),
dry_run: false,
privileged: false,
standalone: false,
}
}
fn create_test_cli() -> Cli {
Cli {
username: "testuser".to_string(),
pipeline: "test-pipeline".to_string(),
build_id: "test-build-1".to_string(),
dry_run: false,
command: None,
}
}
fn create_test_event_channel() -> (Option<tokio::sync::mpsc::Sender<ExecutionEvent>>, tokio::sync::mpsc::Receiver<ExecutionEvent>) {
let (tx, rx) = tokio::sync::mpsc::channel(64);
(Some(tx), rx)
}
#[tokio::test]
async fn test_full_finalize_with_early_late_hooks() {
let temp_dir = std::env::temp_dir();
let finalize_path = temp_dir.join("test_finalize.yml");
let yaml_content = r#"
version: "0.0.1"
hooks:
early:
- name: "early-echo"
command: "echo early-hook-ok"
timeout: 5
late:
- name: "late-echo"
command: "echo late-hook-ok"
timeout: 5
"#;
std::fs::write(&finalize_path, yaml_content).expect("Failed to write test finalize.yml");
let cli = create_test_cli();
let mut ctx = create_test_context();
let (event_tx, mut event_rx) = create_test_event_channel();
// Spawn an event consumer so the channel does not block
let consumer_handle = tokio::spawn(async move {
while let Some(_event) = event_rx.recv().await {
// Events are consumed but not validated in this test
}
});
let result = finalize(&finalize_path, &cli, &mut ctx, event_tx).await;
let _ = consumer_handle.await;
std::fs::remove_file(&finalize_path).ok();
assert!(result.is_ok(), "Full finalize pipeline should succeed: {:?}", result);
}
#[tokio::test]
async fn test_full_finalize_with_empty_hooks() {
let temp_dir = std::env::temp_dir();
let finalize_path = temp_dir.join("test_finalize_empty.yml");
let yaml_content = r#"
version: "0.0.1"
"#;
std::fs::write(&finalize_path, yaml_content).expect("Failed to write test finalize.yml");
let cli = create_test_cli();
let mut ctx = create_test_context();
let (event_tx, mut event_rx) = create_test_event_channel();
let consumer_handle = tokio::spawn(async move {
while let Some(_event) = event_rx.recv().await {}
});
let result = finalize(&finalize_path, &cli, &mut ctx, event_tx).await;
let _ = consumer_handle.await;
std::fs::remove_file(&finalize_path).ok();
assert!(result.is_ok(), "Finalize with empty hooks should succeed: {:?}", result);
}
#[tokio::test]
async fn test_full_finalize_with_failing_early_hook() {
let temp_dir = std::env::temp_dir();
let finalize_path = temp_dir.join("test_finalize_fail.yml");
let yaml_content = r#"
version: "0.0.1"
hooks:
early:
- name: "failing-hook"
command: "false"
timeout: 5
late:
- name: "never-reached"
command: "echo should-not-run"
timeout: 5
"#;
std::fs::write(&finalize_path, yaml_content).expect("Failed to write test finalize.yml");
let cli = create_test_cli();
let mut ctx = create_test_context();
let (event_tx, mut event_rx) = create_test_event_channel();
let consumer_handle = tokio::spawn(async move {
while let Some(_event) = event_rx.recv().await {}
});
let result = finalize(&finalize_path, &cli, &mut ctx, event_tx).await;
let _ = consumer_handle.await;
std::fs::remove_file(&finalize_path).ok();
// With the notification subsystem, prior stage failures cause finalize to
// send a failure notification and then return Ok (skipping artifacts/latehook)
assert!(result.is_ok(), "Finalize with failing early hook should return Ok after sending failure notification");
}