crazy_train/
step.rs

1//! This module defines the `StepTrait` trait, which outlines the necessary methods that
2//! any step in the execution process must implement. It also defines the `Plan` struct,
3//! which encapsulates a command to be executed as part of a step.
4//!
5
6use std::collections::HashMap;
7
8use crate::{
9    errors,
10    executer::{self, Output},
11    randomizer::Randomizer,
12};
13
14/// Enum representing the different types of steps that can be executed.
15#[derive(Debug)]
16pub enum Kind {
17    Setup,
18    Plan,
19    Check,
20    Test,
21}
22
23/// A trait that defines the behavior required for steps in the execution process.
24#[allow(clippy::module_name_repetitions)]
25pub trait StepTrait {
26    /// Prepares the setup by creating necessary directories and performing initialization steps.
27    ///
28    /// # Errors
29    ///
30    /// Returns an error if the setup fails, such as when it is unable to create the required directory.
31    fn setup(&self) -> errors::Result<()> {
32        Ok(())
33    }
34    /// Generates a plan for execution.
35    ///
36    /// # Errors
37    ///
38    /// when could not prepare the plan
39    fn plan(&self, randomizer: &Randomizer) -> errors::Result<Plan>;
40
41    /// Determines if the execution result indicates success for this step.
42    ///
43    /// the bool result point if the runner should continue to the next steps or not.
44    ///
45    /// # Errors
46    /// When plan result parsing is not the expected behavior.
47    fn is_success(
48        &self,
49        execution_result: &Output,
50        plan_ctx: &PlanCtx,
51    ) -> Result<bool, &'static str>;
52
53    /// Optionally returns a command to run as a check after the execution of the plan.
54    fn run_check(&self) -> Option<String> {
55        None
56    }
57
58    /// Optionally returns a command to run as a test after the execution of the plan.
59    fn run_test(&self) -> Option<String> {
60        None
61    }
62
63    /// Serializes the step to a YAML representation.
64    fn to_yaml(&self) -> serde_yaml::Value;
65}
66
67/// A struct that represents a plan for executing a command as part of a step.
68#[derive(Debug, Clone)]
69pub struct Plan {
70    pub id: String,
71    pub command: String,
72    pub ctx: PlanCtx,
73}
74
75#[derive(Default, Debug, Clone)]
76pub struct PlanCtx {
77    pub vars: HashMap<String, String>,
78}
79
80impl Plan {
81    /// Executes the command defined in the plan.
82    ///
83    /// # Errors
84    ///
85    /// on shell command failure.
86    pub fn execute(&self) -> errors::Result<executer::Output> {
87        executer::run_sh(&self.command)
88    }
89
90    #[must_use]
91    pub fn new<T>(command: impl Into<String>) -> Self {
92        Self {
93            id: std::any::type_name::<T>().to_string(),
94            command: command.into(),
95            ctx: PlanCtx::default(),
96        }
97    }
98
99    #[must_use]
100    pub fn with_vars<T>(command: impl Into<String>, vars: HashMap<String, String>) -> Self {
101        Self {
102            id: std::any::type_name::<T>().to_string(),
103            command: command.into(),
104            ctx: PlanCtx { vars },
105        }
106    }
107}