Skip to content

Commit 56d612b

Browse files
committed
feat(release): Add context-awareness and workspace dependency updates
- Add is_multi_crate_workspace() to detect workspace vs standalone crate - Skip workspace dependency updates in standalone/split repos - Add update_workspace_dependencies() function for multi-crate workspaces - Properly handle both inline and table TOML dependency formats Tested: - Monorepo: Updates workspace Cargo.toml correctly - Split repo: Skips workspace updates (no workspace present) - Fixes Issue #5 (context-awareness) - Fixes Issue #2 (workspace dependency updates)
1 parent fd1fdfe commit 56d612b

File tree

1 file changed

+67
-0
lines changed

1 file changed

+67
-0
lines changed

crates/cargo-rail/src/commands/release/prepare.rs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,33 @@ pub fn run_release_prepare(crate_name: Option<&str>, apply: bool, no_changelog:
126126
println!();
127127
}
128128

129+
// Update workspace dependencies (only in multi-crate workspaces)
130+
if !plan.crates.is_empty() && is_multi_crate_workspace(&metadata) {
131+
let workspace_toml_path = workspace_root.join("Cargo.toml");
132+
if workspace_toml_path.exists() {
133+
// Build version map
134+
let version_map: HashMap<String, String> = plan
135+
.crates
136+
.iter()
137+
.map(|c| (c.name.clone(), c.next_version.clone()))
138+
.collect();
139+
140+
let (old_workspace, new_workspace) = update_workspace_dependencies(&workspace_toml_path, &version_map)?;
141+
142+
if old_workspace != new_workspace {
143+
println!("📌 Updating workspace dependencies");
144+
if apply {
145+
fs::write(&workspace_toml_path, &new_workspace)
146+
.map_err(|e| anyhow::anyhow!("Failed to write workspace Cargo.toml: {}", e))?;
147+
println!(" ✅ Updated workspace Cargo.toml");
148+
} else {
149+
show_diff("Cargo.toml (workspace)", &old_workspace, &new_workspace);
150+
}
151+
println!();
152+
}
153+
}
154+
}
155+
129156
// Summary
130157
if !apply {
131158
println!("💡 This was a dry-run. Use --apply to make these changes.");
@@ -154,6 +181,11 @@ fn load_workspace_metadata() -> RailResult<cargo_metadata::Metadata> {
154181
})?)
155182
}
156183

184+
/// Check if we're in a multi-crate workspace (vs standalone crate)
185+
fn is_multi_crate_workspace(metadata: &cargo_metadata::Metadata) -> bool {
186+
metadata.workspace_members.len() > 1
187+
}
188+
157189
/// Bump version in a Cargo.toml file
158190
fn bump_version_in_manifest(path: &Path, new_version: &str) -> RailResult<(String, String)> {
159191
let old_content =
@@ -207,5 +239,40 @@ fn show_diff(filename: &str, old: &str, new: &str) {
207239
println!();
208240
}
209241

242+
/// Update workspace dependencies in the root Cargo.toml
243+
fn update_workspace_dependencies(path: &Path, version_map: &HashMap<String, String>) -> RailResult<(String, String)> {
244+
let old_content =
245+
fs::read_to_string(path).map_err(|e| anyhow::anyhow!("Failed to read {}: {}", path.display(), e))?;
246+
247+
let mut doc = old_content
248+
.parse::<DocumentMut>()
249+
.map_err(|e| anyhow::anyhow!("Failed to parse TOML: {}", e))?;
250+
251+
// Update workspace.dependencies
252+
if let Some(workspace) = doc.get_mut("workspace") &&
253+
let Some(workspace_table) = workspace.as_table_mut() &&
254+
let Some(dependencies) = workspace_table.get_mut("dependencies") &&
255+
let Some(deps_table) = dependencies.as_table_mut()
256+
{
257+
for (crate_name, new_version) in version_map {
258+
if let Some(dep) = deps_table.get_mut(crate_name) {
259+
// Handle both inline table and table format
260+
if let Some(dep_table) = dep.as_inline_table_mut() {
261+
if dep_table.contains_key("version") {
262+
dep_table.insert("version", new_version.clone().into());
263+
}
264+
} else if let Some(dep_table) = dep.as_table_mut() {
265+
if dep_table.contains_key("version") {
266+
dep_table["version"] = toml_edit::value(new_version);
267+
}
268+
}
269+
}
270+
}
271+
}
272+
273+
let new_content = doc.to_string();
274+
Ok((old_content, new_content))
275+
}
276+
210277
// Note: Version bumping logic is tested in src/commands/release/semver.rs
211278
// Changelog generation is tested in src/commands/release/changelog.rs

0 commit comments

Comments
 (0)