diff --git a/Cargo.lock b/Cargo.lock index 9f29e82..921297e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -787,7 +787,7 @@ dependencies = [ [[package]] name = "github-webhook-notification" -version = "2.1.0-beta" +version = "2.1.0-rc" dependencies = [ "actix", "actix-rt", @@ -806,6 +806,7 @@ dependencies = [ "teloxide-macros", "tokio", "toml", + "walkdir", ] [[package]] @@ -1545,6 +1546,15 @@ version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b30e4c09749c107e83dd61baf9604198efc4542863c88af39dafcaca89c7c9f9" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "scopeguard" version = "1.1.0" @@ -2155,6 +2165,17 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "walkdir" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +dependencies = [ + "same-file", + "winapi", + "winapi-util", +] + [[package]] name = "want" version = "0.3.0" diff --git a/Cargo.toml b/Cargo.toml index b4169ff..8eee228 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "github-webhook-notification" -version = "2.1.0-beta" +version = "2.1.0-rc" edition = "2021" [dependencies] @@ -28,4 +28,4 @@ panic = "abort" [dev-dependencies] ntest = "0.7.3" - +walkdir = "2.3" diff --git a/src/configure.rs b/src/configure.rs index 7b52e90..fd865d5 100644 --- a/src/configure.rs +++ b/src/configure.rs @@ -60,128 +60,31 @@ impl TomlConfig { pub fn repository(&self) -> &Option> { &self.repository } - - pub fn convert_hashmap(&self) -> HashMap { - let mut m = HashMap::new(); - if let Some(repositories) = &self.repository() { - for repository in repositories { - m.insert(repository.full_name().clone(), Repository::from(repository)); - } - } - m - } } -#[derive(Deserialize, Serialize, Debug, Clone)] -pub struct TomlRepository { - full_name: String, - send_to: Option, - branch_ignore: Option>, +#[derive(Deserialize, Serialize, Clone)] +pub struct TomlServer { + bind: String, + port: u16, secrets: Option, + token: Option, } -impl TomlRepository { - pub fn full_name(&self) -> &String { - &self.full_name - } - pub fn send_to(&self) -> &Option { - &self.send_to +impl TomlServer { + pub fn bind(&self) -> &str { + &self.bind } - pub fn branch_ignore(&self) -> &Option> { - &self.branch_ignore + pub fn port(&self) -> u16 { + self.port } pub fn secrets(&self) -> &Option { &self.secrets } -} - -#[derive(Debug, Clone)] -pub struct Repository { - //full_name: String, - send_to: Vec, - branch_ignore: Vec, - secrets: String, -} - -impl Repository { - /*pub fn full_name(&self) -> &str { - &self.full_name - }*/ - pub fn send_to(&self) -> &Vec { - &self.send_to - } - pub fn branch_ignore(&self) -> &Vec { - &self.branch_ignore - } - pub fn secrets(&self) -> &String { - &self.secrets - } -} - -impl From<&TomlRepository> for Repository { - fn from(repo: &TomlRepository) -> Self { - Self { - //full_name: repo.full_name().clone(), - send_to: match repo.send_to() { - None => vec![], - Some(v) => parse_value(v), - }, - branch_ignore: match repo.branch_ignore() { - Some(v) => v.clone(), - None => vec![], - }, - secrets: match repo.secrets() { - None => "".to_string(), - Some(ref secret) => secret.clone(), - }, - } - } -} - -/*impl From<&Config> for Repository { - fn from(s: &Config) -> Self { - Self { - send_to: s.telegram().send_to().clone(), - secrets: Some(s.server().secrets().clone()), - ..Default::default() - } - } -}*/ - -#[derive(Debug, Default, Clone)] -pub struct RepositoryBuilder { - send_to: Vec, - branch_ignore: Vec, - secrets: String, -} - -impl RepositoryBuilder { - pub fn set_send_to(&mut self, send_to: Vec) -> &mut Self { - self.send_to = send_to; - self - } - #[allow(unused)] - pub fn set_branch_ignore(&mut self, branch_ignore: Vec) -> &mut Self { - self.branch_ignore = branch_ignore; - self - } - pub fn set_secrets(&mut self, secrets: &String) -> &mut Self{ - self.secrets = secrets.clone(); - self - } - pub fn build(&self) -> Repository { - Repository { - send_to: self.send_to.clone(), - branch_ignore: self.branch_ignore.clone(), - secrets: self.secrets.clone(), - } - } - pub fn new() -> Self { - Self { ..Default::default() } + pub fn token(&self) -> &Option { + &self.token } } - #[derive(Debug, Clone)] pub struct Telegram { bot_token: String, @@ -263,64 +166,85 @@ impl Config { pub fn telegram(&self) -> &Telegram { &self.telegram } + + #[allow(dead_code)] + #[deprecated( + note = "Avoid access from repository directly, use `Self::fetch_repository_configure` function instead." + )] pub fn repo_mapping(&self) -> &HashMap { + self.mapping() + } + + fn mapping(&self) -> &HashMap { &self.repo_mapping } -} -impl Config { pub fn new>(path: P) -> anyhow::Result { let config = TomlConfig::new(path)?; Ok(Self::from(&config)) } pub fn fetch_repository_configure(&self, branch_name: &str) -> Repository { - let conf = self.repo_mapping().get(branch_name); + let conf = self.mapping().get(branch_name); match conf { - None => { - RepositoryBuilder::new() - .set_send_to(self.telegram().send_to().clone()) - .set_secrets(self.server().secrets()) - .build() - } - Some(repository) => repository.clone() + None => RepositoryBuilder::new() + .set_send_to(self.telegram().send_to().clone()) + .set_secrets(self.server().secrets()) + .set_is_default(true) + .build(), + Some(repository) => repository.clone(), } } + + pub fn build_repository_from_configure( + default_secret: &String, + default_target: &Vec, + repository: &TomlRepository, + ) -> Repository { + let secrets = match repository.secrets() { + None => default_secret.clone(), + Some(s) => s.clone(), + }; + let send_to = match repository.send_to() { + None => default_target.clone(), + Some(v) => parse_value(v), + }; + RepositoryBuilder::new() + .set_secrets(&secrets) + .set_branch_ignore(repository.branch_ignore.clone().unwrap_or_default()) + .set_send_to(send_to) + .set_is_default(false) + .build() + } } impl From<&TomlConfig> for Config { fn from(config: &TomlConfig) -> Self { + let real_secret = config.server().secrets().clone().unwrap_or_default(); + let real_receiver = parse_value(config.telegram().send_to()); Self { server: Server::from(config.server()), telegram: Telegram::from(config.telegram()), - repo_mapping: config.convert_hashmap(), + repo_mapping: { + let mut m = HashMap::new(); + if let Some(repositories) = config.repository() { + for repository in repositories { + m.insert( + repository.full_name().clone(), + Config::build_repository_from_configure( + &real_secret, + &real_receiver, + &repository, + ), + ); + } + } + m + }, } } } -#[derive(Deserialize, Serialize, Clone)] -pub struct TomlServer { - bind: String, - port: u16, - secrets: Option, - token: Option, -} - -impl TomlServer { - pub fn bind(&self) -> &str { - &self.bind - } - pub fn port(&self) -> u16 { - self.port - } - pub fn secrets(&self) -> &Option { - &self.secrets - } - pub fn token(&self) -> &Option { - &self.token - } -} - #[derive(Debug, Clone)] pub struct Server { bind: String, @@ -363,3 +287,122 @@ impl Server { &self.token } } + +#[derive(Deserialize, Serialize, Debug, Clone)] +pub struct TomlRepository { + full_name: String, + send_to: Option, + branch_ignore: Option>, + secrets: Option, +} + +impl TomlRepository { + pub fn full_name(&self) -> &String { + &self.full_name + } + pub fn send_to(&self) -> &Option { + &self.send_to + } + pub fn branch_ignore(&self) -> &Option> { + &self.branch_ignore + } + pub fn secrets(&self) -> &Option { + &self.secrets + } +} + +#[derive(Debug, Clone)] +pub struct Repository { + #[cfg(test)] + is_default: bool, + //full_name: String, + send_to: Vec, + branch_ignore: Vec, + secrets: String, +} + +impl Repository { + /*pub fn full_name(&self) -> &str { + &self.full_name + }*/ + pub fn send_to(&self) -> &Vec { + &self.send_to + } + pub fn branch_ignore(&self) -> &Vec { + &self.branch_ignore + } + pub fn secrets(&self) -> &String { + &self.secrets + } + #[cfg(test)] + pub fn is_default(&self) -> bool { + self.is_default + } +} + +impl From<&TomlRepository> for Repository { + fn from(repo: &TomlRepository) -> Self { + Self { + //full_name: repo.full_name().clone(), + send_to: match repo.send_to() { + None => vec![], + Some(v) => parse_value(v), + }, + branch_ignore: match repo.branch_ignore() { + Some(v) => v.clone(), + None => vec![], + }, + secrets: match repo.secrets() { + None => "".to_string(), + Some(ref secret) => secret.clone(), + }, + #[cfg(test)] + is_default: true, + } + } +} + +#[derive(Debug, Default, Clone)] +pub struct RepositoryBuilder { + send_to: Vec, + branch_ignore: Vec, + secrets: String, + #[cfg(test)] + is_default: bool, +} + +impl RepositoryBuilder { + pub fn set_send_to(&mut self, send_to: Vec) -> &mut Self { + self.send_to = send_to; + self + } + pub fn set_branch_ignore(&mut self, branch_ignore: Vec) -> &mut Self { + self.branch_ignore = branch_ignore; + self + } + pub fn set_secrets(&mut self, secrets: &String) -> &mut Self { + self.secrets = secrets.clone(); + self + } + #[cfg(test)] + pub fn set_is_default(&mut self, default: bool) -> &mut Self { + self.is_default = default; + self + } + pub fn build(&self) -> Repository { + Repository { + send_to: self.send_to.clone(), + branch_ignore: self.branch_ignore.clone(), + secrets: self.secrets.clone(), + #[cfg(test)] + is_default: self.is_default, + } + } + pub fn new() -> Self { + Self { + #[cfg(test)] + is_default: true, + ..Default::default() + } + } +} diff --git a/src/main.rs b/src/main.rs index 23a2bbd..fe32dcb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -120,8 +120,7 @@ async fn route_post( return Ok(HttpResponse::InternalServerError().finish()); }; let object = object?; - let settings = configure - .fetch_repository_configure(object.get_full_name()); + let settings = configure.fetch_repository_configure(object.get_full_name()); let secrets = settings.secrets(); if !secrets.is_empty() { diff --git a/src/test.rs b/src/test.rs index 4210371..c3ac944 100644 --- a/src/test.rs +++ b/src/test.rs @@ -19,10 +19,10 @@ #[cfg(test)] mod test { use crate::configure::Config; - use crate::{DisplayableEvent, GitHubPingEvent, GitHubPushEvent}; + use crate::{DisplayableEvent, GitHubEarlyParse, GitHubPingEvent, GitHubPushEvent}; + use walkdir::WalkDir; #[test] - #[should_panic] // Will, just a joke fn test_configure() { let cfg = Config::new("example/sample.toml").unwrap(); assert_eq!(cfg.server().bind(), "127.0.0.1:11451"); @@ -40,20 +40,36 @@ mod test { .count(), result.len() ); - let repositories = cfg.repo_mapping(); - assert_eq!(repositories.len(), 3); - let r1 = repositories.get("MonsterSenpai/SummerNight-HornyFantasy"); - assert!(r1.is_some()); - let r1 = r1.unwrap(); - assert!(r1.branch_ignore().is_empty()); - assert!(!r1.send_to().is_empty()); - assert_eq!(r1.send_to().len(), 6); - let r2 = repositories.get("BillyKing/Wrestling"); - assert!(r2.is_some()); - let r2 = r2.unwrap(); - assert_eq!(r2.send_to().len(), 1); - assert_eq!(r2.branch_ignore().len(), 2); - assert_eq!(r2.secrets(), cfg.server().secrets()); + + // Test first repository + let repo = cfg.fetch_repository_configure("MonsterSenpai/SummerNight-HornyFantasy"); + assert!(!repo.is_default()); + assert!(repo.branch_ignore().is_empty()); + assert!(!repo.send_to().is_empty()); + assert_eq!(repo.send_to().len(), 6); + + // Test second repository + let repo = cfg.fetch_repository_configure("BillyKing/Wrestling"); + assert!(!repo.is_default()); + assert_eq!(repo.send_to().len(), 1); + assert_eq!(repo.branch_ignore().len(), 2); + assert_eq!(repo.secrets(), cfg.server().secrets()); + + // Test third repository + let repo = cfg.fetch_repository_configure("sample/test"); + assert!(!repo.is_default()); + assert!(repo.branch_ignore().is_empty()); + assert_eq!( + repo.send_to() + .into_iter() + .zip(&result) + .filter(|(a, b)| a == b) + .count(), + result.len() + ); + assert_eq!(repo.secrets(), "2333"); + + // Test not exist repository let r_missing = cfg.fetch_repository_configure("114514/1919810"); assert_eq!(r_missing.secrets(), cfg.server().secrets()); assert!(r_missing.branch_ignore().is_empty()); @@ -91,4 +107,15 @@ mod test { assert_eq!(event.repository().full_name(), "MagomeYae/test-action"); assert_eq!(event.branch_name(), "master"); } + + #[test] + fn test_basic_parse() { + for entry in WalkDir::new("example") { + let entry = entry.unwrap(); + if entry.path().ends_with(".json") { + let s = std::fs::read_to_string(entry.path()).unwrap(); + let _event: GitHubEarlyParse = serde_json::from_str(s.as_str()).unwrap(); + } + } + } }