Add support for issue events

This commit is contained in:
2023-09-16 20:26:59 -07:00
parent faba9d8b69
commit 821dcdf277
4 changed files with 261 additions and 40 deletions

View File

@ -1,6 +1,6 @@
pub trait GitlabEventExt {
fn project(&self) -> &Project;
fn r#ref(&self) -> &str;
fn r#ref(&self) -> Option<&str>;
fn user(&self) -> &str;
fn titles(&self) -> Vec<String>;
}
@ -109,6 +109,40 @@ pub struct PipelineMergeRequest {
pub title: String,
}
#[derive(PartialEq, Debug, Deserialize)]
pub enum IssueAction {
#[serde(rename = "open")]
Opened,
#[serde(rename = "close")]
Closed,
#[serde(rename = "reopen")]
Reopened,
#[serde(rename = "update")]
Updated,
#[serde(other)]
Other,
}
impl IssueAction {
pub fn as_str(&self) -> &str {
match self {
IssueAction::Opened => "opened",
IssueAction::Closed => "closed",
IssueAction::Reopened => "reopened",
IssueAction::Updated => "updated",
IssueAction::Other => "other",
}
}
}
#[derive(Debug, Deserialize)]
pub struct IssueObjectAttributes {
id: u32,
title: String,
action: IssueAction,
url: String,
}
#[derive(Debug, Deserialize)]
#[serde(tag = "object_kind")]
pub enum GitlabEvent {
@ -148,6 +182,12 @@ pub enum GitlabEvent {
commits: Vec<Commit>,
total_commits_count: u64,
},
#[serde(rename = "issue")]
Issue {
user: User,
project: Project,
object_attributes: IssueObjectAttributes,
},
#[serde(rename = "merge_request")]
MergeRequest {
user: User,
@ -169,17 +209,19 @@ impl GitlabEventExt for GitlabEvent {
match self {
GitlabEvent::Push { project, .. } => &project,
GitlabEvent::TagPush { project, .. } => &project,
GitlabEvent::Issue { project, .. } => project,
GitlabEvent::MergeRequest { project, .. } => &project,
GitlabEvent::Pipeline { project, .. } => &project,
}
}
fn r#ref(&self) -> &str {
fn r#ref(&self) -> Option<&str> {
match self {
GitlabEvent::Push { r#ref, .. } => &r#ref,
GitlabEvent::TagPush { r#ref, .. } => &r#ref,
GitlabEvent::MergeRequest { object_attributes, .. } => &object_attributes.target_branch,
GitlabEvent::Pipeline { object_attributes, .. } => &object_attributes.r#ref,
GitlabEvent::Push { r#ref, .. } => Some(&r#ref),
GitlabEvent::TagPush { r#ref, .. } => Some(&r#ref),
GitlabEvent::Issue { .. } => None,
GitlabEvent::MergeRequest { object_attributes, .. } => Some(&object_attributes.target_branch),
GitlabEvent::Pipeline { object_attributes, .. } => Some(&object_attributes.r#ref),
}
}
@ -187,6 +229,7 @@ impl GitlabEventExt for GitlabEvent {
match self {
GitlabEvent::Push { user_name, .. } => &user_name,
GitlabEvent::TagPush { user_name, .. } => &user_name,
GitlabEvent::Issue { user, .. } => &user.name,
GitlabEvent::MergeRequest { user, .. } => &user.name,
GitlabEvent::Pipeline { user, .. } => &user.name,
}
@ -239,31 +282,52 @@ impl GitlabEventExt for GitlabEvent {
let url = format!("{}/-/tags/{}", project.web_url, parse_ref(r#ref));
vec![markdown_link(&title, &url)]
}
GitlabEvent::Issue { object_attributes, .. } => {
if object_attributes.action != IssueAction::Other {
let title = format!(
"Issue #{} **{}**: {}",
object_attributes.id,
object_attributes.action.as_str(),
object_attributes.title
);
vec![markdown_link(&title, &object_attributes.url)]
} else {
vec![]
}
}
GitlabEvent::MergeRequest { object_attributes, .. } => {
let title = format!(
"MR !{} **{}**: {}",
object_attributes.iid,
object_attributes.action.as_str(),
object_attributes.title
);
vec![markdown_link(&title, &object_attributes.url)]
if object_attributes.action != MergeRequestAction::Other {
let title = format!(
"MR !{} **{}**: {}",
object_attributes.iid,
object_attributes.action.as_str(),
object_attributes.title
);
vec![markdown_link(&title, &object_attributes.url)]
} else {
vec![]
}
}
GitlabEvent::Pipeline {
object_attributes,
merge_request,
..
} => {
let title = object_attributes
.name
.as_ref()
.map(|n| n.clone())
.or(merge_request.as_ref().map(|mr| mr.title.clone()))
.iter()
.fold(
format!("Pipeline **{}**", object_attributes.status.as_str()),
|accum, title| format!("{}: {}", accum, title),
);
vec![markdown_link(&title, &object_attributes.url)]
if object_attributes.status != PipelineStatus::Other {
let title = object_attributes
.name
.as_ref()
.map(|n| n.clone())
.or(merge_request.as_ref().map(|mr| mr.title.clone()))
.iter()
.fold(
format!("Pipeline **{}**", object_attributes.status.as_str()),
|accum, title| format!("{}: {}", accum, title),
);
vec![markdown_link(&title, &object_attributes.url)]
} else {
vec![]
}
}
}
}
@ -368,6 +432,26 @@ mod test {
Ok(())
}
#[test]
pub fn parse_issue_event() -> anyhow::Result<()> {
let event = load_test_data("issue-event")?;
match event {
GitlabEvent::Issue {
user,
object_attributes,
..
} => {
assert_eq!(user.name, "Administrator");
assert_eq!(object_attributes.id, 301);
assert_eq!(object_attributes.action, IssueAction::Opened);
}
_ => panic!("not an issue event"),
}
Ok(())
}
#[test]
pub fn parse_merge_request_event() -> anyhow::Result<()> {
let event = load_test_data("merge-request-event")?;

View File

@ -23,8 +23,6 @@ use matrix_sdk::{
use tokio::sync::mpsc;
use warp::Filter;
use crate::event::{MergeRequestAction, PipelineStatus};
async fn build_sync_settings(matrix_client: &Client) -> SyncSettings {
let mut settings = SyncSettings::default().timeout(Duration::from_secs(30));
if let Some(token) = matrix_client.sync_token().await {
@ -107,15 +105,18 @@ async fn ensure_matrix_room_joined(matrix_client: &Client, room_id: &OwnedRoomOr
fn build_gitlab_messages(event: &GitlabEvent) -> Vec<String> {
let project = event.project();
let refname = event::parse_ref(event.r#ref());
let refname = event.r#ref().map(event::parse_ref);
event
.titles()
.iter()
.map(|title| {
format!(
"\\[{}\\] `{}` *{}* {}",
"\\[{}\\] {}*{}* {}",
project.path_with_namespace,
refname,
refname
.as_ref()
.map(|rn| format!("`{}` ", rn))
.unwrap_or_else(|| "".to_string()),
event.user(),
title,
)
@ -128,16 +129,6 @@ async fn handle_gitlab_event(
room_id: &OwnedRoomOrAliasId,
matrix_client: &Client,
) -> anyhow::Result<()> {
if let GitlabEvent::MergeRequest { object_attributes, .. } = &event {
if object_attributes.action == MergeRequestAction::Other {
return Ok(());
}
} else if let GitlabEvent::Pipeline { object_attributes, .. } = &event {
if object_attributes.status == PipelineStatus::Other {
return Ok(());
}
}
let room = ensure_matrix_room_joined(matrix_client, room_id).await?;
for msg in build_gitlab_messages(&event) {
debug!("Sending message to {}: {}", room_id, msg);