feat: fetch open issues

This commit is contained in:
Paul Campbell 2024-09-20 07:23:36 +01:00
parent 652b83b541
commit bec15aeb3d
14 changed files with 195 additions and 47 deletions

View file

@ -10,6 +10,9 @@ ureq = "2.10"
kxio = "1.2" kxio = "1.2"
ignore = "0.4" ignore = "0.4"
bon = "2.3" bon = "2.3"
tokio = { version = "1.37", features = [ "full" ] }
serde = { version = "1.0", features = [ "derive" ] }
serde_json = "1.0"
[dev-dependencies] [dev-dependencies]
assert2 = "0.3" assert2 = "0.3"

View file

@ -3,8 +3,9 @@ use crate::model::Config;
use crate::patterns::{issue_pattern, marker_pattern}; use crate::patterns::{issue_pattern, marker_pattern};
use anyhow::{Context, Result}; use anyhow::{Context, Result};
pub fn init_config() -> Result<Config, anyhow::Error> { pub fn init_config(net: kxio::network::Network) -> Result<Config, anyhow::Error> {
let config = Config::builder() let config = Config::builder()
.net(net)
.fs(kxio::fs::new( .fs(kxio::fs::new(
std::env::var("GITHUB_WORKSPACE") std::env::var("GITHUB_WORKSPACE")
.context("GITHUB_WORKSPACE")? .context("GITHUB_WORKSPACE")?

29
src/issues/fetch.rs Normal file
View file

@ -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<Vec<Issue>> {
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::<Vec<Issue>>(request)
.await?
.response_body()
.unwrap_or_default();
Ok(issues)
}

23
src/issues/mod.rs Normal file
View file

@ -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
}
}

29
src/issues/tests.rs Normal file
View file

@ -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(())
}

View file

@ -1,9 +1,11 @@
// //
use anyhow::Result; use anyhow::Result;
use init::init_config; use init::init_config;
use issues::fetch_open_issues;
use scanner::find_markers; use scanner::find_markers;
mod init; mod init;
mod issues;
mod model; mod model;
mod patterns; mod patterns;
mod scanner; mod scanner;
@ -11,21 +13,20 @@ mod scanner;
#[cfg(test)] #[cfg(test)]
mod tests; mod tests;
fn main() -> Result<()> { #[tokio::main]
run() async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
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!"); 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}"); println!("{markers}");
// TODO: add authentication when provided let _issues = fetch_open_issues(&config).await;
// let issues = ureq::get(&api).call()?.into_string()?;
// TODO: parse issues to get list of open issue numbers
// TODO: loop over list of expected issues and drop any where they do exist and are open // 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 // TODO: if remaining list is not empty - add all to error list

View file

@ -6,6 +6,7 @@ use regex::Regex;
#[derive(Debug, Builder)] #[derive(Debug, Builder)]
pub struct Config { pub struct Config {
net: kxio::network::Network,
fs: kxio::fs::FileSystem, fs: kxio::fs::FileSystem,
repo: String, repo: String,
server: String, server: String,
@ -14,18 +15,21 @@ pub struct Config {
issue_pattern: Regex, issue_pattern: Regex,
} }
impl Config { impl Config {
pub fn net(&self) -> &kxio::network::Network {
&self.net
}
pub fn fs(&self) -> &kxio::fs::FileSystem { pub fn fs(&self) -> &kxio::fs::FileSystem {
&self.fs &self.fs
} }
pub fn repo(&self) -> &str { pub fn repo(&self) -> &str {
&self.repo &self.repo
} }
// pub fn server(&self) -> &str { pub fn server(&self) -> &str {
// &self.server &self.server
// } }
// pub fn auth_token(&self) -> Option<&str> { pub fn auth_token(&self) -> Option<&str> {
// self.auth_token.as_deref() self.auth_token.as_deref()
// } }
pub fn prefix_pattern(&self) -> &Regex { pub fn prefix_pattern(&self) -> &Regex {
&self.prefix_pattern &self.prefix_pattern
} }

View file

@ -1,15 +1,32 @@
//
use anyhow::Result; use anyhow::Result;
use crate::patterns::{issue_pattern, marker_pattern}; use crate::{
patterns::{issue_pattern, marker_pattern},
tests::a_config,
};
// #[tokio::test]
use super::*; 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] #[test]
fn with_config_get_fs() -> Result<()> { fn with_config_get_fs() -> Result<()> {
//given //given
let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(fs.clone())?; let config = a_config(net, fs.clone())?;
//when //when
let result = config.fs(); let result = config.fs();
@ -23,8 +40,9 @@ fn with_config_get_fs() -> Result<()> {
#[test] #[test]
fn with_config_get_prefix_pattern() -> Result<()> { fn with_config_get_prefix_pattern() -> Result<()> {
//given //given
let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.prefix_pattern(); let result = config.prefix_pattern();
@ -38,8 +56,9 @@ fn with_config_get_prefix_pattern() -> Result<()> {
#[test] #[test]
fn with_config_get_issue_pattern() -> Result<()> { fn with_config_get_issue_pattern() -> Result<()> {
//given //given
let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.issue_pattern(); let result = config.issue_pattern();
@ -50,11 +69,44 @@ fn with_config_get_issue_pattern() -> Result<()> {
Ok(()) 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] #[test]
fn with_config_get_repo() -> Result<()> { fn with_config_get_repo() -> Result<()> {
//given //given
let net = kxio::network::Network::new_mock();
let fs = kxio::fs::temp()?; let fs = kxio::fs::temp()?;
let config = a_config(fs)?; let config = a_config(net, fs)?;
//when //when
let result = config.repo(); let result = config.repo();
@ -64,13 +116,3 @@ fn with_config_get_repo() -> Result<()> {
Ok(()) Ok(())
} }
fn a_config(fs: kxio::fs::FileSystem) -> Result<Config> {
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())
}

View file

@ -1,4 +1,2 @@
// //
use super::*;
mod config; mod config;

View file

@ -5,12 +5,12 @@ use crate::model::{Config, FoundMarkers, Line, Marker};
use anyhow::Result; use anyhow::Result;
use ignore::Walk; use ignore::Walk;
pub fn find_markers(config: Config) -> Result<FoundMarkers, anyhow::Error> { pub fn find_markers(config: &Config) -> Result<FoundMarkers, anyhow::Error> {
let mut markers = FoundMarkers::default(); let mut markers = FoundMarkers::default();
for file in Walk::new(config.fs().base()).flatten() { for file in Walk::new(config.fs().base()).flatten() {
let path = file.path(); let path = file.path();
if config.fs().path_is_file(path)? { if config.fs().path_is_file(path)? {
scan_file(path, &config, &mut markers)?; scan_file(path, config, &mut markers)?;
} }
} }
Ok(markers) Ok(markers)

View file

@ -13,7 +13,9 @@ fn init_when_all_valid() -> anyhow::Result<()> {
std::env::set_var("GITHUB_WORKSPACE", fs.base()); std::env::set_var("GITHUB_WORKSPACE", fs.base());
std::env::set_var("GITHUB_REPOSITORY", "repo"); std::env::set_var("GITHUB_REPOSITORY", "repo");
std::env::set_var("GITHUB_SERVER_URL", "server"); std::env::set_var("GITHUB_SERVER_URL", "server");
let net = kxio::network::Network::new_mock();
let expected = Config::builder() let expected = Config::builder()
.net(net.clone())
.fs(kxio::fs::new(fs.base().to_path_buf())) .fs(kxio::fs::new(fs.base().to_path_buf()))
.repo("repo".to_string()) .repo("repo".to_string())
.server("server".to_string()) .server("server".to_string())
@ -23,7 +25,7 @@ fn init_when_all_valid() -> anyhow::Result<()> {
.build(); .build();
//when //when
let result = init_config()?; let result = init_config(net)?;
//then //then
assert_eq!(result.fs().base(), expected.fs().base()); 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"); std::env::set_var("GITHUB_SERVER_URL", "server");
//when //when
let result = init_config(); let result = init_config(kxio::network::Network::new_mock());
//then //then
let_assert!(Err(e) = result); let_assert!(Err(e) = result);
@ -69,7 +71,7 @@ fn init_when_no_repository() -> anyhow::Result<()> {
std::env::set_var("GITHUB_SERVER_URL", "server"); std::env::set_var("GITHUB_SERVER_URL", "server");
//when //when
let result = init_config(); let result = init_config(kxio::network::Network::new_mock());
//then //then
let_assert!(Err(e) = result); let_assert!(Err(e) = result);
@ -88,7 +90,7 @@ fn init_when_no_server_url() -> anyhow::Result<()> {
std::env::remove_var("GITHUB_SERVER_URL"); std::env::remove_var("GITHUB_SERVER_URL");
//when //when
let result = init_config(); let result = init_config(kxio::network::Network::new_mock());
//then //then
let_assert!(Err(e) = result); let_assert!(Err(e) = result);

View file

@ -1,5 +1,8 @@
use std::sync::{LazyLock, Mutex}; use std::sync::{LazyLock, Mutex};
use model::Config;
use patterns::{issue_pattern, marker_pattern};
// //
use super::*; use super::*;
@ -8,3 +11,15 @@ mod run;
mod scanner; mod scanner;
pub static THE_ENVIRONMENT: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(())); pub static THE_ENVIRONMENT: LazyLock<Mutex<()>> = LazyLock::new(|| Mutex::new(()));
pub fn a_config(net: kxio::network::Network, fs: kxio::fs::FileSystem) -> Result<Config> {
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())
}

View file

@ -3,8 +3,8 @@ use super::*;
use anyhow::Result; use anyhow::Result;
#[test] #[tokio::test]
fn run_with_some_invalids() -> Result<()> { async fn run_with_some_invalids() -> Result<()> {
//given //given
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?; 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"); std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net");
//when //when
run()?; run(kxio::network::Network::new_mock()).await?;
//then //then
// TODO: add check that run fails because file_1.txt is invalid // TODO: add check that run fails because file_1.txt is invalid
@ -30,8 +30,8 @@ fn run_with_some_invalids() -> Result<()> {
Ok(()) Ok(())
} }
#[test] #[tokio::test]
fn run_with_no_invalids() -> Result<()> { async fn run_with_no_invalids() -> Result<()> {
//given //given
let _env = THE_ENVIRONMENT.lock(); let _env = THE_ENVIRONMENT.lock();
let fs = kxio::fs::temp()?; 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"); std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net");
//when //when
run()?; run(kxio::network::Network::new_mock()).await?;
//then //then
// TODO: add check that run fails because file_1.txt is invalid // TODO: add check that run fails because file_1.txt is invalid

View file

@ -18,6 +18,7 @@ fn find_markers_in_dir() -> anyhow::Result<()> {
)?; )?;
let config = Config::builder() let config = Config::builder()
.net(kxio::network::Network::new_mock())
.fs(fs.clone()) .fs(fs.clone())
.server("".to_string()) .server("".to_string())
.repo("".to_string()) .repo("".to_string())
@ -26,7 +27,7 @@ fn find_markers_in_dir() -> anyhow::Result<()> {
.build(); .build();
//when //when
let markers = find_markers(config)?; let markers = find_markers(&config)?;
//then //then
assert_eq!( assert_eq!(