use crate::domain::file::parsed::FileKind;
use crate::domain::file::scan::Error as WorkflowError;
use glob::glob;
use std::path::{Path, PathBuf};
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ManagedFile {
pub path: PathBuf,
pub kind: FileKind,
}
struct Root {
dir: &'static str,
stem: &'static str,
kind: FileKind,
}
const ROOTS: [Root; 2] = [
Root {
dir: "workflows",
stem: "*",
kind: FileKind::Workflow,
},
Root {
dir: "actions",
stem: "**/action",
kind: FileKind::ActionDefinition,
},
];
pub fn managed_files(repo_root: &Path) -> Result<Vec<ManagedFile>, WorkflowError> {
let github = repo_root.join(".github");
let mut found = Vec::new();
for root in &ROOTS {
let mut group = glob_root(&github.join(root.dir), root)?;
group.sort_by(|a, b| a.path.cmp(&b.path));
found.extend(group);
}
Ok(found)
}
fn glob_root(dir: &Path, root: &Root) -> Result<Vec<ManagedFile>, WorkflowError> {
let mut found = Vec::new();
for extension in &["yml", "yaml"] {
let pattern = dir
.join(format!("{}.{extension}", root.stem))
.to_string_lossy()
.into_owned();
let entries = glob(&pattern).map_err(|e| WorkflowError::ScanFailed {
reason: e.to_string(),
})?;
for path in entries.flatten() {
found.push(ManagedFile {
path,
kind: root.kind,
});
}
}
Ok(found)
}
pub fn managed_paths(repo_root: &Path) -> Result<Vec<PathBuf>, WorkflowError> {
Ok(managed_files(repo_root)?
.into_iter()
.map(|f| f.path)
.collect())
}