use crate::{yes_or_no, Cmd, File, MasterConfig, Worker, AUTH_TOKEN_PATH};
use std::path::PathBuf;
use std::process::exit;
pub trait BuildSystem {
fn preinstall(&mut self) -> Result<(), String> {
Ok(())
}
fn install(&mut self) -> Result<(), String> {
self.preinstall()?;
info!("Installing Python...");
self.install_python()?;
info!("Installing Buildbot...");
self.install_buildbot()?;
info!(
"Next, write your VCS's api token to '{}', and then run the `build` subcommand",
AUTH_TOKEN_PATH
);
Ok(())
}
fn prebuild(&mut self) -> Result<(), String> {
Ok(())
}
fn rebuild(&mut self, master: MasterConfig) -> Result<(), String> {
self.prebuild()?;
if !yes_or_no("Have you already run the install subcommand and activated your virtual env in this shell? (y/n) ") {
error!("You must run the install subcommand and activate your venv before the running the build subcommand!");
exit(0);
}
info!("Creating master...");
self.create_master()?;
let workers = master.get_workers();
info!("Creating workers...");
self.create_workers(&workers)?;
info!("Writing to master/master.cfg...");
self.write_master_config(&master)?;
info!("Writing to worker configs...");
self.write_worker_configs(&workers)?;
info!("Reconfiguring master...");
self.reconfigure_master()?;
Ok(())
}
fn build(&mut self, master: MasterConfig) -> Result<(), String> {
self.prebuild()?;
if !yes_or_no("Have you already run the install subcommand and activated your virtual env in this shell? (y/n) ") {
error!("You must run the install subcommand and activate your venv before the running the build subcommand!");
exit(0);
}
info!("Creating master...");
self.create_master()?;
let workers = master.get_workers();
info!("Creating workers...");
self.create_workers(&workers)?;
info!("Writing to master/master.cfg...");
self.write_master_config(&master)?;
info!("Writing to worker configs...");
self.write_worker_configs(&workers)?;
info!("Next, run the `start` subcommand to execute the master and the workers");
Ok(())
}
fn start(&mut self, workers: &[Worker]) -> Result<(), String> {
if !yes_or_no("Have you already run the build subcommand and activated your virtual env in this shell? (y/n) ") {
error!("You must run the build subcommand and activate your venv before the running the start subcommand!");
exit(0);
}
info!("Starting workers and masters...");
self.start_master()?;
self.start_workers(workers)?;
Ok(())
}
fn stop(&mut self) -> Result<(), String> {
if !yes_or_no("Are you sure you want to kill rusty-ci? This will also kill all python processes! (y/n) ") {
error!("You weren't sure!");
exit(0);
}
info!("Killing python...");
Cmd::new("killall").arg("python").run();
info!("Killing python3...");
Cmd::new("killall").arg("python3").run();
info!("Killing workers...");
Cmd::new("killall").arg("buildbot-worker").run();
Ok(())
}
fn reconfigure_master(&mut self) -> Result<(), String> {
let buildbot = |sub_command| -> Result<(), String> {
Cmd::new("buildbot").arg(sub_command).arg("master").run();
Ok(())
};
buildbot("reconfig")?;
buildbot("cleanupdb")?;
Ok(())
}
fn start_master(&mut self) -> Result<(), String> {
let buildbot = |sub_command| -> Result<(), String> {
Cmd::new("buildbot").arg(sub_command).arg("master").run();
Ok(())
};
buildbot("stop")?;
buildbot("reconfig")?;
buildbot("cleanupdb")?;
buildbot("start")?;
Ok(())
}
fn start_workers(&mut self, workers: &[Worker]) -> Result<(), String> {
let start_worker = |dir| -> Result<(), String> {
Cmd::new("buildbot-worker").arg("restart").arg(&dir).run();
Ok(())
};
for worker in workers {
start_worker(worker.get_dir())?;
}
Ok(())
}
fn create_workers(&mut self, workers: &[Worker]) -> Result<(), String> {
let make_worker = |dir| -> Result<(), String> {
Cmd::new("buildbot-worker")
.arg("create-worker")
.arg(&dir)
.arg("localhost")
.arg(&dir)
.arg("pass")
.run();
Ok(())
};
for worker in workers {
make_worker(worker.get_dir())?;
}
Ok(())
}
fn write_worker_configs(&mut self, workers: &[Worker]) -> Result<(), String> {
for worker in workers {
let mut path = PathBuf::new();
path.push(worker.get_dir());
path.push("buildbot.tac");
match File::write(path, worker.to_string()) {
Err(e) => Err(e + &format!(
"\nDid you enter a valid basedir for the \"{}\" worker?",
worker.get_name()
)),
Ok(()) => Ok(()),
}?;
}
Ok(())
}
fn create_master(&mut self) -> Result<(), String> {
Cmd::new("buildbot")
.arg("create-master")
.arg("master")
.run();
Ok(())
}
fn write_master_config(&mut self, master: &MasterConfig) -> Result<(), String> {
match File::write("master/master.cfg", master.to_string()) {
Err(e) => Err(e + "\nDid you enter your venv by running `. venv/bin/activate`?"),
Ok(()) => Ok(()),
}
}
fn install_python(&mut self) -> Result<(), String> {
let apt_install = |package| -> Result<(), String> {
Cmd::new("apt-get")
.arg("install")
.arg(package)
.arg("-y")
.run();
Ok(())
};
apt_install("python3-dev")?;
apt_install("python3-pip")?;
apt_install("python3-venv")?;
Ok(())
}
fn install_buildbot(&mut self) -> Result<(), String> {
Cmd::new("python3")
.arg("-m")
.arg("pip")
.arg("install")
.arg("-U")
.arg("pip")
.run();
Cmd::new("python3")
.arg("-m")
.arg("pip")
.arg("install")
.arg("-U")
.arg("buildbot[bundle]")
.run();
Cmd::new("python3")
.arg("-m")
.arg("pip")
.arg("install")
.arg("-U")
.arg("txrequest")
.run();
Cmd::new("python3")
.arg("-m")
.arg("pip")
.arg("install")
.arg("-U")
.arg("treq")
.run();
Cmd::new("python3")
.arg("-m")
.arg("pip")
.arg("install")
.arg("buildbot-worker")
.arg("setuptools-trial")
.run();
Ok(())
}
}