git-next/crates/forge-forgejo/src/webhook/register.rs

76 lines
2.7 KiB
Rust
Raw Normal View History

//
use git_next_core::{git, server, RegisteredWebhook, WebhookAuth, WebhookId};
use kxio::network;
use tracing::{info, warn};
use crate::webhook;
use crate::webhook::Hook;
#[tracing::instrument(skip_all)]
pub async fn register(
repo_details: &git::RepoDetails,
webhook_url: &server::WebhookUrl,
net: &network::Network,
) -> git::forge::webhook::Result<RegisteredWebhook> {
let Some(repo_config) = repo_details.repo_config.clone() else {
return Err(git::forge::webhook::Error::NoRepoConfig);
};
// remove any lingering webhooks for the same URL
let existing_webhook_ids = webhook::list(repo_details, webhook_url, net).await?;
for webhook_id in existing_webhook_ids {
webhook::unregister(&webhook_id, repo_details, net).await?;
}
let hostname = &repo_details.forge.hostname();
let repo_path = &repo_details.repo_path;
use secrecy::ExposeSecret;
let token = repo_details.forge.token().expose_secret();
let url = network::NetUrl::new(format!(
"https://{hostname}/api/v1/repos/{repo_path}/hooks?token={token}"
));
let repo_alias = &repo_details.repo_alias;
let headers = network::NetRequestHeaders::new().with("Content-Type", "application/json");
let authorisation = WebhookAuth::generate();
let body = network::json!({
"active": true,
"authorization_header": authorisation.header_value(),
"branch_filter": format!("{{{},{},{}}}", repo_config.branches().main(), repo_config.branches().next(), repo_config.branches().dev()),
"config": {
"content_type": "json",
"url": format!("{}/{}", webhook_url.as_ref(), repo_alias),
},
"events": [ "push" ],
"type": "forgejo"
});
let request = network::NetRequest::new(
network::RequestMethod::Post,
url,
headers,
network::RequestBody::Json(body),
network::ResponseType::Json,
None,
network::NetRequestLogging::None,
);
let result = net.post_json::<Hook>(request).await;
match result {
Ok(response) => {
let Some(hook) = response.response_body() else {
#[cfg(not(tarpaulin_include))]
// request response is Json so response_body never returns None
return Err(git::forge::webhook::Error::NetworkResponseEmpty);
};
info!(webhook_id = %hook.id, "Webhook registered");
Ok(RegisteredWebhook::new(
WebhookId::new(format!("{}", hook.id)),
authorisation,
))
}
Err(e) => {
warn!("Failed to register webhook");
Err(git::forge::webhook::Error::FailedToRegister(e.to_string()))
}
}
}