Merge pull request #349 from NixOS/github-token

GitHub token vending machine
This commit is contained in:
Graham Christensen 2019-04-12 06:54:20 -04:00 committed by GitHub
commit da348bdacc
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 86 additions and 21 deletions

4
ofborg/Cargo.lock generated
View file

@ -1,3 +1,5 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "aho-corasick"
version = "0.5.3"
@ -245,7 +247,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "hubcaps"
version = "0.3.16"
source = "git+https://github.com/grahamc/hubcaps.git#a7477f35f9dbc33a34f4486593f3725b4e523028"
source = "git+https://github.com/grahamc/hubcaps.git#1c5da1e60ee2d0d69188d83da048e7328aae05b9"
dependencies = [
"error-chain 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"frank_jwt 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)",

View file

@ -20,7 +20,7 @@ serde_derive = "1.0"
serde_json = "1.0"
tempfile = "2.2.0"
hubcaps = { git = "https://github.com/grahamc/hubcaps.git" }
#hubcaps = { path = "../hubcaps/" } # for testing patches
#hubcaps = { path = "../../../grahamc/hubcaps/" } # for testing patches
hyper = "0.10.*"
hyper-native-tls = "0.2.4"
lru-cache = "0.1.1"

View file

@ -62,7 +62,7 @@ fn main() {
channel
.consume(
worker::new(tasks::githubcommentposter::GitHubCommentPoster::new(
cfg.github_app(),
cfg.github_app_vendingmachine(),
)),
easyamqp::ConsumeConfig {
queue: "build-results".to_owned(),

View file

@ -3,14 +3,13 @@ use hyper::net::HttpsConnector;
use hyper::Client;
use hyper_native_tls::NativeTlsClient;
use nix::Nix;
use ofborg::acl;
use serde_json;
use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use ofborg::acl;
#[derive(Serialize, Deserialize, Debug)]
pub struct Config {
pub runner: RunnerConfig,
@ -115,17 +114,12 @@ impl Config {
)
}
pub fn github_app(&self) -> Github {
let conf = self.github_app.clone().unwrap();
Github::new(
"github.com/grahamc/ofborg (app)",
// tls configured hyper client
Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap())),
Credentials::InstallationToken(InstallationTokenGenerator::new(
conf.installation_id,
JWTCredentials::new(conf.app_id, conf.private_key),
)),
)
pub fn github_app_vendingmachine(&self) -> GithubAppVendingMachine {
GithubAppVendingMachine {
conf: self.github_app.clone().unwrap(),
id_cache: HashMap::new(),
client_cache: HashMap::new(),
}
}
pub fn nix(&self) -> Nix {
@ -169,3 +163,61 @@ pub fn load(filename: &Path) -> Config {
deserialized
}
pub struct GithubAppVendingMachine {
conf: GithubAppConfig,
id_cache: HashMap<(String, String), Option<i32>>,
client_cache: HashMap<i32, Github>,
}
impl GithubAppVendingMachine {
fn useragent(&self) -> &'static str {
"github.com/grahamc/ofborg (app)"
}
fn jwt(&self) -> JWTCredentials {
JWTCredentials::new(self.conf.app_id, self.conf.private_key.clone())
}
fn install_id_for_repo(&mut self, owner: &str, repo: &str) -> Option<i32> {
let useragent = self.useragent();
let jwt = self.jwt();
let key = (owner.to_owned(), repo.to_owned());
*self.id_cache.entry(key).or_insert_with(|| {
info!("Looking up install ID for {}/{}", owner, repo);
let lookup_gh = Github::new(
useragent,
Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap())),
Credentials::JWT(jwt),
);
match lookup_gh.app().find_repo_installation(owner, repo) {
Ok(install_id) => {
debug!("Received install ID {:#?}", install_id);
Some(install_id.id)
}
Err(e) => {
warn!("Error during install ID lookup: {:#?}", e);
None
}
}
})
}
pub fn for_repo<'a>(&'a mut self, owner: &str, repo: &str) -> Option<&'a Github> {
let useragent = self.useragent();
let jwt = self.jwt();
let install_id = self.install_id_for_repo(owner, repo)?;
Some(self.client_cache.entry(install_id).or_insert_with(|| {
Github::new(
useragent,
Client::with_connector(HttpsConnector::new(NativeTlsClient::new().unwrap())),
Credentials::InstallationToken(InstallationTokenGenerator::new(install_id, jwt)),
)
}))
}
}

View file

@ -313,6 +313,7 @@ impl<E: stats::SysEvents + 'static> worker::SimpleWorker for EvaluationWorker<E>
})
.all(|status| status == Ok(()));
info!("Finished evaluations");
let mut response: worker::Actions = vec![];
if eval_results {
@ -320,6 +321,10 @@ impl<E: stats::SysEvents + 'static> worker::SimpleWorker for EvaluationWorker<E>
.all_evaluations_passed(&Path::new(&refpath), &mut overall_status);
match ret {
Ok(builds) => {
info!(
"Scheduling build jobs {:#?} on arches {:#?}",
builds, auto_schedule_build_archs
);
for buildjob in builds {
for arch in auto_schedule_build_archs.iter() {
let (exchange, routingkey) = arch.as_build_destination();
@ -341,6 +346,7 @@ impl<E: stats::SysEvents + 'static> worker::SimpleWorker for EvaluationWorker<E>
}
}
Err(e) => {
info!("Failed after all the evaluations passed");
if self
.handle_strategy_err(Err(e), &gists, &mut overall_status)
.is_err()
@ -350,6 +356,8 @@ impl<E: stats::SysEvents + 'static> worker::SimpleWorker for EvaluationWorker<E>
}
}
info!("Just about done...");
overall_status.set_with_description("^.^!", hubcaps::statuses::State::Success);
} else {
overall_status
@ -358,6 +366,7 @@ impl<E: stats::SysEvents + 'static> worker::SimpleWorker for EvaluationWorker<E>
self.events.notify(Event::TaskEvaluationCheckComplete);
info!("done!");
self.actions().done(&job, response)
}
}

View file

@ -5,20 +5,20 @@ use serde_json;
use amqp::protocol::basic::{BasicProperties, Deliver};
use chrono::{DateTime, Utc};
use hubcaps;
use hubcaps::checks::{CheckRunOptions, CheckRunState, Conclusion, Output};
use message::buildjob::{BuildJob, QueuedBuildJobs};
use ofborg::config::GithubAppVendingMachine;
use ofborg::message::buildresult::{BuildResult, BuildStatus, LegacyBuildResult};
use ofborg::message::Repo;
use ofborg::worker;
pub struct GitHubCommentPoster {
github: hubcaps::Github,
github_vend: GithubAppVendingMachine,
}
impl GitHubCommentPoster {
pub fn new(github: hubcaps::Github) -> GitHubCommentPoster {
GitHubCommentPoster { github }
pub fn new(github_vend: GithubAppVendingMachine) -> GitHubCommentPoster {
GitHubCommentPoster { github_vend }
}
}
@ -77,7 +77,9 @@ impl worker::SimpleWorker for GitHubCommentPoster {
println!(":{:?}", check);
let check_create_attempt = self
.github
.github_vend
.for_repo(&repo.owner, &repo.name)
.unwrap()
.repo(repo.owner.clone(), repo.name.clone())
.checkruns()
.create(&check);