From 80fcfd86f83ef3162f6568bcbc7083832874744d Mon Sep 17 00:00:00 2001 From: marcof Date: Mon, 1 Sep 2025 11:22:42 +0200 Subject: [PATCH 1/3] (feat) helm charts --- Cargo.toml | 1 + src/project.rs | 80 +++++++++++++++++++++++++++++++++++++++++++ tests/test_project.rs | 36 +++++++++++++++++++ 3 files changed, 117 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index ee36816..18c679d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,7 @@ env_logger = "0.10" chrono = "0.4" colored = "2.0" dialoguer = "0.11" +serde_yaml = "0.9.34" [dev-dependencies] tempfile = "3.8" diff --git a/src/project.rs b/src/project.rs index 60a1201..3e3b400 100644 --- a/src/project.rs +++ b/src/project.rs @@ -63,8 +63,88 @@ pub fn detect_project(dir: &str) -> Result> { return Ok(Box::new(RubyProject::new(gemfile_path))); } + let chart_path = dir_path.join("Chart.yaml"); + if chart_path.exists() { + debug!("Detected Helm chart project (Chart.yaml)"); + return Ok(Box::new(HelmChartProject::new(chart_path))); + } + Err(anyhow!("No supported project files found in {}", dir)) } +// Helm chart project (Chart.yaml) +pub struct HelmChartProject { + path: PathBuf, +} + +impl HelmChartProject { + pub fn new(path: PathBuf) -> Self { + Self { path } + } + + fn update_version_internal(&self, version: &Version, dry_run: bool) -> Result { + // Read the original content + let content = fs::read_to_string(&self.path).context("Failed to read Chart.yaml")?; + + let old_version = self.get_version()?; + + // Using regex for targeted replacement that preserves all formatting + let re = regex::Regex::new(r#"(?m)^(version:\s)([^\s]+)(.*)$"#).unwrap(); + let new_content = re.replace(&content, |caps: ®ex::Captures| { + format!("{}{}{}", &caps[1], version, &caps[3]) + }); + + let diff = format!( + "{} Chart.yaml:\n version: {} → {}", + if dry_run { "Would update" } else { "Updated" }, + old_version, + version + ); + + if !dry_run { + fs::write(&self.path, new_content.as_bytes()) + .context("Failed to write updated Chart.yaml")?; + } + + Ok(diff) + } +} + +impl Project for HelmChartProject { + fn get_version(&self) -> Result { + let content = fs::read_to_string(&self.path).context("Failed to read Chart.yaml")?; + + let yaml: serde_yaml::Value = + serde_yaml::from_str(&content).context("Failed to parse Chart.yaml")?; + + let version_str = yaml["version"] + .as_str() + .ok_or_else(|| anyhow!("No version field found in Chart.yaml"))?; + + Version::parse(version_str).context("Failed to parse version from Chart.yaml") + } + + fn update_version(&self, version: &Version) -> Result<()> { + self.update_version_internal(version, false)?; + Ok(()) + } + + fn dry_run_update(&self, version: &Version) -> Result { + self.update_version_internal(version, true) + } + + fn get_file_path(&self) -> &Path { + &self.path + } + + fn get_files_to_commit(&self) -> Vec { + vec![self.path.clone()] + } + + fn get_package_manager_update_command(&self) -> Option { + // Helm doesn't have a package manager update command + None + } +} // Node.js project (package.json) pub struct NodeProject { diff --git a/tests/test_project.rs b/tests/test_project.rs index 883a9c8..64bd195 100644 --- a/tests/test_project.rs +++ b/tests/test_project.rs @@ -40,6 +40,42 @@ fn test_node_project_detection() -> Result<()> { Ok(()) } +#[test] +fn test_chart_project_detection() -> Result<()> { + let temp_dir = tempdir()?; + let package_json_path = temp_dir.path().join("Chart.yaml"); + + // Create a minimal package.json + fs::write( + &package_json_path, + r#" +apiVersion: v2 +name: Helm Chart +description: A Helm chart for Kubernetes +type: application +version: 1.2.3 +appVersion: "Release-1.0.0" +"#, + )?; + + // Detect project type + let project = detect_project(temp_dir.path().to_str().unwrap())?; + + // Verify detected version + let version = project.get_version()?; + assert_eq!(version, Version::new(1, 2, 3)); + + // Test update + let new_version = Version::new(2, 0, 0); + project.update_version(&new_version)?; + + // Verify updated version + let updated_content = fs::read_to_string(&package_json_path)?; + assert!(updated_content.contains(r#"version: 2.0.0"#)); + + Ok(()) +} + #[test] fn test_python_project_detection() -> Result<()> { let temp_dir = tempdir()?; From 290066704b8acf37ebc608af663aa7f8a1c18332 Mon Sep 17 00:00:00 2001 From: marcof Date: Mon, 1 Sep 2025 11:44:32 +0200 Subject: [PATCH 2/3] (doc) added supported projects --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 73e04cb..6799a01 100644 --- a/README.md +++ b/README.md @@ -146,6 +146,7 @@ For more detailed development instructions, see [DEVELOPMENT.md](docs/DEVELOPMEN - Runs go mod tidy to update dependencies - **Ruby**: Updates versions in gemspec and version.rb files - Runs bundle install to update dependencies +- **Helm charts** Updates version in the Chart.yaml file ## Acknowledgements From 181471236568d766ff5ea40485da1bd43330a997 Mon Sep 17 00:00:00 2001 From: marcof Date: Mon, 1 Sep 2025 14:05:14 +0200 Subject: [PATCH 3/3] review comments --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6799a01..c1f120c 100644 --- a/README.md +++ b/README.md @@ -146,7 +146,7 @@ For more detailed development instructions, see [DEVELOPMENT.md](docs/DEVELOPMEN - Runs go mod tidy to update dependencies - **Ruby**: Updates versions in gemspec and version.rb files - Runs bundle install to update dependencies -- **Helm charts** Updates version in the Chart.yaml file +- **Helm charts**: Updates version in the Chart.yaml file ## Acknowledgements