From 22db6982673af61fdeefc54b4eea25774e3dce66 Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Sun, 6 Oct 2024 15:16:17 +0100 Subject: [PATCH 1/3] 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 --- git-cliff-core/src/release.rs | 287 +++++++++++++++++++++++++ git-cliff-core/src/remote/bitbucket.rs | 10 +- git-cliff-core/src/remote/mod.rs | 10 +- 3 files changed, 298 insertions(+), 9 deletions(-) diff --git a/git-cliff-core/src/release.rs b/git-cliff-core/src/release.rs index 3e4dd6f7be..fec293f51f 100644 --- a/git-cliff-core/src/release.rs +++ b/git-cliff-core/src/release.rs @@ -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) + .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(()) + } } diff --git a/git-cliff-core/src/remote/bitbucket.rs b/git-cliff-core/src/remote/bitbucket.rs index f45a47cfe7..a3e3603d73 100644 --- a/git-cliff-core/src/remote/bitbucket.rs +++ b/git-cliff-core/src/remote/bitbucket.rs @@ -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, + pub title: Option, /// 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 { @@ -136,7 +136,7 @@ impl RemotePullRequest for BitbucketPullRequest { } fn merge_commit(&self) -> Option { - Some(self.merge_commit_sha.hash.clone()) + Some(self.merge_commit.hash.clone()) } } diff --git a/git-cliff-core/src/remote/mod.rs b/git-cliff-core/src/remote/mod.rs index 77d14e72b5..a79137b291 100644 --- a/git-cliff-core/src/remote/mod.rs +++ b/git-cliff-core/src/remote/mod.rs @@ -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. @@ -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 = From fca1819fa420779cf4adcfe0d2e865e175cc3840 Mon Sep 17 00:00:00 2001 From: Matthew Warman Date: Sun, 6 Oct 2024 22:32:32 +0100 Subject: [PATCH 2/3] test: update bitbucket fixture to include pr test --- .github/fixtures/test-bitbucket-integration/cliff.toml | 8 ++++++-- .github/fixtures/test-bitbucket-integration/commit.sh | 2 +- .github/fixtures/test-bitbucket-integration/expected.md | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.github/fixtures/test-bitbucket-integration/cliff.toml b/.github/fixtures/test-bitbucket-integration/cliff.toml index 9ad05d1aff..9e9690ad05 100644 --- a/.github/fixtures/test-bitbucket-integration/cliff.toml +++ b/.github/fixtures/test-bitbucket-integration/cliff.toml @@ -1,11 +1,15 @@ [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 %} @@ -21,7 +25,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 -%} diff --git a/.github/fixtures/test-bitbucket-integration/commit.sh b/.github/fixtures/test-bitbucket-integration/commit.sh index 5bb810071b..7bed941a15 100755 --- a/.github/fixtures/test-bitbucket-integration/commit.sh +++ b/.github/fixtures/test-bitbucket-integration/commit.sh @@ -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 diff --git a/.github/fixtures/test-bitbucket-integration/expected.md b/.github/fixtures/test-bitbucket-integration/expected.md index 0c72638ad1..219e015a51 100644 --- a/.github/fixtures/test-bitbucket-integration/expected.md +++ b/.github/fixtures/test-bitbucket-integration/expected.md @@ -1,6 +1,7 @@ ## What's Changed * feat(config): support multiple file formats by @orhun * feat(cache): use cache while fetching pages by @orhun +* feat(ci): add pipeline config by @mcwarman <7236500+mcwarman@users.noreply.github.com> in #1 ## What's Changed in v1.0.1 * refactor(parser): expose string functions by @orhun From cb169a3c015af4a0143f7eb3b8bbe399c18126e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Mon, 7 Oct 2024 09:35:36 +0300 Subject: [PATCH 3/3] chore(fixture): use link in bitbucket fixture --- .github/fixtures/test-bitbucket-integration/cliff.toml | 4 +++- .github/fixtures/test-bitbucket-integration/expected.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/fixtures/test-bitbucket-integration/cliff.toml b/.github/fixtures/test-bitbucket-integration/cliff.toml index 9e9690ad05..10a7ec2ad6 100644 --- a/.github/fixtures/test-bitbucket-integration/cliff.toml +++ b/.github/fixtures/test-bitbucket-integration/cliff.toml @@ -15,7 +15,9 @@ body = """ {% 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 %} diff --git a/.github/fixtures/test-bitbucket-integration/expected.md b/.github/fixtures/test-bitbucket-integration/expected.md index 219e015a51..84fbdee247 100644 --- a/.github/fixtures/test-bitbucket-integration/expected.md +++ b/.github/fixtures/test-bitbucket-integration/expected.md @@ -1,7 +1,7 @@ ## What's Changed * feat(config): support multiple file formats by @orhun * feat(cache): use cache while fetching pages by @orhun -* feat(ci): add pipeline config by @mcwarman <7236500+mcwarman@users.noreply.github.com> in #1 +* 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