From c08918ad6f85a710d4571f4ed3b7de2ce0bcce3e Mon Sep 17 00:00:00 2001 From: kjuulh Date: Fri, 4 Aug 2023 18:32:09 +0200 Subject: [PATCH 1/5] feat(json-edit): added json-edit to update some json content with next global version Signed-off-by: kjuulh --- Cargo.lock | 13 ++++ Cargo.toml | 2 + cr | 1 + .../cuddle-please-release-strategy/Cargo.toml | 31 ++++++++++ .../src/json_edit.rs | 57 ++++++++++++++++++ .../cuddle-please-release-strategy/src/lib.rs | 6 ++ .../src/strategy.rs | 59 +++++++++++++++++++ .../tests/json_edit.rs | 50 ++++++++++++++++ 8 files changed, 219 insertions(+) create mode 100644 cr create mode 100644 crates/cuddle-please-release-strategy/Cargo.toml create mode 100644 crates/cuddle-please-release-strategy/src/json_edit.rs create mode 100644 crates/cuddle-please-release-strategy/src/lib.rs create mode 100644 crates/cuddle-please-release-strategy/src/strategy.rs create mode 100644 crates/cuddle-please-release-strategy/tests/json_edit.rs diff --git a/Cargo.lock b/Cargo.lock index 838f373..60f6edf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -520,6 +520,19 @@ dependencies = [ "url", ] +[[package]] +name = "cuddle-please-release-strategy" +version = "0.1.0" +dependencies = [ + "anyhow", + "pretty_assertions", + "semver", + "serde", + "tempdir", + "tracing", + "tracing-test", +] + [[package]] name = "dagger-core" version = "0.2.11" diff --git a/Cargo.toml b/Cargo.toml index f50eef8..16bc1a1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "crates/cuddle-please-frontend", "crates/cuddle-please-commands", "crates/cuddle-please-misc", + "crates/cuddle-please-release-strategy", "ci" ] resolver = "2" @@ -13,6 +14,7 @@ cuddle-please = { path = "crates/cuddle-please", version = "0.1.0" } cuddle-please-frontend = { path = "crates/cuddle-please-frontend", version = "0.1.0" } cuddle-please-commands = { path = "crates/cuddle-please-commands", version = "0.1.0" } cuddle-please-misc = { path = "crates/cuddle-please-misc", version = "0.1.0" } +cuddle-please-release-strategy = { path = "crates/cuddle-please-release-strategy", version = "0.1.0" } anyhow = { version = "1.0.72" } tracing = { version = "0.1", features = ["log"] } diff --git a/cr b/cr new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/cr @@ -0,0 +1 @@ + diff --git a/crates/cuddle-please-release-strategy/Cargo.toml b/crates/cuddle-please-release-strategy/Cargo.toml new file mode 100644 index 0000000..8869eac --- /dev/null +++ b/crates/cuddle-please-release-strategy/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "cuddle-please-release-strategy" +description = "A release-please inspired release manager tool, built on top of cuddle, but also useful standalone, cuddle-please supports, your ci of choice, as well as gitea, github" +repository = "https://git.front.kjuulh.io/kjuulh/cuddle-please" +version = "0.1.0" +edition = "2021" +readme = "../../README.md" +license-file = "../../LICENSE" +publishable = true + +[dependencies] +anyhow.workspace = true +tracing.workspace = true +serde.workspace = true +semver.workspace = true + +[dev-dependencies] +tracing-test = { workspace = true, features = ["no-env-filter"] } +pretty_assertions.workspace = true +tempdir.workspace = true + +[features] +rust-workspace = [] +rust-crate = [] +toml-edit = [] +json-edit = [] +yaml-edit = [] + +default = [ + "json-edit" +] diff --git a/crates/cuddle-please-release-strategy/src/json_edit.rs b/crates/cuddle-please-release-strategy/src/json_edit.rs new file mode 100644 index 0000000..b3a7d51 --- /dev/null +++ b/crates/cuddle-please-release-strategy/src/json_edit.rs @@ -0,0 +1,57 @@ +use std::path::Path; + +use anyhow::Context; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub struct JsonEditOptions { + pub jq: String, +} + +impl JsonEditOptions { + pub fn execute(&self, path: &Path, next_version: impl AsRef) -> anyhow::Result<()> { + let next_version = next_version.as_ref(); + + let jq_query = self.jq.replace("%%version%%", next_version); + + if !path.exists() { + anyhow::bail!("could not find file at: {}", path.display()); + } + + if let Ok(metadata) = path.metadata() { + if !metadata.is_file() { + anyhow::bail!("{} is not a file", path.display()); + } + } + + let abs_path = path.canonicalize().context(anyhow::anyhow!( + "could not get absolute path from {}", + path.display() + ))?; + + let output = std::process::Command::new("jq") + .arg(format!("{}", jq_query)) + .arg( + abs_path + .to_str() + .ok_or(anyhow::anyhow!("path contains non utf-8 chars"))?, + ) + .output() + .context(anyhow::anyhow!("failed to run jq on file"))?; + + if !output.status.success() { + let err_content = std::str::from_utf8(output.stderr.as_slice())?; + anyhow::bail!("failed to run jq with output: {}", err_content); + } + + let edited_json_content = std::str::from_utf8(output.stdout.as_slice())?; + tracing::trace!( + new_content = edited_json_content, + file = &abs_path.display().to_string(), + "applied jq to file" + ); + std::fs::write(abs_path, edited_json_content)?; + + Ok(()) + } +} diff --git a/crates/cuddle-please-release-strategy/src/lib.rs b/crates/cuddle-please-release-strategy/src/lib.rs new file mode 100644 index 0000000..8ff1005 --- /dev/null +++ b/crates/cuddle-please-release-strategy/src/lib.rs @@ -0,0 +1,6 @@ +#[cfg(feature = "json-edit")] +mod json_edit; +mod strategy; + +#[cfg(feature = "json-edit")] +pub use json_edit::JsonEditOptions; diff --git a/crates/cuddle-please-release-strategy/src/strategy.rs b/crates/cuddle-please-release-strategy/src/strategy.rs new file mode 100644 index 0000000..1db872b --- /dev/null +++ b/crates/cuddle-please-release-strategy/src/strategy.rs @@ -0,0 +1,59 @@ +use std::path::PathBuf; + +use serde::{Deserialize, Serialize}; + +pub struct UpdateOptions { + next_version: String, + global_changelog: String, +} + +pub type Projects = Vec; + +#[derive(Clone, Debug, Deserialize, Serialize)] +pub struct Project { + path: Option, + r#type: ProjectType, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(tag = "type")] +pub enum ProjectType { + #[cfg(feature = "rust-workspace")] + #[serde(alias = "rust_workspace")] + RustWorkspace, + #[cfg(feature = "rust-crate")] + #[serde(alias = "json_edit")] + RustCrate, + #[cfg(feature = "toml-edit")] + #[serde(alias = "toml_edit")] + TomlEdit, + #[cfg(feature = "yaml-edit")] + #[serde(alias = "yaml_edit")] + YamlEdit, + #[cfg(feature = "json-edit")] + #[serde(alias = "json_edit")] + JsonEdit, +} + +impl Project { + pub fn new(path: Option, r#type: ProjectType) -> Self { + Self { path, r#type } + } + + pub fn execute(&self, options: &UpdateOptions) -> anyhow::Result<()> { + match self.r#type { + #[cfg(feature = "rust-workspace")] + ProjectType::RustWorkspace => todo!(), + #[cfg(feature = "rust-crate")] + ProjectType::RustCrate => todo!(), + #[cfg(feature = "toml-edit")] + ProjectType::TomlEdit => todo!(), + #[cfg(feature = "yaml-edit")] + ProjectType::YamlEdit => todo!(), + #[cfg(feature = "json-edit")] + ProjectType::JsonEdit => todo!(), + } + + Ok(()) + } +} diff --git a/crates/cuddle-please-release-strategy/tests/json_edit.rs b/crates/cuddle-please-release-strategy/tests/json_edit.rs new file mode 100644 index 0000000..a9a92b8 --- /dev/null +++ b/crates/cuddle-please-release-strategy/tests/json_edit.rs @@ -0,0 +1,50 @@ +use tracing_test::traced_test; + +#[test] +#[traced_test] +#[cfg(feature = "json-edit")] +pub fn test_can_update_version_in_jq() { + use cuddle_please_release_strategy::JsonEditOptions; + + let dir = tempdir::TempDir::new("can_update_version_in_jq").unwrap(); + let dir_path = dir.path(); + let json_file = dir_path.join("some-test.json"); + let initial_content = r#"{ + "some": { + "nested": [ + { + "structure": { + "version": "v1.0.1" + } + } + ] + } +} +"#; + + let expected = r#"{ + "some": { + "nested": [ + { + "structure": { + "version": "v1.0.2" + } + } + ] + } +} +"#; + + std::fs::write(&json_file, initial_content).unwrap(); + let actual_file = std::fs::read_to_string(&json_file).unwrap(); + pretty_assertions::assert_eq!(initial_content, actual_file); + + let edit_options = JsonEditOptions { + jq: r#".some.nested[].structure.version="%%version%%""#.into(), + }; + + edit_options.execute(&json_file, "v1.0.2").unwrap(); + + let actual_file = std::fs::read_to_string(&json_file).unwrap(); + pretty_assertions::assert_eq!(expected, &actual_file); +} -- 2.49.1 From 19dd0ff636d9529b42b6684de082f89b324daf0a Mon Sep 17 00:00:00 2001 From: kjuulh Date: Fri, 4 Aug 2023 18:36:03 +0200 Subject: [PATCH 2/5] fix(ci): without token Signed-off-by: kjuulh --- ci/src/main.rs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/ci/src/main.rs b/ci/src/main.rs index 0be3103..6d5f8d5 100644 --- a/ci/src/main.rs +++ b/ci/src/main.rs @@ -306,12 +306,6 @@ mod please_release { std::env::var("CUDDLE_PLEASE_TOKEN")? ), ]) - .with_exec(vec![ - "git", - "config", - "http.extraheader", - "'Authorization: token b52c18cab8a95d33f34b0d081440f77a2b156886'", - ]) .with_exec(vec![ "cuddle-please", "release", @@ -605,6 +599,7 @@ pub async fn get_base_debian_image( "pkg-config", "openssl", "git", + "jq", ]); Ok(base_image) @@ -725,7 +720,9 @@ pub async fn base_rust_image( .as_ref() .unwrap_or(&"rustlang/rust:nightly".into()), ) - .with_exec(vec!["rustup", "target", "add", rust_target]); + .with_exec(vec!["rustup", "target", "add", rust_target]) + .with_exec(vec!["apt", "update"]) + .with_exec(vec!["apt", "install", "-y", "jq"]); let target_cache = client.cache_volume(format!("rust_target_{}", profile)); let mut build_options = vec!["cargo", "build", "--target", rust_target, "-p", bin_name]; -- 2.49.1 From ff2b59dd029ad36a1c0b8d3869c7e6096b4fea33 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Fri, 4 Aug 2023 18:37:32 +0200 Subject: [PATCH 3/5] chore(json-edit): clarify errors Signed-off-by: kjuulh --- crates/cuddle-please-release-strategy/src/json_edit.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/cuddle-please-release-strategy/src/json_edit.rs b/crates/cuddle-please-release-strategy/src/json_edit.rs index b3a7d51..07aa492 100644 --- a/crates/cuddle-please-release-strategy/src/json_edit.rs +++ b/crates/cuddle-please-release-strategy/src/json_edit.rs @@ -37,7 +37,9 @@ impl JsonEditOptions { .ok_or(anyhow::anyhow!("path contains non utf-8 chars"))?, ) .output() - .context(anyhow::anyhow!("failed to run jq on file"))?; + .context(anyhow::anyhow!( + "failed to run jq on file, jq may not be installed or query was invalid" + ))?; if !output.status.success() { let err_content = std::str::from_utf8(output.stderr.as_slice())?; -- 2.49.1 From 2919ca9a042ad71d71ac52148bed39a8cfa1ffef Mon Sep 17 00:00:00 2001 From: kjuulh Date: Fri, 4 Aug 2023 18:38:11 +0200 Subject: [PATCH 4/5] chore: remove cr Signed-off-by: kjuulh --- cr | 1 - 1 file changed, 1 deletion(-) delete mode 100644 cr diff --git a/cr b/cr deleted file mode 100644 index 8b13789..0000000 --- a/cr +++ /dev/null @@ -1 +0,0 @@ - -- 2.49.1 From 56b44cf2e259151e597097527ae223f3718587a3 Mon Sep 17 00:00:00 2001 From: kjuulh Date: Fri, 4 Aug 2023 18:56:43 +0200 Subject: [PATCH 5/5] fix(json-edit): with actual arg instead of stupid str replace Signed-off-by: kjuulh --- crates/cuddle-please-release-strategy/src/json_edit.rs | 7 ++++--- crates/cuddle-please-release-strategy/tests/json_edit.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/crates/cuddle-please-release-strategy/src/json_edit.rs b/crates/cuddle-please-release-strategy/src/json_edit.rs index 07aa492..9398b9d 100644 --- a/crates/cuddle-please-release-strategy/src/json_edit.rs +++ b/crates/cuddle-please-release-strategy/src/json_edit.rs @@ -12,8 +12,6 @@ impl JsonEditOptions { pub fn execute(&self, path: &Path, next_version: impl AsRef) -> anyhow::Result<()> { let next_version = next_version.as_ref(); - let jq_query = self.jq.replace("%%version%%", next_version); - if !path.exists() { anyhow::bail!("could not find file at: {}", path.display()); } @@ -30,7 +28,10 @@ impl JsonEditOptions { ))?; let output = std::process::Command::new("jq") - .arg(format!("{}", jq_query)) + .arg("--arg") + .arg("version") + .arg(next_version) + .arg(&self.jq) .arg( abs_path .to_str() diff --git a/crates/cuddle-please-release-strategy/tests/json_edit.rs b/crates/cuddle-please-release-strategy/tests/json_edit.rs index a9a92b8..069966f 100644 --- a/crates/cuddle-please-release-strategy/tests/json_edit.rs +++ b/crates/cuddle-please-release-strategy/tests/json_edit.rs @@ -40,7 +40,7 @@ pub fn test_can_update_version_in_jq() { pretty_assertions::assert_eq!(initial_content, actual_file); let edit_options = JsonEditOptions { - jq: r#".some.nested[].structure.version="%%version%%""#.into(), + jq: r#".some.nested[].structure.version=$version"#.into(), }; edit_options.execute(&json_file, "v1.0.2").unwrap(); -- 2.49.1