Autoschedule builds from trusted users

This commit is contained in:
Graham Christensen 2018-02-01 21:30:23 -05:00
parent ac63df2a24
commit 5e4360e6af
No known key found for this signature in database
GPG key ID: ACA1C1D120C83D5C
5 changed files with 89 additions and 42 deletions

View file

@ -12,6 +12,20 @@ impl ACL {
}; };
} }
pub fn build_job_destinations_for_user_repo(&self, user: &str, repo: &str)
-> Vec<(Option<String>, Option<String>)> {
if self.can_build_unrestricted(user, repo) {
vec![(Some("build-jobs".to_owned()), None)]
} else if self.can_build_restricted(user, repo) {
vec![
(None, Some("build-inputs-x86_64-linux".to_owned())),
(None, Some("build-inputs-aarch64-linux".to_owned())),
]
} else {
vec![]
}
}
pub fn can_build_restricted(&self, user: &str, repo: &str) -> bool { pub fn can_build_restricted(&self, user: &str, repo: &str) -> bool {
if repo.to_lowercase() != "nixos/nixpkgs" { if repo.to_lowercase() != "nixos/nixpkgs" {
return false; return false;

View file

@ -8,8 +8,37 @@ pub struct BuildJob {
pub pr: Pr, pub pr: Pr,
pub subset: Option<Subset>, pub subset: Option<Subset>,
pub attrs: Vec<String>, pub attrs: Vec<String>,
pub logs: Option<(Option<String>, Option<String>)>, // (Exchange, Routing Key) pub logs: Option<ExchangeQueue>, // (Exchange, Routing Key)
pub statusreport: Option<(Option<String>, Option<String>)>, // (Exchange, Routing Key) pub statusreport: Option<ExchangeQueue>, // (Exchange, Routing Key)
}
pub type ExchangeQueue = (Option<Exchange>, Option<RoutingKey>);
type Exchange = String;
type RoutingKey = String;
impl BuildJob {
pub fn new(repo: Repo,
pr: Pr,
subset: Subset,
attrs: Vec<String>,
logs: Option<ExchangeQueue>,
statusreport: Option<ExchangeQueue>) -> BuildJob {
let logbackrk = format!(
"{}.{}",
repo.full_name.clone(),
pr.number,
).to_lowercase();
BuildJob {
repo: repo,
pr: pr,
subset: Some(subset),
attrs: attrs,
logs: Some(logs.unwrap_or((Some("logs".to_owned()), Some(logbackrk)))),
statusreport: Some(statusreport.unwrap_or((Some("build-results".to_owned()), None))),
}
}
} }
pub fn from(data: &Vec<u8>) -> Result<BuildJob, serde_json::error::Error> { pub fn from(data: &Vec<u8>) -> Result<BuildJob, serde_json::error::Error> {

View file

@ -20,7 +20,8 @@ impl Actions {
return vec![worker::Action::Ack]; return vec![worker::Action::Ack];
} }
pub fn done(&mut self, _job: &MassRebuildJob) -> worker::Actions { pub fn done(&mut self, _job: &MassRebuildJob, mut response: worker::Actions) -> worker::Actions {
return vec![worker::Action::Ack]; response.push(worker::Action::Ack);
return response;
} }
} }

View file

@ -53,30 +53,13 @@ impl worker::SimpleWorker for GitHubCommentWorker {
return vec![worker::Action::Ack]; return vec![worker::Action::Ack];
} }
let build_destinations: Vec<(Option<String>, Option<String>)>; let build_destinations = self.acl.build_job_destinations_for_user_repo(
&job.comment.user.login,
&job.repository.full_name,
);
if self.acl.can_build_unrestricted( if build_destinations.len() == 0 {
&job.comment.user.login, // Don't process comments if they can't build anything
&job.repository.full_name,
)
{
build_destinations = vec![(Some("build-jobs".to_owned()), None)];
} else if self.acl.can_build_restricted(
&job.comment.user.login,
&job.repository.full_name,
)
{
build_destinations = vec![
(None, Some("build-inputs-x86_64-linux".to_owned())),
(None, Some("build-inputs-aarch64-linux".to_owned())),
];
} else {
println!(
"ACL prohibits {} from building {:?} for {}",
job.comment.user.login,
instructions,
job.repository.full_name
);
return vec![worker::Action::Ack]; return vec![worker::Action::Ack];
} }
@ -124,19 +107,14 @@ impl worker::SimpleWorker for GitHubCommentWorker {
for instruction in instructions { for instruction in instructions {
match instruction { match instruction {
commentparser::Instruction::Build(subset, attrs) => { commentparser::Instruction::Build(subset, attrs) => {
let logbackrk = format!( let msg = buildjob::BuildJob::new(
"{}.{}", repo_msg.clone(),
job.repository.full_name.clone(), pr_msg.clone(),
job.issue.number.clone() subset,
attrs,
None,
None
); );
let msg = buildjob::BuildJob {
repo: repo_msg.clone(),
pr: pr_msg.clone(),
subset: Some(subset),
attrs: attrs,
logs: Some((Some("logs".to_owned()), Some(logbackrk.to_lowercase()))),
statusreport: Some((Some("build-results".to_owned()), None)),
};
for (exch, rk) in build_destinations.clone() { for (exch, rk) in build_destinations.clone() {
response.push(worker::publish_serde_action(exch, rk, &msg)); response.push(worker::publish_serde_action(exch, rk, &msg));

View file

@ -9,15 +9,17 @@ use std::io::BufReader;
use std::path::Path; use std::path::Path;
use std::path::PathBuf; use std::path::PathBuf;
use ofborg::checkout; use ofborg::checkout;
use ofborg::message::massrebuildjob; use ofborg::message::{massrebuildjob, buildjob};
use ofborg::nix::Nix; use ofborg::nix::Nix;
use ofborg::acl::ACL;
use ofborg::stats; use ofborg::stats;
use ofborg::worker; use ofborg::worker;
use ofborg::tagger::{StdenvTagger, RebuildTagger}; use ofborg::tagger::{StdenvTagger, RebuildTagger};
use ofborg::outpathdiff::{OutPaths, OutPathDiff}; use ofborg::outpathdiff::{OutPaths, OutPathDiff};
use ofborg::evalchecker::EvalChecker; use ofborg::evalchecker::EvalChecker;
use ofborg::commitstatus::CommitStatus; use ofborg::commitstatus::CommitStatus;
use ofborg::commentparser::Subset;
use amqp::protocol::basic::{Deliver, BasicProperties}; use amqp::protocol::basic::{Deliver, BasicProperties};
use hubcaps; use hubcaps;
@ -25,6 +27,7 @@ pub struct MassRebuildWorker<E> {
cloner: checkout::CachedCloner, cloner: checkout::CachedCloner,
nix: Nix, nix: Nix,
github: hubcaps::Github, github: hubcaps::Github,
acl: ACL,
identity: String, identity: String,
events: E, events: E,
} }
@ -34,6 +37,7 @@ impl<E: stats::SysEvents> MassRebuildWorker<E> {
cloner: checkout::CachedCloner, cloner: checkout::CachedCloner,
nix: Nix, nix: Nix,
github: hubcaps::Github, github: hubcaps::Github,
acl: ACL,
identity: String, identity: String,
events: E, events: E,
) -> MassRebuildWorker<E> { ) -> MassRebuildWorker<E> {
@ -41,6 +45,7 @@ impl<E: stats::SysEvents> MassRebuildWorker<E> {
cloner: cloner, cloner: cloner,
nix: nix.without_limited_supported_systems(), nix: nix.without_limited_supported_systems(),
github: github, github: github,
acl: acl,
identity: identity, identity: identity,
events: events, events: events,
}; };
@ -86,6 +91,8 @@ impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
let gists = self.github.gists(); let gists = self.github.gists();
let issue = repo.issue(job.pr.number); let issue = repo.issue(job.pr.number);
let auto_schedule_build_archs: Option<Vec<buildjob::ExchangeQueue>>;
match issue.get() { match issue.get() {
Ok(iss) => { Ok(iss) => {
if iss.state == "closed" { if iss.state == "closed" {
@ -93,6 +100,11 @@ impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
info!("Skipping {} because it is closed", job.pr.number); info!("Skipping {} because it is closed", job.pr.number);
return self.actions().skip(&job); return self.actions().skip(&job);
} }
auto_schedule_build_archs = Some(self.acl.build_job_destinations_for_user_repo(
&iss.user.login,
&job.repo.full_name,
));
} }
Err(e) => { Err(e) => {
self.events.tick("issue-fetch-failed"); self.events.tick("issue-fetch-failed");
@ -345,6 +357,9 @@ impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
}) })
.all(|status| status == Ok(())); .all(|status| status == Ok(()));
let mut response: worker::Actions = vec![];
if eval_results { if eval_results {
let mut status = CommitStatus::new( let mut status = CommitStatus::new(
repo.statuses(), repo.statuses(),
@ -375,7 +390,17 @@ impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
try_build.sort(); try_build.sort();
try_build.dedup(); try_build.dedup();
println!("try to build: {:?}", try_build); let msg = buildjob::BuildJob::new(
job.repo.clone(),
job.pr.clone(),
Subset::Nixpkgs,
try_build,
None,
None,
);
for (dest, rk) in auto_schedule_build_archs.unwrap_or(vec![]) {
response.push(worker::publish_serde_action(dest, rk, &msg));
}
} }
Err(mut out) => { Err(mut out) => {
eval_results = false; eval_results = false;
@ -428,7 +453,7 @@ impl<E: stats::SysEvents> worker::SimpleWorker for MassRebuildWorker<E> {
); );
} }
return self.actions().done(&job); return self.actions().done(&job, response);
} }
} }