From 399aab39b330677a293c2e1ca9366dd88db3d4bd Mon Sep 17 00:00:00 2001 From: hosted-fornet Date: Wed, 4 Sep 2024 20:15:42 -0700 Subject: [PATCH] build: provide useful errors when process_lib versions mismatch --- Cargo.lock | 36 +++++++++++++++++++++++ Cargo.toml | 1 + src/build/mod.rs | 75 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 112 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0f6d5419..468ee72c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1012,6 +1012,38 @@ dependencies = [ "serde", ] +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo-platform" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" +dependencies = [ + "serde", +] + +[[package]] +name = "cargo_metadata" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" +dependencies = [ + "camino", + "cargo-platform", + "semver 1.0.23", + "serde", + "serde_json", + "thiserror", +] + [[package]] name = "cc" version = "1.1.13" @@ -2074,6 +2106,7 @@ dependencies = [ "alloy-sol-types", "anyhow", "base64 0.21.7", + "cargo_metadata", "clap", "color-eyre", "dirs", @@ -3220,6 +3253,9 @@ name = "semver" version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +dependencies = [ + "serde", +] [[package]] name = "semver-parser" diff --git a/Cargo.toml b/Cargo.toml index 1f029c7f..2b30fa56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -30,6 +30,7 @@ alloy = { version = "0.1.3", features = [ alloy-sol-macro = "0.7.6" alloy-sol-types = "0.7.6" base64 = "0.21" +cargo_metadata = "0.18" clap = { version = "4.4", features = ["cargo", "string"] } color-eyre = { version = "0.6", features = ["capture-spantrace"] } dirs = "5.0" diff --git a/src/build/mod.rs b/src/build/mod.rs index 9409c5ab..86c8710a 100644 --- a/src/build/mod.rs +++ b/src/build/mod.rs @@ -38,6 +38,7 @@ const KINODE_WIT_0_8_0_URL: &str = const WASI_VERSION: &str = "19.0.1"; // TODO: un-hardcode const DEFAULT_WORLD_0_7_0: &str = "process"; const DEFAULT_WORLD_0_8_0: &str = "process-v0"; +const KINODE_PROCESS_LIB_CRATE_NAME: &str = "kinode_process_lib"; #[derive(Debug, Clone, Serialize, Deserialize)] struct CargoFile { @@ -333,6 +334,78 @@ fn file_with_extension_exists(dir: &Path, extension: &str) -> bool { false } +#[instrument(level = "trace", skip_all)] +fn parse_version_from_url(url: &str) -> Result { + let re = regex::Regex::new(r"\?tag=v([0-9]+\.[0-9]+\.[0-9]+)$").unwrap(); + if let Some(caps) = re.captures(url) { + if let Some(version) = caps.get(1) { + return Ok(semver::VersionReq::parse(&format!("^{}", version.as_str()))?); + } + } + Err(eyre!("No valid version found in the URL")) +} + +#[instrument(level = "trace", skip_all)] +fn find_crate_versions( + crate_name: &str, + packages: &HashMap, +) -> Result>> { + let mut versions = HashMap::new(); + + // Iterate over all packages + for package in packages.values() { + // Check each dependency of the package + for dependency in &package.dependencies { + if dependency.name == crate_name { + let version = if dependency.req != semver::VersionReq::default() { + dependency.req.clone() + } else { + if let Some(ref source) = dependency.source { + parse_version_from_url(source)? + } else { + semver::VersionReq::default() + } + }; + versions + .entry(version) + .or_insert_with(Vec::new) + .push(package.name.clone()); + } + } + } + + Ok(versions) +} + +#[instrument(level = "trace", skip_all)] +fn check_process_lib_version(cargo_toml_path: &Path) -> Result<()> { + let metadata = cargo_metadata::MetadataCommand::new() + .manifest_path(cargo_toml_path) + .exec()?; + let packages: HashMap = metadata + .packages + .iter() + .map(|package| (package.id.clone(), package)) + .collect(); + let versions = find_crate_versions(KINODE_PROCESS_LIB_CRATE_NAME, &packages)?; + if versions.len() > 1 { + return Err( + eyre!( + "Found different versions of {} in different crates:{}", + KINODE_PROCESS_LIB_CRATE_NAME, + versions.iter().fold(String::new(), |s, (version, crates)| { + format!("{s}\n{version}\t{crates:?}") + }) + ) + .with_suggestion(|| format!( + "Set all {} versions to be the same to avoid hard-to-debug errors.", + KINODE_PROCESS_LIB_CRATE_NAME, + )) + ); + } + Ok(()) +} + #[instrument(level = "trace", skip_all)] fn get_most_recent_modified_time( dir: &Path, @@ -1256,6 +1329,8 @@ pub async fn execute( fs::create_dir_all(package_dir.join("target"))?; fs::write(&build_with_features_path, features)?; + check_process_lib_version(&package_dir.join("Cargo.toml"))?; + let ui_dir = package_dir.join("ui"); if !ui_dir.exists() { if ui_only {