wrkflw_executor/
substitution.rs1use lazy_static::lazy_static;
2use regex::Regex;
3use serde_yaml::Value;
4use std::collections::HashMap;
5
6lazy_static! {
7 static ref MATRIX_PATTERN: Regex =
8 Regex::new(r"\$\{\{\s*matrix\.([a-zA-Z0-9_]+)\s*\}\}").unwrap();
9}
10
11#[allow(dead_code)]
14pub fn preprocess_command(command: &str, matrix_values: &HashMap<String, Value>) -> String {
15 let result = MATRIX_PATTERN.replace_all(command, |caps: ®ex::Captures| {
17 let var_name = &caps[1];
18
19 if let Some(value) = matrix_values.get(var_name) {
21 match value {
23 Value::String(s) => s.clone(),
24 Value::Number(n) => n.to_string(),
25 Value::Bool(b) => b.to_string(),
26 _ => format!("\\${{{{ matrix.{} }}}}", var_name), }
28 } else {
29 format!("\\${{{{ matrix.{} }}}}", var_name)
31 }
32 });
33
34 result.into_owned()
35}
36
37#[allow(dead_code)]
39pub fn process_step_run(run: &str, matrix_combination: &Option<HashMap<String, Value>>) -> String {
40 if let Some(matrix) = matrix_combination {
41 preprocess_command(run, matrix)
42 } else {
43 MATRIX_PATTERN
45 .replace_all(run, |caps: ®ex::Captures| {
46 let var_name = &caps[1];
47 format!("\\${{{{ matrix.{} }}}}", var_name)
48 })
49 .to_string()
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn test_preprocess_simple_matrix_vars() {
59 let mut matrix = HashMap::new();
60 matrix.insert("os".to_string(), Value::String("ubuntu-latest".to_string()));
61 matrix.insert(
62 "node".to_string(),
63 Value::Number(serde_yaml::Number::from(14)),
64 );
65
66 let cmd = "echo \"Running on ${{ matrix.os }} with Node ${{ matrix.node }}\"";
67 let processed = preprocess_command(cmd, &matrix);
68
69 assert_eq!(processed, "echo \"Running on ubuntu-latest with Node 14\"");
70 }
71
72 #[test]
73 fn test_preprocess_with_missing_vars() {
74 let mut matrix = HashMap::new();
75 matrix.insert("os".to_string(), Value::String("ubuntu-latest".to_string()));
76
77 let cmd = "echo \"Running on ${{ matrix.os }} with Node ${{ matrix.node }}\"";
78 let processed = preprocess_command(cmd, &matrix);
79
80 assert_eq!(
82 processed,
83 "echo \"Running on ubuntu-latest with Node \\${{ matrix.node }}\""
84 );
85 }
86
87 #[test]
88 fn test_preprocess_preserves_other_text() {
89 let mut matrix = HashMap::new();
90 matrix.insert("os".to_string(), Value::String("ubuntu-latest".to_string()));
91
92 let cmd = "echo \"Starting job\" && echo \"OS: ${{ matrix.os }}\" && echo \"Done!\"";
93 let processed = preprocess_command(cmd, &matrix);
94
95 assert_eq!(
96 processed,
97 "echo \"Starting job\" && echo \"OS: ubuntu-latest\" && echo \"Done!\""
98 );
99 }
100
101 #[test]
102 fn test_process_without_matrix() {
103 let cmd = "echo \"Value: ${{ matrix.value }}\"";
104 let processed = process_step_run(cmd, &None);
105
106 assert_eq!(processed, "echo \"Value: \\${{ matrix.value }}\"");
107 }
108}