Compare commits
8 Commits
fix/initia
...
feat/with-
Author | SHA1 | Date | |
---|---|---|---|
b711258790
|
|||
56b44cf2e2
|
|||
2919ca9a04
|
|||
ff2b59dd02
|
|||
19dd0ff636
|
|||
c08918ad6f
|
|||
19e7adfedb
|
|||
27cb31f433 |
50
Cargo.lock
generated
50
Cargo.lock
generated
@@ -201,6 +201,38 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
|
||||
|
||||
[[package]]
|
||||
name = "camino"
|
||||
version = "1.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo-platform"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cfa25e60aea747ec7e1124f238816749faa93759c6ff5b31f1ccdda137f4479"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cargo_metadata"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7daec1a2a2129eeba1644b220b4647ec537b0b5d4bfd6876fcc5a540056b592"
|
||||
dependencies = [
|
||||
"camino",
|
||||
"cargo-platform",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.79"
|
||||
@@ -520,6 +552,21 @@ dependencies = [
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cuddle-please-release-strategy"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_metadata",
|
||||
"pretty_assertions",
|
||||
"semver",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"tempdir",
|
||||
"tracing",
|
||||
"tracing-test",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dagger-core"
|
||||
version = "0.2.11"
|
||||
@@ -2184,6 +2231,9 @@ name = "semver"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0293b4b29daaf487284529cc2f5675b8e57c61f70167ba415a463651fd6a918"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
|
@@ -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"] }
|
||||
@@ -21,6 +23,7 @@ clap = { version = "4.3.19", features = ["derive", "env"] }
|
||||
dotenv = { version = "0.15.0" }
|
||||
url = { version = "2.4.0" }
|
||||
serde_yaml = { version = "0.9.25" }
|
||||
serde_json = { version = "*" }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
semver = "1.0.18"
|
||||
conventional_commit_parser = "0.9.4"
|
||||
|
13
README.md
13
README.md
@@ -36,20 +36,9 @@ See docs for more information about installation and some such
|
||||
|
||||
## Checklist
|
||||
|
||||
### 0.2 Milestone
|
||||
|
||||
- [x] Add docs
|
||||
- [ ] Add asciinema
|
||||
- [x] Create docker image
|
||||
- [x] Add examples
|
||||
- [x] Fx drone config
|
||||
- [x] Releaser
|
||||
- [x] On main/master
|
||||
- [ ] tbd...
|
||||
|
||||
### 0.3 Milestone
|
||||
|
||||
- [ ] Fix: 0.0.0 -> **v**0.0.0
|
||||
- [x] Fix: 0.0.0 -> **v**0.0.0
|
||||
- [ ] Add release strategies
|
||||
- [ ] Add reporter for PR and Repositories
|
||||
- [ ] Add inquire for missing values when needed (when not running in ci or have a proper tty)
|
||||
|
@@ -9,7 +9,6 @@ use clap::ValueEnum;
|
||||
|
||||
use dagger_sdk::Platform;
|
||||
use dagger_sdk::QueryContainerOpts;
|
||||
use futures::StreamExt;
|
||||
|
||||
use crate::please_release::run_release_please;
|
||||
|
||||
@@ -306,12 +305,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 +598,7 @@ pub async fn get_base_debian_image(
|
||||
"pkg-config",
|
||||
"openssl",
|
||||
"git",
|
||||
"jq",
|
||||
]);
|
||||
|
||||
Ok(base_image)
|
||||
@@ -725,7 +719,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];
|
||||
|
34
crates/cuddle-please-release-strategy/Cargo.toml
Normal file
34
crates/cuddle-please-release-strategy/Cargo.toml
Normal file
@@ -0,0 +1,34 @@
|
||||
[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
|
||||
cargo_metadata = "0.17.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tracing-test = { workspace = true, features = ["no-env-filter"] }
|
||||
pretty_assertions.workspace = true
|
||||
tempdir.workspace = true
|
||||
serde_json.workspace = true
|
||||
|
||||
[features]
|
||||
rust-workspace = []
|
||||
rust-crate = []
|
||||
toml-edit = []
|
||||
json-edit = []
|
||||
yaml-edit = []
|
||||
|
||||
default = [
|
||||
"json-edit",
|
||||
"rust-workspace"
|
||||
]
|
60
crates/cuddle-please-release-strategy/src/json_edit.rs
Normal file
60
crates/cuddle-please-release-strategy/src/json_edit.rs
Normal file
@@ -0,0 +1,60 @@
|
||||
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<str>) -> anyhow::Result<()> {
|
||||
let next_version = next_version.as_ref();
|
||||
|
||||
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("--arg")
|
||||
.arg("version")
|
||||
.arg(next_version)
|
||||
.arg(&self.jq)
|
||||
.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, jq may not be installed or query was invalid"
|
||||
))?;
|
||||
|
||||
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(())
|
||||
}
|
||||
}
|
11
crates/cuddle-please-release-strategy/src/lib.rs
Normal file
11
crates/cuddle-please-release-strategy/src/lib.rs
Normal file
@@ -0,0 +1,11 @@
|
||||
#[cfg(feature = "json-edit")]
|
||||
mod json_edit;
|
||||
#[cfg(feature = "rust-workspace")]
|
||||
mod rust_workspace;
|
||||
mod strategy;
|
||||
|
||||
#[cfg(feature = "json-edit")]
|
||||
pub use json_edit::JsonEditOptions;
|
||||
|
||||
#[cfg(feature = "rust-workspace")]
|
||||
pub use rust_workspace::RustWorkspaceOptions;
|
72
crates/cuddle-please-release-strategy/src/rust_workspace.rs
Normal file
72
crates/cuddle-please-release-strategy/src/rust_workspace.rs
Normal file
@@ -0,0 +1,72 @@
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use anyhow::Context;
|
||||
use cargo_metadata::camino::{Utf8Path, Utf8PathBuf};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
fn lock_step_default() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct RustWorkspaceOptions {
|
||||
#[serde(default = "lock_step_default")]
|
||||
pub lock_step: bool,
|
||||
}
|
||||
|
||||
impl RustWorkspaceOptions {
|
||||
pub fn execute(&self, path: &Path, next_version: impl AsRef<str>) -> anyhow::Result<()> {
|
||||
let members = self.get_workspace(path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn get_workspace(&self, path: &Path) -> anyhow::Result<Vec<cargo_metadata::Package>> {
|
||||
let entries = std::fs::read_dir(path)
|
||||
.context(anyhow::anyhow!("could not read dir: {}", path.display()))?
|
||||
.flatten()
|
||||
.filter(|p| p.file_name().to_str().unwrap() == "Cargo.toml")
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let cargo_manifest_file = match entries.first() {
|
||||
Some(x) => x,
|
||||
None => anyhow::bail!("did not find any Cargo.toml in: {}", path.display()),
|
||||
};
|
||||
|
||||
let mut cmd = cargo_metadata::MetadataCommand::new();
|
||||
|
||||
let manifest = cmd
|
||||
.no_deps()
|
||||
.manifest_path(cargo_manifest_file.path())
|
||||
.exec()
|
||||
.context("could not parse manifest")?;
|
||||
|
||||
let members = manifest.workspace_members.iter().collect::<Vec<_>>();
|
||||
let workspace_members = manifest
|
||||
.packages
|
||||
.into_iter()
|
||||
.filter(|p| members.contains(&&p.id))
|
||||
.map(|mut p| {
|
||||
p.manifest_path = abs_path(&p.manifest_path);
|
||||
|
||||
for dependency in p.dependencies.iter_mut() {
|
||||
dependency.path = dependency.path.take().map(|path| abs_path(&path))
|
||||
}
|
||||
|
||||
p
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(workspace_members)
|
||||
}
|
||||
}
|
||||
|
||||
fn abs_path(path: &Utf8Path) -> Utf8PathBuf {
|
||||
match path.canonicalize_utf8() {
|
||||
Ok(path) => path,
|
||||
Err(e) => {
|
||||
tracing::debug!("failed to transform manifest_path into abs path: {}", path);
|
||||
path.to_path_buf()
|
||||
}
|
||||
}
|
||||
}
|
59
crates/cuddle-please-release-strategy/src/strategy.rs
Normal file
59
crates/cuddle-please-release-strategy/src/strategy.rs
Normal file
@@ -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<Project>;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub struct Project {
|
||||
path: Option<PathBuf>,
|
||||
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<PathBuf>, 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(())
|
||||
}
|
||||
}
|
50
crates/cuddle-please-release-strategy/tests/json_edit.rs
Normal file
50
crates/cuddle-please-release-strategy/tests/json_edit.rs
Normal file
@@ -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);
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
use cargo_metadata::{
|
||||
camino::{Utf8Path, Utf8PathBuf},
|
||||
Package,
|
||||
};
|
||||
use cuddle_please_release_strategy::RustWorkspaceOptions;
|
||||
use serde_json::json;
|
||||
use tracing_test::traced_test;
|
||||
|
||||
#[test]
|
||||
#[traced_test]
|
||||
fn test_can_read_manifest() {
|
||||
let temp = tempdir::TempDir::new("test_rust_workspace_can_read_manifest").unwrap();
|
||||
let temp_path = temp.path();
|
||||
|
||||
std::fs::write(
|
||||
temp_path.join("Cargo.toml"),
|
||||
r#"
|
||||
[workspace]
|
||||
members = [
|
||||
"nested"
|
||||
]
|
||||
|
||||
[workspace.dependencies]
|
||||
nested = { path = "nested" }
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
std::fs::create_dir_all(temp_path.join("nested")).unwrap();
|
||||
std::fs::write(
|
||||
temp_path.join("nested").join("Cargo.toml"),
|
||||
r#"
|
||||
[package]
|
||||
name = "nested"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
nested.workspace = true
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
std::fs::create_dir_all(temp_path.join("nested").join("src")).unwrap();
|
||||
std::fs::write(
|
||||
temp_path.join("nested").join("src").join("lib.rs"),
|
||||
r#"
|
||||
#[test]
|
||||
test () {}
|
||||
"#,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let options = RustWorkspaceOptions { lock_step: true };
|
||||
|
||||
let members = options.get_workspace(temp_path).unwrap();
|
||||
|
||||
assert!(!members.is_empty());
|
||||
let first = members.first().unwrap();
|
||||
pretty_assertions::assert_eq!("nested", &first.name);
|
||||
}
|
Reference in New Issue
Block a user