Skip to content

Commit

Permalink
fix(bitbucket): match PR and release metadata correctly (#907)
Browse files Browse the repository at this point in the history
* fix(bitbucket): pull requests release metadata not matched correctly

- update BitbucketPullRequest struct to use merge_commit
- update metadata matching to support short sha format
- add tests for Bitbucket remote

* test: update bitbucket fixture to include pr test

* chore(fixture): use link in bitbucket fixture

---------

Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
  • Loading branch information
mcwarman and orhun authored Oct 7, 2024
1 parent 508a97e commit e936ed5
Show file tree
Hide file tree
Showing 6 changed files with 309 additions and 13 deletions.
12 changes: 9 additions & 3 deletions .github/fixtures/test-bitbucket-integration/cliff.toml
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
[remote.bitbucket]
owner = "orhunp"
owner = "mcwarman-playground"
repo = "git-cliff-readme-example"

[changelog]
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{%- macro remote_url() -%}
https://bitbucket.org/{{ remote.bitbucket.owner }}/{{ remote.bitbucket.repo }}
{%- endmacro -%}
## What's Changed
{%- if version %} in {{ version }}{%- endif -%}
{% for commit in commits %}
* {{ commit.message | split(pat="\n") | first | trim }}\
{% if commit.remote.username %} by @{{ commit.remote.username }}{%- endif -%}
{% if commit.remote.pr_number %} in #{{ commit.remote.pr_number }}{%- endif %}
{% if commit.remote.pr_number %} in \
[#{{ commit.remote.pr_number }}]({{ self::remote_url() }}/pull-requests/{{ commit.remote.pr_number }})\
{%- endif %}
{%- endfor -%}
{% if bitbucket.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
Expand All @@ -21,7 +27,7 @@ body = """
{% for contributor in bitbucket.contributors | filter(attribute="is_first_time", value=true) %}
* @{{ contributor.username }} made their first contribution
{%- if contributor.pr_number %} in \
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \
[#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull-requests/{{ contributor.pr_number }}) \
{%- endif %}
{%- endfor -%}
{% raw %}\n\n{% endraw -%}
Expand Down
2 changes: 1 addition & 1 deletion .github/fixtures/test-bitbucket-integration/commit.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -e

git remote add origin https://bitbucket.org/orhunp/git-cliff-readme-example
git remote add origin https://bitbucket.org/mcwarman-playground/git-cliff-readme-example
git pull origin master
git fetch --tags
1 change: 1 addition & 0 deletions .github/fixtures/test-bitbucket-integration/expected.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## What's Changed
* feat(config): support multiple file formats by @orhun <orhun@archlinux.org>
* feat(cache): use cache while fetching pages by @orhun <orhun@archlinux.org>
* feat(ci): add pipeline config by @mcwarman <7236500+mcwarman@users.noreply.github.com> in [#1](https://bitbucket.org/mcwarman-playground/git-cliff-readme-example/pull-requests/1)

## What's Changed in v1.0.1
* refactor(parser): expose string functions by @orhun <orhun@archlinux.org>
Expand Down
287 changes: 287 additions & 0 deletions git-cliff-core/src/release.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1424,4 +1424,291 @@ mod test {

Ok(())
}

#[cfg(feature = "bitbucket")]
#[test]
fn update_bitbucket_metadata() -> Result<()> {
use crate::remote::bitbucket::{
BitbucketCommit,
BitbucketCommitAuthor,
BitbucketPullRequest,
BitbucketPullRequestMergeCommit,
};

let mut release = Release {
version: None,
message: None,
extra: None,
commits: vec![
Commit::from(String::from(
"1d244937ee6ceb8e0314a4a201ba93a7a61f2071 add bitbucket \
integration",
)),
Commit::from(String::from(
"21f6aa587fcb772de13f2fde0e92697c51f84162 fix bitbucket \
integration",
)),
Commit::from(String::from(
"35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973 update metadata",
)),
Commit::from(String::from(
"4d3ffe4753b923f4d7807c490e650e6624a12074 do some stuff",
)),
Commit::from(String::from(
"5a55e92e5a62dc5bf9872ffb2566959fad98bd05 alright",
)),
Commit::from(String::from(
"6c34967147560ea09658776d4901709139b4ad66 should be fine",
)),
],
commit_id: None,
timestamp: 0,
previous: Some(Box::new(Release {
version: Some(String::from("1.0.0")),
..Default::default()
})),
repository: Some(String::from("/root/repo")),
#[cfg(feature = "github")]
github: RemoteReleaseMetadata {
contributors: vec![],
},
#[cfg(feature = "gitlab")]
gitlab: RemoteReleaseMetadata {
contributors: vec![],
},
#[cfg(feature = "gitea")]
gitea: RemoteReleaseMetadata {
contributors: vec![],
},
#[cfg(feature = "bitbucket")]
bitbucket: RemoteReleaseMetadata {
contributors: vec![],
},
};
release.update_bitbucket_metadata(
vec![
BitbucketCommit {
hash: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("orhun")),
}),
},
BitbucketCommit {
hash: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("orhun")),
}),
},
BitbucketCommit {
hash: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("nuhro")),
}),
},
BitbucketCommit {
hash: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("awesome_contributor")),
}),
},
BitbucketCommit {
hash: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("orhun")),
}),
},
BitbucketCommit {
hash: String::from("6c34967147560ea09658776d4901709139b4ad66"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("someone")),
}),
},
BitbucketCommit {
hash: String::from("0c34967147560e809658776d4901709139b4ad68"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("idk")),
}),
},
BitbucketCommit {
hash: String::from("kk34967147560e809658776d4901709139b4ad68"),
author: Some(BitbucketCommitAuthor {
login: Some(String::from("orhun")),
}),
},
]
.into_iter()
.map(|v| Box::new(v) as Box<dyn RemoteCommit>)
.collect(),
vec![Box::new(BitbucketPullRequest {
id: 1,
title: Some(String::from("1")),
author: BitbucketCommitAuthor {
login: Some(String::from("42")),
},
merge_commit: BitbucketPullRequestMergeCommit {
// Bitbucket merge commits returned in short format
hash: String::from("1d244937ee6c"),
},
})],
)?;
#[allow(deprecated)]
let expected_commits = vec![
Commit {
id: String::from("1d244937ee6ceb8e0314a4a201ba93a7a61f2071"),
message: String::from("add bitbucket integration"),
bitbucket: RemoteContributor {
username: Some(String::from("orhun")),
pr_title: Some(String::from("1")),
pr_number: Some(1),
pr_labels: vec![],
is_first_time: false,
},
remote: Some(RemoteContributor {
username: Some(String::from("orhun")),
pr_title: Some(String::from("1")),
pr_number: Some(1),
pr_labels: vec![],
is_first_time: false,
}),
..Default::default()
},
Commit {
id: String::from("21f6aa587fcb772de13f2fde0e92697c51f84162"),
message: String::from("fix bitbucket integration"),
bitbucket: RemoteContributor {
username: Some(String::from("orhun")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
},
remote: Some(RemoteContributor {
username: Some(String::from("orhun")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
}),
..Default::default()
},
Commit {
id: String::from("35d8c6b6329ecbcf131d7df02f93c3bbc5ba5973"),
message: String::from("update metadata"),
bitbucket: RemoteContributor {
username: Some(String::from("nuhro")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
},
remote: Some(RemoteContributor {
username: Some(String::from("nuhro")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
}),
..Default::default()
},
Commit {
id: String::from("4d3ffe4753b923f4d7807c490e650e6624a12074"),
message: String::from("do some stuff"),
bitbucket: RemoteContributor {
username: Some(String::from("awesome_contributor")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
},
remote: Some(RemoteContributor {
username: Some(String::from("awesome_contributor")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
}),
..Default::default()
},
Commit {
id: String::from("5a55e92e5a62dc5bf9872ffb2566959fad98bd05"),
message: String::from("alright"),
bitbucket: RemoteContributor {
username: Some(String::from("orhun")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
},
remote: Some(RemoteContributor {
username: Some(String::from("orhun")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
}),
..Default::default()
},
Commit {
id: String::from("6c34967147560ea09658776d4901709139b4ad66"),
message: String::from("should be fine"),
bitbucket: RemoteContributor {
username: Some(String::from("someone")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
},
remote: Some(RemoteContributor {
username: Some(String::from("someone")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: false,
}),
..Default::default()
},
];
assert_eq!(expected_commits, release.commits);

release
.bitbucket
.contributors
.sort_by(|a, b| a.pr_number.cmp(&b.pr_number));

let expected_metadata = RemoteReleaseMetadata {
contributors: vec![
RemoteContributor {
username: Some(String::from("nuhro")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: true,
},
RemoteContributor {
username: Some(String::from("awesome_contributor")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: true,
},
RemoteContributor {
username: Some(String::from("someone")),
pr_title: None,
pr_number: None,
pr_labels: vec![],
is_first_time: true,
},
RemoteContributor {
username: Some(String::from("orhun")),
pr_title: Some(String::from("1")),
pr_number: Some(1),
pr_labels: vec![],
is_first_time: false,
},
],
};
assert_eq!(expected_metadata, release.bitbucket);

Ok(())
}
}
10 changes: 5 additions & 5 deletions git-cliff-core/src/remote/bitbucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,13 @@ pub struct BitbucketPullRequestMergeCommit {
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct BitbucketPullRequest {
/// Pull request number.
pub id: i64,
pub id: i64,
/// Pull request title.
pub title: Option<String>,
pub title: Option<String>,
/// Bitbucket Pull Request Merge Commit
pub merge_commit_sha: BitbucketPullRequestMergeCommit,
pub merge_commit: BitbucketPullRequestMergeCommit,
/// Author of Pull Request
pub author: BitbucketCommitAuthor,
pub author: BitbucketCommitAuthor,
}

impl RemotePullRequest for BitbucketPullRequest {
Expand All @@ -136,7 +136,7 @@ impl RemotePullRequest for BitbucketPullRequest {
}

fn merge_commit(&self) -> Option<String> {
Some(self.merge_commit_sha.hash.clone())
Some(self.merge_commit.hash.clone())
}
}

Expand Down
10 changes: 6 additions & 4 deletions git-cliff-core/src/remote/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ use serde::{
Serialize,
};
use std::fmt::Debug;
use std::hash::Hash;
use std::time::Duration;

/// User agent for interacting with the GitHub API.
Expand Down Expand Up @@ -306,9 +305,12 @@ macro_rules! update_release_metadata {
if let Some(commit) =
self.commits.iter_mut().find(|commit| commit.id == v.id())
{
let pull_request = pull_requests
.iter()
.find(|pr| pr.merge_commit() == Some(v.id().clone()));
let sha_short =
Some(v.id().clone().chars().take(12).collect());
let pull_request = pull_requests.iter().find(|pr| {
pr.merge_commit() == Some(v.id().clone()) ||
pr.merge_commit() == sha_short
});
commit.$remote.username = v.username();
commit.$remote.pr_number = pull_request.map(|v| v.number());
commit.$remote.pr_title =
Expand Down

0 comments on commit e936ed5

Please sign in to comment.