From b281cf8b44738e986311136eaa4921625ae535f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maxime=20=E2=80=9Cpep=E2=80=9D=20Buquet?= Date: Sat, 31 Aug 2024 22:16:19 +0200 Subject: [PATCH] Readd support for Gitlab's NoteHook MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trying to reuse other converters so that we don't have to redo all the work Signed-off-by: Maxime “pep” Buquet --- src/hook.rs | 328 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 233 insertions(+), 95 deletions(-) diff --git a/src/hook.rs b/src/hook.rs index c149310..c45461e 100644 --- a/src/hook.rs +++ b/src/hook.rs @@ -17,7 +17,10 @@ use crate::Error; pub use forgejo_hooks::Hook as ForgejoHook; pub use gitlab::webhooks::{ - IssueAction as GlIssueAction, MergeRequestAction, WebHook as GitlabHook, WikiPageAction, + CommitHookAttrs, IssueAction as GlIssueAction, IssueHook as GlIssueHook, + IssueHookAttrs as GlIssueHookAttrs, MergeRequestAction as GlMergeRequestAction, + MergeRequestHook as GlMergeRequestHook, MergeRequestHookAttrs as GlMergeRequestHookAttrs, + NoteHook as GlNoteHook, PushHook as GlPushHook, WebHook as GitlabHook, WikiPageAction, }; use log::debug; @@ -30,6 +33,8 @@ pub(crate) struct User { #[derive(Debug, Clone)] pub(crate) struct Commit { + /// Reference of the commit + ref_: String, /// Commit message message: String, /// URL where the commit can be read at @@ -74,6 +79,52 @@ pub(crate) struct Issue { url: Option, } +#[derive(Debug, Clone)] +pub(crate) struct IssueAttrs { + id: u64, + title: String, +} + +#[derive(Debug, Clone)] +pub(crate) enum MergeRequestAction { + Update, + Open, + Close, + Reopen, + Merge, + Approved, + Unapproved, + Approval, + Unapproval, +} + +#[derive(Debug, Clone)] +pub(crate) struct MergeRequest { + action: Option, + repository: Repository, + author: User, + id: u64, + title: String, + url: Option, +} + +#[derive(Debug, Clone)] +pub(crate) struct MergeRequestAttrs { + id: u64, + title: String, +} + +#[derive(Debug, Clone)] +pub(crate) struct Note { + snippet: bool, + commit: Option, + issue: Option, + merge_request: Option, + repository: Repository, + author: User, + url: String, +} + /// Lowest common denominator struct so that we don't have to duplicate our code for each platform /// we support. #[derive(Debug)] @@ -81,6 +132,131 @@ pub(crate) enum Hook { /// Push event Push(Push), Issue(Issue), + MergeRequest(MergeRequest), + Note(Note), +} + +impl From for Commit { + fn from(other: CommitHookAttrs) -> Commit { + Commit { + ref_: other.id, + message: other.message, + url: other.url, + } + } +} + +impl From for Push { + fn from(other: GlPushHook) -> Push { + Push { + ref_: other.ref_, + object_kind: other.object_kind, + commits: other.commits.into_iter().map(Into::into).collect(), + repository: Repository { + name: other.project.name, + }, + pusher: User { + name: other.user_name, + }, + } + } +} + +impl From for IssueAction { + fn from(other: GlIssueAction) -> IssueAction { + match other { + GlIssueAction::Update => IssueAction::Update, + GlIssueAction::Open => IssueAction::Open, + GlIssueAction::Close => IssueAction::Close, + GlIssueAction::Reopen => IssueAction::Reopen, + } + } +} + +impl From for Issue { + fn from(other: GlIssueHook) -> Issue { + Issue { + action: other.object_attributes.action.map(Into::into), + repository: Repository { + name: other.project.name, + }, + author: User { + name: other.user.name, + }, + id: other.object_attributes.iid, + title: other.object_attributes.title, + url: other.object_attributes.url, + } + } +} + +impl From for IssueAttrs { + fn from(other: GlIssueHookAttrs) -> IssueAttrs { + IssueAttrs { + id: other.iid, + title: other.title, + } + } +} + +impl From for MergeRequestAction { + fn from(other: GlMergeRequestAction) -> MergeRequestAction { + match other { + GlMergeRequestAction::Update => MergeRequestAction::Update, + GlMergeRequestAction::Open => MergeRequestAction::Open, + GlMergeRequestAction::Close => MergeRequestAction::Close, + GlMergeRequestAction::Reopen => MergeRequestAction::Reopen, + GlMergeRequestAction::Merge => MergeRequestAction::Merge, + GlMergeRequestAction::Approved => MergeRequestAction::Approved, + GlMergeRequestAction::Unapproved => MergeRequestAction::Unapproved, + GlMergeRequestAction::Approval => MergeRequestAction::Approval, + GlMergeRequestAction::Unapproval => MergeRequestAction::Unapproval, + } + } +} + +impl From for MergeRequest { + fn from(other: GlMergeRequestHook) -> MergeRequest { + MergeRequest { + action: other.object_attributes.action.map(Into::into), + repository: Repository { + name: other.project.name, + }, + author: User { + name: other.user.name, + }, + id: other.object_attributes.iid, + title: other.object_attributes.title, + url: other.object_attributes.url, + } + } +} + +impl From for MergeRequestAttrs { + fn from(other: GlMergeRequestHookAttrs) -> MergeRequestAttrs { + MergeRequestAttrs { + id: other.id, + title: other.title, + } + } +} + +impl From for Note { + fn from(other: GlNoteHook) -> Note { + Note { + snippet: other.snippet.is_some(), + commit: other.commit.map(Into::into), + issue: other.issue.map(Into::into), + merge_request: other.merge_request.map(Into::into), + repository: Repository { + name: other.project.name, + }, + author: User { + name: other.user.name, + }, + url: other.object_attributes.url, + } + } } impl TryFrom for Hook { @@ -88,41 +264,10 @@ impl TryFrom for Hook { fn try_from(hook: GitlabHook) -> Result { Ok(match hook { - GitlabHook::Push(push) => Hook::Push(Push { - ref_: push.ref_, - object_kind: push.object_kind, - commits: push - .commits - .into_iter() - .map(|commit| Commit { - message: commit.message, - url: commit.url, - }) - .collect(), - repository: Repository { - name: push.project.name, - }, - pusher: User { - name: push.user_name, - }, - }), - GitlabHook::Issue(issue) => Hook::Issue(Issue { - action: issue.object_attributes.action.map(|action| match action { - GlIssueAction::Update => IssueAction::Update, - GlIssueAction::Open => IssueAction::Open, - GlIssueAction::Close => IssueAction::Close, - GlIssueAction::Reopen => IssueAction::Reopen, - }), - repository: Repository { - name: issue.project.name, - }, - author: User { - name: issue.user.name, - }, - id: issue.object_attributes.iid, - title: issue.object_attributes.title, - url: issue.object_attributes.url, - }), + GitlabHook::Push(push) => Hook::Push((*push).into()), + GitlabHook::Issue(issue) => Hook::Issue((*issue).into()), + GitlabHook::MergeRequest(mr) => Hook::MergeRequest((*mr).into()), + GitlabHook::Note(note) => Hook::Note((*note).into()), _ => return Err(Error::UnsupportedHookConversion), }) } @@ -140,6 +285,7 @@ impl TryFrom for Hook { .commits .into_iter() .map(|commit| Commit { + ref_: commit.id, message: commit.message, url: commit.url, }) @@ -213,66 +359,58 @@ pub(crate) fn format_hook(hook: &Hook) -> Option { .map(|url| format!(" <{}>", url)) .unwrap_or("".to_owned()) ) + } + Hook::MergeRequest(merge_req) => { + let action = match merge_req.action { + Some(MergeRequestAction::Update) => return None, + Some(MergeRequestAction::Open) => "opened", + Some(MergeRequestAction::Close) => "closed", + Some(MergeRequestAction::Reopen) => "reopened", + Some(MergeRequestAction::Merge) => "merged", + None => return None, + _ => { + log::warn!("Unsupported merge request action: {:?}", merge_req.action); + return None; + } + }; + format!( + "[{}] {} {} merge request {}: {}{}", + merge_req.repository.name, + merge_req.author.name, + action, + merge_req.id, + merge_req.title, + merge_req + .url + .as_ref() + .map(|url| format!(" <{}>", url)) + .unwrap_or("".to_owned()) + ) + } + Hook::Note(note) => { + if note.snippet { + return None; + } + if let Some(commit) = ¬e.commit { + format!( + "[{}] {} commented on commit {:?} <{}>", + note.repository.name, note.author.name, commit.ref_, commit.url, + ) + } else if let Some(issue) = ¬e.issue { + format!( + "[{}] {} commented on issue {}: {} <{}>", + note.repository.name, note.author.name, issue.id, issue.title, note.url, + ) + } else if let Some(mr) = ¬e.merge_request { + format!( + "[{}] {} commented on merge request {}: {} <{}>", + note.repository.name, note.author.name, mr.id, mr.title, note.url, + ) + } else { + unreachable!() + } } /* - Hook::MergeRequest(merge_req) => { - let action = match merge_req.object_attributes.action { - Some(MergeRequestAction::Update) => return None, - Some(MergeRequestAction::Open) => "opened", - Some(MergeRequestAction::Close) => "closed", - Some(MergeRequestAction::Reopen) => "reopened", - Some(MergeRequestAction::Merge) => "merged", - None => return None, - _ => { - log::warn!( - "Unsupported merge request action: {:?}", - merge_req.object_attributes.action - ); - return None; - } - }; - format!( - "[{}] {} {} merge request {}: {}{}", - merge_req.project.name, - merge_req.user.name, - action, - merge_req.object_attributes.iid, - merge_req.object_attributes.title, - merge_req - .object_attributes - .url - .as_ref() - .map(|url| format!(" <{}>", url)) - .unwrap_or("".to_owned()) - ) - } - Hook::Note(note) => { - if let Some(_) = note.snippet { - return None; - } - if let Some(commit) = ¬e.commit { - format!( - "[{}] {} commented on commit {:?} <{}>", - note.project.name, note.user.name, commit.id, commit.url, - ) - } else if let Some(issue) = ¬e.issue { - format!( - "[{}] {} commented on issue {}: {} <{}>", - note.project.name, - note.user.name, - issue.iid, - issue.title, - note.object_attributes.url, - ) - } else if let Some(mr) = ¬e.merge_request { - format!( - "[{}] {} commented on merge request {}: {} <{}>", - note.project.name, note.user.name, mr.iid, mr.title, note.object_attributes.url, - ) - } else { - unreachable!() - } - } - Hook::Build(build) => { + Hook::Build(build) => { println!("Build: {:?}", build); return None; }