blob: adb907040f7588b63c83760c5191696dd5b285c2 [file] [log] [blame]
use std::io::BufReader;
use std::path::PathBuf;
use std::process;
use anyhow::{anyhow, Result};
use clap::{Parser, Subcommand};
use cliclack::{intro, outro, outro_cancel, spinner};
use serde::Deserialize;
#[derive(Parser)]
#[command(version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Command,
}
#[derive(Subcommand)]
enum Command {
/// runs presubmit testing
Presubmit {},
}
#[derive(Clone, Debug, Deserialize)]
pub struct BazelPrograms {
pub default: Vec<Vec<String>>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct BazelPresubmit {
pub remote_cache: bool,
pub upload_local_results: bool,
pub programs: BazelPrograms,
}
#[derive(Clone, Debug, Deserialize)]
pub struct PigweedConfig {
pub bazel_presubmit: BazelPresubmit,
}
#[derive(Clone, Debug, Deserialize)]
pub struct PigweedProject {
pub pw: PigweedConfig,
}
fn load_project_config() -> Result<PigweedProject> {
let workspace_dir = std::env::var("BUILD_WORKSPACE_DIRECTORY")
.map_err(|_| anyhow!("BUILD_WORKSPACE_DIRECTORY not found. Please run inside bazel."))?;
let path: PathBuf = [&workspace_dir, "pigweed.json"].iter().collect();
let reader = BufReader::new(std::fs::File::open(path)?);
let project_config = serde_json::from_reader(reader)?;
Ok(project_config)
}
fn run_bazel_presubmit(args: Vec<String>) -> Result<()> {
let workspace_dir = std::env::var("BUILD_WORKSPACE_DIRECTORY")
.map_err(|_| anyhow!("BUILD_WORKSPACE_DIRECTORY not found. Please run inside bazel."))?;
let spinner = spinner();
spinner.start(format!("Running {args:?}..."));
let output = process::Command::new("bazelisk")
.current_dir(workspace_dir)
.args(args.clone())
.output()?;
if !output.status.success() {
return Err(anyhow!(
"{args:?} failed:\n{}",
String::from_utf8_lossy(&output.stdout)
));
}
spinner.stop(format!("{args:?} success."));
Ok(())
}
fn command_presubmit() -> Result<()> {
intro("Running presubmits")?;
let config =
load_project_config().map_err(|e| anyhow!("Failed to load project config: {e}"))?;
for args in config.pw.bazel_presubmit.programs.default {
run_bazel_presubmit(args)?;
}
outro("All presubmits succeeded")?;
Ok(())
}
fn main() {
let cli = Cli::parse();
let result = match cli.command {
Command::Presubmit {} => command_presubmit(),
};
if let Err(e) = result {
outro_cancel(format!("{e}")).expect("outro succeeds");
std::process::exit(1);
}
}