From 8ec041b42dda2e1c6287d379bea3eadb67d85e51 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 26 Jul 2024 12:44:36 -0400 Subject: [PATCH 1/7] [src/lib/types.rs] Add `before_each_task` and `after_each_task` to `ConfigSection` `struct` ; [src/lib/execution_plan.rs] Implement `before_each_task` and `after_each_task` via interspersal of steps --- src/lib/execution_plan.rs | 54 ++++++++++++++++++++++++++++++++++++--- src/lib/types.rs | 4 +++ 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 6292d707..52ac2ba1 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -19,6 +19,7 @@ use fsio::path::{get_basename, get_parent_directory}; use glob::Pattern; use indexmap::IndexMap; use regex::Regex; +use std::borrow::Cow; use std::collections::HashSet; use std::env; use std::path::Path; @@ -481,8 +482,8 @@ impl<'a> ExecutionPlanBuilder<'a> { skip_tasks_pattern, skip_init_end_tasks, } = *self; - let mut task_names = HashSet::new(); - let mut steps = Vec::new(); + let mut task_names = HashSet::::new(); + let mut steps = Vec::::new(); let default_crate_info = CrateInfo::new(); let crate_info = crate_info.unwrap_or(&default_crate_info); let skip_init_end_tasks = skip_init_end_tasks || sub_flow; @@ -549,6 +550,53 @@ impl<'a> ExecutionPlanBuilder<'a> { }; } - Ok(ExecutionPlan { steps }) + Ok(ExecutionPlan { + steps: Self::handle_before_each_and_after_each_tasks(&config, &steps)?.into_owned(), + }) + } + + /// `before_each` and `after_each` interspersal for the steps vector + fn handle_before_each_and_after_each_tasks<'b>( + config: &Config, + steps: &'b Vec, + ) -> Result>, CargoMakeError> { + let mut before_and_after_each = Vec::::with_capacity(2); + let scale = { + let mut handle_some = |name: &String| -> Result { + let task_config = get_normalized_task(config, name, false)?; + if !task_config.disabled.unwrap_or(false) { + before_and_after_each.push(Step { + name: name.to_string(), + config: task_config, + }); + Ok(1) + } else { + Ok(0) + } + }; + let _has_after_each: u8 = match &config.config.after_each_task { + None => 0, + Some(after_each) => handle_some(after_each)?, + }; + let _has_before_each: u8 = match &config.config.before_each_task { + None => 0, + Some(before_each) => handle_some(before_each)?, + }; + _has_before_each + _has_after_each + }; + if scale > 0 { + let before_and_after_each_len = scale as usize + 1; + let mut interspersed_steps = + Vec::::with_capacity(steps.len() * before_and_after_each_len); + interspersed_steps.extend(steps.into_iter().flat_map(|e| -> Vec { + let mut _steps = Vec::::with_capacity(before_and_after_each_len + 1); + _steps.clone_from_slice(&before_and_after_each); + _steps.push(e.to_owned()); + _steps + })); + Ok(Cow::Owned(interspersed_steps)) + } else { + Ok(Cow::Borrowed(&steps)) + } } } diff --git a/src/lib/types.rs b/src/lib/types.rs index 4582c09e..c52538ba 100755 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -2150,6 +2150,10 @@ pub struct ConfigSection { pub init_task: Option, /// End task name which will be invoked at the end of every run pub end_task: Option, + /// before_each task name which will be invoked before each task (except `init_task`) + pub before_each_task: Option, + /// after_each task name which will be invoked after each task (except `end_task`) + pub after_each_task: Option, /// The name of the task to run in case of any error during the invocation of the flow pub on_error_task: Option, /// The name of the task which runs legacy migration flows From 41cf1ce94841b639d9d17024aa0699d5b275c666 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:17:46 -0400 Subject: [PATCH 2/7] [src/lib/{execution_plan,types}.rs] Explicitly parse out before_each and after_each --- Cargo.lock | 52 +++++++++++++++++++-------------------- src/lib/execution_plan.rs | 27 ++++++++++++++++---- src/lib/types.rs | 22 +++++++++++++++++ 3 files changed, 70 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f70b01cd..5cd6747d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "bstr" -version = "1.9.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +checksum = "40723b8fb387abc38f4f4a37c09073622e41dd12327033091ef8950659e6dc0c" dependencies = [ "memchr", "serde", @@ -205,9 +205,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" [[package]] name = "cfg-if" @@ -792,9 +792,9 @@ dependencies = [ [[package]] name = "lazy-regex" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d12be4595afdf58bd19e4a9f4e24187da2a66700786ff660a418e9059937a4c" +checksum = "576c8060ecfdf2e56995cf3274b4f2d71fa5e4fa3607c1c0b63c10180ee58741" dependencies = [ "lazy-regex-proc_macros", "once_cell", @@ -803,9 +803,9 @@ dependencies = [ [[package]] name = "lazy-regex-proc_macros" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44bcd58e6c97a7fcbaffcdc95728b393b8d98933bfadad49ed4097845b57ef0b" +checksum = "9efb9e65d4503df81c615dc33ff07042a9408ac7f26b45abee25566f7fbfd12c" dependencies = [ "proc-macro2", "quote", @@ -1326,9 +1326,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -1396,9 +1396,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.71" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -1419,18 +1419,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", @@ -1473,9 +1473,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "toml" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" dependencies = [ "serde", "serde_spanned", @@ -1485,18 +1485,18 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" dependencies = [ "indexmap 2.2.6", "serde", @@ -1572,9 +1572,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vte" @@ -1892,9 +1892,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" dependencies = [ "memchr", ] diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 52ac2ba1..0857b81b 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -549,15 +549,32 @@ impl<'a> ExecutionPlanBuilder<'a> { } }; } + let mut before_each_task: Option = None; + let mut after_each_task: Option = None; + for step in steps.iter() { + match step.name.as_str() { + "before_each" => before_each_task = Some(step.name.clone()), + "after_each" => after_each_task = Some(step.name.clone()), + _ => {} + } + } Ok(ExecutionPlan { - steps: Self::handle_before_each_and_after_each_tasks(&config, &steps)?.into_owned(), + steps: Self::handle_before_each_and_after_each_tasks( + &config, + before_each_task, + after_each_task, + &steps, + )? + .into_owned(), }) } /// `before_each` and `after_each` interspersal for the steps vector fn handle_before_each_and_after_each_tasks<'b>( config: &Config, + before_each_task: Option, + after_each_task: Option, steps: &'b Vec, ) -> Result>, CargoMakeError> { let mut before_and_after_each = Vec::::with_capacity(2); @@ -574,13 +591,13 @@ impl<'a> ExecutionPlanBuilder<'a> { Ok(0) } }; - let _has_after_each: u8 = match &config.config.after_each_task { + let _has_after_each: u8 = match after_each_task { None => 0, - Some(after_each) => handle_some(after_each)?, + Some(after_each) => handle_some(&after_each)?, }; - let _has_before_each: u8 = match &config.config.before_each_task { + let _has_before_each: u8 = match before_each_task { None => 0, - Some(before_each) => handle_some(before_each)?, + Some(before_each) => handle_some(&before_each)?, }; _has_before_each + _has_after_each }; diff --git a/src/lib/types.rs b/src/lib/types.rs index c52538ba..70783c9e 100755 --- a/src/lib/types.rs +++ b/src/lib/types.rs @@ -2214,6 +2214,20 @@ impl ConfigSection { )); } + if self.before_each_task.is_some() { + self.before_each_task = Some(get_namespaced_task_name( + namespace, + &self.before_each_task.clone().unwrap(), + )); + } + + if self.after_each_task.is_some() { + self.after_each_task = Some(get_namespaced_task_name( + namespace, + &self.after_each_task.clone().unwrap(), + )); + } + if self.on_error_task.is_some() { self.on_error_task = Some(get_namespaced_task_name( namespace, @@ -2254,6 +2268,14 @@ impl ConfigSection { self.end_task = extended.end_task.clone(); } + if let Some(before_each_task) = &extended.before_each_task { + self.before_each_task = Some(before_each_task.clone()); + } + + if let Some(after_each_task) = &extended.after_each_task { + self.after_each_task = Some(after_each_task.clone()); + } + if extended.on_error_task.is_some() { self.on_error_task = extended.on_error_task.clone(); } From 8b7594e9b135a756a83082426d909f9fd0c97bf1 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 26 Jul 2024 15:44:54 -0400 Subject: [PATCH 3/7] [src/lib/descriptor/mod.rs] Manually parse out `before_each` and `after_each` in `cli::descriptor::load` ; [src/lib/execution_plan.rs] Return to using the already parsed out before|after each --- src/lib/descriptor/mod.rs | 8 ++++++++ src/lib/execution_plan.rs | 25 ++++--------------------- 2 files changed, 12 insertions(+), 21 deletions(-) diff --git a/src/lib/descriptor/mod.rs b/src/lib/descriptor/mod.rs index 0a84fe4b..6cde3b01 100755 --- a/src/lib/descriptor/mod.rs +++ b/src/lib/descriptor/mod.rs @@ -638,5 +638,13 @@ pub fn load( } } + for (name, _) in config.tasks.iter() { + match name.as_str() { + "before_each" => config.config.before_each_task = Some(name.to_string()), + "after_each" => config.config.after_each_task = Some(name.to_string()), + _ => {} + } + } + Ok(config) } diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 0857b81b..13dad675 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -549,32 +549,15 @@ impl<'a> ExecutionPlanBuilder<'a> { } }; } - let mut before_each_task: Option = None; - let mut after_each_task: Option = None; - for step in steps.iter() { - match step.name.as_str() { - "before_each" => before_each_task = Some(step.name.clone()), - "after_each" => after_each_task = Some(step.name.clone()), - _ => {} - } - } Ok(ExecutionPlan { - steps: Self::handle_before_each_and_after_each_tasks( - &config, - before_each_task, - after_each_task, - &steps, - )? - .into_owned(), + steps: Self::handle_before_each_and_after_each_tasks(&config, &steps)?.into_owned(), }) } /// `before_each` and `after_each` interspersal for the steps vector fn handle_before_each_and_after_each_tasks<'b>( config: &Config, - before_each_task: Option, - after_each_task: Option, steps: &'b Vec, ) -> Result>, CargoMakeError> { let mut before_and_after_each = Vec::::with_capacity(2); @@ -591,11 +574,11 @@ impl<'a> ExecutionPlanBuilder<'a> { Ok(0) } }; - let _has_after_each: u8 = match after_each_task { + let _has_after_each: u8 = match &config.config.after_each_task { None => 0, Some(after_each) => handle_some(&after_each)?, }; - let _has_before_each: u8 = match before_each_task { + let _has_before_each: u8 = match &config.config.before_each_task { None => 0, Some(before_each) => handle_some(&before_each)?, }; @@ -607,7 +590,7 @@ impl<'a> ExecutionPlanBuilder<'a> { Vec::::with_capacity(steps.len() * before_and_after_each_len); interspersed_steps.extend(steps.into_iter().flat_map(|e| -> Vec { let mut _steps = Vec::::with_capacity(before_and_after_each_len + 1); - _steps.clone_from_slice(&before_and_after_each); + _steps.extend(before_and_after_each.clone()); _steps.push(e.to_owned()); _steps })); From 32eaded4042169c4b0cba9bdeca3a3541f505413 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Fri, 26 Jul 2024 18:47:42 -0400 Subject: [PATCH 4/7] [src/lib/execution_plan.rs] Handle `init` and `end` tasks specially for the before_each and after_each tasks --- src/lib/execution_plan.rs | 62 ++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 24 deletions(-) diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 13dad675..8e5923bd 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -560,37 +560,51 @@ impl<'a> ExecutionPlanBuilder<'a> { config: &Config, steps: &'b Vec, ) -> Result>, CargoMakeError> { - let mut before_and_after_each = Vec::::with_capacity(2); - let scale = { - let mut handle_some = |name: &String| -> Result { - let task_config = get_normalized_task(config, name, false)?; - if !task_config.disabled.unwrap_or(false) { - before_and_after_each.push(Step { - name: name.to_string(), - config: task_config, - }); - Ok(1) - } else { - Ok(0) - } - }; - let _has_after_each: u8 = match &config.config.after_each_task { - None => 0, - Some(after_each) => handle_some(&after_each)?, - }; - let _has_before_each: u8 = match &config.config.before_each_task { - None => 0, - Some(before_each) => handle_some(&before_each)?, - }; - _has_before_each + _has_after_each + let mut after_and_before_each = Vec::::with_capacity(2); + let mut handle_some = |name: &String| -> Result { + let task_config = get_normalized_task(config, name, false)?; + if !task_config.disabled.unwrap_or(false) { + after_and_before_each.push(Step { + name: name.to_string(), + config: task_config, + }); + Ok(1) + } else { + Ok(0) + } + }; + let has_after_each: u8 = match &config.config.after_each_task { + None => 0, + Some(after_each) => handle_some(&after_each)?, }; + let has_before_each: u8 = match &config.config.before_each_task { + None => 0, + Some(before_each) => handle_some(&before_each)?, + }; + let scale: u8 = has_before_each + has_after_each; if scale > 0 { let before_and_after_each_len = scale as usize + 1; let mut interspersed_steps = Vec::::with_capacity(steps.len() * before_and_after_each_len); + let before_special = HashSet::from(["init", "init_task"]); + let end_special = HashSet::from(["end", "end_task"]); interspersed_steps.extend(steps.into_iter().flat_map(|e| -> Vec { let mut _steps = Vec::::with_capacity(before_and_after_each_len + 1); - _steps.extend(before_and_after_each.clone()); + if before_special.contains(e.name.as_str()) { + if has_after_each == 1 { + _steps.push( + unsafe { after_and_before_each.last().unwrap_unchecked() }.to_owned(), + ); + } + } else if end_special.contains(e.name.as_str()) { + if has_before_each == 1 { + _steps.push( + unsafe { after_and_before_each.first().unwrap_unchecked() }.to_owned(), + ); + } + } else { + _steps.extend(after_and_before_each.clone()); + } _steps.push(e.to_owned()); _steps })); From 335f702714ddc82606c5e5c1a4df3ffc12f7c9bc Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Wed, 31 Jul 2024 23:00:04 -0500 Subject: [PATCH 5/7] [src/lib/execution_plan.rs] Improve logic for `before_each` and `after_each` tasks ; [src/lib/execution_plan_test.rs] Add tests for `before_each` and `after_each` --- src/lib/execution_plan.rs | 26 +++---- src/lib/execution_plan_test.rs | 120 +++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 12 deletions(-) diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 8e5923bd..68b1def4 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -581,33 +581,35 @@ impl<'a> ExecutionPlanBuilder<'a> { None => 0, Some(before_each) => handle_some(&before_each)?, }; + let init_task_opt = &config.config.init_task; + let end_task_opt = &config.config.end_task; let scale: u8 = has_before_each + has_after_each; if scale > 0 { let before_and_after_each_len = scale as usize + 1; let mut interspersed_steps = Vec::::with_capacity(steps.len() * before_and_after_each_len); - let before_special = HashSet::from(["init", "init_task"]); - let end_special = HashSet::from(["end", "end_task"]); - interspersed_steps.extend(steps.into_iter().flat_map(|e| -> Vec { + let mut zeroth = true; + interspersed_steps.extend(steps.into_iter().flat_map(|step| -> Vec { let mut _steps = Vec::::with_capacity(before_and_after_each_len + 1); - if before_special.contains(e.name.as_str()) { + if zeroth { + zeroth = false; + } else if init_task_opt == &Some(step.name.to_string()) { if has_after_each == 1 { - _steps.push( - unsafe { after_and_before_each.last().unwrap_unchecked() }.to_owned(), - ); + _steps.push(after_and_before_each.last().unwrap().to_owned()); } - } else if end_special.contains(e.name.as_str()) { + } else if end_task_opt == &Some(step.name.to_string()) { if has_before_each == 1 { - _steps.push( - unsafe { after_and_before_each.first().unwrap_unchecked() }.to_owned(), - ); + _steps.push(after_and_before_each.first().unwrap().to_owned()); } } else { _steps.extend(after_and_before_each.clone()); } - _steps.push(e.to_owned()); + _steps.push(step.to_owned()); _steps })); + if !interspersed_steps.is_empty() && has_after_each == 1 { + interspersed_steps.push(after_and_before_each.first().unwrap().to_owned()); + } Ok(Cow::Owned(interspersed_steps)) } else { Ok(Cow::Borrowed(&steps)) diff --git a/src/lib/execution_plan_test.rs b/src/lib/execution_plan_test.rs index 86447afd..edd37bdc 100644 --- a/src/lib/execution_plan_test.rs +++ b/src/lib/execution_plan_test.rs @@ -1639,3 +1639,123 @@ fn respect_skip_init_end_tasks() { assert_eq!(execution_plan.steps.len(), 1); assert_eq!(execution_plan.steps[0].name, "test"); } + +#[test] +fn respect_before_each_and_after_each_tasks() { + let config = Config { + config: ConfigSection { + init_task: None, + before_each_task: Some("before_each".to_string()), + after_each_task: Some("after_each".to_string()), + end_task: None, + ..ConfigSection::default() + }, + env_files: vec![], + env: IndexMap::new(), + env_scripts: vec![], + tasks: indexmap::indexmap! { + "before_each".to_string() => Task::new(), + "test2".to_string() => Task { + dependencies: Some(vec![DependencyIdentifier::Definition(TaskIdentifier { + name: "test1".to_string(), + path: Some("./examples/workspace".to_string()), + })]), + ..Task::default() + }, + "test1".to_string() => Task { + dependencies: Some(vec![DependencyIdentifier::Definition(TaskIdentifier { + name: "test0".to_string(), + path: Some("./examples/workspace".to_string()), + })]), + ..Task::default() + }, + "test0".to_string() => Task::new(), + "after_each".to_string() => Task::new(), + }, + plugins: None, + }; + + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + skip_init_end_tasks: true, + ..ExecutionPlanBuilder::new(&config, "test2") + } + .build() + .unwrap(); + assert_eq!(execution_plan.steps.len(), 5); + assert_eq!( + execution_plan + .steps + .iter() + .map(|step| step.name.as_str()) + .collect::>(), + vec![ + "test1_proxy", + "after_each", + "before_each", + "test2", + "after_each" + ] + ); +} + +#[test] +fn respect_init_and_end_and_before_each_and_after_each_tasks() { + let config = Config { + config: ConfigSection { + init_task: Some("init".to_string()), + before_each_task: Some("before_each".to_string()), + after_each_task: Some("after_each".to_string()), + end_task: Some("end".to_string()), + ..ConfigSection::default() + }, + env_files: vec![], + env: IndexMap::new(), + env_scripts: vec![], + tasks: indexmap::indexmap! { + "init".to_string() => Task::new(), + "before_each".to_string() => Task::new(), + "test2".to_string() => Task { + dependencies: Some(vec![DependencyIdentifier::Definition(TaskIdentifier { + name: "test1".to_string(), + path: Some("./examples/workspace".to_string()), + })]), + ..Task::default() + }, + "test1".to_string() => Task { + dependencies: Some(vec![DependencyIdentifier::Definition(TaskIdentifier { + name: "test0".to_string(), + path: Some("./examples/workspace".to_string()), + })]), + ..Task::default() + }, + "test0".to_string() => Task::new(), + "after_each".to_string() => Task::new(), + "end".to_string() => Task::new(), + }, + plugins: None, + }; + + let execution_plan = ExecutionPlanBuilder { + allow_private: true, + skip_init_end_tasks: true, + ..ExecutionPlanBuilder::new(&config, "test2") + } + .build() + .unwrap(); + assert_eq!(execution_plan.steps.len(), 5); + assert_eq!( + execution_plan + .steps + .iter() + .map(|step| step.name.as_str()) + .collect::>(), + vec![ + "test1_proxy", + "after_each", + "before_each", + "test2", + "after_each" + ] + ); +} From 2e826c0c8d1421ac2792b10d0a3cf9413c64087c Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Wed, 31 Jul 2024 23:07:26 -0500 Subject: [PATCH 6/7] [src/lib/execution_plan.rs] Improve logic for `after_each` task --- src/lib/execution_plan.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 68b1def4..737cec7f 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -608,7 +608,10 @@ impl<'a> ExecutionPlanBuilder<'a> { _steps })); if !interspersed_steps.is_empty() && has_after_each == 1 { - interspersed_steps.push(after_and_before_each.first().unwrap().to_owned()); + let after_each = after_and_before_each.first().unwrap().to_owned(); + if interspersed_steps[interspersed_steps.len() - 1].name != after_each.name { + interspersed_steps.push(after_each); + } } Ok(Cow::Owned(interspersed_steps)) } else { From 5f28cc4c20a2016b6bfbd0ea89716b2f03ce5f44 Mon Sep 17 00:00:00 2001 From: Samuel Marks <807580+SamuelMarks@users.noreply.github.com> Date: Wed, 31 Jul 2024 23:31:16 -0500 Subject: [PATCH 7/7] [src/lib/execution_plan.rs] Improve logic for `after_each` task --- src/lib/execution_plan.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/lib/execution_plan.rs b/src/lib/execution_plan.rs index 737cec7f..f5bb026d 100644 --- a/src/lib/execution_plan.rs +++ b/src/lib/execution_plan.rs @@ -607,10 +607,14 @@ impl<'a> ExecutionPlanBuilder<'a> { _steps.push(step.to_owned()); _steps })); - if !interspersed_steps.is_empty() && has_after_each == 1 { - let after_each = after_and_before_each.first().unwrap().to_owned(); - if interspersed_steps[interspersed_steps.len() - 1].name != after_each.name { - interspersed_steps.push(after_each); + if let Some(last_step) = interspersed_steps.last() { + if has_after_each == 1 { + let after_each = after_and_before_each.first().unwrap().to_owned(); + if last_step.name != after_each.name + && Some(&last_step.name) != Option::from(end_task_opt) + { + interspersed_steps.push(after_each); + } } } Ok(Cow::Owned(interspersed_steps))