diff --git a/ofborg/src/bin/github-comment-poster.rs b/ofborg/src/bin/github-comment-poster.rs new file mode 100644 index 0000000..1f41e5c --- /dev/null +++ b/ofborg/src/bin/github-comment-poster.rs @@ -0,0 +1,89 @@ +extern crate ofborg; +extern crate amqp; +extern crate env_logger; + +extern crate hyper; +extern crate hubcaps; +extern crate hyper_native_tls; + + +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 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(); + + channel + .declare_exchange(easyamqp::ExchangeConfig { + exchange: "build-results".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: "build-results".to_owned(), + passive: false, + durable: true, + exclusive: false, + auto_delete: false, + no_wait: false, + arguments: None, + }) + .unwrap(); + + channel + .bind_queue(easyamqp::BindQueueConfig { + queue: "build-results".to_owned(), + exchange: "build-results".to_owned(), + routing_key: None, + no_wait: false, + arguments: None, + }) + .unwrap(); + + channel.basic_prefetch(1).unwrap(); + channel + .consume( + worker::new(tasks::githubcommentposter::GitHubCommentPoster::new( + cfg.github(), + )), + easyamqp::ConsumeConfig { + queue: "build-inputs".to_owned(), + consumer_tag: format!("{}-github-comment-poster", 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"); +} diff --git a/ofborg/src/tasks/githubcommentposter.rs b/ofborg/src/tasks/githubcommentposter.rs new file mode 100644 index 0000000..fddb275 --- /dev/null +++ b/ofborg/src/tasks/githubcommentposter.rs @@ -0,0 +1,276 @@ +extern crate amqp; +extern crate env_logger; + +use serde_json; + +use hubcaps; +use ofborg::message::buildresult::BuildResult; +use ofborg::worker; +use amqp::protocol::basic::{Deliver, BasicProperties}; + + +pub struct GitHubCommentPoster { + github: hubcaps::Github, +} + +impl GitHubCommentPoster { + pub fn new(github: hubcaps::Github) -> GitHubCommentPoster { + return GitHubCommentPoster { github: github }; + } +} + +impl worker::SimpleWorker for GitHubCommentPoster { + type J = BuildResult; + + fn msg_to_job( + &mut self, + _: &Deliver, + _: &BasicProperties, + body: &Vec, + ) -> Result { + return match serde_json::from_slice(body) { + Ok(e) => Ok(e), + Err(e) => { + println!( + "Failed to deserialize BuildResult: {:?}", + String::from_utf8(body.clone()) + ); + panic!("{:?}", e); + } + }; + } + + fn consumer(&mut self, job: &BuildResult) -> worker::Actions { + let comment = hubcaps::comments::CommentOptions { body: result_to_comment(&job) }; + + let comment_attempt = self.github + .repo(job.repo.owner.clone(), job.repo.name.clone()) + .pulls() + .get(job.pr.number) + .comments() + .create(&comment); + + match comment_attempt { + Ok(comment) => { + info!( + "Successfully sent {:?} to {}", + comment, + job.pr.number, + ) + } + Err(err) => { + info!( + "Failed to send comment {:?} to {}", + err, + job.pr.number, + ) + } + } + + return vec![worker::Action::Ack]; + } +} + +fn result_to_comment(result: &BuildResult) -> String { + let mut reply: Vec = vec![]; + + reply.push(format!( + "{} on {} [(full log)](https://logs.nix.gsc.io/?key={}/{}.{}&attempt_id={})", + (match result.success { + true => "Success", + false => "Failure", + }), + result.system, + &result.repo.owner.to_lowercase(), + &result.repo.name.to_lowercase(), + result.pr.number, + (match result.attempt_id { + Some(ref attempt_id) => &attempt_id, + None => "none", + }) + )); + reply.push("".to_owned()); + reply.push( + "
Partial log (click to expand)

".to_owned(), + ); + reply.push("".to_owned()); + reply.push("```".to_owned()); + reply.extend(result.output.clone()); + reply.push("```".to_owned()); + reply.push("

".to_owned()); + reply.push("".to_owned()); + reply.push("".to_owned()); + + reply.join("\n") +} + +#[cfg(test)] +mod tests { + use super::*; + use message::{Pr, Repo}; + + #[test] + pub fn test_passing_build() { + let result = BuildResult { + repo: Repo { + clone_url: "https://github.com/nixos/nixpkgs.git".to_owned(), + full_name: "NixOS/nixpkgs".to_owned(), + owner: "NixOS".to_owned(), + name: "nixpkgs".to_owned(), + }, + pr: Pr { + head_sha: "abc123".to_owned(), + number: 2345, + target_branch: Some("master".to_owned()), + }, + output: vec![ + "make[2]: Entering directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline'".to_owned(), + "make[2]: Nothing to be done for 'install'.".to_owned(), + "make[2]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline'".to_owned(), + "make[1]: Nothing to be done for 'install-target'.".to_owned(), + "make[1]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1'".to_owned(), + "removed '/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1/share/info/bfd.info'".to_owned(), + "post-installation fixup".to_owned(), + "strip is /nix/store/5a88zk3jgimdmzg8rfhvm93kxib3njf9-cctools-binutils-darwin/bin/strip".to_owned(), + "patching script interpreter paths in /nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1".to_owned(), + "/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1".to_owned(), + ], + attempt_id: Some("neatattemptid".to_owned()), + system: "x86_64-linux".to_owned(), + success: true, + }; + + assert_eq!( + &result_to_comment(&result), + "Success on x86_64-linux [(full log)](https://logs.nix.gsc.io/?key=nixos/nixpkgs.2345&attempt_id=neatattemptid) + +
Partial log (click to expand)

+ +``` +make[2]: Entering directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline' +make[2]: Nothing to be done for 'install'. +make[2]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline' +make[1]: Nothing to be done for 'install-target'. +make[1]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1' +removed '/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1/share/info/bfd.info' +post-installation fixup +strip is /nix/store/5a88zk3jgimdmzg8rfhvm93kxib3njf9-cctools-binutils-darwin/bin/strip +patching script interpreter paths in /nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1 +/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1 +``` +

+ +" + ); + } + + #[test] + pub fn test_failing_build() { + let result = BuildResult { + repo: Repo { + clone_url: "https://github.com/nixos/nixpkgs.git".to_owned(), + full_name: "NixOS/nixpkgs".to_owned(), + owner: "NixOS".to_owned(), + name: "nixpkgs".to_owned(), + }, + pr: Pr { + head_sha: "abc123".to_owned(), + number: 2345, + target_branch: Some("master".to_owned()), + }, + output: vec![ + "make[2]: Entering directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline'".to_owned(), + "make[2]: Nothing to be done for 'install'.".to_owned(), + "make[2]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline'".to_owned(), + "make[1]: Nothing to be done for 'install-target'.".to_owned(), + "make[1]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1'".to_owned(), + "removed '/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1/share/info/bfd.info'".to_owned(), + "post-installation fixup".to_owned(), + "strip is /nix/store/5a88zk3jgimdmzg8rfhvm93kxib3njf9-cctools-binutils-darwin/bin/strip".to_owned(), + "patching script interpreter paths in /nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1".to_owned(), + "/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1".to_owned(), + ], + attempt_id: Some("neatattemptid".to_owned()), + system: "x86_64-linux".to_owned(), + success: false, + }; + + assert_eq!( + &result_to_comment(&result), + "Failure on x86_64-linux [(full log)](https://logs.nix.gsc.io/?key=nixos/nixpkgs.2345&attempt_id=neatattemptid) + +
Partial log (click to expand)

+ +``` +make[2]: Entering directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline' +make[2]: Nothing to be done for 'install'. +make[2]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline' +make[1]: Nothing to be done for 'install-target'. +make[1]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1' +removed '/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1/share/info/bfd.info' +post-installation fixup +strip is /nix/store/5a88zk3jgimdmzg8rfhvm93kxib3njf9-cctools-binutils-darwin/bin/strip +patching script interpreter paths in /nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1 +/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1 +``` +

+ +" + ); + } + + #[test] + pub fn test_failing_build_no_attempt_id() { + let result = BuildResult { + repo: Repo { + clone_url: "https://github.com/nixos/nixpkgs.git".to_owned(), + full_name: "NixOS/nixpkgs".to_owned(), + owner: "NixOS".to_owned(), + name: "nixpkgs".to_owned(), + }, + pr: Pr { + head_sha: "abc123".to_owned(), + number: 2345, + target_branch: Some("master".to_owned()), + }, + output: vec![ + "make[2]: Entering directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline'".to_owned(), + "make[2]: Nothing to be done for 'install'.".to_owned(), + "make[2]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline'".to_owned(), + "make[1]: Nothing to be done for 'install-target'.".to_owned(), + "make[1]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1'".to_owned(), + "removed '/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1/share/info/bfd.info'".to_owned(), + "post-installation fixup".to_owned(), + "strip is /nix/store/5a88zk3jgimdmzg8rfhvm93kxib3njf9-cctools-binutils-darwin/bin/strip".to_owned(), + "patching script interpreter paths in /nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1".to_owned(), + "/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1".to_owned(), + ], + attempt_id: None, + system: "x86_64-linux".to_owned(), + success: false, + }; + + assert_eq!( + &result_to_comment(&result), + "Failure on x86_64-linux [(full log)](https://logs.nix.gsc.io/?key=nixos/nixpkgs.2345&attempt_id=none) + +
Partial log (click to expand)

+ +``` +make[2]: Entering directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline' +make[2]: Nothing to be done for 'install'. +make[2]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1/readline' +make[1]: Nothing to be done for 'install-target'. +make[1]: Leaving directory '/private/tmp/nix-build-gdb-8.1.drv-0/gdb-8.1' +removed '/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1/share/info/bfd.info' +post-installation fixup +strip is /nix/store/5a88zk3jgimdmzg8rfhvm93kxib3njf9-cctools-binutils-darwin/bin/strip +patching script interpreter paths in /nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1 +/nix/store/pcja75y9isdvgz5i00pkrpif9rxzxc29-gdb-8.1 +``` +

+ +" + ); + } +} diff --git a/ofborg/src/tasks/mod.rs b/ofborg/src/tasks/mod.rs index eb6ed18..d735e60 100644 --- a/ofborg/src/tasks/mod.rs +++ b/ofborg/src/tasks/mod.rs @@ -2,4 +2,5 @@ pub mod build; pub mod massrebuilder; pub mod githubcommentfilter; +pub mod githubcommentposter; pub mod log_message_collector;