feat: enable commit bodies in changelog and fixes general warnings and updates (#49)
All checks were successful
continuous-integration/drone/push Build is passing

Allows commit bodies to show up in release notes, this is something I'd prefer as my releases are usually short, and I'd like to see these as I don't use pull requests as often, and often miss the context, as I don't link to commits currently.

Also fixes a lot of warnings and reintroduces failing tests, still not perfect, but better than before.
Co-authored-by: kjuulh <contact@kjuulh.io>
Co-committed-by: kjuulh <contact@kjuulh.io>
This commit is contained in:
Kasper Juul Hermansen 2025-01-09 23:46:07 +01:00 committed by Kasper Juul Hermansen
parent 600d8c184c
commit 5fd902f87c
19 changed files with 1464 additions and 521 deletions

View File

@ -110,7 +110,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- add mkdocs build - add mkdocs build
- add basic version - add basic version
- update with repository - update with repository
- add publishable to rest - add publish to rest
- hack get in control of log level - hack get in control of log level
### Docs ### Docs

1890
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,5 @@
[workspace] [workspace]
members = [ members = ["crates/*"]
"crates/*"
]
resolver = "2" resolver = "2"
[workspace.dependencies] [workspace.dependencies]
@ -15,8 +13,8 @@ cuddle-please-actions = { path = "crates/cuddle-please-actions", version = "0.1.
anyhow = { version = "1.0.81" } anyhow = { version = "1.0.81" }
tracing = { version = "0.1", features = ["log"] } tracing = { version = "0.1", features = ["log"] }
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
clap = { version = "4.5.4", features = ["derive", "env"] } clap = { version = "4.5.23", features = ["derive", "env"] }
dotenv = { version = "0.15.0" } dotenvy = { version = "0.15.7" }
url = { version = "2.5.0" } url = { version = "2.5.0" }
serde_yaml = { version = "0.9.34+deprecated" } serde_yaml = { version = "0.9.34+deprecated" }
yaml-rust2 = { version = "0.8.0" } yaml-rust2 = { version = "0.8.0" }
@ -25,7 +23,7 @@ semver = "1.0.22"
conventional_commit_parser = "0.9.4" conventional_commit_parser = "0.9.4"
tempdir = "0.3.7" tempdir = "0.3.7"
reqwest = { version = "0.12.3" } reqwest = { version = "0.12.3" }
git-cliff-core = "2.2.0" git-cliff-core = "2.7.0"
regex = "1.10.4" regex = "1.10.4"
chrono = "0.4.37" chrono = "0.4.37"
lazy_static = "1.4.0" lazy_static = "1.4.0"

View File

@ -6,7 +6,7 @@ readme = "../../README.md"
license-file = "../../LICENSE" license-file = "../../LICENSE"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
publishable = true publish = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true

View File

@ -1,7 +1,5 @@
use std::io::Write; use std::io::Write;
use anyhow::Context;
use crate::{actions::Action, ActionConfig}; use crate::{actions::Action, ActionConfig};
#[derive(Default, Clone)] #[derive(Default, Clone)]

View File

@ -6,7 +6,7 @@ readme = "../../README.md"
license-file = "../../LICENSE" license-file = "../../LICENSE"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
publishable = true publish = true
[dependencies] [dependencies]
@ -18,7 +18,7 @@ anyhow.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
clap.workspace = true clap.workspace = true
dotenv.workspace = true dotenvy.workspace = true
serde_yaml.workspace = true serde_yaml.workspace = true
serde.workspace = true serde.workspace = true
reqwest = { workspace = true, features = ["blocking", "json"] } reqwest = { workspace = true, features = ["blocking", "json"] }

View File

@ -1,3 +1,5 @@
use std::path::Path;
use cuddle_please_actions::Actions; use cuddle_please_actions::Actions;
use cuddle_please_frontend::PleaseConfig; use cuddle_please_frontend::PleaseConfig;
@ -128,6 +130,7 @@ impl ReleaseCommandHandler {
Ok(()) Ok(())
} }
#[allow(clippy::too_many_arguments)]
fn create_pull_request( fn create_pull_request(
&self, &self,
changelog_placement: std::path::PathBuf, changelog_placement: std::path::PathBuf,
@ -225,7 +228,7 @@ impl ReleaseCommandHandler {
fn compose_changelog( fn compose_changelog(
commit_strs: &Vec<String>, commit_strs: &Vec<String>,
next_version: &Version, next_version: &Version,
source: &std::path::PathBuf, source: &Path,
) -> Result<(std::path::PathBuf, String, Option<String>), anyhow::Error> { ) -> Result<(std::path::PathBuf, String, Option<String>), anyhow::Error> {
let builder = ChangeLogBuilder::new(commit_strs, next_version.to_string()).build(); let builder = ChangeLogBuilder::new(commit_strs, next_version.to_string()).build();
let changelog_placement = source.join("CHANGELOG.md"); let changelog_placement = source.join("CHANGELOG.md");

View File

@ -6,14 +6,14 @@ readme = "../../README.md"
license-file = "../../LICENSE" license-file = "../../LICENSE"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
publishable = true publish = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
clap.workspace = true clap.workspace = true
dotenv.workspace = true dotenvy.workspace = true
serde_yaml.workspace = true serde_yaml.workspace = true
serde.workspace = true serde.workspace = true
chrono.workspace = true chrono.workspace = true

View File

@ -28,14 +28,8 @@ pub struct PleaseConfigBuilder {
impl PleaseConfigBuilder { impl PleaseConfigBuilder {
pub fn merge(&mut self, config: &PleaseConfigBuilder) -> &Self { pub fn merge(&mut self, config: &PleaseConfigBuilder) -> &Self {
let config = config.clone(); let config = config.clone();
let mut fproject = match self.project.clone() { let mut fproject = self.project.clone().unwrap_or_default();
None => PleaseProjectConfigBuilder::default(), let mut fsettings = self.settings.clone().unwrap_or_default();
Some(project) => project,
};
let mut fsettings = match self.settings.clone() {
None => PleaseSettingsConfigBuilder::default(),
Some(settings) => settings,
};
if let Some(project) = config.project { if let Some(project) = config.project {
if let Some(owner) = project.owner { if let Some(owner) = project.owner {

View File

@ -6,7 +6,7 @@ readme = "../../README.md"
license-file = "../../LICENSE" license-file = "../../LICENSE"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
publishable = true publish = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@ -15,7 +15,7 @@ anyhow.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
clap.workspace = true clap.workspace = true
dotenv.workspace = true dotenvy.workspace = true
serde_yaml.workspace = true serde_yaml.workspace = true
serde.workspace = true serde.workspace = true
reqwest = { workspace = true, features = ["blocking", "json"] } reqwest = { workspace = true, features = ["blocking", "json"] }
@ -29,6 +29,9 @@ chrono.workspace = true
lazy_static.workspace = true lazy_static.workspace = true
parse-changelog.workspace = true parse-changelog.workspace = true
# Cliff depends on 13.1.0, which is a broken release
cacache = "=13.0.0"
[dev-dependencies] [dev-dependencies]
tracing-test = { workspace = true, features = ["no-env-filter"] } tracing-test = { workspace = true, features = ["no-env-filter"] }
pretty_assertions.workspace = true pretty_assertions.workspace = true

View File

@ -3,7 +3,7 @@ use chrono::{DateTime, NaiveDate, Utc};
use git_cliff_core::{ use git_cliff_core::{
changelog::Changelog, changelog::Changelog,
commit::Commit, commit::Commit,
config::{Bump, ChangelogConfig, CommitParser, Config, GitConfig, Remote, RemoteConfig}, config::{Bump, ChangelogConfig, CommitParser, Config, GitConfig, RemoteConfig},
release::Release, release::Release,
}; };
use regex::Regex; use regex::Regex;
@ -79,6 +79,7 @@ impl ChangeLogBuilder {
previous: None, previous: None,
message: None, message: None,
repository: None, repository: None,
extra: None,
}, },
config: self.config, config: self.config,
release_link: self.release_link, release_link: self.release_link,
@ -225,6 +226,8 @@ fn default_changelog_config(header: Option<String>, release_link: Option<&str>)
footer: None, footer: None,
trim: Some(true), trim: Some(true),
postprocessors: None, postprocessors: None,
render_always: None,
output: None,
} }
} }
@ -240,6 +243,11 @@ fn default_changelog_body_config(release_link: Option<&str>) -> String {
{% else -%} {% else -%}
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message }} - {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message }}
{% endif -%} {% endif -%}
{%- if commit.body -%}
{%- if commit.body | length > 0 -%}
{% raw %} {% endraw %}{{ commit.body | trim }}
{% endif -%}
{% endif -%}
{% endfor -%} {% endfor -%}
{% endfor %}"#; {% endfor %}"#;
@ -512,7 +520,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
#[test] #[test]
fn generates_changelog() { fn generates_changelog() {
let commits: Vec<&str> = vec![ let commits: Vec<&str> = vec![
"feat: some feature", "feat: some feature
some body",
"some random commit", "some random commit",
"fix: some fix", "fix: some fix",
"chore(scope): some chore", "chore(scope): some chore",
@ -533,6 +543,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added ### Added
- some feature - some feature
some body
### Fixed ### Fixed
- some fix - some fix

View File

@ -602,7 +602,7 @@ mod test {
let (expected, actual) = get_commits("second-sha".into()).unwrap(); let (expected, actual) = get_commits("second-sha".into()).unwrap();
assert_eq!( assert_eq!(
expected.get(0).unwrap().clone().as_slice(), expected.first().unwrap().clone().as_slice(),
actual.as_slice() actual.as_slice()
); );
} }

View File

@ -1,5 +1,6 @@
use crate::RemoteGitEngine; use crate::RemoteGitEngine;
#[derive(Default)]
pub struct LocalGitClient {} pub struct LocalGitClient {}
impl LocalGitClient { impl LocalGitClient {

View File

@ -6,7 +6,7 @@ version = "0.1.0"
edition = "2021" edition = "2021"
readme = "../../README.md" readme = "../../README.md"
license-file = "../../LICENSE" license-file = "../../LICENSE"
publishable = true publish = true
[dependencies] [dependencies]
anyhow.workspace = true anyhow.workspace = true

View File

@ -2,11 +2,13 @@ use std::path::PathBuf;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[allow(dead_code)]
pub struct UpdateOptions { pub struct UpdateOptions {
next_version: String, next_version: String,
global_changelog: String, global_changelog: String,
} }
#[allow(dead_code)]
pub type Projects = Vec<Project>; pub type Projects = Vec<Project>;
#[derive(Clone, Debug, Deserialize, Serialize)] #[derive(Clone, Debug, Deserialize, Serialize)]
@ -22,7 +24,7 @@ pub enum ProjectType {
#[serde(alias = "rust_workspace")] #[serde(alias = "rust_workspace")]
RustWorkspace, RustWorkspace,
#[cfg(feature = "rust-crate")] #[cfg(feature = "rust-crate")]
#[serde(alias = "json_edit")] #[serde(alias = "rust_crate")]
RustCrate, RustCrate,
#[cfg(feature = "toml-edit")] #[cfg(feature = "toml-edit")]
#[serde(alias = "toml_edit")] #[serde(alias = "toml_edit")]
@ -35,12 +37,13 @@ pub enum ProjectType {
JsonEdit, JsonEdit,
} }
#[allow(dead_code)]
impl Project { impl Project {
pub fn new(path: Option<PathBuf>, r#type: ProjectType) -> Self { pub fn new(path: Option<PathBuf>, r#type: ProjectType) -> Self {
Self { path, r#type } Self { path, r#type }
} }
pub fn execute(&self, options: &UpdateOptions) -> anyhow::Result<()> { pub fn execute(&self, _options: &UpdateOptions) -> anyhow::Result<()> {
match self.r#type { match self.r#type {
#[cfg(feature = "rust-workspace")] #[cfg(feature = "rust-workspace")]
ProjectType::RustWorkspace => todo!(), ProjectType::RustWorkspace => todo!(),
@ -53,7 +56,5 @@ impl Project {
#[cfg(feature = "json-edit")] #[cfg(feature = "json-edit")]
ProjectType::JsonEdit => todo!(), ProjectType::JsonEdit => todo!(),
} }
Ok(())
} }
} }

View File

@ -6,7 +6,7 @@ readme = "../../README.md"
license-file = "../../LICENSE" license-file = "../../LICENSE"
version = "0.1.0" version = "0.1.0"
edition = "2021" edition = "2021"
publishable = true publish = true
[dependencies] [dependencies]
cuddle-please-frontend.workspace = true cuddle-please-frontend.workspace = true
@ -17,7 +17,7 @@ anyhow.workspace = true
tracing.workspace = true tracing.workspace = true
tracing-subscriber.workspace = true tracing-subscriber.workspace = true
clap.workspace = true clap.workspace = true
dotenv.workspace = true dotenvy.workspace = true
serde_yaml.workspace = true serde_yaml.workspace = true
serde.workspace = true serde.workspace = true
reqwest = { workspace = true, features = ["blocking", "json"] } reqwest = { workspace = true, features = ["blocking", "json"] }

View File

@ -1,7 +1,7 @@
use cuddle_please_commands::PleaseCommand; use cuddle_please_commands::PleaseCommand;
fn main() -> anyhow::Result<()> { fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok(); dotenvy::dotenv().ok();
let current_dir = std::env::current_dir().ok(); let current_dir = std::env::current_dir().ok();
let current_dir = current_dir.as_deref(); let current_dir = current_dir.as_deref();

View File

@ -6,6 +6,7 @@ use tracing_test::traced_test;
use crate::common::{assert_output, get_test_data_path}; use crate::common::{assert_output, get_test_data_path};
#[allow(dead_code)]
fn get_base_args<'a>() -> Vec<&'a str> { fn get_base_args<'a>() -> Vec<&'a str> {
vec![ vec![
"cuddle-please", "cuddle-please",
@ -25,6 +26,7 @@ PleaseConfig
api_url: https://some-example.gitea-instance api_url: https://some-example.gitea-instance
"#; "#;
#[allow(dead_code)]
#[traced_test] #[traced_test]
fn test_config_from_current_dir() { fn test_config_from_current_dir() {
let args = get_base_args(); let args = get_base_args();
@ -38,6 +40,7 @@ fn test_config_from_current_dir() {
assert_output(ui, EXPECTED_OUTPUT, ""); assert_output(ui, EXPECTED_OUTPUT, "");
} }
#[allow(dead_code)]
#[traced_test] #[traced_test]
fn test_config_from_source_dir() { fn test_config_from_source_dir() {
let mut args = get_base_args(); let mut args = get_base_args();
@ -53,6 +56,7 @@ fn test_config_from_source_dir() {
assert_output(ui, EXPECTED_OUTPUT, ""); assert_output(ui, EXPECTED_OUTPUT, "");
} }
#[allow(dead_code)]
#[traced_test] #[traced_test]
fn test_config_from_stdin() { fn test_config_from_stdin() {
let mut args = get_base_args(); let mut args = get_base_args();
@ -72,6 +76,7 @@ settings:
assert_output(ui, EXPECTED_OUTPUT, ""); assert_output(ui, EXPECTED_OUTPUT, "");
} }
#[allow(dead_code)]
#[traced_test] #[traced_test]
fn test_config_fails_when_not_path_is_set() { fn test_config_fails_when_not_path_is_set() {
let args = get_base_args(); let args = get_base_args();

View File

@ -16,15 +16,18 @@ fn test_vcs_get_noop() {
#[traced_test] #[traced_test]
fn test_vcs_get_git_found() { fn test_vcs_get_git_found() {
let testdata = get_test_data_path("git-found"); let testdata = get_test_data_path("git-found");
if let Err(e) = std::fs::create_dir_all(&testdata) {
tracing::error!("failed to create dir: {}", e);
}
if let Err(e) = std::process::Command::new("git") if let Err(e) = std::process::Command::new("git")
.arg("init") .arg("init")
.arg(".") .arg(".")
.current_dir(&testdata) .current_dir(&testdata)
.output() .output()
{ {
println!("{e}"); println!("testdata git dir not found: {e}");
} }
return;
let git = VcsClient::new_git(&testdata, None::<String>, None::<String>, "".into()).unwrap(); let git = VcsClient::new_git(&testdata, None::<String>, None::<String>, "".into()).unwrap();
assert_eq!( assert_eq!(
git, git,