diff --git a/ofborg/src/maintainers.rs b/ofborg/src/maintainers.rs index 4642ce9..0d257d9 100644 --- a/ofborg/src/maintainers.rs +++ b/ofborg/src/maintainers.rs @@ -1,20 +1,22 @@ use ofborg::nix::Nix; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::io::Write; use std::path::Path; use tempfile::NamedTempFile; #[derive(Deserialize, Debug, Eq, PartialEq)] pub struct ImpactedMaintainers(HashMap>); -#[derive(Deserialize, Debug, Eq, PartialEq, Hash)] -struct Maintainer(String); +pub struct MaintainersByPackage(pub HashMap>); + +#[derive(Deserialize, Clone, Debug, Eq, PartialEq, Hash)] +pub struct Maintainer(String); impl<'a> From<&'a str> for Maintainer { fn from(name: &'a str) -> Maintainer { Maintainer(name.to_owned()) } } -#[derive(Deserialize, Debug, Eq, PartialEq, Hash)] -struct Package(String); +#[derive(Deserialize, Clone, Debug, Eq, PartialEq, Hash)] +pub struct Package(String); impl<'a> From<&'a str> for Package { fn from(name: &'a str) -> Package { Package(name.to_owned()) @@ -80,6 +82,22 @@ impl ImpactedMaintainers { .map(|(maintainer, _)| maintainer.0.clone()) .collect() } + + pub fn maintainers_by_package(&self) -> MaintainersByPackage { + let mut bypkg = MaintainersByPackage(HashMap::new()); + + for (maintainer, packages) in self.0.iter() { + for package in packages.iter() { + bypkg + .0 + .entry(package.clone()) + .or_insert_with(HashSet::new) + .insert(maintainer.clone()); + } + } + + bypkg + } } impl std::fmt::Display for ImpactedMaintainers { diff --git a/ofborg/src/tagger.rs b/ofborg/src/tagger.rs index d53a2c4..3d3bc81 100644 --- a/ofborg/src/tagger.rs +++ b/ofborg/src/tagger.rs @@ -1,3 +1,4 @@ +use crate::maintainers::{Maintainer, MaintainersByPackage}; use ofborg::outpathdiff::PackageArch; use ofborg::tasks; use std::collections::HashMap; @@ -247,6 +248,61 @@ impl PathsTagger { } } +pub struct MaintainerPRTagger { + possible: Vec, + selected: Vec, +} + +impl Default for MaintainerPRTagger { + fn default() -> MaintainerPRTagger { + let mut t = MaintainerPRTagger { + possible: vec![String::from("11.by: package-maintainer")], + selected: vec![], + }; + t.possible.sort(); + + t + } +} + +impl MaintainerPRTagger { + pub fn new() -> MaintainerPRTagger { + Default::default() + } + + pub fn record_maintainer( + &mut self, + pr_submitter: &str, + identified_maintainers: &MaintainersByPackage, + ) { + let submitter = Maintainer::from(pr_submitter); + + if identified_maintainers.0.is_empty() { + // No packages -> not from the maintainer + return; + } + + for (_package, maintainers) in identified_maintainers.0.iter() { + if !maintainers.contains(&submitter) { + // One of the packages is not maintained by this submitter + return; + } + } + + self.selected + .push(String::from("11.by: package-maintainer")); + } + + pub fn tags_to_add(&self) -> Vec { + self.selected.clone() + } + + pub fn tags_to_remove(&self) -> Vec { + // The cleanup tag is too vague to automatically remove. + vec![] + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/ofborg/src/tasks/massrebuilder.rs b/ofborg/src/tasks/massrebuilder.rs index 557baee..bc592f1 100644 --- a/ofborg/src/tasks/massrebuilder.rs +++ b/ofborg/src/tasks/massrebuilder.rs @@ -7,6 +7,7 @@ use crate::maintainers; use crate::maintainers::ImpactedMaintainers; use amqp::protocol::basic::{BasicProperties, Deliver}; use hubcaps; +use hubcaps::issues::Issue; use ofborg::acl::ACL; use ofborg::checkout; use ofborg::commentparser::Subset; @@ -19,7 +20,9 @@ use ofborg::outpathdiff::{OutPathDiff, OutPaths}; use ofborg::stats; use ofborg::stats::Event; use ofborg::systems; -use ofborg::tagger::{PathsTagger, PkgsAddedRemovedTagger, RebuildTagger, StdenvTagger}; +use ofborg::tagger::{ + MaintainerPRTagger, PathsTagger, PkgsAddedRemovedTagger, RebuildTagger, StdenvTagger, +}; use ofborg::worker; use std::collections::HashMap; use std::path::Path; @@ -122,11 +125,11 @@ impl worker::SimpleWorker for MassRebuildWorker; - match issue.get() { + match issue_ref.get() { Ok(iss) => { if iss.state == "closed" { self.events.notify(Event::IssueAlreadyClosed); @@ -142,16 +145,19 @@ impl worker::SimpleWorker for MassRebuildWorker { self.events.notify(Event::IssueFetchFailed); info!("Error fetching {}!", job.pr.number); info!("E: {:?}", e); return self.actions().skip(&job); } - } + }; - self.tag_from_title(&issue); + self.tag_from_title(&issue_ref); let mut overall_status = CommitStatus::new( repo.statuses(), @@ -247,7 +253,7 @@ impl worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker worker::SimpleWorker for MassRebuildWorker bool { false } -fn request_reviews( - m: &Result, - pull: &hubcaps::pulls::PullRequest, -) { - if let Ok(ref maint) = m { - if maint.maintainers().len() < 10 { - for maintainer in maint.maintainers() { - if let Err(e) = - pull.review_requests() - .create(&hubcaps::review_requests::ReviewRequestOptions { - reviewers: vec![maintainer.clone()], - team_reviewers: vec![], - }) - { - println!("Failure requesting a review from {}: {:#?}", maintainer, e,); - } +fn request_reviews(maint: &maintainers::ImpactedMaintainers, pull: &hubcaps::pulls::PullRequest) { + if maint.maintainers().len() < 10 { + for maintainer in maint.maintainers() { + if let Err(e) = + pull.review_requests() + .create(&hubcaps::review_requests::ReviewRequestOptions { + reviewers: vec![maintainer.clone()], + team_reviewers: vec![], + }) + { + println!("Failure requesting a review from {}: {:#?}", maintainer, e,); } } }