Skip to content

Commit

Permalink
feat(bitbucket): add Bitbucket support (#663)
Browse files Browse the repository at this point in the history
* Draft: feat(bitbucket): Closes  #566

Signed-off-by: dark0dave <dark0dave@mykolab.com>

* refactor: improve bitbucket integration

---------

Signed-off-by: dark0dave <dark0dave@mykolab.com>
Co-authored-by: Orhun Parmaksız <orhunparmaksiz@gmail.com>
  • Loading branch information
dark0dave and orhun authored Jun 2, 2024
1 parent 2e1ed71 commit 8ffc054
Show file tree
Hide file tree
Showing 27 changed files with 809 additions and 85 deletions.
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/integration.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: Integration ⚙️
description: Report a bug or request a feature about GitHub/GitLab integration
description: Report a bug or request a feature about an integration (e.g GitHub/GitLab/Bitbucket)
labels: ["integration"]
assignees:
- orhun
Expand All @@ -8,7 +8,7 @@ body:
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please see https://git-cliff.org/docs/category/integration for more information about GitHub/GitLab integration.
Please see https://git-cliff.org/docs/category/integration for more information about integrations.
- type: checkboxes
id: new-bug
attributes:
Expand Down
46 changes: 46 additions & 0 deletions .github/fixtures/test-bitbucket-integration/cliff.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
[remote.bitbucket]
owner = "orhunp"
repo = "git-cliff-readme-example"

[changelog]
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
## What's Changed
{%- if version %} in {{ version }}{%- endif -%}
{% for commit in commits %}
* {{ commit.message | split(pat="\n") | first | trim }}\
{% if commit.bitbucket.username %} by @{{ commit.bitbucket.username }}{%- endif -%}
{% if commit.bitbucket.pr_number %} in #{{ commit.bitbucket.pr_number }}{%- endif %}
{%- endfor -%}
{% if bitbucket.contributors | filter(attribute="is_first_time", value=true) | length != 0 %}
{% raw %}\n{% endraw -%}
## New Contributors
{%- endif %}\
{% 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 }}) \
{%- endif %}
{%- endfor -%}
{% raw %}\n\n{% endraw -%}
"""
# remove the leading and trailing whitespace from the template
trim = true
# changelog footer
footer = """
<!-- generated by -cliff -->
"""

[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = false
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }]
# protect breaking changes from being skipped due to matching a skipping commit_parser
protect_breaking_commits = false
6 changes: 6 additions & 0 deletions .github/fixtures/test-bitbucket-integration/commit.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!/usr/bin/env bash
set -e

git remote add origin https://bitbucket.org/orhunp/git-cliff-readme-example
git pull origin master
git fetch --tags
16 changes: 16 additions & 0 deletions .github/fixtures/test-bitbucket-integration/expected.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
## 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>

## What's Changed in v1.0.1
* refactor(parser): expose string functions by @orhun <orhun@archlinux.org>
* chore(release): add release script by @orhun <orhun@archlinux.org>

## What's Changed in v1.0.0
* Initial commit by @orhun <orhun@archlinux.org>
* docs(project): add README.md by @orhun <orhun@archlinux.org>
* feat(parser): add ability to parse arrays by @orhun <orhun@archlinux.org>
* fix(args): rename help argument due to conflict by @orhun <orhun@archlinux.org>
* docs(example)!: add tested usage example by @orhun <orhun@archlinux.org>

<!-- generated by -cliff -->
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ COPY --from=planner /app/recipe.json recipe.json
ENV CARGO_NET_GIT_FETCH_WITH_CLI=true
RUN cargo chef cook --release --recipe-path recipe.json
COPY . .
RUN cargo build --release --locked --no-default-features --features github --features gitlab
RUN cargo build --release --locked --no-default-features --features github --features gitlab --features bitbucket
RUN rm -f target/release/deps/git_cliff*

FROM debian:buster-slim as runner
Expand Down
10 changes: 10 additions & 0 deletions git-cliff-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ gitlab = [
"dep:tokio",
"dep:futures",
]
## Enable integration with Bitbucket.
## You can turn this off if you don't use Bitbucket and don't want
## to make network requests to the Bitbucket API.
bitbucket = [
"dep:reqwest",
"dep:http-cache-reqwest",
"dep:reqwest-middleware",
"dep:tokio",
"dep:futures",
]

[dependencies]
glob = { workspace = true, optional = true }
Expand Down
88 changes: 86 additions & 2 deletions git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use crate::release::{
Release,
Releases,
};
#[cfg(feature = "bitbucket")]
use crate::remote::bitbucket::BitbucketClient;
#[cfg(feature = "github")]
use crate::remote::github::GitHubClient;
#[cfg(feature = "gitlab")]
Expand Down Expand Up @@ -297,6 +299,62 @@ impl<'a> Changelog<'a> {
}
}

/// Returns the Bitbucket metadata needed for the changelog.
///
/// This function creates a multithread async runtime for handling the
///
/// requests. The following are fetched from the bitbucket REST API:
///
/// - Commits
/// - Pull requests
///
/// Each of these are paginated requests so they are being run in parallel
/// for speedup.
///
///
/// If no bitbucket related variable is used in the template then this
/// function returns empty vectors.
#[cfg(feature = "bitbucket")]
fn get_bitbucket_metadata(&self) -> Result<crate::remote::RemoteMetadata> {
use crate::remote::bitbucket;
if self
.body_template
.contains_variable(bitbucket::TEMPLATE_VARIABLES) ||
self.footer_template
.as_ref()
.map(|v| v.contains_variable(bitbucket::TEMPLATE_VARIABLES))
.unwrap_or(false)
{
warn!("You are using an experimental feature! Please report bugs at <https://git-cliff.org/issues>");
let bitbucket_client =
BitbucketClient::try_from(self.config.remote.bitbucket.clone())?;
info!(
"{} ({})",
bitbucket::START_FETCHING_MSG,
self.config.remote.bitbucket
);
let data = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()?
.block_on(async {
let (commits, pull_requests) = tokio::try_join!(
bitbucket_client.get_commits(),
bitbucket_client.get_pull_requests()
)?;
debug!("Number of Bitbucket commits: {}", commits.len());
debug!(
"Number of Bitbucket pull requests: {}",
pull_requests.len()
);
Ok((commits, pull_requests))
});
info!("{}", bitbucket::FINISHED_FETCHING_MSG);
data
} else {
Ok((vec![], vec![]))
}
}

/// Increments the version for the unreleased changes based on semver.
pub fn bump_version(&mut self) -> Result<Option<String>> {
if let Some(ref mut last_release) = self.releases.iter_mut().next() {
Expand Down Expand Up @@ -337,6 +395,14 @@ impl<'a> Changelog<'a> {
} else {
(vec![], vec![])
};
#[cfg(feature = "bitbucket")]
let (bitbucket_commits, bitbucket_pull_request) =
if self.config.remote.bitbucket.is_set() {
self.get_bitbucket_metadata()
.expect("Could not get bitbucket metadata")
} else {
(vec![], vec![])
};
let postprocessors = self
.config
.changelog
Expand All @@ -363,6 +429,11 @@ impl<'a> Changelog<'a> {
gitlab_commits.clone(),
gitlab_merge_request.clone(),
)?;
#[cfg(feature = "bitbucket")]
release.update_bitbucket_metadata(
bitbucket_commits.clone(),
bitbucket_pull_request.clone(),
)?;
let write_result = write!(
out,
"{}",
Expand Down Expand Up @@ -601,12 +672,17 @@ mod test {
limit_commits: None,
},
remote: RemoteConfig {
github: Remote {
github: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
},
gitlab: Remote {
gitlab: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
},
bitbucket: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
Expand Down Expand Up @@ -685,6 +761,10 @@ mod test {
gitlab: crate::remote::RemoteReleaseMetadata {
contributors: vec![],
},
#[cfg(feature = "bitbucket")]
bitbucket: crate::remote::RemoteReleaseMetadata {
contributors: vec![],
},
};
let releases = vec![
test_release.clone(),
Expand Down Expand Up @@ -736,6 +816,10 @@ mod test {
gitlab: crate::remote::RemoteReleaseMetadata {
contributors: vec![],
},
#[cfg(feature = "bitbucket")]
bitbucket: crate::remote::RemoteReleaseMetadata {
contributors: vec![],
},
},
];
(config, releases)
Expand Down
5 changes: 5 additions & 0 deletions git-cliff-core/src/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,9 @@ pub struct Commit<'a> {
/// GitLab metadata of the commit.
#[cfg(feature = "gitlab")]
pub gitlab: crate::remote::RemoteContributor,
/// Bitbucket metadata of the commit.
#[cfg(feature = "bitbucket")]
pub bitbucket: crate::remote::RemoteContributor,
}

impl<'a> From<String> for Commit<'a> {
Expand Down Expand Up @@ -443,6 +446,8 @@ impl Serialize for Commit<'_> {
commit.serialize_field("github", &self.github)?;
#[cfg(feature = "gitlab")]
commit.serialize_field("gitlab", &self.gitlab)?;
#[cfg(feature = "bitbucket")]
commit.serialize_field("bitbucket", &self.bitbucket)?;
commit.end()
}
}
Expand Down
7 changes: 5 additions & 2 deletions git-cliff-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,13 @@ pub struct GitConfig {
pub struct RemoteConfig {
/// GitHub remote.
#[serde(default)]
pub github: Remote,
pub github: Remote,
/// GitLab remote.
#[serde(default)]
pub gitlab: Remote,
pub gitlab: Remote,
/// Bitbucket remote.
#[serde(default)]
pub bitbucket: Remote,
}

/// A single remote.
Expand Down
6 changes: 3 additions & 3 deletions git-cliff-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,17 @@ pub enum Error {
SemverError(#[from] semver::Error),
/// The errors that may occur when processing a HTTP request.
#[error("HTTP client error: `{0}`")]
#[cfg(any(feature = "github", feature = "gitlab"))]
#[cfg(any(feature = "github", feature = "gitlab", feature = "bitbucket"))]
HttpClientError(#[from] reqwest::Error),
/// The errors that may occur while constructing the HTTP client with
/// middleware.
#[error("HTTP client with middleware error: `{0}`")]
#[cfg(any(feature = "github", feature = "gitlab"))]
#[cfg(any(feature = "github", feature = "gitlab", feature = "bitbucket"))]
HttpClientMiddlewareError(#[from] reqwest_middleware::Error),
/// A possible error when converting a HeaderValue from a string or byte
/// slice.
#[error("HTTP header error: `{0}`")]
#[cfg(any(feature = "github", feature = "gitlab"))]
#[cfg(any(feature = "github", feature = "gitlab", feature = "bitbucket"))]
HttpHeaderError(#[from] reqwest::header::InvalidHeaderValue),
/// Error that may occur during handling pages.
#[error("Pagination error: `{0}`")]
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub mod error;
/// Common release type.
pub mod release;
/// Remote handler.
#[cfg(any(feature = "github", feature = "gitlab"))]
#[cfg(any(feature = "github", feature = "gitlab", feature = "bitbucket"))]
#[allow(async_fn_in_trait)]
pub mod remote;
/// Git repository.
Expand Down
18 changes: 17 additions & 1 deletion git-cliff-core/src/release.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::commit::Commit;
use crate::config::Bump;
use crate::error::Result;
#[cfg(any(feature = "github", feature = "gitlab"))]
#[cfg(any(feature = "github", feature = "gitlab", feature = "bitbucket"))]
use crate::remote::{
RemoteCommit,
RemoteContributor,
Expand Down Expand Up @@ -36,6 +36,9 @@ pub struct Release<'a> {
/// Contributors.
#[cfg(feature = "gitlab")]
pub gitlab: RemoteReleaseMetadata,
/// Contributors.
#[cfg(feature = "bitbucket")]
pub bitbucket: RemoteReleaseMetadata,
}

#[cfg(feature = "github")]
Expand All @@ -44,6 +47,9 @@ crate::update_release_metadata!(github, update_github_metadata);
#[cfg(feature = "gitlab")]
crate::update_release_metadata!(gitlab, update_gitlab_metadata);

#[cfg(feature = "bitbucket")]
crate::update_release_metadata!(bitbucket, update_bitbucket_metadata);

impl<'a> Release<'a> {
/// Calculates the next version based on the commits.
///
Expand Down Expand Up @@ -156,6 +162,10 @@ mod test {
gitlab: crate::remote::RemoteReleaseMetadata {
contributors: vec![],
},
#[cfg(feature = "bitbucket")]
bitbucket: crate::remote::RemoteReleaseMetadata {
contributors: vec![],
},
}
}

Expand Down Expand Up @@ -341,6 +351,9 @@ mod test {
gitlab: RemoteReleaseMetadata {
contributors: vec![],
},
bitbucket: RemoteReleaseMetadata {
contributors: vec![],
},
};
release.update_github_metadata(
vec![
Expand Down Expand Up @@ -617,6 +630,9 @@ mod test {
gitlab: RemoteReleaseMetadata {
contributors: vec![],
},
bitbucket: RemoteReleaseMetadata {
contributors: vec![],
},
};
release.update_gitlab_metadata(
vec![
Expand Down
Loading

0 comments on commit 8ffc054

Please sign in to comment.