Skip to content

Commit

Permalink
feat(remote): support enabling native TLS (#1021)
Browse files Browse the repository at this point in the history
  • Loading branch information
orhun authored Jan 23, 2025
1 parent 20483be commit fe7c464
Show file tree
Hide file tree
Showing 18 changed files with 237 additions and 87 deletions.
62 changes: 62 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions git-cliff-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ semver = "1.0.25"
document-features = { version = "0.2.10", optional = true }
reqwest = { version = "0.12.12", default-features = false, features = [
"rustls-tls",
"rustls-tls-native-roots",
"json",
"zstd",
], optional = true }
Expand Down
44 changes: 24 additions & 20 deletions git-cliff-core/src/changelog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -838,32 +838,36 @@ mod test {
},
remote: RemoteConfig {
github: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
native_tls: None,
},
gitlab: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
native_tls: None,
},
gitea: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
native_tls: None,
},
bitbucket: Remote {
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
owner: String::from("coolguy"),
repo: String::from("awesome"),
token: None,
is_custom: false,
api_url: None,
native_tls: None,
},
},
bump: Bump::default(),
Expand Down
43 changes: 33 additions & 10 deletions git-cliff-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,23 +167,45 @@ impl RemoteConfig {
}
false
}

/// Enables the native TLS for all remotes.
pub fn enable_native_tls(&mut self) {
#[cfg(feature = "github")]
{
self.github.native_tls = Some(true);
}
#[cfg(feature = "gitlab")]
{
self.gitlab.native_tls = Some(true);
}
#[cfg(feature = "gitea")]
{
self.gitea.native_tls = Some(true);
}
#[cfg(feature = "bitbucket")]
{
self.bitbucket.native_tls = Some(true);
}
}
}

/// A single remote.
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
pub struct Remote {
/// Owner of the remote.
pub owner: String,
pub owner: String,
/// Repository name.
pub repo: String,
pub repo: String,
/// Access token.
#[serde(skip_serializing)]
pub token: Option<SecretString>,
pub token: Option<SecretString>,
/// Whether if the remote is set manually.
#[serde(skip_deserializing, default = "default_true")]
pub is_custom: bool,
pub is_custom: bool,
/// Remote API URL.
pub api_url: Option<String>,
pub api_url: Option<String>,
/// Whether to use native TLS.
pub native_tls: Option<bool>,
}

/// Returns `true` for serde's `default` attribute.
Expand All @@ -207,11 +229,12 @@ impl Remote {
/// Constructs a new instance.
pub fn new<S: Into<String>>(owner: S, repo: S) -> Self {
Self {
owner: owner.into(),
repo: repo.into(),
token: None,
is_custom: false,
api_url: None,
owner: owner.into(),
repo: repo.into(),
token: None,
is_custom: false,
api_url: None,
native_tls: None,
}
}

Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/remote/bitbucket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ impl TryFrom<Remote> for BitbucketClient {
type Error = Error;
fn try_from(remote: Remote) -> Result<Self> {
Ok(Self {
client: create_remote_client(&remote, "application/json")?,
client: remote.create_client("application/json")?,
remote,
})
}
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/remote/gitea.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl TryFrom<Remote> for GiteaClient {
type Error = Error;
fn try_from(remote: Remote) -> Result<Self> {
Ok(Self {
client: create_remote_client(&remote, "application/json")?,
client: remote.create_client("application/json")?,
remote,
})
}
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/remote/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ impl TryFrom<Remote> for GitHubClient {
type Error = Error;
fn try_from(remote: Remote) -> Result<Self> {
Ok(Self {
client: create_remote_client(&remote, "application/vnd.github+json")?,
client: remote.create_client("application/vnd.github+json")?,
remote,
})
}
Expand Down
2 changes: 1 addition & 1 deletion git-cliff-core/src/remote/gitlab.rs
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ impl TryFrom<Remote> for GitLabClient {
type Error = Error;
fn try_from(remote: Remote) -> Result<Self> {
Ok(Self {
client: create_remote_client(&remote, "application/json")?,
client: remote.create_client("application/json")?,
remote,
})
}
Expand Down
81 changes: 43 additions & 38 deletions git-cliff-core/src/remote/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,47 +124,52 @@ pub struct RemoteReleaseMetadata {
pub contributors: Vec<RemoteContributor>,
}

/// Creates a HTTP client for the remote.
fn create_remote_client(
remote: &Remote,
accept_header: &str,
) -> Result<ClientWithMiddleware> {
if !remote.is_set() {
return Err(Error::RemoteNotSetError);
}
let mut headers = HeaderMap::new();
headers.insert(
reqwest::header::ACCEPT,
HeaderValue::from_str(accept_header)?,
);
if let Some(token) = &remote.token {
impl Remote {
/// Creates a HTTP client for the remote.
fn create_client(&self, accept_header: &str) -> Result<ClientWithMiddleware> {
if !self.is_set() {
return Err(Error::RemoteNotSetError);
}
let mut headers = HeaderMap::new();
headers.insert(
reqwest::header::AUTHORIZATION,
format!("Bearer {}", token.expose_secret()).parse()?,
reqwest::header::ACCEPT,
HeaderValue::from_str(accept_header)?,
);
if let Some(token) = &self.token {
headers.insert(
reqwest::header::AUTHORIZATION,
format!("Bearer {}", token.expose_secret()).parse()?,
);
}
headers.insert(reqwest::header::USER_AGENT, USER_AGENT.parse()?);
let client_builder = Client::builder()
.timeout(Duration::from_secs(REQUEST_TIMEOUT))
.tcp_keepalive(Duration::from_secs(REQUEST_KEEP_ALIVE))
.default_headers(headers)
.tls_built_in_root_certs(false);
let client_builder = if self.native_tls.unwrap_or(false) {
client_builder.tls_built_in_native_certs(true)
} else {
client_builder.tls_built_in_webpki_certs(true)
};
let client = client_builder.build()?;
let client = ClientBuilder::new(client)
.with(Cache(HttpCache {
mode: CacheMode::Default,
manager: CACacheManager {
path: dirs::cache_dir()
.ok_or_else(|| {
Error::DirsError(String::from(
"failed to find the user's cache directory",
))
})?
.join(env!("CARGO_PKG_NAME")),
},
options: HttpCacheOptions::default(),
}))
.build();
Ok(client)
}
headers.insert(reqwest::header::USER_AGENT, USER_AGENT.parse()?);
let client = Client::builder()
.timeout(Duration::from_secs(REQUEST_TIMEOUT))
.tcp_keepalive(Duration::from_secs(REQUEST_KEEP_ALIVE))
.default_headers(headers)
.build()?;
let client = ClientBuilder::new(client)
.with(Cache(HttpCache {
mode: CacheMode::Default,
manager: CACacheManager {
path: dirs::cache_dir()
.ok_or_else(|| {
Error::DirsError(String::from(
"failed to find the user's cache directory",
))
})?
.join(env!("CARGO_PKG_NAME")),
},
options: HttpCacheOptions::default(),
}))
.build();
Ok(client)
}

/// Trait for handling the API connection and fetching.
Expand Down
Loading

0 comments on commit fe7c464

Please sign in to comment.