forked from the-distro/ofborg
Support eval instructions
This commit is contained in:
parent
dfbd52480e
commit
2150acacc6
|
@ -39,12 +39,12 @@ fn main() {
|
|||
let mut channel = session.open_channel(2).unwrap();
|
||||
|
||||
channel.basic_consume(
|
||||
worker::new(tasks::buildfilter::BuildFilterWorker::new(
|
||||
worker::new(tasks::githubcommentfilter::GitHubCommentWorker::new(
|
||||
cfg.acl(),
|
||||
cfg.github()
|
||||
)),
|
||||
"build-inputs",
|
||||
format!("{}-build-filter", cfg.whoami()).as_ref(),
|
||||
format!("{}-github-comment-filter", cfg.whoami()).as_ref(),
|
||||
false,
|
||||
false,
|
||||
false,
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
pub fn parse(text: &str) -> Option<Instruction> {
|
||||
pub fn parse(text: &str) -> Option<Vec<Instruction>> {
|
||||
let tokens: Vec<String> = text.split_whitespace()
|
||||
.map(|s| s.to_owned()).collect();
|
||||
|
||||
|
@ -7,21 +7,37 @@ pub fn parse(text: &str) -> Option<Instruction> {
|
|||
return None;
|
||||
}
|
||||
|
||||
let (targeter_, params_) = tokens.split_at(2);
|
||||
let targeter: Vec<String> = targeter_.iter()
|
||||
.map(|s| s.to_lowercase()).collect();
|
||||
let params: Vec<String> = params_.to_vec();
|
||||
|
||||
if targeter == ["@grahamcofborg", "build"] {
|
||||
return Some(Instruction::Build(params));
|
||||
if tokens[0].to_lowercase() != "@grahamcofborg" {
|
||||
return None;
|
||||
}
|
||||
|
||||
return None;
|
||||
let commands: Vec<&[String]> = tokens
|
||||
.split(|token| token.to_lowercase() == "@grahamcofborg")
|
||||
.filter(|token| token.len() > 0)
|
||||
.collect();
|
||||
|
||||
let mut instructions: Vec<Instruction> = vec![];
|
||||
for command in commands {
|
||||
let (left, right) = command.split_at(1);
|
||||
match left[0].as_ref() {
|
||||
"build" => {
|
||||
instructions.push(Instruction::Build(right.to_vec()))
|
||||
}
|
||||
"eval" => {
|
||||
instructions.push(Instruction::Eval)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
return Some(instructions);
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Debug)]
|
||||
pub enum Instruction {
|
||||
Build(Vec<String>)
|
||||
Build(Vec<String>),
|
||||
Eval
|
||||
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -37,37 +53,94 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn bogus_comment() {
|
||||
assert_eq!(None, parse(":) :) :)"));
|
||||
assert_eq!(None, parse(":) :) :) @grahamcofborg build hi"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_comment() {
|
||||
assert_eq!(Some(vec![Instruction::Eval]),
|
||||
parse("@grahamcofborg eval"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn eval_and_build_comment() {
|
||||
assert_eq!(Some(vec![
|
||||
Instruction::Eval,
|
||||
Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
])
|
||||
]),
|
||||
parse("@grahamcofborg eval @grahamcofborg build foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_and_eval_and_build_comment() {
|
||||
assert_eq!(Some(vec![
|
||||
Instruction::Build(vec![
|
||||
String::from("bar"),
|
||||
]),
|
||||
Instruction::Eval,
|
||||
Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
])
|
||||
]),
|
||||
parse("
|
||||
@grahamcofborg build bar
|
||||
@grahamcofborg eval
|
||||
@grahamcofborg build foo"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_and_eval_comment() {
|
||||
assert_eq!(Some(vec![
|
||||
Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
]),
|
||||
Instruction::Eval,
|
||||
]),
|
||||
parse("@grahamcofborg build foo @grahamcofborg eval"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_comment() {
|
||||
assert_eq!(Some(Instruction::Build(vec![
|
||||
assert_eq!(Some(vec![Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
String::from("bar"),
|
||||
String::from("baz")
|
||||
])),
|
||||
])]),
|
||||
parse("@GrahamCOfBorg build foo bar
|
||||
|
||||
baz"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_comment_newlines() {
|
||||
assert_eq!(Some(vec![Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
String::from("bar"),
|
||||
String::from("baz")
|
||||
])]),
|
||||
parse("@GrahamCOfBorg build foo bar baz"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_comment_lower() {
|
||||
assert_eq!(Some(Instruction::Build(vec![
|
||||
assert_eq!(Some(vec![Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
String::from("bar"),
|
||||
String::from("baz")
|
||||
])),
|
||||
])]),
|
||||
parse("@grahamcofborg build foo bar baz"));
|
||||
}
|
||||
|
||||
|
||||
#[test]
|
||||
fn build_whitespace_disregarded() {
|
||||
assert_eq!(Some(Instruction::Build(vec![
|
||||
assert_eq!(Some(vec![Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
String::from("bar"),
|
||||
String::from("baz")
|
||||
])),
|
||||
])]),
|
||||
parse("
|
||||
|
||||
|
||||
|
@ -84,11 +157,11 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn build_comment_lower_package_case_retained() {
|
||||
assert_eq!(Some(Instruction::Build(vec![
|
||||
assert_eq!(Some(vec![Instruction::Build(vec![
|
||||
String::from("foo"),
|
||||
String::from("bar"),
|
||||
String::from("baz.Baz")
|
||||
])),
|
||||
])]),
|
||||
parse("@grahamcofborg build foo bar baz.Baz"));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,126 +0,0 @@
|
|||
extern crate amqp;
|
||||
extern crate env_logger;
|
||||
|
||||
use ofborg::ghevent;
|
||||
use ofborg::acl;
|
||||
use serde_json;
|
||||
|
||||
use hubcaps;
|
||||
use ofborg::message::{Repo, Pr, buildjob};
|
||||
use ofborg::worker;
|
||||
use ofborg::commentparser;
|
||||
use amqp::protocol::basic::{Deliver,BasicProperties};
|
||||
|
||||
|
||||
pub struct BuildFilterWorker {
|
||||
acl: acl::ACL,
|
||||
github: hubcaps::Github
|
||||
}
|
||||
|
||||
impl BuildFilterWorker {
|
||||
pub fn new(acl: acl::ACL, github: hubcaps::Github) -> BuildFilterWorker {
|
||||
return BuildFilterWorker{
|
||||
acl: acl,
|
||||
github: github,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl worker::SimpleWorker for BuildFilterWorker {
|
||||
type J = ghevent::IssueComment;
|
||||
|
||||
fn msg_to_job(&self, _: &Deliver, _: &BasicProperties,
|
||||
body: &Vec<u8>) -> Result<Self::J, String> {
|
||||
return match serde_json::from_slice(body) {
|
||||
Ok(e) => { Ok(e) }
|
||||
Err(e) => {
|
||||
println!("Failed to deserialize IsssueComment: {:?}", String::from_utf8(body.clone()));
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn consumer(&self, job: &ghevent::IssueComment) -> worker::Actions {
|
||||
let instructions = commentparser::parse(&job.comment.body);
|
||||
if instructions == None {
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
|
||||
if !self.acl.can_build(&job.comment.user.login, &job.repository.full_name) {
|
||||
println!("ACL prohibits {} from building {:?} for {}",
|
||||
job.comment.user.login,
|
||||
instructions,
|
||||
job.repository.full_name);
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
|
||||
println!("Got job: {:?}", job);
|
||||
|
||||
let instructions = commentparser::parse(&job.comment.body);
|
||||
println!("Instructions: {:?}", instructions);
|
||||
|
||||
let pr = self.github
|
||||
.repo(job.repository.owner.login.clone(), job.repository.name.clone())
|
||||
.pulls()
|
||||
.get(job.issue.number)
|
||||
.get();
|
||||
|
||||
if let Err(x) = pr {
|
||||
info!("fetching PR {}#{} from GitHub yielded error {}",
|
||||
job.repository.full_name,
|
||||
job.issue.number,
|
||||
x
|
||||
);
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
|
||||
let pr = pr.unwrap();
|
||||
|
||||
match instructions {
|
||||
Some(commentparser::Instruction::Build(attrs)) => {
|
||||
let msg = buildjob::BuildJob{
|
||||
repo: Repo {
|
||||
clone_url: job.repository.clone_url.clone(),
|
||||
full_name: job.repository.full_name.clone(),
|
||||
owner: job.repository.owner.login.clone(),
|
||||
name: job.repository.name.clone(),
|
||||
},
|
||||
pr: Pr {
|
||||
number: job.issue.number.clone(),
|
||||
head_sha: pr.head.sha,
|
||||
target_branch: Some(pr.base.commit_ref)
|
||||
},
|
||||
attrs: attrs
|
||||
};
|
||||
|
||||
let props = BasicProperties {
|
||||
content_type: Some("application/json".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
return vec![
|
||||
worker::Action::Publish(worker::QueueMsg{
|
||||
exchange: Some("build-jobs".to_owned()),
|
||||
routing_key: None,
|
||||
mandatory: true,
|
||||
immediate: false,
|
||||
properties: Some(props),
|
||||
content: serde_json::to_string(&msg).unwrap().into_bytes()
|
||||
}),
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
_ => {
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
160
ofborg/src/tasks/githubcommentfilter.rs
Normal file
160
ofborg/src/tasks/githubcommentfilter.rs
Normal file
|
@ -0,0 +1,160 @@
|
|||
extern crate amqp;
|
||||
extern crate env_logger;
|
||||
|
||||
use ofborg::ghevent;
|
||||
use ofborg::acl;
|
||||
use serde_json;
|
||||
|
||||
use hubcaps;
|
||||
use ofborg::message::{Repo, Pr, buildjob, massrebuildjob};
|
||||
use ofborg::worker;
|
||||
use ofborg::commentparser;
|
||||
use amqp::protocol::basic::{Deliver,BasicProperties};
|
||||
|
||||
|
||||
pub struct GitHubCommentWorker {
|
||||
acl: acl::ACL,
|
||||
github: hubcaps::Github
|
||||
}
|
||||
|
||||
impl GitHubCommentWorker {
|
||||
pub fn new(acl: acl::ACL, github: hubcaps::Github) -> GitHubCommentWorker {
|
||||
return GitHubCommentWorker{
|
||||
acl: acl,
|
||||
github: github,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
impl worker::SimpleWorker for GitHubCommentWorker {
|
||||
type J = ghevent::IssueComment;
|
||||
|
||||
fn msg_to_job(&self, _: &Deliver, _: &BasicProperties,
|
||||
body: &Vec<u8>) -> Result<Self::J, String> {
|
||||
return match serde_json::from_slice(body) {
|
||||
Ok(e) => { Ok(e) }
|
||||
Err(e) => {
|
||||
println!("Failed to deserialize IsssueComment: {:?}", String::from_utf8(body.clone()));
|
||||
panic!("{:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn consumer(&self, job: &ghevent::IssueComment) -> worker::Actions {
|
||||
let instructions = commentparser::parse(&job.comment.body);
|
||||
if instructions == None {
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
|
||||
if !self.acl.can_build(&job.comment.user.login, &job.repository.full_name) {
|
||||
println!("ACL prohibits {} from building {:?} for {}",
|
||||
job.comment.user.login,
|
||||
instructions,
|
||||
job.repository.full_name);
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
|
||||
println!("Got job: {:?}", job);
|
||||
|
||||
let instructions = commentparser::parse(&job.comment.body);
|
||||
println!("Instructions: {:?}", instructions);
|
||||
|
||||
let pr = self.github
|
||||
.repo(job.repository.owner.login.clone(), job.repository.name.clone())
|
||||
.pulls()
|
||||
.get(job.issue.number)
|
||||
.get();
|
||||
|
||||
if let Err(x) = pr {
|
||||
info!("fetching PR {}#{} from GitHub yielded error {}",
|
||||
job.repository.full_name,
|
||||
job.issue.number,
|
||||
x
|
||||
);
|
||||
return vec![
|
||||
worker::Action::Ack
|
||||
];
|
||||
}
|
||||
|
||||
let pr = pr.unwrap();
|
||||
|
||||
let mut response: Vec<worker::Action> = vec![];
|
||||
if let Some(instructions) = instructions {
|
||||
for instruction in instructions {
|
||||
match instruction {
|
||||
commentparser::Instruction::Build(attrs) => {
|
||||
let msg = buildjob::BuildJob{
|
||||
repo: Repo {
|
||||
clone_url: job.repository.clone_url.clone(),
|
||||
full_name: job.repository.full_name.clone(),
|
||||
owner: job.repository.owner.login.clone(),
|
||||
name: job.repository.name.clone(),
|
||||
},
|
||||
pr: Pr {
|
||||
number: job.issue.number.clone(),
|
||||
head_sha: pr.head.sha.clone(),
|
||||
target_branch: Some(pr.base.commit_ref.clone())
|
||||
},
|
||||
attrs: attrs
|
||||
};
|
||||
|
||||
let props = BasicProperties {
|
||||
content_type: Some("application/json".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
response.push(
|
||||
worker::Action::Publish(worker::QueueMsg{
|
||||
exchange: Some("build-jobs".to_owned()),
|
||||
routing_key: None,
|
||||
mandatory: true,
|
||||
immediate: false,
|
||||
properties: Some(props),
|
||||
content: serde_json::to_string(&msg).unwrap().into_bytes()
|
||||
})
|
||||
);
|
||||
}
|
||||
commentparser::Instruction::Eval => {
|
||||
let msg = massrebuildjob::MassRebuildJob{
|
||||
repo: Repo {
|
||||
clone_url: job.repository.clone_url.clone(),
|
||||
full_name: job.repository.full_name.clone(),
|
||||
owner: job.repository.owner.login.clone(),
|
||||
name: job.repository.name.clone(),
|
||||
},
|
||||
pr: Pr {
|
||||
number: job.issue.number.clone(),
|
||||
head_sha: pr.head.sha.clone(),
|
||||
target_branch: Some(pr.base.commit_ref.clone()),
|
||||
},
|
||||
};
|
||||
|
||||
let props = BasicProperties {
|
||||
content_type: Some("application/json".to_owned()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
response.push(
|
||||
worker::Action::Publish(worker::QueueMsg{
|
||||
exchange: None,
|
||||
routing_key: Some("mass-rebuild-check-jobs".to_owned()),
|
||||
mandatory: true,
|
||||
immediate: false,
|
||||
properties: Some(props),
|
||||
content: serde_json::to_string(&msg).unwrap().into_bytes()
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.push(worker::Action::Ack);
|
||||
return response;
|
||||
}
|
||||
}
|
|
@ -2,4 +2,4 @@
|
|||
pub mod heartbeat;
|
||||
pub mod build;
|
||||
pub mod massrebuilder;
|
||||
pub mod buildfilter;
|
||||
pub mod githubcommentfilter;
|
||||
|
|
Loading…
Reference in a new issue