158 lines
4.5 KiB
Rust
158 lines
4.5 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::cli::Cli;
|
|
use workshop_baker::engine::{ExecutionContext, ExecutionEvent};
|
|
use workshop_baker::finalize::finalize;
|
|
|
|
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"
|
|
);
|
|
}
|