From bec15aeb3deda27f4dc4b2eeb44a0769a8882fbc Mon Sep 17 00:00:00 2001 From: Paul Campbell Date: Fri, 20 Sep 2024 07:23:36 +0100 Subject: [PATCH] feat: fetch open issues --- Cargo.toml | 3 ++ src/init.rs | 3 +- src/issues/fetch.rs | 29 +++++++++++++++ src/issues/mod.rs | 23 ++++++++++++ src/issues/tests.rs | 29 +++++++++++++++ src/main.rs | 17 ++++----- src/model/config.rs | 16 +++++---- src/model/tests/config.rs | 76 ++++++++++++++++++++++++++++++--------- src/model/tests/mod.rs | 2 -- src/scanner.rs | 4 +-- src/tests/init.rs | 10 +++--- src/tests/mod.rs | 15 ++++++++ src/tests/run.rs | 12 +++---- src/tests/scanner.rs | 3 +- 14 files changed, 195 insertions(+), 47 deletions(-) create mode 100644 src/issues/fetch.rs create mode 100644 src/issues/mod.rs create mode 100644 src/issues/tests.rs diff --git a/Cargo.toml b/Cargo.toml index 1c0b047..9d5a7ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,9 @@ ureq = "2.10" kxio = "1.2" ignore = "0.4" bon = "2.3" +tokio = { version = "1.37", features = [ "full" ] } +serde = { version = "1.0", features = [ "derive" ] } +serde_json = "1.0" [dev-dependencies] assert2 = "0.3" diff --git a/src/init.rs b/src/init.rs index 97f41ec..e7bc50f 100644 --- a/src/init.rs +++ b/src/init.rs @@ -3,8 +3,9 @@ use crate::model::Config; use crate::patterns::{issue_pattern, marker_pattern}; use anyhow::{Context, Result}; -pub fn init_config() -> Result { +pub fn init_config(net: kxio::network::Network) -> Result { let config = Config::builder() + .net(net) .fs(kxio::fs::new( std::env::var("GITHUB_WORKSPACE") .context("GITHUB_WORKSPACE")? diff --git a/src/issues/fetch.rs b/src/issues/fetch.rs new file mode 100644 index 0000000..bec0ad7 --- /dev/null +++ b/src/issues/fetch.rs @@ -0,0 +1,29 @@ +// +use crate::model::Config; + +use anyhow::Result; +use kxio::network::{NetRequest, NetUrl}; + +use super::Issue; + +pub async fn fetch_open_issues(config: &Config) -> Result> { + let server_url = config.server(); + let repo = config.repo(); + let url = format!("{server_url}/api/v1/repos/{repo}/issues?state=open"); + let request_builder = NetRequest::get(NetUrl::new(url)); + let request = if let Some(auth_token) = config.auth_token() { + request_builder.header("Authorization", auth_token) + } else { + request_builder + } + .build(); + + let issues = config + .net() + .get::>(request) + .await? + .response_body() + .unwrap_or_default(); + + Ok(issues) +} diff --git a/src/issues/mod.rs b/src/issues/mod.rs new file mode 100644 index 0000000..2ad6ec0 --- /dev/null +++ b/src/issues/mod.rs @@ -0,0 +1,23 @@ +// +mod fetch; + +#[cfg(test)] +mod tests; + +pub use fetch::fetch_open_issues; +use serde::Deserialize; + +#[derive(Debug, Deserialize, PartialEq, Eq)] +pub struct Issue { + number: u64, +} +impl Issue { + #[cfg(test)] + pub fn new(number: u64) -> Self { + Self { number } + } + #[cfg(test)] + pub fn number(&self) -> u64 { + self.number + } +} diff --git a/src/issues/tests.rs b/src/issues/tests.rs new file mode 100644 index 0000000..f0b7bcc --- /dev/null +++ b/src/issues/tests.rs @@ -0,0 +1,29 @@ +use crate::tests::a_config; + +// +use super::*; + +use anyhow::Result; +use kxio::network::StatusCode; + +#[tokio::test] +async fn fetch_lists_issues() -> Result<()> { + //given + let mut net = kxio::network::MockNetwork::new(); + net.add_get_response( + "https://git.kemitix.net/api/v1/repos/kemitix/test/issues?state=open", + StatusCode::OK, + r#"[{"number":13},{"number":64}]"#, + ); + let config = a_config(net.into(), kxio::fs::temp()?)?; + + //when + let result = fetch_open_issues(&config).await?; + + //then + assert_eq!(result, vec![Issue::new(13), Issue::new(64)]); + assert_eq!(result[0].number(), 13); + assert_eq!(result[1].number(), 64); + + Ok(()) +} diff --git a/src/main.rs b/src/main.rs index b5ae892..bda3679 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,11 @@ // use anyhow::Result; use init::init_config; +use issues::fetch_open_issues; use scanner::find_markers; mod init; +mod issues; mod model; mod patterns; mod scanner; @@ -11,21 +13,20 @@ mod scanner; #[cfg(test)] mod tests; -fn main() -> Result<()> { - run() +#[tokio::main] +async fn main() -> std::result::Result<(), Box> { + Ok(run(kxio::network::Network::new_real()).await?) } -fn run() -> std::result::Result<(), anyhow::Error> { +async fn run(net: kxio::network::Network) -> Result<()> { println!("Forgejo TODO Checker!"); - let config = init_config()?; + let config = init_config(net)?; - let markers = find_markers(config)?; + let markers = find_markers(&config)?; println!("{markers}"); - // TODO: add authentication when provided - // let issues = ureq::get(&api).call()?.into_string()?; - // TODO: parse issues to get list of open issue numbers + let _issues = fetch_open_issues(&config).await; // TODO: loop over list of expected issues and drop any where they do exist and are open // TODO: if remaining list is not empty - add all to error list diff --git a/src/model/config.rs b/src/model/config.rs index 7c7be4f..6253436 100644 --- a/src/model/config.rs +++ b/src/model/config.rs @@ -6,6 +6,7 @@ use regex::Regex; #[derive(Debug, Builder)] pub struct Config { + net: kxio::network::Network, fs: kxio::fs::FileSystem, repo: String, server: String, @@ -14,18 +15,21 @@ pub struct Config { issue_pattern: Regex, } impl Config { + pub fn net(&self) -> &kxio::network::Network { + &self.net + } pub fn fs(&self) -> &kxio::fs::FileSystem { &self.fs } pub fn repo(&self) -> &str { &self.repo } - // pub fn server(&self) -> &str { - // &self.server - // } - // pub fn auth_token(&self) -> Option<&str> { - // self.auth_token.as_deref() - // } + pub fn server(&self) -> &str { + &self.server + } + pub fn auth_token(&self) -> Option<&str> { + self.auth_token.as_deref() + } pub fn prefix_pattern(&self) -> &Regex { &self.prefix_pattern } diff --git a/src/model/tests/config.rs b/src/model/tests/config.rs index a0cda62..3a9ec5b 100644 --- a/src/model/tests/config.rs +++ b/src/model/tests/config.rs @@ -1,15 +1,32 @@ +// use anyhow::Result; -use crate::patterns::{issue_pattern, marker_pattern}; +use crate::{ + patterns::{issue_pattern, marker_pattern}, + tests::a_config, +}; -// -use super::*; +#[tokio::test] +async fn with_config_get_net() -> Result<()> { + //given + let net = kxio::network::Network::new_mock(); + let fs = kxio::fs::temp()?; + let config = a_config(net, fs)?; + + //when + config.net(); + + //then + + Ok(()) +} #[test] fn with_config_get_fs() -> Result<()> { //given + let net = kxio::network::Network::new_mock(); let fs = kxio::fs::temp()?; - let config = a_config(fs.clone())?; + let config = a_config(net, fs.clone())?; //when let result = config.fs(); @@ -23,8 +40,9 @@ fn with_config_get_fs() -> Result<()> { #[test] fn with_config_get_prefix_pattern() -> Result<()> { //given + let net = kxio::network::Network::new_mock(); let fs = kxio::fs::temp()?; - let config = a_config(fs)?; + let config = a_config(net, fs)?; //when let result = config.prefix_pattern(); @@ -38,8 +56,9 @@ fn with_config_get_prefix_pattern() -> Result<()> { #[test] fn with_config_get_issue_pattern() -> Result<()> { //given + let net = kxio::network::Network::new_mock(); let fs = kxio::fs::temp()?; - let config = a_config(fs)?; + let config = a_config(net, fs)?; //when let result = config.issue_pattern(); @@ -50,11 +69,44 @@ fn with_config_get_issue_pattern() -> Result<()> { Ok(()) } +#[test] +fn with_config_get_server() -> Result<()> { + //given + let net = kxio::network::Network::new_mock(); + let fs = kxio::fs::temp()?; + let config = a_config(net, fs)?; + + //when + let result = config.server(); + + //then + assert_eq!(result, "https://git.kemitix.net"); + + Ok(()) +} + +#[test] +fn with_config_get_auth_token() -> Result<()> { + //given + let net = kxio::network::Network::new_mock(); + let fs = kxio::fs::temp()?; + let config = a_config(net, fs)?; + + //when + let result = config.auth_token(); + + //then + assert_eq!(result, Some("secret")); + + Ok(()) +} + #[test] fn with_config_get_repo() -> Result<()> { //given + let net = kxio::network::Network::new_mock(); let fs = kxio::fs::temp()?; - let config = a_config(fs)?; + let config = a_config(net, fs)?; //when let result = config.repo(); @@ -64,13 +116,3 @@ fn with_config_get_repo() -> Result<()> { Ok(()) } - -fn a_config(fs: kxio::fs::FileSystem) -> Result { - Ok(Config::builder() - .fs(fs) - .server("https://git.kemitix.net".to_string()) - .repo("kemitix/test".to_string()) - .prefix_pattern(marker_pattern()?) - .issue_pattern(issue_pattern()?) - .build()) -} diff --git a/src/model/tests/mod.rs b/src/model/tests/mod.rs index c81d539..72402bf 100644 --- a/src/model/tests/mod.rs +++ b/src/model/tests/mod.rs @@ -1,4 +1,2 @@ // -use super::*; - mod config; diff --git a/src/scanner.rs b/src/scanner.rs index 49cd060..76acaf0 100644 --- a/src/scanner.rs +++ b/src/scanner.rs @@ -5,12 +5,12 @@ use crate::model::{Config, FoundMarkers, Line, Marker}; use anyhow::Result; use ignore::Walk; -pub fn find_markers(config: Config) -> Result { +pub fn find_markers(config: &Config) -> Result { let mut markers = FoundMarkers::default(); for file in Walk::new(config.fs().base()).flatten() { let path = file.path(); if config.fs().path_is_file(path)? { - scan_file(path, &config, &mut markers)?; + scan_file(path, config, &mut markers)?; } } Ok(markers) diff --git a/src/tests/init.rs b/src/tests/init.rs index 96764ab..9e61a70 100644 --- a/src/tests/init.rs +++ b/src/tests/init.rs @@ -13,7 +13,9 @@ fn init_when_all_valid() -> anyhow::Result<()> { std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_REPOSITORY", "repo"); std::env::set_var("GITHUB_SERVER_URL", "server"); + let net = kxio::network::Network::new_mock(); let expected = Config::builder() + .net(net.clone()) .fs(kxio::fs::new(fs.base().to_path_buf())) .repo("repo".to_string()) .server("server".to_string()) @@ -23,7 +25,7 @@ fn init_when_all_valid() -> anyhow::Result<()> { .build(); //when - let result = init_config()?; + let result = init_config(net)?; //then assert_eq!(result.fs().base(), expected.fs().base()); @@ -50,7 +52,7 @@ fn init_when_no_workspace() -> anyhow::Result<()> { std::env::set_var("GITHUB_SERVER_URL", "server"); //when - let result = init_config(); + let result = init_config(kxio::network::Network::new_mock()); //then let_assert!(Err(e) = result); @@ -69,7 +71,7 @@ fn init_when_no_repository() -> anyhow::Result<()> { std::env::set_var("GITHUB_SERVER_URL", "server"); //when - let result = init_config(); + let result = init_config(kxio::network::Network::new_mock()); //then let_assert!(Err(e) = result); @@ -88,7 +90,7 @@ fn init_when_no_server_url() -> anyhow::Result<()> { std::env::remove_var("GITHUB_SERVER_URL"); //when - let result = init_config(); + let result = init_config(kxio::network::Network::new_mock()); //then let_assert!(Err(e) = result); diff --git a/src/tests/mod.rs b/src/tests/mod.rs index b2b2058..c477d4f 100644 --- a/src/tests/mod.rs +++ b/src/tests/mod.rs @@ -1,5 +1,8 @@ use std::sync::{LazyLock, Mutex}; +use model::Config; +use patterns::{issue_pattern, marker_pattern}; + // use super::*; @@ -8,3 +11,15 @@ mod run; mod scanner; pub static THE_ENVIRONMENT: LazyLock> = LazyLock::new(|| Mutex::new(())); + +pub fn a_config(net: kxio::network::Network, fs: kxio::fs::FileSystem) -> Result { + Ok(Config::builder() + .net(net) + .fs(fs) + .server("https://git.kemitix.net".to_string()) + .repo("kemitix/test".to_string()) + .auth_token("secret".to_string()) + .prefix_pattern(marker_pattern()?) + .issue_pattern(issue_pattern()?) + .build()) +} diff --git a/src/tests/run.rs b/src/tests/run.rs index f681928..1dbf6a8 100644 --- a/src/tests/run.rs +++ b/src/tests/run.rs @@ -3,8 +3,8 @@ use super::*; use anyhow::Result; -#[test] -fn run_with_some_invalids() -> Result<()> { +#[tokio::test] +async fn run_with_some_invalids() -> Result<()> { //given let _env = THE_ENVIRONMENT.lock(); let fs = kxio::fs::temp()?; @@ -21,7 +21,7 @@ fn run_with_some_invalids() -> Result<()> { std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net"); //when - run()?; + run(kxio::network::Network::new_mock()).await?; //then // TODO: add check that run fails because file_1.txt is invalid @@ -30,8 +30,8 @@ fn run_with_some_invalids() -> Result<()> { Ok(()) } -#[test] -fn run_with_no_invalids() -> Result<()> { +#[tokio::test] +async fn run_with_no_invalids() -> Result<()> { //given let _env = THE_ENVIRONMENT.lock(); let fs = kxio::fs::temp()?; @@ -44,7 +44,7 @@ fn run_with_no_invalids() -> Result<()> { std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net"); //when - run()?; + run(kxio::network::Network::new_mock()).await?; //then // TODO: add check that run fails because file_1.txt is invalid diff --git a/src/tests/scanner.rs b/src/tests/scanner.rs index 9e586a6..4e7470e 100644 --- a/src/tests/scanner.rs +++ b/src/tests/scanner.rs @@ -18,6 +18,7 @@ fn find_markers_in_dir() -> anyhow::Result<()> { )?; let config = Config::builder() + .net(kxio::network::Network::new_mock()) .fs(fs.clone()) .server("".to_string()) .repo("".to_string()) @@ -26,7 +27,7 @@ fn find_markers_in_dir() -> anyhow::Result<()> { .build(); //when - let markers = find_markers(config)?; + let markers = find_markers(&config)?; //then assert_eq!(