feat: ignore github ping webhook messages

Closes kemitix/git-next#101
This commit is contained in:
Paul Campbell 2024-06-30 15:20:00 +01:00
parent 8fceafc3e1
commit 55d8ccb0bd
5 changed files with 74 additions and 2 deletions

View file

@ -34,6 +34,18 @@ impl git::ForgeLike for Github {
github::webhook::is_authorised(msg, webhook_auth)
}
fn should_ignore_message(&self, message: &config::ForgeNotification) -> bool {
let Some(event) = message.header("x-github-event") else {
return false;
};
if event == "ping" {
tracing::info!("successfull ping received");
return true;
}
tracing::info!(%event, "message");
false
}
fn parse_webhook_body(
&self,
body: &config::webhook::forge_notification::Body,

File diff suppressed because one or more lines are too long

View file

@ -7,13 +7,20 @@ pub trait ForgeLike: std::fmt::Debug + Send + Sync {
fn duplicate(&self) -> Box<dyn ForgeLike>;
fn name(&self) -> String;
/// Checks that the message has a valid authorisation
/// Checks that the message has a valid authorisation.
fn is_message_authorised(
&self,
message: &config::ForgeNotification,
expected: &config::WebhookAuth,
) -> bool;
/// Checks if the message should be ignored.
///
/// Default implementation says that no messages should be ignored.
fn should_ignore_message(&self, _message: &config::ForgeNotification) -> bool {
false
}
/// Parses the webhook body into Some(Push) struct if appropriate, or None if not.
fn parse_webhook_body(
&self,

View file

@ -34,6 +34,10 @@ impl Handler<WebhookNotification> for actor::RepoActor {
);
return;
}
if self.forge.should_ignore_message(&msg) {
actor::logger(&self.log, "forge sent ignorable message");
return;
}
let body = msg.body();
match self.forge.parse_webhook_body(body) {
Err(err) => {

View file

@ -107,6 +107,48 @@ async fn when_message_auth_is_invalid_drop_notification() -> TestResult {
Ok(())
}
#[actix::test]
async fn when_message_is_ignorable_drop_notification() -> TestResult {
//given
let fs = given::a_filesystem();
let repo_details = given::repo_details(&fs);
let forge_alias = given::a_forge_alias();
let repo_alias = given::a_repo_alias();
let headers = BTreeMap::new();
let body = Body::new("".to_string());
let forge_notification = ForgeNotification::new(forge_alias, repo_alias, headers, body);
let repository_factory = MockRepositoryFactory::new();
let mut forge = given::a_forge();
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| true);
forge
.expect_parse_webhook_body()
.return_once(|_| Err(git::forge::webhook::Error::NetworkResponseEmpty));
let (actor, log) = given::a_repo_actor(
repo_details,
Box::new(repository_factory),
forge,
given::a_network().into(),
);
let actor = actor.with_webhook_auth(Some(given::a_webhook_auth()));
//when
actor
.start()
.send(actor::messages::WebhookNotification::new(
forge_notification,
))
.await?;
System::current().stop();
//then
log.no_message_contains("send")?;
log.require_message_containing("forge sent ignorable message")?;
Ok(())
}
#[actix::test]
async fn when_message_is_not_a_push_drop_notification() -> TestResult {
//given
@ -122,6 +164,7 @@ async fn when_message_is_not_a_push_drop_notification() -> TestResult {
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge
.expect_parse_webhook_body()
.return_once(|_| Err(git::forge::webhook::Error::NetworkResponseEmpty));
@ -169,6 +212,7 @@ async fn when_message_is_push_on_unknown_branch_drop_notification() -> TestResul
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,
@ -216,6 +260,7 @@ async fn when_message_is_push_already_seen_commit_to_main() -> TestResult {
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,
@ -263,6 +308,7 @@ async fn when_message_is_push_already_seen_commit_to_next() -> TestResult {
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,
@ -310,6 +356,7 @@ async fn when_message_is_push_already_seen_commit_to_dev() -> TestResult {
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,
@ -357,6 +404,7 @@ async fn when_message_is_push_new_commit_to_main_should_stash_and_validate_repo(
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,
@ -404,6 +452,7 @@ async fn when_message_is_push_new_commit_to_next_should_stash_and_validate_repo(
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,
@ -451,6 +500,7 @@ async fn when_message_is_push_new_commit_to_dev_should_stash_and_validate_repo()
forge
.expect_is_message_authorised()
.return_once(|_, _| true); // is valid
forge.expect_should_ignore_message().returning(|_| false);
forge.expect_parse_webhook_body().return_once(|_| Ok(push));
let (actor, log) = given::a_repo_actor(
repo_details,