Skip to content

Commit

Permalink
fix(changelog): fix missing commit fields in context (#837)
Browse files Browse the repository at this point in the history
  • Loading branch information
dqkqd committed Oct 13, 2024
1 parent da1cb61 commit b72f556
Show file tree
Hide file tree
Showing 9 changed files with 280 additions and 2 deletions.
35 changes: 35 additions & 0 deletions .github/fixtures/test-conventional-commit/cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[changelog]
# template for the changelog footer
header = """
# Changelog\n
All notable changes to this project will be documented in this file.
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% for group, commits in commits | group_by(attribute="group") %}
## {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
{% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**]: {{ commit.breaking_description }}{% endif %}
{{ commit.message }}: {{ commit.body }}\
{% for footer in commit.footers %}
- {{ footer.token }}{{ footer.separator }} {{ footer.value }}\
{% endfor %}
{% endfor %}\
{% endfor %}\n
"""
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""

[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# process each line of a commit as an individual commit
split_commits = false
commit_parsers = [
{ message = "^feat", group = "Features", default_scope = "app" },
{ message = "^fix" },
]
52 changes: 52 additions & 0 deletions .github/fixtures/test-conventional-commit/commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -e

GIT_COMMITTER_DATE="2022-04-06 01:25:08" git commit --allow-empty -m "Initial commit"
GIT_COMMITTER_DATE="2022-04-06 01:25:09" git commit --allow-empty -m \
"feat(web): feature 1, breaking change in footer
Body feature 1
BREAKING CHANGE: breaking change description feature 1
Signed-off-by: user1 <[email protected]>
Reviewed-by: user2
"

GIT_COMMITTER_DATE="2022-04-06 01:25:10" git commit --allow-empty -m \
"feat(web)!: feature 2, breaking chain in description
Body feature 2
Signed-off-by: user3 <[email protected]>
"

GIT_COMMITTER_DATE="2022-04-06 01:25:11" git commit --allow-empty -m \
"feat!: feature 3, use default scope = app
Body feature 2
Signed-off-by: user3 <[email protected]>
"

GIT_COMMITTER_DATE="2022-04-06 01:25:12" git commit --allow-empty -m \
"fix(scope): fix 1, use scope as group
Body fix 1
Fix: #1
"

GIT_COMMITTER_DATE="2022-04-06 01:25:13" git commit --allow-empty -m \
"fix(front-end): fix 2, no footer
Body fix 2
"

GIT_COMMITTER_DATE="2022-04-06 01:25:14" git commit --allow-empty -m \
"fix(front-end): fix 3 and 4, no body but footer
Fix: #3
Fix: #4
"

git tag v0.1.0
35 changes: 35 additions & 0 deletions .github/fixtures/test-conventional-commit/expected.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Changelog

All notable changes to this project will be documented in this file.

## Features

*(web)* [**breaking**]: breaking change description feature 1
feature 1, breaking change in footer: Body feature 1
- BREAKING CHANGE: breaking change description feature 1
- Signed-off-by: user1 <[email protected]>
- Reviewed-by: user2

*(web)* [**breaking**]: feature 2, breaking chain in description
feature 2, breaking chain in description: Body feature 2
- Signed-off-by: user3 <[email protected]>

*(app)* [**breaking**]: feature 3, use default scope = app
feature 3, use default scope = app: Body feature 2
- Signed-off-by: user3 <[email protected]>

## Fix

*(scope)*
fix 1, use scope as group: Body fix 1
- Fix: #1

*(front-end)*
fix 2, no footer: Body fix 2

*(front-end)*
fix 3 and 4, no body but footer:
- Fix: #3
- Fix: #4

<!-- generated by git-cliff -->
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[changelog]
# template for the changelog footer
header = """
# Changelog\n
All notable changes to this project will be documented in this file.
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% for group, commits in commits | group_by(attribute="group") %}
## {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
{% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**]: {{ commit.breaking_description }}{% endif %}
{{ commit.message }}: {{ commit.body }}\
{% for footer in commit.footers %}
- {{ footer.token }}{{ footer.separator }} {{ footer.value }}\
{% endfor %}
{% endfor %}\
{% endfor %}\n
"""
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""

[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# process each line of a commit as an individual commit
split_commits = false
commit_parsers = [
{ message = "^feat", group = "Features", default_scope = "app" },
{ message = "^fix" },
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -e

GIT_COMMITTER_DATE="2022-04-06 01:25:08" git commit --allow-empty -m "Initial commit"
GIT_COMMITTER_DATE="2022-04-06 01:25:09" git commit --allow-empty -m \
"feat(web): feature 1, breaking change in footer
Body feature 1
BREAKING CHANGE: breaking change description feature 1
Signed-off-by: user1 <[email protected]>
Reviewed-by: user2
"

GIT_COMMITTER_DATE="2022-04-06 01:25:10" git commit --allow-empty -m \
"feat(web)!: feature 2, breaking chain in description
Body feature 2
Signed-off-by: user3 <[email protected]>
"

GIT_COMMITTER_DATE="2022-04-06 01:25:11" git commit --allow-empty -m \
"feat!: feature 3, use default scope = app
Body feature 2
Signed-off-by: user3 <[email protected]>
"

GIT_COMMITTER_DATE="2022-04-06 01:25:12" git commit --allow-empty -m \
"fix(scope): fix 1, use scope as group
Body fix 1
Fix: #1
"

GIT_COMMITTER_DATE="2022-04-06 01:25:13" git commit --allow-empty -m \
"fix(front-end): fix 2, no footer
Body fix 2
"

GIT_COMMITTER_DATE="2022-04-06 01:25:14" git commit --allow-empty -m \
"fix(front-end): fix 3 and 4, no body but footer
Fix: #3
Fix: #4
"

git tag v0.1.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Changelog

All notable changes to this project will be documented in this file.

## Features

*(web)* [**breaking**]: breaking change description feature 1
feature 1, breaking change in footer: Body feature 1
- BREAKING CHANGE: breaking change description feature 1
- Signed-off-by: user1 <[email protected]>
- Reviewed-by: user2

*(web)* [**breaking**]: feature 2, breaking chain in description
feature 2, breaking chain in description: Body feature 2
- Signed-off-by: user3 <[email protected]>

*(app)* [**breaking**]: feature 3, use default scope = app
feature 3, use default scope = app: Body feature 2
- Signed-off-by: user3 <[email protected]>

## Fix

*(scope)*
fix 1, use scope as group: Body fix 1
- Fix: #1

*(front-end)*
fix 2, no footer: Body fix 2

*(front-end)*
fix 3 and 4, no body but footer:
- Fix: #3
- Fix: #4

<!-- generated by git-cliff -->
3 changes: 3 additions & 0 deletions .github/workflows/test-fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ jobs:
command: --latest
- fixtures-name: test-commit-footers
- fixtures-name: test-commit-preprocessors
- fixtures-name: test-conventional-commit
- fixtures-name: test-custom-scope
- fixtures-name: test-limit-commits
- fixtures-name: test-skip-breaking-changes
Expand Down Expand Up @@ -93,6 +94,8 @@ jobs:
command: --bump --unreleased --with-tag-message "Some text"
- fixtures-name: test-from-context
command: --from-context context.json
- fixtures-name: test-from-context-does-not-discard-fields
command: --context | git cliff --from-context -
- fixtures-name: test-always-render-unreleased
command: --unreleased
- fixtures-name: test-always-render
Expand Down
33 changes: 31 additions & 2 deletions git-cliff-core/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use serde::ser::{
};
use serde::{
Deserialize,
Deserializer,
Serialize,
};
use serde_json::value::Value;
Expand Down Expand Up @@ -143,6 +144,10 @@ pub struct Commit<'a> {
#[cfg(feature = "bitbucket")]
#[deprecated(note = "Use `remote` field instead")]
pub bitbucket: crate::contributor::RemoteContributor,

/// Message of the normal commit, to avoid lossly message conversion between
/// conventional commit
pub raw_message: Option<String>,
}

impl<'a> From<String> for Commit<'a> {
Expand Down Expand Up @@ -191,6 +196,11 @@ impl Commit<'_> {
}
}

/// Get raw commit message uses for converting to conventional commit
pub fn raw_message(&self) -> &str {
self.raw_message.as_deref().unwrap_or(&self.message)
}

/// Processes the commit.
///
/// * converts commit to a conventional commit
Expand Down Expand Up @@ -226,7 +236,7 @@ impl Commit<'_> {
/// Returns the commit with its conventional type set.
pub fn into_conventional(mut self) -> Result<Self> {
match ConventionalCommit::parse(Box::leak(
self.message.to_string().into_boxed_str(),
self.raw_message().to_string().into_boxed_str(),
)) {
Ok(conv) => {
self.conv = Some(conv);
Expand Down Expand Up @@ -423,8 +433,9 @@ impl Serialize for Commit<'_> {
}
}

let mut commit = serializer.serialize_struct("Commit", 9)?;
let mut commit = serializer.serialize_struct("Commit", 20)?;
commit.serialize_field("id", &self.id)?;
commit.serialize_field("raw_message", &self.raw_message())?;
if let Some(conv) = &self.conv {
commit.serialize_field("message", conv.description())?;
commit.serialize_field("body", &conv.body())?;
Expand Down Expand Up @@ -476,6 +487,24 @@ impl Serialize for Commit<'_> {
}
}

/// Deserialize commits into conventional commits if they are convertible
///
/// Serialized commits cannot be deserialized into commits that have
/// [`Commit::conv`]. Thus, we need to manually convert them using
/// [`Commit::into_conventional`].
///
/// This function is only used in [`crate::release::Release::commits`]
pub(crate) fn commits_to_conventional_commits<'de, 'a, D: Deserializer<'de>>(
deserializer: D,
) -> std::result::Result<Vec<Commit<'a>>, D::Error> {
let commits = Vec::<Commit<'a>>::deserialize(deserializer)?;
let commits = commits
.into_iter()
.map(|commit| commit.clone().into_conventional().unwrap_or(commit))
.collect();
Ok(commits)
}

#[cfg(test)]
mod test {
use super::*;
Expand Down
2 changes: 2 additions & 0 deletions git-cliff-core/src/release.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use crate::commit::commits_to_conventional_commits;
use crate::error::Result;
use crate::{
commit::Commit,
Expand Down Expand Up @@ -34,6 +35,7 @@ pub struct Release<'a> {
/// git tag's message.
pub message: Option<String>,
/// Commits made for the release.
#[serde(deserialize_with = "commits_to_conventional_commits")]
pub commits: Vec<Commit<'a>>,
/// Commit ID of the tag.
#[serde(rename = "commit_id")]
Expand Down

0 comments on commit b72f556

Please sign in to comment.