Run bench for each commit.
This commit is contained in:
parent
0ee02d199e
commit
c67fa96700
183
src/main.rs
183
src/main.rs
@ -1,9 +1,12 @@
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rocket;
|
extern crate rocket;
|
||||||
use std::{
|
use std::{
|
||||||
fs, io,
|
fs,
|
||||||
|
fs::File,
|
||||||
|
io,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
process::Command,
|
process::{Command, Output},
|
||||||
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use glog::Flags;
|
use glog::Flags;
|
||||||
@ -29,63 +32,149 @@ fn post_reload(config: &State<Config>, repo: &str) -> Result<String, SyncError>
|
|||||||
reload(config, repo)
|
reload(config, repo)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn logging_run(cmd: &mut Command) -> &mut Command {
|
fn indent_output(bytes: &[u8]) -> String {
|
||||||
info!("Running {cmd:?}");
|
let s = String::from_utf8_lossy(bytes);
|
||||||
cmd
|
let s = if s.is_empty() { "<NO OUTPUT>" } else { &s };
|
||||||
|
s.split('\n')
|
||||||
|
.map(|l| format!("\t{l}"))
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_task_status(ts: &TaskStatus) -> String {
|
||||||
|
format!(
|
||||||
|
"Status {} ({}) {}s:\nStdout:\n{}\nStderr:\n{}",
|
||||||
|
ts.command,
|
||||||
|
ts.output.status,
|
||||||
|
ts.duration.as_secs_f32(),
|
||||||
|
indent_output(&ts.output.stdout),
|
||||||
|
indent_output(&ts.output.stderr)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TaskStatus {
|
||||||
|
command: String,
|
||||||
|
output: Output,
|
||||||
|
duration: Duration,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn logging_run(cmd: &mut Command) -> Result<TaskStatus, SyncError> {
|
||||||
|
let start = Instant::now();
|
||||||
|
let o = cmd.output()?;
|
||||||
|
let ts = TaskStatus {
|
||||||
|
output: o,
|
||||||
|
command: format!("{:?}", cmd),
|
||||||
|
duration: start.elapsed(),
|
||||||
|
};
|
||||||
|
info!("{}", format_task_status(&ts));
|
||||||
|
Ok(ts)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn git_checkout(build_path: &Path, rev: &str) -> Result<TaskStatus, SyncError> {
|
||||||
|
logging_run(
|
||||||
|
Command::new("git")
|
||||||
|
.current_dir(&build_path)
|
||||||
|
.arg("checkout")
|
||||||
|
.arg("-q")
|
||||||
|
.arg(rev),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn bench_at_commit(
|
||||||
|
commit: &str,
|
||||||
|
build_path: &Path,
|
||||||
|
target_path: &Path,
|
||||||
|
) -> Result<Vec<TaskStatus>, SyncError> {
|
||||||
|
let mut output = Vec::new();
|
||||||
|
output.push(git_checkout(build_path, commit)?);
|
||||||
|
// Run `cargo aoc bench`
|
||||||
|
output.push(logging_run(
|
||||||
|
Command::new("cargo")
|
||||||
|
.env("CARGO_TARGET_DIR", target_path)
|
||||||
|
.current_dir(&build_path)
|
||||||
|
.arg("aoc")
|
||||||
|
.arg("bench"),
|
||||||
|
)?);
|
||||||
|
output.push(git_checkout(build_path, "HEAD")?);
|
||||||
|
|
||||||
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reload(config: &State<Config>, repo: &str) -> Result<String, SyncError> {
|
fn reload(config: &State<Config>, repo: &str) -> Result<String, SyncError> {
|
||||||
info!("Need to reload '{}': {:?}", repo, config);
|
info!("Need to reload '{}': {:?}", repo, config);
|
||||||
let source_path = config.source_root.join(repo);
|
let source_path = config.source_root.join(repo);
|
||||||
let build_path = config.build_root.join(repo);
|
let build_path = config.build_root.join("git").join(repo);
|
||||||
dbg!(&build_path);
|
let target_path = config.build_root.join("target").join(repo);
|
||||||
dbg!(&source_path);
|
let commits_root = config.build_root.join("commits");
|
||||||
|
let www_root = config.www_root.join(repo);
|
||||||
|
|
||||||
|
dbg!(
|
||||||
|
&source_path,
|
||||||
|
&build_path,
|
||||||
|
&target_path,
|
||||||
|
&commits_root,
|
||||||
|
&www_root
|
||||||
|
);
|
||||||
|
|
||||||
|
if !commits_root.exists() {
|
||||||
|
info!("Creating {}", commits_root.display());
|
||||||
|
fs::create_dir_all(&commits_root)?;
|
||||||
|
}
|
||||||
|
if !www_root.exists() {
|
||||||
|
info!("Creating {}", www_root.display());
|
||||||
|
fs::create_dir_all(&www_root)?;
|
||||||
|
}
|
||||||
let mut output = Vec::new();
|
let mut output = Vec::new();
|
||||||
let needs_clone = !build_path.exists();
|
let needs_clone = !build_path.exists();
|
||||||
if needs_clone {
|
if needs_clone {
|
||||||
output.push(
|
output.push(logging_run(
|
||||||
logging_run(
|
Command::new("git")
|
||||||
Command::new("/run/current-system/sw/bin/git")
|
.current_dir(&config.build_root)
|
||||||
.current_dir(&config.build_root)
|
.arg("clone")
|
||||||
.arg("clone")
|
.arg(&source_path)
|
||||||
.arg(&source_path)
|
.arg(&build_path),
|
||||||
.arg(&build_path),
|
)?);
|
||||||
)
|
|
||||||
.output()?,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
output.push(logging_run(
|
||||||
|
Command::new("git")
|
||||||
|
.current_dir(&config.build_root)
|
||||||
|
.arg("checkout")
|
||||||
|
.arg("-f")
|
||||||
|
.arg("origin"),
|
||||||
|
)?);
|
||||||
// Make sure buildable clone is up to date
|
// Make sure buildable clone is up to date
|
||||||
output.push(
|
output.push(logging_run(
|
||||||
logging_run(
|
Command::new("git").current_dir(&build_path).arg("pull"),
|
||||||
Command::new("/run/current-system/sw/bin/git")
|
)?);
|
||||||
.current_dir(&build_path)
|
let commits = logging_run(Command::new("git").current_dir(&build_path).args([
|
||||||
.arg("pull"),
|
"log",
|
||||||
)
|
"--format=%H",
|
||||||
.output()?,
|
"origin",
|
||||||
);
|
]))?;
|
||||||
// Run `cargo aoc bench`
|
let binding = String::from_utf8_lossy(&commits.output.stdout).into_owned();
|
||||||
output.push(
|
let mut unknown_commits: Vec<_> = binding
|
||||||
logging_run(
|
.lines()
|
||||||
Command::new("cargo")
|
.filter(|commit| !commits_root.join(commit).exists())
|
||||||
.current_dir(&build_path)
|
.collect();
|
||||||
.arg("aoc")
|
unknown_commits.reverse();
|
||||||
.arg("bench"),
|
output.push(commits);
|
||||||
)
|
info!("Need to bench commits: {:?}", unknown_commits);
|
||||||
.output()?,
|
for commit in unknown_commits {
|
||||||
);
|
match bench_at_commit(commit, &build_path, &target_path) {
|
||||||
|
Ok(outputs) => {
|
||||||
|
output.extend(outputs);
|
||||||
|
File::create(commits_root.join(commit))?;
|
||||||
|
}
|
||||||
|
Err(err) => error!("Failed to bench {}@{}: {}", repo, commit, err),
|
||||||
|
}
|
||||||
|
}
|
||||||
// Copy files from `target/` to serving directory
|
// Copy files from `target/` to serving directory
|
||||||
let bench_path = build_path.join("target/aoc/aoc-autobench/target/criterion");
|
let bench_path = target_path.join("criterion");
|
||||||
copy_dir_all(bench_path, config.www_root.join(repo))?;
|
info!("Copying {} -> {}", bench_path.display(), www_root.display());
|
||||||
|
copy_dir_all(bench_path, www_root)?;
|
||||||
let response = output
|
let response = output
|
||||||
.iter()
|
.iter()
|
||||||
.map(|o| {
|
.map(|ts| format!("{}", format_task_status(ts)))
|
||||||
format!(
|
|
||||||
"Status {}:\nStdout: {}\nStderr: {}",
|
|
||||||
o.status,
|
|
||||||
String::from_utf8_lossy(&o.stdout),
|
|
||||||
String::from_utf8_lossy(&o.stderr)
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.join("\n");
|
.join("\n");
|
||||||
info!("{}", response);
|
info!("{}", response);
|
||||||
@ -138,6 +227,6 @@ fn rocket() -> _ {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
rocket::build()
|
rocket::build()
|
||||||
.mount("/", routes![index, get_reload, post_reload])
|
.mount("/", routes![index, get_reload, post_reload])
|
||||||
.register("/", catchers![http500])
|
//.register("/", catchers![http500])
|
||||||
.attach(AdHoc::config::<Config>())
|
.attach(AdHoc::config::<Config>())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user