mirror of
https://github.com/serai-dex/serai.git
synced 2025-04-23 06:28:14 +00:00
Only rebuild Docker images when their source has been modified
This commit is contained in:
parent
818215b570
commit
c26beae0f9
2 changed files with 100 additions and 13 deletions
tests/docker
|
@ -12,3 +12,6 @@ publish = false
|
|||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustdoc-args = ["--cfg", "docsrs"]
|
||||
|
||||
[dependencies]
|
||||
chrono = "0.4"
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
use std::{
|
||||
sync::{Mutex, OnceLock},
|
||||
collections::HashMap,
|
||||
env,
|
||||
collections::{HashSet, HashMap},
|
||||
time::SystemTime,
|
||||
path::PathBuf,
|
||||
fs, env,
|
||||
process::Command,
|
||||
};
|
||||
|
||||
static BUILT: OnceLock<Mutex<HashMap<String, bool>>> = OnceLock::new();
|
||||
|
@ -15,20 +18,101 @@ pub fn build(name: String) {
|
|||
}
|
||||
|
||||
// Else, hold the lock while we build
|
||||
let mut path = env::current_exe().unwrap();
|
||||
path.pop();
|
||||
assert!(path.as_path().ends_with("deps"));
|
||||
path.pop();
|
||||
assert!(path.as_path().ends_with("debug"));
|
||||
path.pop();
|
||||
assert!(path.as_path().ends_with("target"));
|
||||
path.pop();
|
||||
path.push("deploy");
|
||||
let mut repo_path = env::current_exe().unwrap();
|
||||
repo_path.pop();
|
||||
assert!(repo_path.as_path().ends_with("deps"));
|
||||
repo_path.pop();
|
||||
assert!(repo_path.as_path().ends_with("debug"));
|
||||
repo_path.pop();
|
||||
assert!(repo_path.as_path().ends_with("target"));
|
||||
repo_path.pop();
|
||||
|
||||
let mut deploy_path = repo_path.clone();
|
||||
deploy_path.push("deploy");
|
||||
|
||||
// If this Docker image was created after this repo was last edited, return here
|
||||
// This should have better performance than Docker and allows running while offline
|
||||
if let Ok(res) = Command::new("docker")
|
||||
.arg("inspect")
|
||||
.arg("-f")
|
||||
.arg("{{ .Metadata.LastTagTime }}")
|
||||
.arg(format!("serai-dev-{name}"))
|
||||
.output()
|
||||
{
|
||||
let created_time = SystemTime::from(
|
||||
chrono::DateTime::parse_and_remainder(
|
||||
String::from_utf8(res.stdout).expect("docker had non-utf8 output").trim(),
|
||||
"%F %T.%f %z",
|
||||
)
|
||||
.expect("docker formatted last tag time unexpectedly")
|
||||
.0,
|
||||
);
|
||||
|
||||
let mut dockerfile_path = repo_path.join("deploy");
|
||||
if HashSet::from(["bitcoin", "ethereum", "monero"]).contains(name.as_str()) {
|
||||
dockerfile_path = dockerfile_path.join("coins");
|
||||
}
|
||||
dockerfile_path = dockerfile_path.join(&name).join("Dockerfile");
|
||||
|
||||
// For all services, if the Dockerfile was edited after the image was built we should rebuild
|
||||
let mut last_modified =
|
||||
fs::metadata(dockerfile_path).ok().and_then(|meta| meta.modified().ok());
|
||||
|
||||
// Check any additionally specified paths
|
||||
let meta = |path: PathBuf| (path.clone(), fs::metadata(path));
|
||||
let mut metadatas = match name.as_str() {
|
||||
"bitcoin" => vec![],
|
||||
"monero" => vec![],
|
||||
"message-queue" => vec![
|
||||
meta(repo_path.join("common")),
|
||||
meta(repo_path.join("crypto")),
|
||||
meta(repo_path.join("substrate").join("primitives")),
|
||||
meta(repo_path.join("message-queue")),
|
||||
],
|
||||
"processor" => vec![
|
||||
meta(repo_path.join("common")),
|
||||
meta(repo_path.join("crypto")),
|
||||
meta(repo_path.join("coins")),
|
||||
meta(repo_path.join("substrate")),
|
||||
meta(repo_path.join("message-queue")),
|
||||
meta(repo_path.join("processor")),
|
||||
],
|
||||
_ => panic!("building unrecognized docker image"),
|
||||
};
|
||||
|
||||
while !metadatas.is_empty() {
|
||||
if let (path, Ok(metadata)) = metadatas.pop().unwrap() {
|
||||
if metadata.is_file() {
|
||||
if let Ok(modified) = metadata.modified() {
|
||||
if modified >
|
||||
last_modified
|
||||
.expect("got when source was last modified yet not when the Dockerfile was")
|
||||
{
|
||||
last_modified = Some(modified);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for entry in fs::read_dir(path.clone()).expect("couldn't read directory") {
|
||||
metadatas
|
||||
.push(meta(path.join(entry.expect("couldn't access item in directory").file_name())));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(last_modified) = last_modified {
|
||||
if last_modified < created_time {
|
||||
println!("{} was built after the most recent source code edits, assuming built.", name);
|
||||
built_lock.insert(name, true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
println!("Building {}...", &name);
|
||||
|
||||
assert!(std::process::Command::new("docker")
|
||||
.current_dir(path)
|
||||
assert!(Command::new("docker")
|
||||
.current_dir(deploy_path)
|
||||
.arg("compose")
|
||||
.arg("build")
|
||||
.arg(&name)
|
||||
|
|
Loading…
Reference in a new issue