You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/03/31 10:05:16 UTC
(opendal) 01/01: fix(dev): sync release package versions
This is an automated email from the ASF dual-hosted git repository.
xuanwo pushed a commit to branch xuanwo/release-tooling-sync
in repository https://gitbox.apache.org/repos/asf/opendal.git
commit 463b019a4dd68bbd28b7da607080188b12c5d2b6
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Tue Mar 31 18:03:58 2026 +0800
fix(dev): sync release package versions
---
dev/src/release/package.rs | 300 +++++++++++++++++++++++++++++++++++++++++----
1 file changed, 276 insertions(+), 24 deletions(-)
diff --git a/dev/src/release/package.rs b/dev/src/release/package.rs
index 9fcbbe6b7..e90b46664 100644
--- a/dev/src/release/package.rs
+++ b/dev/src/release/package.rs
@@ -19,6 +19,7 @@ use crate::workspace_dir;
use semver::Version;
use std::path::{Path, PathBuf};
use std::str::FromStr;
+use toml_edit::{DocumentMut, Item, TableLike};
#[derive(Debug, Clone)]
pub struct Package {
@@ -65,7 +66,7 @@ pub fn all_packages() -> Vec<Package> {
// Integrations
let dav_server = make_package("integrations/dav-server", "0.7.0", vec![core.clone()]);
let object_store = make_package("integrations/object_store", "0.55.0", vec![core.clone()]);
- let parquet = make_package("integrations/parquet", "0.7.0", vec![core.clone()]);
+ let parquet = make_package("integrations/parquet", "0.8.0", vec![core.clone()]);
let unftp_sbe = make_package("integrations/unftp-sbe", "0.4.0", vec![core.clone()]);
// Binaries moved to separate repositories; no longer released from this repo
@@ -93,17 +94,25 @@ pub fn all_packages() -> Vec<Package> {
pub fn update_package_version(package: &Package) -> bool {
match package.name.as_str() {
- "core" => update_cargo_version(&package.path, &package.version),
- "integrations/dav-server" => update_cargo_version(&package.path, &package.version),
- "integrations/object_store" => update_cargo_version(&package.path, &package.version),
- "integrations/parquet" => update_cargo_version(&package.path, &package.version),
- "integrations/unftp-sbe" => update_cargo_version(&package.path, &package.version),
+ "core" => update_cargo_version(&package.path, &package.version, package.dependencies()),
+ "integrations/dav-server" => {
+ update_cargo_version(&package.path, &package.version, package.dependencies())
+ }
+ "integrations/object_store" => {
+ update_cargo_version(&package.path, &package.version, package.dependencies())
+ }
+ "integrations/parquet" => {
+ update_cargo_version(&package.path, &package.version, package.dependencies())
+ }
+ "integrations/unftp-sbe" => {
+ update_cargo_version(&package.path, &package.version, package.dependencies())
+ }
"bindings/c" => false, // C bindings has no version to update
"bindings/cpp" => false, // C++ bindings has no version to update
"bindings/lua" => false, // Lua bindings has no version to update
- "bindings/python" => update_cargo_version(&package.path, &package.version),
+ "bindings/python" => update_cargo_version(&package.path, &package.version, &[]),
"bindings/java" => update_maven_version(&package.path, &package.version),
"bindings/nodejs" => update_nodejs_version(&package.path, &package.version),
@@ -111,28 +120,148 @@ pub fn update_package_version(package: &Package) -> bool {
}
}
-fn update_cargo_version(path: &Path, version: &Version) -> bool {
+fn update_cargo_version(path: &Path, version: &Version, dependencies: &[Package]) -> bool {
let path = path.join("Cargo.toml");
let manifest = std::fs::read_to_string(&path).unwrap();
- let mut manifest = toml_edit::DocumentMut::from_str(manifest.as_str()).unwrap();
+ let mut manifest = DocumentMut::from_str(manifest.as_str()).unwrap();
+ let mut updated = update_manifest_version(&mut manifest, version, &path);
- let old_version = match manifest["package"]["version"].as_str() {
- Some(version) => Version::parse(version).unwrap(),
- None => panic!("missing version for package: {}", path.display()),
- };
+ for dependency in dependencies {
+ updated |= update_dependency_version(&mut manifest, dependency);
+ }
- if &old_version != version {
- manifest["package"]["version"] = toml_edit::value(version.to_string());
+ if updated {
std::fs::write(&path, manifest.to_string()).unwrap();
- println!(
- "updating version for package: {} from {} to {}",
- path.display(),
- old_version,
- version
- );
- true
- } else {
- false
+ }
+
+ updated
+}
+
+fn update_manifest_version(manifest: &mut DocumentMut, version: &Version, path: &Path) -> bool {
+ if let Some(old_version) = manifest["package"]["version"]
+ .as_str()
+ .map(Version::parse)
+ .transpose()
+ .unwrap()
+ {
+ if &old_version != version {
+ manifest["package"]["version"] = toml_edit::value(version.to_string());
+ println!(
+ "updating version for package: {} from {} to {}",
+ path.display(),
+ old_version,
+ version
+ );
+ return true;
+ }
+
+ return false;
+ }
+
+ if let Some(old_version) = manifest["workspace"]["package"]["version"]
+ .as_str()
+ .map(Version::parse)
+ .transpose()
+ .unwrap()
+ {
+ if &old_version != version {
+ manifest["workspace"]["package"]["version"] = toml_edit::value(version.to_string());
+ println!(
+ "updating version for package: {} from {} to {}",
+ path.display(),
+ old_version,
+ version
+ );
+ return true;
+ }
+
+ return false;
+ }
+
+ panic!("missing version for package: {}", path.display());
+}
+
+fn update_dependency_version(manifest: &mut DocumentMut, dependency: &Package) -> bool {
+ let Some(crate_name) = dependency.crate_name() else {
+ return false;
+ };
+
+ update_dependency_version_in_table(manifest.as_table_mut(), crate_name, dependency)
+}
+
+fn update_dependency_version_in_table(
+ table: &mut dyn TableLike,
+ crate_name: &str,
+ dependency: &Package,
+) -> bool {
+ let mut updated = false;
+
+ for table_name in ["dependencies", "dev-dependencies", "build-dependencies"] {
+ let Some(dependencies) = table.get_mut(table_name).and_then(Item::as_table_like_mut) else {
+ continue;
+ };
+
+ updated |= update_dependency_version_in_dependencies(dependencies, crate_name, dependency);
+ }
+
+ let Some(targets) = table.get_mut("target").and_then(Item::as_table_like_mut) else {
+ return updated;
+ };
+
+ for (_, target) in targets.iter_mut() {
+ let Some(target) = target.as_table_like_mut() else {
+ continue;
+ };
+ updated |= update_dependency_version_in_table(target, crate_name, dependency);
+ }
+
+ updated
+}
+
+fn update_dependency_version_in_dependencies(
+ dependencies: &mut dyn TableLike,
+ crate_name: &str,
+ dependency: &Package,
+) -> bool {
+ let Some(entry) = dependencies.get_mut(crate_name) else {
+ return false;
+ };
+ let Some(entry) = entry.as_table_like_mut() else {
+ return false;
+ };
+ let Some("../../core") = entry.get("path").and_then(Item::as_str) else {
+ return false;
+ };
+ let Some(value) = entry.get_mut("version") else {
+ return false;
+ };
+
+ let old_version = match value.as_str() {
+ Some(version) => match Version::parse(version) {
+ Ok(version) => version,
+ Err(_) => return false,
+ },
+ None => panic!("missing dependency version for crate: {crate_name}"),
+ };
+
+ if old_version == dependency.version {
+ return false;
+ }
+
+ *value = toml_edit::value(dependency.version.to_string());
+ println!(
+ "updating dependency version for crate: {} from {} to {}",
+ crate_name, old_version, dependency.version
+ );
+ true
+}
+
+impl Package {
+ fn crate_name(&self) -> Option<&'static str> {
+ match self.name.as_str() {
+ "core" => Some("opendal"),
+ _ => None,
+ }
}
}
@@ -193,3 +322,126 @@ fn update_nodejs_version(path: &Path, version: &Version) -> bool {
updated
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ fn temp_test_dir(name: &str) -> PathBuf {
+ let nanos = std::time::SystemTime::now()
+ .duration_since(std::time::UNIX_EPOCH)
+ .unwrap()
+ .as_nanos();
+ std::env::temp_dir().join(format!("odev-package-{name}-{nanos}"))
+ }
+
+ #[test]
+ fn parquet_release_version_matches_manifest() {
+ let parquet = all_packages()
+ .into_iter()
+ .find(|package| package.name() == "integrations/parquet")
+ .unwrap();
+
+ assert_eq!(parquet.version, Version::parse("0.8.0").unwrap());
+ }
+
+ #[test]
+ fn update_manifest_version_supports_workspace_package_version() {
+ let mut manifest = DocumentMut::from_str(
+ r#"
+[workspace.package]
+version = "0.55.0"
+
+[package]
+name = "opendal"
+version = { workspace = true }
+"#,
+ )
+ .unwrap();
+
+ let updated = update_manifest_version(
+ &mut manifest,
+ &Version::parse("0.56.0").unwrap(),
+ Path::new("core/Cargo.toml"),
+ );
+
+ assert!(updated);
+ assert_eq!(
+ manifest["workspace"]["package"]["version"].as_str(),
+ Some("0.56.0")
+ );
+ assert!(!manifest["package"]["version"].is_str());
+ }
+
+ #[test]
+ fn update_dependency_version_only_touches_release_managed_core_constraints() {
+ let dir = temp_test_dir("dependency-sync");
+ std::fs::create_dir_all(&dir).unwrap();
+
+ let manifest_path = dir.join("Cargo.toml");
+ std::fs::write(
+ &manifest_path,
+ r#"[package]
+name = "demo"
+version = "0.8.0"
+
+[dependencies]
+opendal = { version = "0.55.0", path = "../../core" }
+serde = "1"
+
+[dev-dependencies]
+opendal = { version = "0.55.0", path = "../../core", features = ["services-memory"] }
+
+[build-dependencies]
+opendal = { version = ">=0", path = "../../core" }
+
+[target.'cfg(unix)'.dependencies]
+opendal = { version = "0.55.0", path = "../../core" }
+
+[target.'cfg(windows)'.dependencies]
+opendal = { version = "0.55.0", path = "../core" }
+"#,
+ )
+ .unwrap();
+
+ let dependency = Package {
+ name: "core".to_string(),
+ path: PathBuf::from("core"),
+ version: Version::parse("0.56.0").unwrap(),
+ dependencies: vec![],
+ };
+
+ let updated = update_cargo_version(
+ dir.as_path(),
+ &Version::parse("0.8.0").unwrap(),
+ &[dependency],
+ );
+ assert!(updated);
+
+ let manifest = std::fs::read_to_string(&manifest_path).unwrap();
+ let manifest = DocumentMut::from_str(&manifest).unwrap();
+
+ assert_eq!(
+ manifest["dependencies"]["opendal"]["version"].as_str(),
+ Some("0.56.0")
+ );
+ assert_eq!(
+ manifest["dev-dependencies"]["opendal"]["version"].as_str(),
+ Some("0.56.0")
+ );
+ assert_eq!(
+ manifest["target"]["cfg(unix)"]["dependencies"]["opendal"]["version"].as_str(),
+ Some("0.56.0")
+ );
+ assert_eq!(
+ manifest["build-dependencies"]["opendal"]["version"].as_str(),
+ Some(">=0")
+ );
+ assert_eq!(
+ manifest["target"]["cfg(windows)"]["dependencies"]["opendal"]["version"].as_str(),
+ Some("0.55.0")
+ );
+
+ std::fs::remove_dir_all(dir).unwrap();
+ }
+}