diff --git a/ofborg/src/bin/builder.rs b/ofborg/src/bin/builder.rs index 711b164..bb12fc7 100644 --- a/ofborg/src/bin/builder.rs +++ b/ofborg/src/bin/builder.rs @@ -1,6 +1,7 @@ extern crate ofborg; extern crate amqp; +use std::collections::LinkedList; use std::env; use amqp::{Consumer, Channel}; use amqp::protocol::basic::{Deliver,BasicProperties}; @@ -12,6 +13,9 @@ use amqp::Session; use amqp::Table; use std::process; use std::io::Error; +use std::fs::File; +use std::io::BufReader; +use std::io::BufRead; use ofborg::config; use ofborg::checkout; @@ -34,11 +38,14 @@ fn main() { process::exit(1); } - let cloner = checkout::cached_cloner(Path::new("/home/grahamc/.nix-test-rs")); + let cloner = checkout::cached_cloner(Path::new(&cfg.checkout.root)); + let nix = nix::new(cfg.nix.system.clone(), cfg.nix.remote); channel.basic_consume( worker::new(BuildWorker{ - cloner: cloner + cloner: cloner, + nix: nix, + system: cfg.nix.system.clone() }), "build-inputs-samples", "lmao1", @@ -58,6 +65,8 @@ fn main() { struct BuildWorker { cloner: checkout::CachedCloner, + nix: nix::Nix, + system: String, } impl worker::SimpleWorker for BuildWorker { @@ -76,8 +85,12 @@ impl worker::SimpleWorker for BuildWorker { } } - fn job_to_actions(&self, channel: &mut amqp::Channel, job: &buildjob::BuildJob) -> buildjob::Actions { - return buildjob::Actions{}; + fn job_to_actions(&self, channel: amqp::Channel, job: buildjob::BuildJob) -> buildjob::Actions { + return buildjob::Actions{ + system: self.system.clone(), + channel: channel, + job: job, + }; } @@ -95,9 +108,48 @@ impl worker::SimpleWorker for BuildWorker { co.fetch_pr(job.pr.number).unwrap(); co.merge_commit(job.pr.head_sha.as_ref()).unwrap(); - println!("Got path: {:?}", refpath); + println!("Got path: {:?}, building", refpath); - let cmd = nix::safely_build_attrs_cmd(refpath, job.attrs); + + let success: bool; + let reader: BufReader; + match self.nix.safely_build_attrs(refpath.as_ref(), job.attrs) { + Ok(r) => { + success = true; + reader = BufReader::new(r); + } + Err(r) => { + success = false; + reader = BufReader::new(r); + } + } + println!("ok built ({:?}), building", success); + + let l10 = reader.lines().fold(LinkedList::new(), + + |mut coll, line| + { + match line { + Ok(e) => { coll.push_back(e); } + Err(wtf) => { + println!("Got err in lines: {:?}", wtf); + coll.push_back(String::from("")); + } + } + + if coll.len() == 11 { + coll.pop_front(); + } + + return coll + } + ); + println!("Lines: {:?}", l10); + + resp.build_finished( + success, + l10.into_iter().collect::>() + ); return Ok(()) } diff --git a/ofborg/src/config.rs b/ofborg/src/config.rs index 90793a5..61a1e48 100644 --- a/ofborg/src/config.rs +++ b/ofborg/src/config.rs @@ -5,6 +5,8 @@ use std::io::Read; #[derive(Serialize, Deserialize, Debug)] pub struct Config { + pub checkout: CheckoutConfig, + pub nix: NixConfig, pub rabbitmq: RabbitMQConfig, } @@ -15,6 +17,18 @@ pub struct RabbitMQConfig { pub password: String, } +#[derive(Serialize, Deserialize, Debug)] +pub struct NixConfig { + pub system: String, + pub remote: String, +} + +#[derive(Serialize, Deserialize, Debug)] +pub struct CheckoutConfig { + pub root: String, +} + + impl RabbitMQConfig { pub fn as_uri(&self) -> String{ return format!("amqps://{}:{}@{}//", self.username, self.password, self.host); diff --git a/ofborg/src/message/buildjob.rs b/ofborg/src/message/buildjob.rs index 25e4637..04c18d6 100644 --- a/ofborg/src/message/buildjob.rs +++ b/ofborg/src/message/buildjob.rs @@ -1,15 +1,41 @@ use ofborg::message::{Pr,Repo}; +use ofborg::message::buildresult; use serde_json; +use amqp::{Basic, Channel, protocol}; #[derive(Serialize, Deserialize, Debug)] pub struct BuildJob { pub repo: Repo, pub pr: Pr, - pub attrs: Vec, + pub attrs: Vec } pub fn from(data: &Vec) -> Result { return serde_json::from_slice(&data); } -pub struct Actions{} +pub struct Actions { + pub system: String, + pub job: BuildJob, + pub channel: Channel +} + +impl Actions { + pub fn build_finished(&mut self, success: bool, lines: Vec) { + let msg = buildresult::BuildResult { + repo: self.job.repo.clone(), + pr: self.job.pr.clone(), + system: self.system.clone(), + output: lines, + success: success + }; + + let props = protocol::basic::BasicProperties { + content_type: Some("application/json".to_owned()), + ..Default::default() + }; + + self.channel.basic_publish("build-results", "", true, true, + props, serde_json::to_string(&msg).unwrap().into_bytes()).unwrap(); + } +} diff --git a/ofborg/src/message/buildresult.rs b/ofborg/src/message/buildresult.rs new file mode 100644 index 0000000..1c25087 --- /dev/null +++ b/ofborg/src/message/buildresult.rs @@ -0,0 +1,10 @@ +use ofborg::message::{Pr,Repo}; + +#[derive(Serialize, Deserialize, Debug)] +pub struct BuildResult { + pub repo: Repo, + pub pr: Pr, + pub system: String, + pub output: Vec, + pub success: bool +} diff --git a/ofborg/src/message/common.rs b/ofborg/src/message/common.rs index 4071b8d..9d1f88a 100644 --- a/ofborg/src/message/common.rs +++ b/ofborg/src/message/common.rs @@ -1,11 +1,11 @@ -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Repo { pub full_name: String, pub clone_url: String, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] pub struct Pr { pub target_branch: Option, pub number: i64, diff --git a/ofborg/src/message/mod.rs b/ofborg/src/message/mod.rs index 3564393..bb305a2 100644 --- a/ofborg/src/message/mod.rs +++ b/ofborg/src/message/mod.rs @@ -1,4 +1,5 @@ mod common; pub mod buildjob; +pub mod buildresult; use self::common::{Pr,Repo}; diff --git a/ofborg/src/nix.rs b/ofborg/src/nix.rs index d6754aa..225e02b 100644 --- a/ofborg/src/nix.rs +++ b/ofborg/src/nix.rs @@ -3,34 +3,60 @@ use std::ffi::OsString; use std::process::{Command,Stdio}; use tempfile::tempfile; use std::fs::File; +use std::io::Seek; +use std::io::SeekFrom; -pub fn safely_build_attrs(nixpkgs: &Path, attrs: Vec) -> Result { - let mut nixpath = OsString::new(); - nixpath.push("nixpkgs="); - nixpath.push(nixpkgs.as_os_str()); +pub struct Nix { + system: String, + remote: String +} - let stdout = tempfile().unwrap(); - let stderr = stdout.try_clone().unwrap(); - let reader = stderr.try_clone().unwrap(); - - let mut cmd = Command::new("nix-build") - .env_clear() - .current_dir(nixpkgs) - .stdout(Stdio::from(stdout)) - .stderr(Stdio::from(stderr)) - .env("NIX_PATH", nixpath); - - for attr in attrs { - cmd.arg("-A"); - cmd.arg(attr); +pub fn new(system: String, remote: String) -> Nix { + return Nix{ + system: system, + remote: remote, } +} - let stat = cmd - .status() - .unwrap(); +impl Nix { + pub fn safely_build_attrs(&self, nixpkgs: &Path, attrs: Vec) -> Result { + let mut nixpath = OsString::new(); + nixpath.push("nixpkgs="); + nixpath.push(nixpkgs.as_os_str()); + let mut attrargs: Vec = Vec::with_capacity(attrs.len() * 2); + for attr in attrs { + attrargs.push(String::from("-A")); + attrargs.push(attr); + } - return Ok(reader); + let stdout = tempfile().unwrap(); + let stderr = stdout.try_clone().unwrap(); + let mut reader = stderr.try_clone().unwrap(); + + let status = Command::new("nix-build") + .env_clear() + .current_dir(nixpkgs) + .stdout(Stdio::from(stdout)) + .stderr(Stdio::from(stderr)) + .env("NIX_PATH", nixpath) + .env("NIX_REMOTE", &self.remote) + .arg("--no-out-link") + .args(&["--option", "restrict-eval", "true"]) + .args(&["--argstr", "system", &self.system]) + .arg("--keep-going") + .args(attrargs) + .status() + .unwrap(); + + reader.seek(SeekFrom::Start(0)).unwrap(); + + if status.success() { + return Ok(reader) + } else { + return Err(reader) + } + } } /* diff --git a/ofborg/src/worker.rs b/ofborg/src/worker.rs index 5b8515e..d9b0471 100644 --- a/ofborg/src/worker.rs +++ b/ofborg/src/worker.rs @@ -19,7 +19,7 @@ pub trait SimpleWorker { fn msg_to_job(&self, method: &Deliver, headers: &BasicProperties, body: &Vec) -> Result; - fn job_to_actions(&self, channel: &mut Channel, job: &Self::J) -> Self::A; + fn job_to_actions(&self, channel: Channel, job: Self::J) -> Self::A; } pub fn new(worker: T) -> Worker { diff --git a/shell.nix b/shell.nix index 481e36a..bc6bfe7 100644 --- a/shell.nix +++ b/shell.nix @@ -12,7 +12,7 @@ let phpEnv = stdenv.mkDerivation rec { name = "gh-event-forwarder"; - src = ./.; + src = null; buildInputs = with pkgs; [ php phpPackages.composer @@ -29,7 +29,6 @@ let rustEnv = stdenv.mkDerivation rec { name = "gh-event-forwarder"; - src = ./.; buildInputs = with pkgs; [ php phpPackages.composer @@ -38,7 +37,7 @@ let openssl ]; - HISTFILE = "${src}/.bash_hist"; + HISTFILE = "${toString ./.}/.bash_hist"; };