refactor(baker/bake): move relating part into separate directory
This commit is contained in:
@@ -3,7 +3,7 @@ pub mod env;
|
||||
pub mod security;
|
||||
pub mod stage;
|
||||
|
||||
use crate::cli::Cli;
|
||||
use crate::{cli::Cli, error::PrebakeError};
|
||||
|
||||
pub use config::PrebakeConfig;
|
||||
pub use security::prebake_drop_privilege;
|
||||
@@ -24,7 +24,7 @@ pub async fn prebake(config_path: &str, cli: &Cli) -> anyhow::Result<()> {
|
||||
for error in errors {
|
||||
log::error!("Error: {}", error);
|
||||
}
|
||||
// TODO: Raise an error
|
||||
anyhow::bail!(PrebakeError::ValidateError());
|
||||
}
|
||||
|
||||
let mut ctx = crate::ExecutionContext {
|
||||
@@ -38,8 +38,7 @@ pub async fn prebake(config_path: &str, cli: &Cli) -> anyhow::Result<()> {
|
||||
// Bootstrap stage
|
||||
ctx.task_id = format!("{}-{}-bootstrap", cli.pipeline, cli.build_id);
|
||||
// TODO: Pass real event_tx
|
||||
let result = stage::bootstrap::bootstrap(&config, &ctx, &None).await;
|
||||
result?;
|
||||
stage::bootstrap::bootstrap(&config, &ctx, &None).await?;
|
||||
// TODO: Early security implementation
|
||||
|
||||
// EarlyHook stage
|
||||
@@ -48,15 +47,21 @@ pub async fn prebake(config_path: &str, cli: &Cli) -> anyhow::Result<()> {
|
||||
Some(hooks) => hooks.early.clone(),
|
||||
None => None,
|
||||
};
|
||||
let result = stage::hook::hook(earlyhook, &ctx, None).await;
|
||||
result?;
|
||||
stage::hook::hook(earlyhook, &ctx, None).await?;
|
||||
|
||||
// DepsSystem stage
|
||||
ctx.task_id = format!("{}-{}-depssystem", cli.pipeline, cli.build_id);
|
||||
// TODO: Dependency stage
|
||||
// DepsUser stage
|
||||
ctx.task_id = format!("{}-{}-depsuser", cli.pipeline, cli.build_id);
|
||||
// TODO: Dependency stage
|
||||
if let Some(dependencies) = config.dependencies {
|
||||
// DepsSystem stage
|
||||
ctx.task_id = format!("{}-{}-depssystem", cli.pipeline, cli.build_id);
|
||||
if let Some(system) = dependencies.system {
|
||||
stage::depssystem::depssystem(&system, &ctx, None).await?;
|
||||
}
|
||||
|
||||
// DepsUser stage
|
||||
ctx.task_id = format!("{}-{}-depsuser", cli.pipeline, cli.build_id);
|
||||
if let Some(user) = dependencies.user {
|
||||
stage::depsuser::depsuser(&user, &ctx, None).await?;
|
||||
}
|
||||
}
|
||||
|
||||
// LateHook stage
|
||||
ctx.task_id = format!("{}-{}-latehook", cli.pipeline, cli.build_id);
|
||||
@@ -64,13 +69,12 @@ pub async fn prebake(config_path: &str, cli: &Cli) -> anyhow::Result<()> {
|
||||
Some(hooks) => hooks.late.clone(),
|
||||
None => None,
|
||||
};
|
||||
let result = stage::hook::hook(latehook, &ctx, None).await;
|
||||
result?;
|
||||
stage::hook::hook(latehook, &ctx, None).await?;
|
||||
|
||||
// Ready stage
|
||||
ctx.task_id = format!("{}-{}-ready", cli.pipeline, cli.build_id);
|
||||
// TODO: Security stage
|
||||
|
||||
// TODO: Ready here!
|
||||
todo!();
|
||||
log::info!("Prebake done!");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ use std::collections::HashMap;
|
||||
pub async fn depssystem(
|
||||
config: &HashMap<String, SystemDependency>,
|
||||
ctx: &ExecutionContext,
|
||||
event_tx: &EventSender,
|
||||
event_tx: EventSender,
|
||||
) -> Result<(), DependencyError> {
|
||||
let osinfo = os_info::get();
|
||||
let engine = Engine::new();
|
||||
|
||||
@@ -8,7 +8,7 @@ use std::collections::HashMap;
|
||||
pub async fn depsuser(
|
||||
config: &HashMap<String, Value>,
|
||||
ctx: &ExecutionContext,
|
||||
event_tx: &EventSender,
|
||||
event_tx: EventSender,
|
||||
) -> Result<(), DependencyError> {
|
||||
for (name, cfg) in config {
|
||||
let package_manager = match upm::select(name){
|
||||
@@ -20,7 +20,7 @@ pub async fn depsuser(
|
||||
};
|
||||
log::info!("Running user package manager: {}", name);
|
||||
|
||||
package_manager.main(cfg, ctx, event_tx).await?;
|
||||
package_manager.main(cfg, ctx, &event_tx).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
use regex::Regex;
|
||||
use std::collections::HashSet;
|
||||
pub struct Variable {
|
||||
pub name: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
static ref VAR_REGEX: Regex = Regex::new(r#"\$(?:\{(?:#)?([a-zA-Z_][a-zA-Z0-9_]*)(?:\[(?:\d+|@|\*)?\])?(?:\s*:\s*[+-]?\d+(?::[+-]?\d+)?)?\}|\b([a-zA-Z_][a-zA-Z0-9_]*)\b)"#)
|
||||
.expect("Failed to compile variable regex");
|
||||
}
|
||||
|
||||
pub fn extract_variables(body: String) -> Vec<Variable> {
|
||||
let mut variables = HashSet::<String>::new();
|
||||
let mut variable_list = Vec::<Variable>::new();
|
||||
|
||||
for captures in VAR_REGEX.captures_iter(&body) {
|
||||
if let Some(name) = captures.get(1) {
|
||||
dbg!(name);
|
||||
variables.insert(name.as_str().to_string());
|
||||
} else if let Some(name) = captures.get(2) {
|
||||
dbg!(name);
|
||||
variables.insert(name.as_str().to_string());
|
||||
}
|
||||
}
|
||||
|
||||
for variable in variables {
|
||||
let variable_element = Variable {
|
||||
name: variable.clone(),
|
||||
value: Default::default(), // TODO: 换成workshop-agent通信
|
||||
};
|
||||
variable_list.push(variable_element);
|
||||
}
|
||||
|
||||
variable_list
|
||||
}
|
||||
|
||||
// 单元测试模块
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::collections::BTreeSet;
|
||||
|
||||
/// 辅助函数:将Variable列表转换为排序后的字符串集合(解决HashSet无序问题)
|
||||
fn sorted_var_names(vars: &[Variable]) -> BTreeSet<String> {
|
||||
vars.iter().map(|v| v.name.clone()).collect::<BTreeSet<_>>()
|
||||
}
|
||||
|
||||
/// 测试1:基础场景(重复变量去重 + 多种合法格式)
|
||||
#[test]
|
||||
fn test_extract_duplicate_variables() {
|
||||
let script = r#"
|
||||
echo $var
|
||||
echo ${var}
|
||||
echo ${#var}
|
||||
echo ${var:3:5}
|
||||
echo ${var: -3}
|
||||
echo ${var[0]}
|
||||
echo ${var[@]}
|
||||
echo ${var[*]}
|
||||
echo $_var123
|
||||
echo ${_var123: -5:10}
|
||||
"#;
|
||||
|
||||
let variables = extract_variables(script.to_string());
|
||||
let sorted_names = sorted_var_names(&variables);
|
||||
|
||||
// 预期结果:去重后仅保留var和_var123
|
||||
let expected = BTreeSet::from(["var".to_string(), "_var123".to_string()]);
|
||||
assert_eq!(sorted_names, expected);
|
||||
}
|
||||
|
||||
/// 测试2:非法变量(数字开头、特殊字符、$1/$?等)
|
||||
#[test]
|
||||
fn test_extract_illegal_variables() {
|
||||
let script = r#"
|
||||
echo $1 # 数字开头,不匹配
|
||||
echo $? # 特殊符号,不匹配
|
||||
echo $@ # 特殊符号,不匹配
|
||||
echo ${123var} # 数字开头,不匹配
|
||||
echo ${var-with-dash} # 含非法字符,不匹配
|
||||
echo ${var+123} # 含非法字符,不匹配
|
||||
echo ${} # 空变量,不匹配
|
||||
echo $ # 无变量名,不匹配
|
||||
"#;
|
||||
|
||||
let variables = extract_variables(script.to_string());
|
||||
assert!(variables.is_empty());
|
||||
}
|
||||
|
||||
/// 测试3:空输入
|
||||
#[test]
|
||||
fn test_extract_empty_body() {
|
||||
let variables = extract_variables("".to_string());
|
||||
assert!(variables.is_empty());
|
||||
}
|
||||
|
||||
/// 测试4:无合法变量的输入
|
||||
#[test]
|
||||
fn test_extract_no_valid_variables() {
|
||||
let script = r#"
|
||||
echo "hello world"
|
||||
cd /tmp
|
||||
ls -l
|
||||
echo $123abc # 数字开头,不匹配
|
||||
"#;
|
||||
|
||||
let variables = extract_variables(script.to_string());
|
||||
assert!(variables.is_empty());
|
||||
}
|
||||
|
||||
/// 测试5:混合合法/非法变量(仅保留合法项)
|
||||
#[test]
|
||||
fn test_extract_mixed_variables() {
|
||||
let script = r#"
|
||||
echo $APP_NAME
|
||||
echo ${DEPLOY_ENV}
|
||||
echo ${#PORT}
|
||||
echo $1 # 非法
|
||||
echo ${invalid-var} # 非法
|
||||
echo ${_DB_PASSWORD: 5}
|
||||
echo $? # 非法
|
||||
"#;
|
||||
|
||||
let variables = extract_variables(script.to_string());
|
||||
let sorted_names = sorted_var_names(&variables);
|
||||
|
||||
let expected = BTreeSet::from([
|
||||
"APP_NAME".to_string(),
|
||||
"DEPLOY_ENV".to_string(),
|
||||
"PORT".to_string(),
|
||||
"_DB_PASSWORD".to_string(),
|
||||
]);
|
||||
assert_eq!(sorted_names, expected);
|
||||
}
|
||||
|
||||
/// 测试6:变量名包含数字(合法场景)
|
||||
#[test]
|
||||
fn test_extract_var_with_numbers() {
|
||||
let script = r#"
|
||||
echo $var123
|
||||
echo ${var_456}
|
||||
echo ${#var789: 10}
|
||||
"#;
|
||||
|
||||
let variables = extract_variables(script.to_string());
|
||||
let sorted_names = sorted_var_names(&variables);
|
||||
|
||||
let expected = BTreeSet::from([
|
||||
"var123".to_string(),
|
||||
"var_456".to_string(),
|
||||
"var789".to_string(),
|
||||
]);
|
||||
assert_eq!(sorted_names, expected);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user