/** * This module contains all the defined structures which will process the UrCI * configuration file */ use serde::de::{Deserialize, Deserializer}; use std::collections::HashMap; use std::str::FromStr; #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Config { pub projects: Vec, pub agents: Vec, pub handlers: HashMap, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Project { name: String, trigger: Trigger, handler: String, scm: Scm, } #[derive(Deserialize)] #[serde(rename_all = "camelCase")] pub struct Trigger { #[serde(deserialize_with = "deserialize_cron_schedule")] cron: Option, } impl std::fmt::Debug for Trigger { fn fmt(&self, formatter: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> { write!(formatter, "Trigger: ")?; if let Some(cron) = &self.cron { write!(formatter, "cron: {}", cron)?; } Ok(()) } } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Scm { git: Option, r#ref: Option, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub enum AgentType { Local, Ssh, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Agent { name: String, description: String, r#type: AgentType, params: Option>, } #[derive(Debug, Deserialize)] #[serde(rename_all = "camelCase")] pub struct Handler { filename: String, defaults: Option>, } fn deserialize_cron_schedule<'de, D>(deserializer: D) -> Result, D::Error> where D: Deserializer<'de>, { let buf = String::deserialize(deserializer)?; if let Ok(schedule) = cron::Schedule::from_str(&buf) { return Ok(Some(schedule)); } Err(serde::de::Error::custom( "Failed to parse cron, make sure you have at least six fields", )) } #[cfg(test)] mod tests { use std::fs::File; use std::io::Read; use super::*; #[test] fn test_deserialize_example_config() { let mut f = File::open("urci.yml").unwrap(); let mut yaml = String::new(); f.read_to_string(&mut yaml) .expect("Failed to read into string"); let _config: Config = serde_yaml::from_str(&yaml).expect("Failed to parse the yaml"); } #[test] fn test_cron_deserialize() { let trigger_yaml = r#"--- # Fire every second lol cron: '* * * * * *' "#; let trigger: Trigger = serde_yaml::from_str(trigger_yaml).expect("Should be able to parse our yaml"); assert!(trigger.cron.is_some()); } }