use super::{Context, Diagnostic, Rule, RuleName};
use crate::config::Level;
use crate::domain::action::spec::Spec;
use crate::domain::action::specifier::Specifier;
use crate::domain::action::uses_ref::ParsedRef;
pub struct ShaMismatchRule;
impl ShaMismatchRule {
pub fn check_action(
action: &crate::domain::file::actions::Located,
lock: &crate::domain::lock::Lock,
) -> Option<Diagnostic> {
let ParsedRef::Sha(sha) = &action.action.reference else {
return None;
};
let key = Spec::new(action.action.id.clone(), Specifier::from_v1(sha.as_str()));
if lock.has(&key) {
return None;
}
let msg = format!(
"action {} SHA {} not found in lock file",
&action.action.id,
sha.as_str()
);
Some(
Diagnostic::new(RuleName::ShaMismatch, Level::Error, msg)
.with_workflow(action.site.file.clone())
.with_line(action.origin.line),
)
}
}
impl Rule for ShaMismatchRule {
fn name(&self) -> RuleName {
RuleName::ShaMismatch
}
fn default_level(&self) -> Level {
Level::Error
}
fn check(&self, ctx: &Context) -> Vec<Diagnostic> {
ctx.workflows
.iter()
.filter_map(|a| Self::check_action(a, ctx.lock))
.collect()
}
}
#[cfg(test)]
mod tests {
use super::{Level, Rule as _, RuleName, ShaMismatchRule};
#[test]
fn sha_mismatch_rule_has_correct_metadata() {
let rule = ShaMismatchRule;
assert_eq!(rule.name(), RuleName::ShaMismatch);
assert_eq!(rule.default_level(), Level::Error);
}
}