Skip to content

Commit

Permalink
feat(changelog): make changelog.header a template (#697)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cyclonit committed Jun 17, 2024
1 parent dabe716 commit ea9841e
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 13 deletions.
31 changes: 31 additions & 0 deletions .github/fixtures/test-header-template/cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
[changelog]
# changelog header
header = """
# Changelog
{% for release in releases %}\
{% if release.version %}\
{% if release.previous.version %}\
<!--{{ release.previous.version }}..{{ release.version }}-->
{% endif %}\
{% else %}\
<!--{{ release.previous.version }}..HEAD-->
{% endif %}\
{% endfor %}\
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}]
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {% if commit.breaking %}[**breaking**] {% endif %}{{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
"""
# remove the leading and trailing whitespace from the templates
trim = true
16 changes: 16 additions & 0 deletions .github/fixtures/test-header-template/commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
set -e

GIT_COMMITTER_DATE="2021-01-23 01:23:45" git commit --allow-empty -m "feat: add feature 1"
GIT_COMMITTER_DATE="2021-01-23 01:23:45" git commit --allow-empty -m "feat: add feature 2"
git tag v0.1.0

GIT_COMMITTER_DATE="2021-01-23 01:23:46" git commit --allow-empty -m "fix: fix feature 1"
GIT_COMMITTER_DATE="2021-01-23 01:23:46" git commit --allow-empty -m "fix: fix feature 2"
git tag v0.2.0

GIT_COMMITTER_DATE="2021-01-23 01:23:47" git commit --allow-empty -m "feat: add footer"
git tag v3.0.0

GIT_COMMITTER_DATE="2021-01-23 01:23:47" git commit --allow-empty -m "test: footer"
GIT_COMMITTER_DATE="2021-01-23 01:23:47" git commit --allow-empty -m "perf: footer"
33 changes: 33 additions & 0 deletions .github/fixtures/test-header-template/expected.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Changelog
<!--v3.0.0..HEAD-->
<!--v0.2.0..v3.0.0-->
<!--v0.1.0..v0.2.0-->
## [unreleased]

### Perf

- Footer

### Test

- Footer

## [3.0.0]

### Feat

- Add footer

## [0.2.0]

### Fix

- Fix feature 1
- Fix feature 2

## [0.1.0]

### Feat

- Add feature 1
- Add feature 2
38 changes: 31 additions & 7 deletions git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use std::time::{
pub struct Changelog<'a> {
/// Releases that the changelog will contain.
pub releases: Vec<Release<'a>>,
header_template: Option<Template>,
body_template: Template,
footer_template: Option<Template>,
config: &'a Config,
Expand All @@ -41,6 +42,10 @@ impl<'a> Changelog<'a> {
let trim = config.changelog.trim.unwrap_or(true);
let mut changelog = Self {
releases,
header_template: match &config.changelog.header {
Some(header) => Some(Template::new(header.to_string(), trim)?),
None => None,
},
body_template: Template::new(
config
.changelog
Expand Down Expand Up @@ -420,16 +425,14 @@ impl<'a> Changelog<'a> {
serde_json::to_value(self.config.remote.clone())?,
);
#[cfg(feature = "github")]
let (github_commits, github_pull_requests) = if self.config.remote.github.is_set()
{
let (github_commits, github_pull_requests) = if self.config.remote.github.is_set() {
self.get_github_metadata()
.expect("Could not get github metadata")
} else {
(vec![], vec![])
};
#[cfg(feature = "gitlab")]
let (gitlab_commits, gitlab_merge_request) = if self.config.remote.gitlab.is_set()
{
let (gitlab_commits, gitlab_merge_request) = if self.config.remote.gitlab.is_set() {
self.get_gitlab_metadata()
.expect("Could not get gitlab metadata")
} else {
Expand Down Expand Up @@ -502,15 +505,30 @@ impl<'a> Changelog<'a> {
.postprocessors
.clone()
.unwrap_or_default();
if let Some(header) = &self.config.changelog.header {
let write_result = write!(out, "{header}");

let mut releases = self.releases.clone();

// render the header template
if let Some(header_template) = &self.header_template {
let write_result = writeln!(
out,
"{}",
header_template.render(
&Releases {
releases: &releases,
},
Some(&self.additional_context),
&postprocessors,
)?
);
if let Err(e) = write_result {
if e.kind() != std::io::ErrorKind::BrokenPipe {
return Err(e.into());
}
}
}
let mut releases = self.releases.clone();

// render the body template
for release in releases.iter_mut() {
let write_result = write!(
out,
Expand All @@ -527,6 +545,8 @@ impl<'a> Changelog<'a> {
}
}
}

// render the footer template
if let Some(footer_template) = &self.footer_template {
let write_result = writeln!(
out,
Expand All @@ -545,6 +565,7 @@ impl<'a> Changelog<'a> {
}
}
}

Ok(())
}

Expand Down Expand Up @@ -927,6 +948,7 @@ mod test {
assert_eq!(
String::from(
r#"# Changelog
## Release [v1.1.0] - 1970-01-01
Expand Down Expand Up @@ -1032,6 +1054,7 @@ chore(deps): fix broken deps
assert_eq!(
String::from(
r#"# Changelog
## Unreleased
### Bug Fixes
Expand Down Expand Up @@ -1135,6 +1158,7 @@ chore(deps): fix broken deps
changelog.generate(&mut out)?;
expect_test::expect![[r#"
# Changelog
## Unreleased
### Bug Fixes
Expand Down
15 changes: 9 additions & 6 deletions website/docs/configuration/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,26 @@ postprocessors = [{ pattern = "foo", replace = "bar"}]

<!-- {% endraw %} -->

See [templating](/docs/category/templating) for more detail.


### header

Header text that will be added to the beginning of the changelog.
Footer template that will be rendered and added to the beginning of the changelog.

The template context contains the full list of releases in the variable `releases`. See [templating](/docs/category/templating) for more details.

### body

Body template that represents a single release in the changelog.
Body template that will be rendered for each release in the changelog. For example, if the changelog contains 3 releases, it will be rendered 3 times, once for each release.

See [templating](/docs/category/templating) for more detail.
The template context contains one release in the variable `release`. See [templating](/docs/category/templating) for more detail.

### footer

Footer template that will be rendered and added to the end of the changelog.

The template context is the same as [`body`](#body) and contains all the releases instead of a single release.

For example, to get the list of releases, use the `{{ releases }}` variable in the template. To get information about a single release, iterate over this array and access the fields similar to [`body`](#body).
The template context contains the full list of releases in the variable `releases`. See [templating](/docs/category/templating) for more details.

See [Keep a Changelog configuration](/docs/templating/examples#keep-a-changelog) for seeing the example of adding links to the end of the changelog.

Expand Down

0 comments on commit ea9841e

Please sign in to comment.