Skip to content

Commit

Permalink
feat(changelog): link version to github release
Browse files Browse the repository at this point in the history
This reads from the remote configuration to determine the repository
url. It is currently assumed to be GitHub, but a future release may make
this configurable if the functionality is desired.
  • Loading branch information
justinrubek committed May 16, 2024
1 parent 786378b commit 581ff8e
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 8 deletions.
13 changes: 9 additions & 4 deletions src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,12 @@ impl App {
} else {
None
};
let changelog_entry =
generate_changelog_entry(&commits, &new_version.to_string(), version_description);
let changelog_entry = generate_changelog_entry(
&repo,
&commits,
&new_version.to_string(),
version_description,
)?;

let replacement = VersionReplacement {
old_version: tag.version.to_string(),
Expand Down Expand Up @@ -88,13 +92,14 @@ impl App {
let commits =
get_commits_between_tags(&repo, &version_range[1], &version_range[0])?;
let changelog_entry =
generate_changelog_entry(&commits, &version.to_string(), None);
generate_changelog_entry(&repo, &commits, &version.to_string(), None)?;
println!("{}", changelog_entry);
}
None => {
let tag = get_latest_tag(&repo)?;
let commits = get_commits_since_tag(&repo, &tag)?;
let changelog_entry = generate_changelog_entry(&commits, "unreleased", None);
let changelog_entry =
generate_changelog_entry(&repo, &commits, "unreleased", None)?;
let path = std::path::PathBuf::from("CHANGELOG.md");
if opts.no_decorations {
match opts.only_current_version {
Expand Down
34 changes: 30 additions & 4 deletions src/changelog.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::versioning::Commit;
use crate::{error::Result, versioning::Commit};
use conventional_commit_parser::commit::CommitType;
use std::collections::HashMap;

Expand All @@ -11,7 +11,7 @@ pub struct ChangelogEntry<'a> {
pub description: Option<String>,
}

#[derive(Clone, Debug, serde::Serialize)]
#[derive(Clone, Debug)]
pub struct ChangelogCommit {
pub scope: Option<String>,
pub summary: String,
Expand Down Expand Up @@ -56,13 +56,20 @@ pub fn display_commit_type(commit_type: &CommitType) -> String {
}

pub fn generate_changelog_entry<'a, I: IntoIterator<Item = &'a Commit>>(
repo: &gix::Repository,
commits: I,
version: &str,
description: Option<String>,
) -> String {
) -> Result<String> {
let mut env = minijinja::Environment::new();
env.add_template("changelog_entry", TEMPLATE).unwrap();

let url = gix_repo_url(repo)?;
let version = match &url {
Some(url) => &format!("[{version}]({url}/releases/tag/{version})"),
None => version,
};

let typed_commits: HashMap<String, Vec<ChangelogCommit>> =
commits.into_iter().fold(HashMap::new(), |mut acc, commit| {
let key = display_commit_type(&commit.conventional_commit.commit_type);
Expand All @@ -87,5 +94,24 @@ pub fn generate_changelog_entry<'a, I: IntoIterator<Item = &'a Commit>>(
.render(minijinja::context!(
entry => entry,
))
.unwrap()
.map_err(Into::into)
}

fn gix_repo_url(repo: &gix::Repository) -> Result<Option<String>> {
let remote = match repo.find_default_remote(gix::remote::Direction::Push) {
Some(remote) => remote?,
None => return Ok(None),
};

match remote.url(gix::remote::Direction::Push) {
Some(url) => {
let host = url.host_argument_safe();
let path = url.path_argument_safe();
match (host, path) {
(Some(host), Some(path)) => Ok(Some(format!("https://{host}/{path}"))),
_ => Ok(None),
}
}
None => Ok(None),
}
}
6 changes: 6 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,21 @@ pub enum Error {
#[error(transparent)]
GixReferenceHeadId(#[from] gix::reference::head_id::Error),
#[error(transparent)]
GixRemoteFindExisting(#[from] gix::remote::find::existing::Error),
#[error(transparent)]
GixHeadCommit(#[from] gix::reference::head_commit::Error),
#[error(transparent)]
GixWalk(#[from] gix::revision::walk::Error),
#[error(transparent)]
ConventialCommitParse(#[from] conventional_commit_parser::error::ParseError),
#[error(transparent)]
MiniJinja(#[from] minijinja::Error),
#[error(transparent)]
Other(#[from] anyhow::Error),
#[error(transparent)]
StdPathStripPrefix(#[from] std::path::StripPrefixError),
#[error(transparent)]
StdStrUtf8Error(#[from] std::str::Utf8Error),
#[error("invalid version: {0}")]
TomlSerialize(#[from] toml::ser::Error),
#[error("invalid toml: {0}")]
Expand Down

0 comments on commit 581ff8e

Please sign in to comment.