Merge pull request #59 from NixOS/auto-tag-topic-issue-56
Auto tag topic issue 56
This commit is contained in:
commit
a2d29c0de7
|
@ -40,6 +40,18 @@
|
|||
"zimbatm"
|
||||
]
|
||||
},
|
||||
"tag_paths": {
|
||||
"6.topic: python": [
|
||||
"pkgs/top-level/python-packages.nix",
|
||||
"pkgs/development/interpreters/python",
|
||||
"pkgs/development/python-modules",
|
||||
"doc/languages-frameworks/python.md"
|
||||
],
|
||||
"6.topic: ruby": [
|
||||
"pkgs/development/interpreters/ruby",
|
||||
"pkgs/development/ruby-modules"
|
||||
]
|
||||
},
|
||||
"checkout": {
|
||||
"root": "/var/lib/gc-of-borg/.nix-test-rs"
|
||||
},
|
||||
|
|
|
@ -39,6 +39,7 @@ fn main() {
|
|||
cfg.acl(),
|
||||
cfg.runner.identity.clone(),
|
||||
events,
|
||||
cfg.tag_paths.clone().unwrap(),
|
||||
);
|
||||
|
||||
channel.basic_prefetch(1).unwrap();
|
||||
|
|
|
@ -148,7 +148,6 @@ impl CachedProjectCo {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
pub fn commit_messages_from_head(&self, commit: &str) -> Result<Vec<String>, Error> {
|
||||
let mut lock = self.lock()?;
|
||||
|
||||
|
@ -175,6 +174,33 @@ impl CachedProjectCo {
|
|||
));
|
||||
}
|
||||
}
|
||||
|
||||
pub fn files_changed_from_head(&self, commit: &str) -> Result<Vec<String>, Error> {
|
||||
let mut lock = self.lock()?;
|
||||
|
||||
let result = Command::new("git")
|
||||
.arg("diff")
|
||||
.arg("--name-only")
|
||||
.arg(format!("HEAD...{}", commit))
|
||||
.current_dir(self.clone_to())
|
||||
.output()?;
|
||||
|
||||
lock.unlock();
|
||||
|
||||
if result.status.success() {
|
||||
return Ok(
|
||||
String::from_utf8_lossy(&result.stdout)
|
||||
.lines()
|
||||
.map(|l| l.to_owned())
|
||||
.collect(),
|
||||
);
|
||||
} else {
|
||||
return Err(Error::new(
|
||||
ErrorKind::Other,
|
||||
String::from_utf8_lossy(&result.stderr).to_lowercase(),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl clone::GitClonable for CachedProjectCo {
|
||||
|
@ -264,7 +290,9 @@ mod tests {
|
|||
let working_co = project
|
||||
.clone_for("testing-commit-msgs".to_owned(), "123".to_owned())
|
||||
.expect("clone should work");
|
||||
working_co.checkout_origin_ref(OsStr::new("master"));
|
||||
working_co
|
||||
.checkout_origin_ref(OsStr::new("master"))
|
||||
.unwrap();
|
||||
|
||||
let expect: Vec<String> = vec!["check out this cool PR".to_owned()];
|
||||
|
||||
|
@ -275,4 +303,31 @@ mod tests {
|
|||
expect
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_files_changed_list() {
|
||||
let workingdir = TestScratch::new_dir("test-test-files-changed-list");
|
||||
|
||||
let bare = TestScratch::new_dir("bare-files-changed");
|
||||
let mk_co = TestScratch::new_dir("mk-files-changed");
|
||||
let hash = make_pr_repo(&bare.path(), &mk_co.path());
|
||||
|
||||
let cloner = cached_cloner(&workingdir.path());
|
||||
let project = cloner.project("commit-files-changed-list".to_owned(), bare.string());
|
||||
let working_co = project
|
||||
.clone_for("testing-files-changed".to_owned(), "123".to_owned())
|
||||
.expect("clone should work");
|
||||
working_co
|
||||
.checkout_origin_ref(OsStr::new("master"))
|
||||
.unwrap();
|
||||
|
||||
let expect: Vec<String> = vec!["default.nix".to_owned(), "hi another file".to_owned()];
|
||||
|
||||
assert_eq!(
|
||||
working_co.files_changed_from_head(&hash).expect(
|
||||
"fetching files changed should work",
|
||||
),
|
||||
expect
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ use hyper::net::HttpsConnector;
|
|||
use hyper_native_tls::NativeTlsClient;
|
||||
use hubcaps::{Credentials, Github};
|
||||
use nix::Nix;
|
||||
use std::collections::HashMap;
|
||||
|
||||
|
||||
use ofborg::acl;
|
||||
|
@ -20,6 +21,7 @@ pub struct Config {
|
|||
pub rabbitmq: RabbitMQConfig,
|
||||
pub github: Option<GithubConfig>,
|
||||
pub log_storage: Option<LogStorage>,
|
||||
pub tag_paths: Option<HashMap<String, Vec<String>>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug)]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use ofborg::tasks;
|
||||
use ofborg::outpathdiff::PackageArch;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct StdenvTagger {
|
||||
possible: Vec<String>,
|
||||
|
@ -154,3 +155,104 @@ impl RebuildTagger {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PathsTagger {
|
||||
possible: HashMap<String, Vec<String>>,
|
||||
selected: Vec<String>,
|
||||
}
|
||||
|
||||
impl PathsTagger {
|
||||
pub fn new(tags_and_criteria: HashMap<String, Vec<String>>) -> PathsTagger {
|
||||
PathsTagger {
|
||||
possible: tags_and_criteria,
|
||||
selected: vec![],
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_changed(&mut self, path: &str) {
|
||||
let mut tags_to_add: Vec<String> = self.possible
|
||||
.iter()
|
||||
.filter(|&(ref tag, ref _paths)| !self.selected.contains(&tag))
|
||||
.filter(|&(ref _tag, ref paths)| {
|
||||
paths.iter().any(|tp| path.contains(tp))
|
||||
})
|
||||
.map(|(tag, _paths)| tag.clone())
|
||||
.collect();
|
||||
self.selected.append(&mut tags_to_add);
|
||||
self.selected.sort();
|
||||
}
|
||||
|
||||
pub fn tags_to_add(&self) -> Vec<String> {
|
||||
self.selected.clone()
|
||||
}
|
||||
|
||||
pub fn tags_to_remove(&self) -> Vec<String> {
|
||||
let mut remove: Vec<String> = self.possible.keys().map(|k| k.to_owned()).collect();
|
||||
remove.sort();
|
||||
for tag in &self.selected {
|
||||
let pos = remove.binary_search(&tag).unwrap();
|
||||
remove.remove(pos);
|
||||
}
|
||||
|
||||
return remove;
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
pub fn test_files_changed_list() {
|
||||
let mut criteria: HashMap<String, Vec<String>> = HashMap::new();
|
||||
criteria.insert(
|
||||
"topic: python".to_owned(),
|
||||
vec![
|
||||
"pkgs/top-level/python-packages.nix".to_owned(),
|
||||
"bogus".to_owned(),
|
||||
],
|
||||
);
|
||||
criteria.insert(
|
||||
"topic: ruby".to_owned(),
|
||||
vec![
|
||||
"pkgs/development/interpreters/ruby".to_owned(),
|
||||
"bogus".to_owned(),
|
||||
],
|
||||
);
|
||||
|
||||
{
|
||||
let mut tagger = PathsTagger::new(criteria.clone());
|
||||
tagger.path_changed("default.nix");
|
||||
assert_eq!(tagger.tags_to_add().len(), 0);
|
||||
assert_eq!(
|
||||
tagger.tags_to_remove(),
|
||||
vec!["topic: python".to_owned(), "topic: ruby".to_owned()]
|
||||
);
|
||||
|
||||
|
||||
tagger.path_changed("pkgs/development/interpreters/ruby/default.nix");
|
||||
assert_eq!(tagger.tags_to_add(), vec!["topic: ruby".to_owned()]);
|
||||
assert_eq!(tagger.tags_to_remove(), vec!["topic: python".to_owned()]);
|
||||
|
||||
tagger.path_changed("pkgs/development/interpreters/ruby/foobar.nix");
|
||||
assert_eq!(tagger.tags_to_add(), vec!["topic: ruby".to_owned()]);
|
||||
assert_eq!(tagger.tags_to_remove(), vec!["topic: python".to_owned()]);
|
||||
|
||||
|
||||
tagger.path_changed("pkgs/top-level/python-packages.nix");
|
||||
assert_eq!(
|
||||
tagger.tags_to_add(),
|
||||
vec!["topic: python".to_owned(), "topic: ruby".to_owned()]
|
||||
);
|
||||
}
|
||||
|
||||
{
|
||||
let mut tagger = PathsTagger::new(criteria.clone());
|
||||
tagger.path_changed("bogus");
|
||||
assert_eq!(
|
||||
tagger.tags_to_add(),
|
||||
vec!["topic: python".to_owned(), "topic: ruby".to_owned()]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ use ofborg::nix::Nix;
|
|||
use ofborg::acl::ACL;
|
||||
use ofborg::stats;
|
||||
use ofborg::worker;
|
||||
use ofborg::tagger::{StdenvTagger, RebuildTagger};
|
||||
use ofborg::tagger::{StdenvTagger, RebuildTagger, PathsTagger};
|
||||
use ofborg::outpathdiff::{OutPaths, OutPathDiff};
|
||||
use ofborg::evalchecker::EvalChecker;
|
||||
use ofborg::commitstatus::CommitStatus;
|
||||
|
@ -30,6 +30,7 @@ pub struct MassRebuildWorker<E> {
|
|||
acl: ACL,
|
||||
identity: String,
|
||||
events: E,
|
||||
tag_paths: HashMap<String, Vec<String>>,
|
||||
}
|
||||
|
||||
impl<E: stats::SysEvents> MassRebuildWorker<E> {
|
||||
|
@ -40,6 +41,7 @@ impl<E: stats::SysEvents> MassRebuildWorker<E> {
|
|||
acl: ACL,
|
||||
identity: String,
|
||||
events: E,
|
||||
tag_paths: HashMap<String, Vec<String>>,
|
||||
) -> MassRebuildWorker<E> {
|
||||
return MassRebuildWorker {
|
||||
cloner: cloner,
|
||||
|
@ -48,12 +50,27 @@ impl<E: stats::SysEvents> MassRebuildWorker<E> {
|
|||
acl: acl,
|
||||
identity: identity,
|
||||
events: events,
|
||||
tag_paths: tag_paths
|
||||
};
|
||||
}
|
||||
|
||||
fn actions(&self) -> massrebuildjob::Actions {
|
||||
return massrebuildjob::Actions {};
|
||||
}
|
||||
|
||||
fn tag_from_paths(&self, issue: &hubcaps::issues::IssueRef, paths: Vec<String>) {
|
||||
let mut tagger = PathsTagger::new(self.tag_paths.clone());
|
||||
|
||||
for path in paths {
|
||||
tagger.path_changed(&path);
|
||||
}
|
||||
|
||||
update_labels(
|
||||
&issue,
|
||||
tagger.tags_to_add(),
|
||||
tagger.tags_to_remove(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
|
||||
|
@ -199,6 +216,11 @@ impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
|
|||
vec!["".to_owned()],
|
||||
));
|
||||
|
||||
self.tag_from_paths(
|
||||
&issue,
|
||||
co.files_changed_from_head(&job.pr.head_sha).unwrap_or(vec![])
|
||||
);
|
||||
|
||||
overall_status.set_with_description("Merging PR", hubcaps::statuses::State::Pending);
|
||||
|
||||
if let Err(_) = co.merge_commit(job.pr.head_sha.as_ref()) {
|
||||
|
|
0
ofborg/test-srcs/build-pr/hi another file
Normal file
0
ofborg/test-srcs/build-pr/hi another file
Normal file
Loading…
Reference in a new issue