use super::args::CiArgs;
use crate::providers::detect_ci_provider;
use cuenv_ci::discovery::find_cue_module_root;
use cuenv_ci::executor::run_ci;
use cuenv_core::Result;
pub async fn execute_runner(args: &CiArgs) -> Result<()> {
let provider = detect_ci_provider(args.from.clone());
if !args.filter_matrix.is_empty() {
tracing::info!(
filter = ?args.filter_matrix,
"Matrix filter specified (not yet fully implemented)"
);
}
if args.jobs != 0 {
tracing::info!(
jobs = args.effective_jobs(),
"Parallel jobs limit specified"
);
}
let effective_path = resolve_path_filter(&args.path)?;
run_ci(
provider,
args.dry_run.into(),
args.pipeline.clone(),
args.environment.clone(),
effective_path.as_deref(),
)
.await
}
fn resolve_path_filter(path: &str) -> Result<Option<String>> {
let cwd = std::env::current_dir().map_err(|e| cuenv_core::Error::Io {
source: e,
path: None,
operation: "get current directory".to_string(),
})?;
let Some(module_root) = find_cue_module_root(&cwd) else {
return Ok(Some(path.to_string()));
};
let cwd_canon = cwd.canonicalize().map_err(|e| cuenv_core::Error::Io {
source: e,
path: Some(cwd.clone().into_boxed_path()),
operation: "canonicalize current directory".to_string(),
})?;
let module_root_canon = module_root
.canonicalize()
.map_err(|e| cuenv_core::Error::Io {
source: e,
path: Some(module_root.clone().into_boxed_path()),
operation: "canonicalize module root".to_string(),
})?;
if cwd_canon == module_root_canon && path == "." {
return Ok(None);
}
if path == "." {
let relative = cwd_canon.strip_prefix(&module_root_canon).map_err(|_| {
cuenv_core::Error::configuration(format!(
"Current directory '{}' is not inside module root '{}'",
cwd.display(),
module_root.display()
))
})?;
return Ok(Some(relative.to_string_lossy().to_string()));
}
let absolute_path = if std::path::Path::new(path).is_absolute() {
std::path::PathBuf::from(path)
} else {
cwd.join(path)
};
if !absolute_path.exists() {
return Err(cuenv_core::Error::configuration(format!(
"Path '{}' does not exist",
path
)));
}
let absolute_canon = absolute_path
.canonicalize()
.map_err(|e| cuenv_core::Error::Io {
source: e,
path: Some(absolute_path.clone().into_boxed_path()),
operation: "canonicalize path".to_string(),
})?;
let relative = absolute_canon
.strip_prefix(&module_root_canon)
.map_err(|_| {
cuenv_core::Error::configuration(format!(
"Path '{}' is not inside module root '{}'",
path,
module_root.display()
))
})?;
Ok(Some(relative.to_string_lossy().to_string()))
}