Compare commits
3 commits
57f88bb832
...
bec15aeb3d
Author | SHA1 | Date | |
---|---|---|---|
bec15aeb3d | |||
652b83b541 | |||
b6de7831e5 |
16 changed files with 315 additions and 39 deletions
|
@ -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"
|
||||
|
|
|
@ -3,8 +3,9 @@ use crate::model::Config;
|
|||
use crate::patterns::{issue_pattern, marker_pattern};
|
||||
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()
|
||||
.net(net)
|
||||
.fs(kxio::fs::new(
|
||||
std::env::var("GITHUB_WORKSPACE")
|
||||
.context("GITHUB_WORKSPACE")?
|
||||
|
|
29
src/issues/fetch.rs
Normal file
29
src/issues/fetch.rs
Normal 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
23
src/issues/mod.rs
Normal 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
29
src/issues/tests.rs
Normal 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(())
|
||||
}
|
17
src/main.rs
17
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,17 +13,20 @@ mod scanner;
|
|||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
#[tokio::main]
|
||||
async fn main() -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||
Ok(run(kxio::network::Network::new_real()).await?)
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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<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())
|
||||
}
|
||||
|
|
|
@ -1,4 +1,2 @@
|
|||
//
|
||||
use super::*;
|
||||
|
||||
mod config;
|
||||
|
|
|
@ -3,13 +3,14 @@ use std::path::Path;
|
|||
|
||||
use crate::model::{Config, FoundMarkers, Line, Marker};
|
||||
use anyhow::Result;
|
||||
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();
|
||||
for file in ignore::Walk::new(config.fs().base()).flatten() {
|
||||
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)
|
||||
|
|
7
src/tests/data/file_with_invalids.txt
Normal file
7
src/tests/data/file_with_invalids.txt
Normal file
|
@ -0,0 +1,7 @@
|
|||
This is a text file.
|
||||
|
||||
It contains a todo comment: // TODO: this is it
|
||||
|
||||
It also contains a fix-me comment: // FIXME: and this is it
|
||||
|
||||
Both of these are missing an issue identifier.
|
5
src/tests/data/file_with_valids.txt
Normal file
5
src/tests/data/file_with_valids.txt
Normal file
|
@ -0,0 +1,5 @@
|
|||
This is another text file.
|
||||
|
||||
It also has a todo comment: // TODO: (#23) and it has an issue number
|
||||
|
||||
Here is a fix-me comment: // FIXME: (#43) and is also has an issue number
|
|
@ -8,11 +8,14 @@ use patterns::{issue_pattern, marker_pattern};
|
|||
#[test]
|
||||
fn init_when_all_valid() -> anyhow::Result<()> {
|
||||
//given
|
||||
let _env = THE_ENVIRONMENT.lock();
|
||||
let fs = kxio::fs::temp()?;
|
||||
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())
|
||||
|
@ -22,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());
|
||||
|
@ -43,12 +46,13 @@ fn init_when_all_valid() -> anyhow::Result<()> {
|
|||
#[test]
|
||||
fn init_when_no_workspace() -> anyhow::Result<()> {
|
||||
//given
|
||||
let _env = THE_ENVIRONMENT.lock();
|
||||
std::env::remove_var("GITHUB_WORKSPACE");
|
||||
std::env::set_var("GITHUB_REPOSITORY", "repo");
|
||||
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);
|
||||
|
@ -60,13 +64,14 @@ fn init_when_no_workspace() -> anyhow::Result<()> {
|
|||
#[test]
|
||||
fn init_when_no_repository() -> anyhow::Result<()> {
|
||||
//given
|
||||
let _env = THE_ENVIRONMENT.lock();
|
||||
let fs = kxio::fs::temp()?;
|
||||
std::env::set_var("GITHUB_WORKSPACE", fs.base());
|
||||
std::env::remove_var("GITHUB_REPOSITORY");
|
||||
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);
|
||||
|
@ -78,13 +83,14 @@ fn init_when_no_repository() -> anyhow::Result<()> {
|
|||
#[test]
|
||||
fn init_when_no_server_url() -> anyhow::Result<()> {
|
||||
//given
|
||||
let _env = THE_ENVIRONMENT.lock();
|
||||
let fs = kxio::fs::temp()?;
|
||||
std::env::set_var("GITHUB_WORKSPACE", fs.base());
|
||||
std::env::set_var("GITHUB_REPOSITORY", "repo");
|
||||
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);
|
||||
|
|
|
@ -1,4 +1,25 @@
|
|||
use std::sync::{LazyLock, Mutex};
|
||||
|
||||
use model::Config;
|
||||
use patterns::{issue_pattern, marker_pattern};
|
||||
|
||||
//
|
||||
use super::*;
|
||||
|
||||
mod init;
|
||||
mod run;
|
||||
mod scanner;
|
||||
|
||||
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())
|
||||
}
|
||||
|
|
54
src/tests/run.rs
Normal file
54
src/tests/run.rs
Normal file
|
@ -0,0 +1,54 @@
|
|||
//
|
||||
use super::*;
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
#[tokio::test]
|
||||
async fn run_with_some_invalids() -> Result<()> {
|
||||
//given
|
||||
let _env = THE_ENVIRONMENT.lock();
|
||||
let fs = kxio::fs::temp()?;
|
||||
fs.file_write(
|
||||
&fs.base().join("file_with_invalids.txt"),
|
||||
include_str!("data/file_with_invalids.txt"),
|
||||
)?;
|
||||
fs.file_write(
|
||||
&fs.base().join("file_with_valids.txt"),
|
||||
include_str!("data/file_with_valids.txt"),
|
||||
)?;
|
||||
std::env::set_var("GITHUB_WORKSPACE", fs.base());
|
||||
std::env::set_var("GITHUB_REPOSITORY", "kemitix/test");
|
||||
std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net");
|
||||
|
||||
//when
|
||||
run(kxio::network::Network::new_mock()).await?;
|
||||
|
||||
//then
|
||||
// TODO: add check that run fails because file_1.txt is invalid
|
||||
// TODO: add check that network requests were made to get issues
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn run_with_no_invalids() -> Result<()> {
|
||||
//given
|
||||
let _env = THE_ENVIRONMENT.lock();
|
||||
let fs = kxio::fs::temp()?;
|
||||
fs.file_write(
|
||||
&fs.base().join("file_with_valids.txt"),
|
||||
include_str!("data/file_with_valids.txt"),
|
||||
)?;
|
||||
std::env::set_var("GITHUB_WORKSPACE", fs.base());
|
||||
std::env::set_var("GITHUB_REPOSITORY", "kemitix/test");
|
||||
std::env::set_var("GITHUB_SERVER_URL", "https://git.kemitix.net");
|
||||
|
||||
//when
|
||||
run(kxio::network::Network::new_mock()).await?;
|
||||
|
||||
//then
|
||||
// TODO: add check that run fails because file_1.txt is invalid
|
||||
// TODO: add check that network requests were made to get issues
|
||||
|
||||
Ok(())
|
||||
}
|
48
src/tests/scanner.rs
Normal file
48
src/tests/scanner.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
use model::Config;
|
||||
use patterns::{issue_pattern, marker_pattern};
|
||||
|
||||
//
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn find_markers_in_dir() -> anyhow::Result<()> {
|
||||
//given
|
||||
let fs = kxio::fs::temp()?;
|
||||
fs.file_write(
|
||||
&fs.base().join("file_with_invalids.txt"),
|
||||
include_str!("data/file_with_invalids.txt"),
|
||||
)?;
|
||||
fs.file_write(
|
||||
&fs.base().join("file_with_valids.txt"),
|
||||
include_str!("data/file_with_valids.txt"),
|
||||
)?;
|
||||
|
||||
let config = Config::builder()
|
||||
.net(kxio::network::Network::new_mock())
|
||||
.fs(fs.clone())
|
||||
.server("".to_string())
|
||||
.repo("".to_string())
|
||||
.prefix_pattern(marker_pattern()?)
|
||||
.issue_pattern(issue_pattern()?)
|
||||
.build();
|
||||
|
||||
//when
|
||||
let markers = find_markers(&config)?;
|
||||
|
||||
//then
|
||||
assert_eq!(
|
||||
markers.to_string().lines().collect::<Vec<_>>(),
|
||||
vec![
|
||||
"- Invalid: file_with_invalids.txt#2:",
|
||||
" It contains a todo comment: // TODO: this is it",
|
||||
"- Invalid: file_with_invalids.txt#4:",
|
||||
" It also contains a fix-me comment: // FIXME: and this is it",
|
||||
"- Valid : file_with_valids.txt#2:",
|
||||
" It also has a todo comment: // TODO: (#23) and it has an issue number",
|
||||
"- Valid : file_with_valids.txt#4:",
|
||||
" Here is a fix-me comment: // FIXME: (#43) and is also has an issue number"
|
||||
]
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in a new issue