diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2023-04-29 15:23:53 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-29 15:23:53 +0000 |
commit | 3685081a27cad1e4a403b34450356c3401727f56 (patch) | |
tree | 5dd5fe036b0b5153067b185553d5a027941174aa | |
parent | e520d935d465ced66d16afabb3bfb60aff33912d (diff) | |
parent | 2df5f3be5767f31ec07be3a446164741cd6276ed (diff) |
Merge #230
230: Feature/import existing r=matthiasbeyer a=TheNeikos
Solves #224
Co-authored-by: Marcel Müller <neikos@neikos.email>
-rw-r--r-- | .changelogs/template.md | 3 | ||||
-rw-r--r-- | .changelogs/unreleased/2023-04-29T15_18_11_131678077.md | 5 | ||||
-rw-r--r-- | .changelogs/unreleased/2023-04-29T15_19_10_88832722.md | 7 | ||||
-rw-r--r-- | README.md | 26 | ||||
-rw-r--r-- | assets/default_template.handlebars.md | 3 | ||||
-rw-r--r-- | src/command/release_command.rs | 51 | ||||
-rw-r--r-- | src/main.rs | 21 | ||||
-rw-r--r-- | tests/init_command.rs | 18 | ||||
-rw-r--r-- | tests/release_command.rs | 89 |
9 files changed, 214 insertions, 9 deletions
diff --git a/.changelogs/template.md b/.changelogs/template.md index 3cf83f8..fe05a00 100644 --- a/.changelogs/template.md +++ b/.changelogs/template.md @@ -16,3 +16,6 @@ {{~ /each ~}} {{~ /each ~}} {{/if}} +{{#if this.suffix}} +{{this.suffix}} +{{/if}} diff --git a/.changelogs/unreleased/2023-04-29T15_18_11_131678077.md b/.changelogs/unreleased/2023-04-29T15_18_11_131678077.md new file mode 100644 index 0000000..f92438f --- /dev/null +++ b/.changelogs/unreleased/2023-04-29T15_18_11_131678077.md @@ -0,0 +1,5 @@ ++++ +subject = "Appending to generated changelogs can now be done through a suffix.md file in the changelogs directory." +type = "Feature" ++++ + diff --git a/.changelogs/unreleased/2023-04-29T15_19_10_88832722.md b/.changelogs/unreleased/2023-04-29T15_19_10_88832722.md new file mode 100644 index 0000000..c4d08fe --- /dev/null +++ b/.changelogs/unreleased/2023-04-29T15_19_10_88832722.md @@ -0,0 +1,7 @@ ++++ +subject = "The init subcommand now moves any existing CHANGELOG.md files to the suffix.md file" +type = "Feature" ++++ + +With this change, existing repositories will be able to keep their previous +CHANGELOG and use the generated file from now on. @@ -4,6 +4,23 @@ Changelog management tool for CLI. `cargo-changelog` is a merge-friendly changelog management utility. +## Getting Started + +⚠️ `cargo-changelog` is still in alpha and will change and evolve. Do not use it +unless you are ready to, potentially manually, upgrade configuration and/or +templates on a regular basis. + +With that out of the way, to get started with `cargo-changelog` is to install it, +and running `cargo changelog init`. + +If you are running this on a new project, you are good to go and can directly +start building and adding changelog entries. + +If you are planning to use `cargo-changelog` on an already ongoing project, +your old CHANGELOG.md will have moved to `.changelogs/suffix.md` and will be +appended to the generated changelog. Be sure to update it so that it can +seamlessly integrate with the generated one. + ## Usage `cargo-changelog` is a tool to generate and manage changelog entries. @@ -52,6 +69,15 @@ optional metadata fields to your changelog entries. You can also specify a template file that gets used when rendering your changelogs to your final `CHANGELOG.md` file. +### Suffix + +If you wish to add something to the CHANGELOG that gets appended to the end of +the file, you can create a `suffix.md` in your changelog directory (per default +`.changelogs`). + +This is also where the `cargo changelog init` moves your existing CHANGELOG.md +if you had one while running the command. + ## Current state This project is in pre-alpha. diff --git a/assets/default_template.handlebars.md b/assets/default_template.handlebars.md index fc99288..2b3002c 100644 --- a/assets/default_template.handlebars.md +++ b/assets/default_template.handlebars.md @@ -16,3 +16,6 @@ {{~ /each ~}} {{~ /each ~}} {{/if}} +{{#if this.suffix}} +{{this.suffix}} +{{/if}} diff --git a/src/command/release_command.rs b/src/command/release_command.rs index 436e25d..f9b5f80 100644 --- a/src/command/release_command.rs +++ b/src/command/release_command.rs @@ -31,7 +31,32 @@ impl crate::command::Command for ReleaseCommand { .join(config.template_path()); let template_source = std::fs::read_to_string(template_path)?; let template = crate::template::new_handlebars(&template_source)?; - let template_data = compute_template_data(load_release_files(workdir, config, self.all))?; + + let suffix_path = workdir.join(config.fragment_dir()).join("suffix.md"); + let suffix = match std::fs::read_to_string(&suffix_path) { + Ok(suffix) => Some(suffix), + Err(err) => { + match err.kind() { + std::io::ErrorKind::NotFound => { + // We don't want to spam the user for something they don't use + log::trace!( + "Did not find {}, not appending suffix", + suffix_path.display() + ) + } + _ => { + log::error!( + "Could not read suffix file at {}: {err}", + suffix_path.display() + ); + } + } + None + } + }; + + let template_data = + generate_template_data(load_release_files(workdir, config, self.all), suffix)?; let changelog_contents = template.render(crate::consts::INTERNAL_TEMPLATE_NAME, &template_data)?; @@ -117,6 +142,13 @@ fn load_release_files( }) } +/// The data sent to the handlebars template +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize, getset::Getters)] +pub struct TemplateData { + versions: Vec<VersionData>, + suffix: Option<String>, +} + /// Helper type for storing version associated with Fragments /// /// only used for handlebars templating @@ -128,9 +160,10 @@ pub struct VersionData { entries: Vec<Fragment>, } -fn compute_template_data( +fn generate_template_data( release_files: impl Iterator<Item = Result<(Option<semver::Version>, Fragment), Error>>, -) -> Result<HashMap<String, Vec<VersionData>>, Error> { + suffix: Option<String>, +) -> Result<TemplateData, Error> { let versions = { use itertools::Itertools; let mut hm = HashMap::new(); @@ -150,9 +183,10 @@ fn compute_template_data( .sorted_by(|va, vb| va.version.cmp(&vb.version)) }; - let mut hm: HashMap<String, Vec<VersionData>> = HashMap::new(); - hm.insert("versions".to_string(), versions.collect()); - Ok(hm) + Ok(TemplateData { + versions: versions.collect(), + suffix, + }) } #[cfg(test)] @@ -164,7 +198,7 @@ mod tests { #[test] fn test_template_data_is_sorted() { - let result = compute_template_data( + let result = generate_template_data( [ Ok(( Some(semver::Version::new(0, 2, 0)), @@ -190,12 +224,13 @@ mod tests { )), ] .into_iter(), + None, ); assert!(result.is_ok()); let result = result.unwrap(); - let versions = result.get("versions").unwrap(); + let versions = result.versions; assert_eq!(versions[0].version, "0.1.0"); assert_eq!(versions[1].version, "0.2.0"); } diff --git a/src/main.rs b/src/main.rs index d57e5f6..162c610 100644 --- a/src/main.rs +++ b/src/main.rs @@ -150,5 +150,24 @@ fn init(repo_workdir_path: PathBuf) -> miette::Result<()> { template_file .sync_all() .map_err(Error::from) - .into_diagnostic() + .into_diagnostic()?; + + let existing_changelog = repo_workdir_path.join("CHANGELOG.md"); + + if existing_changelog.exists() { + let suffix_path = repo_workdir_path + .join(crate::config::fragment_dir_default()) + .join("suffix.md"); + + std::fs::rename(existing_changelog, &suffix_path) + .map_err(Error::from) + .into_diagnostic()?; + + println!( + "Found an existing CHANGELOG.md, moved it to {}", + suffix_path.display() + ); + } + + Ok(()) } diff --git a/tests/init_command.rs b/tests/init_command.rs index 843caaf..9f17fa4 100644 --- a/tests/init_command.rs +++ b/tests/init_command.rs @@ -61,3 +61,21 @@ fn init_command_creates_default_template() { ); } } + +#[test] +fn init_command_creates_moves_existing_changelog() { + let temp_dir = tempfile::Builder::new() + .prefix("cargo-changelog") + .tempdir() + .unwrap(); + self::common::init_git(temp_dir.path()); + + std::fs::write(temp_dir.path().join("CHANGELOG.md"), "foobar").unwrap(); + + self::common::init_cargo_changelog(temp_dir.path()); + + let suffix_file_path = temp_dir.path().join(".changelogs").join("suffix.md"); + if !suffix_file_path.exists() { + panic!("Suffix file does not exist after `cargo-changelog init`"); + } +} diff --git a/tests/release_command.rs b/tests/release_command.rs index 24cad11..b8bf018 100644 --- a/tests/release_command.rs +++ b/tests/release_command.rs @@ -127,3 +127,92 @@ fn release_command_works_for_alpha_release() { assert!(changelog.contains("0.1.0-alpha.1")); assert!(changelog.contains("test text")); } + +#[test] +fn release_command_works_with_suffix() { + let temp_dir = tempfile::Builder::new() + .prefix("cargo-changelog") + .tempdir() + .unwrap(); + self::common::init_git(temp_dir.path()); + self::common::init_cargo(temp_dir.path(), "release_command_works_with_suffix"); + self::common::init_cargo_changelog(temp_dir.path()); + + self::common::cargo_changelog_new(temp_dir.path()) + .args([ + "--format=toml", + "--set", + "issue=123", + "--set", + "subject='Test subject'", + "--set", + "type=Misc", + ]) + .assert() + .success(); + + let unreleased_dir = temp_dir.path().join(".changelogs").join("unreleased"); + + let new_fragment_file_path = std::fs::read_dir(unreleased_dir) + .unwrap() + .into_iter() + .find(|rde| match rde { + Ok(de) => !de.path().ends_with(".gitkeep"), + Err(_) => true, + }) + .unwrap() + .unwrap(); + + let mut new_fragment_file = std::fs::OpenOptions::new() + .write(true) + .append(true) + .create(false) + .open(new_fragment_file_path.path()) + .unwrap(); + + writeln!(new_fragment_file).unwrap(); + writeln!(new_fragment_file, "test text").unwrap(); + new_fragment_file.sync_all().unwrap(); + drop(new_fragment_file); + + { + let suffix_path = temp_dir.path().join(".changelogs").join("suffix.md"); + + let mut suffix_file = std::fs::OpenOptions::new() + .write(true) + .create(true) + .open(suffix_path) + .unwrap(); + + writeln!(suffix_file, "this is the suffix part").unwrap(); + suffix_file.sync_all().unwrap(); + } + + Command::cargo_bin("cargo-changelog") + .unwrap() + .args(["generate", "custom", "0.1.0-alpha.1"]) + .current_dir(&temp_dir) + .assert() + .success(); + + Command::cargo_bin("cargo-changelog") + .unwrap() + .args(["release"]) + .current_dir(&temp_dir) + .assert() + .success(); + + let changelog_file_path = temp_dir.path().join("CHANGELOG.md"); + if !changelog_file_path.exists() { + panic!("Changelog does not exist"); + } + + if !changelog_file_path.is_file() { + panic!("Changelog is not a file"); + } + + let changelog = std::fs::read_to_string(changelog_file_path).unwrap(); + assert!(changelog.contains("0.1.0-alpha.1")); + assert!(changelog.contains("test text")); + assert!(changelog.contains("this is the suffix part")); +} |