From 0d16f33018b85b4cae8c9ba558a5c71681c5ec0f Mon Sep 17 00:00:00 2001 From: Luc Perkins Date: Mon, 17 Jun 2024 22:59:55 -0700 Subject: [PATCH] Vet condition prior to evaluation --- src/condition.rs | 22 +++++++++++++++++++++- src/error.rs | 4 ++-- src/main.rs | 2 ++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/condition.rs b/src/condition.rs index c56cd93..7050ec8 100644 --- a/src/condition.rs +++ b/src/condition.rs @@ -46,7 +46,11 @@ pub(super) fn evaluate_condition( }); } Value::Bool(b) if b => continue, - result => return Err(FlakeCheckerError::InvalidCelCondition(format!("CEL conditions must return a Boolean but your supplied condition returned a {}", result.type_of()))), + result => { + return Err(FlakeCheckerError::NonBooleanCondition( + result.type_of().to_string(), + )) + } }, Err(e) => return Err(FlakeCheckerError::CelExecution(e)), } @@ -71,3 +75,19 @@ fn nixpkgs_cel_values(repo: Box) -> Vec<(&'static str, Value)> { (KEY_OWNER, Value::from(repo.original.owner)), ] } + +pub(super) fn vet_condition(condition: &str) -> Result<(), FlakeCheckerError> { + let mut ctx = Context::default(); + ctx.add_variable_from_value(KEY_SUPPORTED_REFS, Value::List(Vec::::new().into())); + ctx.add_variable_from_value(KEY_GIT_REF, Value::from("some-ref")); + ctx.add_variable_from_value(KEY_NUM_DAYS_OLD, Value::from(27)); + ctx.add_variable_from_value(KEY_OWNER, Value::from("some-og")); + + match Program::compile(condition)?.execute(&ctx) { + Ok(value) if matches!(value, Value::Bool(_)) => Ok(()), + Ok(value) => Err(FlakeCheckerError::NonBooleanCondition( + value.type_of().to_string(), + )), + Err(e) => Err(FlakeCheckerError::CelExecution(e)), + } +} diff --git a/src/error.rs b/src/error.rs index 5161cad..a22ef8a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,8 +10,8 @@ pub enum FlakeCheckerError { FlakeLock(#[from] parse_flake_lock::FlakeLockParseError), #[error("http client error: {0}")] Http(#[from] reqwest::Error), - #[error("invalid CEL condition: {0}")] - InvalidCelCondition(String), + #[error("CEL conditions must return a Boolean but returned {0} instead")] + NonBooleanCondition(String), #[error("couldn't access flake.lock: {0}")] Io(#[from] std::io::Error), #[error("couldn't parse flake.lock: {0}")] diff --git a/src/main.rs b/src/main.rs index a029aa2..f9bb8c7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,7 @@ mod issue; mod summary; mod telemetry; +use condition::vet_condition; use error::FlakeCheckerError; use flake::{check_flake_lock, FlakeCheckConfig}; use summary::Summary; @@ -179,6 +180,7 @@ fn main() -> Result { }; let issues = if let Some(condition) = &condition { + vet_condition(condition)?; evaluate_condition(&flake_lock, &nixpkgs_keys, condition, allowed_refs.clone())? } else { check_flake_lock(&flake_lock, &flake_check_config, allowed_refs.clone())?