diff --git a/ci-broker.md b/ci-broker.md index 3b318331..0a4eaaf1 100644 --- a/ci-broker.md +++ b/ci-broker.md @@ -943,7 +943,7 @@ adapters: triggers: - adapter: default filters: - - !Tag "v1.0" + - !Tag "v\\d+(\\.\\d+)" ~~~ ## Filter predicate `Branch` diff --git a/src/filter.rs b/src/filter.rs index 66c336c9..66c76abe 100644 --- a/src/filter.rs +++ b/src/filter.rs @@ -1,10 +1,11 @@ use std::path::{Path, PathBuf}; +use regex::Regex; use serde::{Deserialize, Serialize}; use radicle::{ cob::patch::PatchId, - git::{raw::ObjectType, BranchName, Oid, RefString}, + git::{raw::ObjectType, BranchName, Oid}, node::NodeId, prelude::{Profile, RepoId}, storage::git::Repository, @@ -55,8 +56,8 @@ pub enum EventFilter { /// Event is for a specific branch. Branch(BranchName), - /// Event is for a specific tag. - Tag(RefString), + /// Event is for a tag whose name matches a regular expression. + Tag(String), /// Event if for the default branch for the repository. DefaultBranch, @@ -155,11 +156,24 @@ impl EventFilter { format!("wanted={wanted} actual={actual:?}"), ) } - Self::Tag(wanted) => { - let actual = event.tag(); - let allowed = Some(wanted) == actual; - Decision::string("Tag", allowed, format!("wanted={wanted} actual={actual:?}")) - } + Self::Tag(wanted) => match Regex::new(wanted) { + Ok(re) => { + let actual = event.tag(); + let allowed = match &actual { + Some(actual) => re.is_match_at(actual.as_str(), 0), + _ => false, + }; + Decision::string( + "Tag", + allowed, + format!("wanted={wanted:?} actual={actual:?}"), + ) + } + Err(err) => { + logger::queueproc_filter_regex_error(wanted, err); + Decision::new("Tag", false, "regex syntax error") + } + }, Self::DefaultBranch => { let repo = event.repository(); let actual = event.branch(); diff --git a/src/logger.rs b/src/logger.rs index 2e1afe2a..19012d48 100644 --- a/src/logger.rs +++ b/src/logger.rs @@ -444,6 +444,15 @@ pub fn queueproc_queue_length(len: usize) { ); } +pub fn queueproc_filter_regex_error(pattern: &str, err: regex::Error) { + warn!( + msg_id = ?Id::QueueProcFilterDecision, + kind = %Kind::FilterDecision, + ?pattern, + ?err, + "regular expression syntax error"); +} + pub fn queueproc_filter_decision(event: &CiEvent, filter: &EventFilter, allowed: bool) { info!( msg_id = ?Id::QueueProcFilterDecision,