Skip to content

Commit

Permalink
feat: add tag message to release context
Browse files Browse the repository at this point in the history
- add to the release context the tag's message if it exists
- add message to the default config
  • Loading branch information
MeitarR committed Jun 21, 2024
1 parent 4a3edca commit b5b1d3c
Show file tree
Hide file tree
Showing 13 changed files with 257 additions and 26 deletions.
37 changes: 37 additions & 0 deletions .github/fixtures/test-tag-message/cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
[changelog]
# template for the changelog footer
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% if message %}
{{ message }}\
{% endif %}\
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | upper_first }}
{% for commit in commits %}
- {{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
"""
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""
# remove the leading and trailing whitespace from the templates
trim = true

[git]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "Features", default_scope = "app" },
{ message = "^fix", group = "Bug Fixes", scope = "cli" },
]
11 changes: 11 additions & 0 deletions .github/fixtures/test-tag-message/commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/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: add feature 1"
GIT_COMMITTER_DATE="2022-04-06 01:25:10" git commit --allow-empty -m "fix: fix feature 1"
git tag v0.1.0 -m "Some text"
GIT_COMMITTER_DATE="2022-04-06 01:25:11" git commit --allow-empty -m "feat(gui): add feature 2"
GIT_COMMITTER_DATE="2022-04-06 01:25:12" git commit --allow-empty -m "fix(gui): fix feature 2"
git tag v0.2.0
GIT_COMMITTER_DATE="2022-04-06 01:25:13" git commit --allow-empty -m "test: add tests"
33 changes: 33 additions & 0 deletions .github/fixtures/test-tag-message/expected.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Changelog

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

## [unreleased]

### Test

- Add tests

## [0.2.0] - 2022-04-06

### Bug Fixes

- Fix feature 2

### Features

- Add feature 2

## [0.1.0] - 2022-04-06

Some text

### Bug Fixes

- Fix feature 1

### Features

- Add feature 1

<!-- generated by git-cliff -->
1 change: 1 addition & 0 deletions .github/workflows/test-fixtures.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ jobs:
command: --bump --tag=2.1.1
- fixtures-name: test-cli-arg-ignore-tags
command: --ignore-tags ".*beta"
- fixtures-name: test-tag-message

steps:
- name: Checkout
Expand Down
3 changes: 3 additions & 0 deletions config/cliff.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ All notable changes to this project will be documented in this file.\n
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% if message %}
{{ message }}
{% endif %}\
{% else %}\
## [unreleased]
{% endif %}\
Expand Down
2 changes: 2 additions & 0 deletions git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,7 @@ mod test {
};
let test_release = Release {
version: Some(String::from("v1.0.0")),
message: None,
commits: vec![
Commit::new(
String::from("coffee"),
Expand Down Expand Up @@ -909,6 +910,7 @@ mod test {
},
Release {
version: None,
message: None,
commits: vec![
Commit::new(
String::from("abc123"),
Expand Down
2 changes: 2 additions & 0 deletions git-cliff-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ pub mod remote;
/// Git repository.
#[cfg(feature = "repo")]
pub mod repo;
/// Git tag.
pub mod tag;
/// Template engine.
pub mod template;

Expand Down
6 changes: 6 additions & 0 deletions git-cliff-core/src/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ use serde::{
pub struct Release<'a> {
/// Release version, git tag.
pub version: Option<String>,
/// git tag's message.
pub message: Option<String>,
/// Commits made for the release.
pub commits: Vec<Commit<'a>>,
/// Commit ID of the tag.
Expand Down Expand Up @@ -159,6 +161,7 @@ mod test {
fn build_release<'a>(version: &str, commits: &'a [&str]) -> Release<'a> {
Release {
version: None,
message: None,
commits: commits
.iter()
.map(|v| Commit::from(v.to_string()))
Expand Down Expand Up @@ -340,6 +343,7 @@ mod test {

let mut release = Release {
version: None,
message: None,
commits: vec![
Commit::from(String::from(
"1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github \
Expand Down Expand Up @@ -625,6 +629,7 @@ mod test {

let mut release = Release {
version: None,
message: None,
commits: vec![
Commit::from(String::from(
"1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github \
Expand Down Expand Up @@ -968,6 +973,7 @@ mod test {

let mut release = Release {
version: None,
message: None,
commits: vec![
Commit::from(String::from(
"1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add github \
Expand Down
115 changes: 98 additions & 17 deletions git-cliff-core/src/repo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::error::{
Error,
Result,
};
use crate::tag::Tag;
use git2::{
BranchType,
Commit,
Expand Down Expand Up @@ -95,11 +96,47 @@ impl Repository {
/// Returns the current tag.
///
/// It is the same as running `git describe --tags`
pub fn current_tag(&self) -> Option<String> {
pub fn current_tag(&self) -> Option<Tag> {
self.inner
.describe(DescribeOptions::new().describe_tags())
.ok()
.and_then(|describe| describe.format(None).ok())
.and_then(|describe| {
describe
.format(None)
.ok()
.map(|name| self.resolve_tag(&name))
})
}

/// Returns the tag object of the given name.
/// if given name don't exists, still returns Tag object with the given name
pub fn resolve_tag(&self, name: &str) -> Tag {
match self.inner.resolve_reference_from_short_name(name) {
Ok(reference) => match reference.peel_to_tag() {
Ok(tag) => Tag {
name: tag.name().unwrap_or_default().to_owned(),
message: tag.message().map(Self::cleanup_message),
},
_ => Tag {
name: name.to_owned(),
message: None,
},
},
_ => Tag {
name: name.to_owned(),
message: None,
},
}
}

/// used to remove signature from signed tag message
fn cleanup_message(message: &str) -> String {
let re = Regex::new(
r"(?s)-----BEGIN PGP SIGNATURE-----(.*?)-----END PGP SIGNATURE-----",
)
.expect("invalid regex, wtf");

re.replace(message, "").trim().to_string()
}

/// Returns the commit object of the given ID.
Expand All @@ -119,8 +156,8 @@ impl Repository {
&self,
pattern: &Option<Regex>,
topo_order: bool,
) -> Result<IndexMap<String, String>> {
let mut tags: Vec<(Commit, String)> = Vec::new();
) -> Result<IndexMap<String, Tag>> {
let mut tags: Vec<(Commit, Tag)> = Vec::new();
let tag_names = self.inner.tag_names(None)?;
for name in tag_names
.iter()
Expand All @@ -132,14 +169,21 @@ impl Repository {
{
let obj = self.inner.revparse_single(&name)?;
if let Ok(commit) = obj.clone().into_commit() {
tags.push((commit, name));
// lightweight commit?
tags.push((commit, Tag {
name,
message: None,
}));
} else if let Some(tag) = obj.as_tag() {
if let Some(commit) = tag
.target()
.ok()
.and_then(|target| target.into_commit().ok())
{
tags.push((commit, name));
tags.push((commit, Tag {
name: tag.name().expect("tag don't have name").to_owned(),
message: tag.message().map(|msg| msg.to_owned()),
}));
}
}
}
Expand Down Expand Up @@ -261,7 +305,7 @@ mod test {
fn get_latest_tag() -> Result<()> {
let repository = get_repository()?;
let tags = repository.tags(&None, false)?;
assert_eq!(&get_last_tag()?, tags.last().expect("no tags found").1);
assert_eq!(get_last_tag()?, tags.last().expect("no tags found").1.name);
Ok(())
}

Expand All @@ -270,16 +314,20 @@ mod test {
let repository = get_repository()?;
let tags = repository.tags(&None, true)?;
assert_eq!(
tags.get("2b8b4d3535f29231e05c3572e919634b9af907b6").expect(
"the commit hash does not exist in the repository (tag v0.1.0)"
),
tags.get("2b8b4d3535f29231e05c3572e919634b9af907b6")
.expect(
"the commit hash does not exist in the repository (tag v0.1.0)"
)
.name,
"v0.1.0"
);
assert_eq!(
tags.get("4ddef08debfff48117586296e49d5caa0800d1b5").expect(
"the commit hash does not exist in the repository (tag \
v0.1.0-beta.4)"
),
tags.get("4ddef08debfff48117586296e49d5caa0800d1b5")
.expect(
"the commit hash does not exist in the repository (tag \
v0.1.0-beta.4)"
)
.name,
"v0.1.0-beta.4"
);
let tags = repository.tags(
Expand All @@ -290,9 +338,11 @@ mod test {
true,
)?;
assert_eq!(
tags.get("2b8b4d3535f29231e05c3572e919634b9af907b6").expect(
"the commit hash does not exist in the repository (tag v0.1.0)"
),
tags.get("2b8b4d3535f29231e05c3572e919634b9af907b6")
.expect(
"the commit hash does not exist in the repository (tag v0.1.0)"
)
.name,
"v0.1.0"
);
assert!(!tags.contains_key("4ddef08debfff48117586296e49d5caa0800d1b5"));
Expand All @@ -313,4 +363,35 @@ mod test {
);
Ok(())
}

#[test]
fn resolves_existing_tag_with_name_and_message() -> Result<()> {
let repository = get_repository()?;

let tag = repository.resolve_tag("v0.2.3");

assert_eq!(tag.name, "v0.2.3");
assert_eq!(
tag.message,
Some(
"Release v0.2.3\n\nBug Fixes\n- Fetch the dependencies before \
copying the file to embed (9e29c95)"
.to_string()
)
);

Ok(())
}

#[test]
fn resolves_tag_when_no_tags_exist() -> Result<()> {
let repository = get_repository()?;

let tag = repository.resolve_tag("nonexistent-tag");

assert_eq!(tag.name, "nonexistent-tag");
assert_eq!(tag.message, None);

Ok(())
}
}
46 changes: 46 additions & 0 deletions git-cliff-core/src/tag.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/// Common tag object that is parsed from a repository.
/// lightweight tag will have None at message.
#[derive(Debug)]
pub struct Tag {
/// The name of the tag
pub name: String,
/// the message of the tag. only if it was annotated
pub message: Option<String>,
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn create_tag_with_name_and_message() {
let tag = Tag {
name: String::from("v1.0"),
message: Some(String::from("Initial release")),
};
assert_eq!(tag.name, "v1.0");
assert_eq!(tag.message, Some(String::from("Initial release")));
}

#[test]
fn create_tag_with_name_and_no_message() {
let tag = Tag {
name: String::from("v1.0"),
message: None,
};
assert_eq!(tag.name, "v1.0");
assert_eq!(tag.message, None);
}

#[test]
fn debug_print_tag_with_message() {
let tag = Tag {
name: String::from("v1.0"),
message: Some(String::from("Initial release")),
};
assert_eq!(
format!("{:?}", tag),
"Tag { name: \"v1.0\", message: Some(\"Initial release\") }"
);
}
}
Loading

0 comments on commit b5b1d3c

Please sign in to comment.