Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 100 additions & 0 deletions ofborg/src/bin/github-labeler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
extern crate ofborg;
extern crate amqp;
extern crate env_logger;

extern crate hyper;
extern crate hubcaps;
extern crate hyper_native_tls;


use std::collections::HashMap;
use std::env;

use amqp::Basic;

use ofborg::config;
use ofborg::worker;
use ofborg::tasks;
use ofborg::easyamqp;
use ofborg::easyamqp::TypedWrappers;


fn main() {
let mut label_map = HashMap::new();
label_map.insert("bug".to_owned(), "0.kind: bug".to_owned());
label_map.insert("enhancement".to_owned(), "0.kind: enhancement".to_owned());
label_map.insert("question".to_owned(), "0.kind: question".to_owned());
label_map.insert("regression".to_owned(), "0.kind: regression".to_owned());
// TODO: add more labels (this is an implicit whitelist) and load from config file

let cfg = config::load(env::args().nth(1).unwrap().as_ref());
ofborg::setup_log();

let mut session = easyamqp::session_from_config(&cfg.rabbitmq).unwrap();
let mut channel = session.open_channel(1).unwrap();

// TODO: I have no idea what I'm doing, this is basically github-comment-parser
// adapted in a "let's hope this will work" fashion.
channel
.declare_exchange(easyamqp::ExchangeConfig {
exchange: "label-jobs".to_owned(),
exchange_type: easyamqp::ExchangeType::Fanout,
passive: false,
durable: true,
auto_delete: false,
no_wait: false,
internal: false,
arguments: None,
})
.unwrap();

channel
.declare_queue(easyamqp::QueueConfig {
queue: "label-jobs".to_owned(),
passive: false,
durable: true,
exclusive: false,
auto_delete: false,
no_wait: false,
arguments: None,
})
.unwrap();

channel
.bind_queue(easyamqp::BindQueueConfig {
queue: "label-jobs".to_owned(),
exchange: "label-jobs".to_owned(),
routing_key: None,
no_wait: false,
arguments: None,
})
.unwrap();

channel.basic_prefetch(1).unwrap();
channel
.consume(
worker::new(tasks::githublabeler::GitHubLabeler::new(
cfg.github(),
label_map,
)),
easyamqp::ConsumeConfig {
queue: "label-jobs".to_owned(),
consumer_tag: format!("{}-github-labeler", cfg.whoami()),
no_local: false,
no_ack: false,
no_wait: false,
exclusive: false,
arguments: None,
},
)
.unwrap();

channel.start_consuming();

println!("Finished consuming?");

channel.close(200, "Bye").unwrap();
println!("Closed the channel");
session.close(200, "Good Bye");
println!("Closed the session... EOF");
}
33 changes: 33 additions & 0 deletions ofborg/src/commentparser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,22 @@ named!(parse_line_impl(CompleteStr) -> Option<Vec<Instruction>>, alt!(
tests: ws!(many1!(map!(normal_token, |s| format!("tests.{}", s.0)))) >>
(Some(Instruction::Build(Subset::NixOS, tests)))
)) |
ws!(do_parse!(
tag!("label") >>
// `labels` is a list of (add, remove), with both values Options
labels: ws!(many1!(do_parse!(
op: opt!(alt!(tag!("+") | tag!("-"))) >>
tag: normal_token >>
(match op {
Some(s) if s.0 == "-" => (None, Some(tag.0)),
_ => (Some(tag.0), None),
})
))) >>
(Some(Instruction::Label(
labels.iter().filter_map(|x| x.0.map(|y| y.to_owned())).collect(),
labels.iter().filter_map(|x| x.1.map(|y| y.to_owned())).collect(),
)))
)) |
value!(Some(Instruction::Eval), tag!("eval")) |
// TODO: Currently keeping previous behaviour of ignoring unknown commands. Maybe
// it would be better to return an error so that the caller would know one of the
Expand Down Expand Up @@ -61,6 +77,7 @@ pub fn parse_line(text: &str) -> Option<Vec<Instruction>> {
pub enum Instruction {
Build(Subset, Vec<String>),
Eval,
Label(Vec<String>, Vec<String>), // (add, remove)
}

#[derive(Serialize, Deserialize, Debug, PartialEq)]
Expand Down Expand Up @@ -119,6 +136,22 @@ mod tests {
);
}

#[test]
fn label_and_eval_comment() {
assert_eq!(
Some(vec![
Instruction::Label(vec![
"darwin".to_owned(),
"feature".to_owned(),
], vec![
"wontfix".to_owned(),
]),
Instruction::Eval,
]),
parse("@grahamcofborg label darwin +feature -wontfix @grahamcofborg eval")
);
}

#[test]
fn build_and_eval_and_build_comment() {
assert_eq!(
Expand Down
9 changes: 9 additions & 0 deletions ofborg/src/message/labeljob.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use ofborg::message::{Pr, Repo};

#[derive(Serialize, Deserialize, Debug)]
pub struct LabelJob {
pub repo: Repo,
pub pr: Pr,
pub add_labels: Vec<String>,
pub remove_labels: Vec<String>,
}
1 change: 1 addition & 0 deletions ofborg/src/message/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod common;
pub mod buildjob;
pub mod buildresult;
pub mod labeljob;
pub mod massrebuildjob;
pub mod buildlogmsg;

Expand Down
15 changes: 14 additions & 1 deletion ofborg/src/tasks/githubcommentfilter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use ofborg::acl;
use serde_json;

use hubcaps;
use ofborg::message::{Repo, Pr, buildjob, massrebuildjob};
use ofborg::message::{Repo, Pr, buildjob, labeljob, massrebuildjob};
use ofborg::worker;
use ofborg::commentparser;
use amqp::protocol::basic::{Deliver, BasicProperties};
Expand Down Expand Up @@ -136,7 +136,20 @@ impl worker::SimpleWorker for GitHubCommentWorker {
&msg,
));
}
commentparser::Instruction::Label(add_labels, remove_labels) => {
let msg = labeljob::LabelJob {
repo: repo_msg.clone(),
pr: pr_msg.clone(),
add_labels,
remove_labels,
};

response.push(worker::publish_serde_action(
None,
Some("label-jobs".to_owned()),
&msg,
));
}
}
}
}
Expand Down
64 changes: 64 additions & 0 deletions ofborg/src/tasks/githublabeler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
extern crate amqp;
extern crate env_logger;

use std::collections::HashMap;

use serde_json;

use hubcaps;
use ofborg::message::labeljob::LabelJob;
use ofborg::tasks::massrebuilder::update_labels;
use ofborg::worker;
use amqp::protocol::basic::{Deliver, BasicProperties};


pub struct GitHubLabeler {
github: hubcaps::Github,
labels: HashMap<String, String>,
}

impl GitHubLabeler {
pub fn new(github: hubcaps::Github, labels: HashMap<String, String>) -> GitHubLabeler {
return GitHubLabeler { github, labels };
}
}

impl worker::SimpleWorker for GitHubLabeler {
type J = LabelJob;

fn msg_to_job(
&mut self,
_: &Deliver,
_: &BasicProperties,
body: &Vec<u8>,
) -> Result<Self::J, String> {
return match serde_json::from_slice(body) {
Ok(e) => Ok(e),
Err(e) => {
Err(format!(
"Failed to deserialize LabelJob: {:?}, err: {:}",
String::from_utf8_lossy(&body.clone()),
e
))
}
};
}

fn consumer(&mut self, job: &LabelJob) -> worker::Actions {
let add_labels = job.add_labels
.iter()
.filter_map(|x| self.labels.get(x).cloned())
.collect::<Vec<String>>();
let remove_labels = job.remove_labels
.iter()
.filter_map(|x| self.labels.get(x).cloned())
.collect::<Vec<String>>();

let repo = self.github.repo(job.repo.owner.clone(), job.repo.name.clone());
let issue = repo.issue(job.pr.number);

update_labels(&issue, add_labels, remove_labels);

return vec![worker::Action::Ack];
}
}
1 change: 1 addition & 0 deletions ofborg/src/tasks/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pub mod build;
pub mod massrebuilder;
pub mod githubcommentfilter;
pub mod githubcommentposter;
pub mod githublabeler;
pub mod statscollector;
pub mod log_message_collector;
pub mod evaluationfilter;