feat: add filter
All checks were successful
continuous-integration/drone/push Build is passing

Signed-off-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2024-04-12 22:30:45 +02:00
parent 3709e37599
commit 706a62a292
Signed by: kjuulh
GPG Key ID: 9AA7BC13CE474394
5 changed files with 81 additions and 4 deletions

39
Cargo.lock generated
View File

@ -30,6 +30,15 @@ dependencies = [
"zerocopy", "zerocopy",
] ]
[[package]]
name = "aho-corasick"
version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "allocator-api2" name = "allocator-api2"
version = "0.2.18" version = "0.2.18"
@ -320,6 +329,7 @@ dependencies = [
"dotenv", "dotenv",
"futures", "futures",
"itertools", "itertools",
"regex",
"reqwest", "reqwest",
"serde", "serde",
"sqlx", "sqlx",
@ -1240,6 +1250,35 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]]
name = "regex"
version = "1.10.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.3" version = "0.12.3"

View File

@ -19,3 +19,4 @@ tower-http = { version = "0.5.2", features = ["cors", "trace"] }
futures = "0.3.30" futures = "0.3.30"
reqwest = {version = "0.12.3", default-features = false, features = ["json", "rustls-tls"]} reqwest = {version = "0.12.3", default-features = false, features = ["json", "rustls-tls"]}
itertools = "0.12.1" itertools = "0.12.1"
regex = "1.10.4"

View File

@ -23,6 +23,9 @@ enum Commands {
user: Option<String>, user: Option<String>,
#[arg(long)] #[arg(long)]
org: Option<Vec<String>>, org: Option<Vec<String>>,
#[arg(long, env = "CONTRACTOR_FILTER")]
filter: Option<String>,
}, },
} }
@ -61,12 +64,12 @@ async fn main() -> anyhow::Result<()> {
result?? result??
} }
} }
Some(Commands::Reconcile { user, org }) => { Some(Commands::Reconcile { user, org, filter }) => {
tracing::info!("running reconcile"); tracing::info!("running reconcile");
let state = SharedState::from(Arc::new(State::new().await?)); let state = SharedState::from(Arc::new(State::new().await?));
state.reconciler().reconcile(user, org).await?; state.reconciler().reconcile(user, org, filter).await?;
} }
None => {} None => {}
} }

View File

@ -1,4 +1,4 @@
use std::{ops::Deref, pin::Pin, sync::Arc}; use std::{fmt::Display, ops::Deref, pin::Pin, sync::Arc};
type DynGiteaClient = Arc<dyn traits::GiteaClient + Send + Sync + 'static>; type DynGiteaClient = Arc<dyn traits::GiteaClient + Send + Sync + 'static>;
pub struct GiteaClient(DynGiteaClient); pub struct GiteaClient(DynGiteaClient);
@ -23,6 +23,12 @@ pub struct Repository {
pub name: String, pub name: String,
} }
impl Display for Repository {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_fmt(format_args!("{}/{}", self.owner, self.name))
}
}
impl TryFrom<GiteaRepository> for Repository { impl TryFrom<GiteaRepository> for Repository {
type Error = anyhow::Error; type Error = anyhow::Error;

View File

@ -1,3 +1,4 @@
use anyhow::Context;
use futures::{stream::FuturesUnordered, StreamExt}; use futures::{stream::FuturesUnordered, StreamExt};
use itertools::Itertools; use itertools::Itertools;
@ -18,11 +19,38 @@ impl Reconciler {
&self, &self,
user: Option<String>, user: Option<String>,
orgs: Option<Vec<String>>, orgs: Option<Vec<String>>,
filter: Option<String>,
) -> anyhow::Result<()> { ) -> anyhow::Result<()> {
let repos = self.get_repos(user, orgs).await?; let repos = self.get_repos(user, orgs).await?;
tracing::debug!("found repositories: {}", repos.len()); tracing::debug!("found repositories: {}", repos.len());
let renovate_enabled = self.get_renovate_enabled(&repos).await?; let filtered_repos = match filter {
Some(filter) => {
let re = regex::Regex::new(&filter).context(
"filter regex failed to compile, make sure it is valid against rust-lang/regex",
)?;
repos
.into_iter()
.filter(|r| {
if re.is_match(&r.to_string()) {
true
} else {
tracing::trace!(
filter = &filter,
"repository: {}, didn't match filter",
r.to_string(),
);
false
}
})
.collect()
}
None => repos,
};
tracing::debug!("filtered repositories: {}", filtered_repos.len());
let renovate_enabled = self.get_renovate_enabled(&filtered_repos).await?;
tracing::debug!( tracing::debug!(
"found repositories with renovate enabled: {}", "found repositories with renovate enabled: {}",
renovate_enabled.len() renovate_enabled.len()