Skip to content

Commit

Permalink
Merge pull request #1778 from apiraino/query-the-assigned-prs-from-zulip
Browse files Browse the repository at this point in the history
Add Zulip integration to query PRs assignment
  • Loading branch information
jackh726 authored Feb 27, 2024
2 parents 75dc576 + 1196b6e commit 4f833ca
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 1 deletion.
16 changes: 16 additions & 0 deletions src/handlers/pull_requests_assignment_update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::collections::HashMap;
use crate::db::notifications::record_username;
use crate::github::retrieve_pull_requests;
use crate::jobs::Job;
use crate::ReviewPrefs;
use anyhow::Context as _;
use async_trait::async_trait;
use tokio_postgres::Client as DbClient;
Expand Down Expand Up @@ -70,3 +71,18 @@ WHERE review_prefs.user_id=$1";
.await
.context("Insert DB error")
}

/// Get pull request assignments for a team member
pub async fn get_review_prefs(db: &DbClient, user_id: u64) -> anyhow::Result<ReviewPrefs> {
let q = "
SELECT username,r.*
FROM review_prefs r
JOIN users on r.user_id=users.user_id
WHERE r.user_id = $1;";
let row = db
.query_one(q, &[&(user_id as i64)])
.await
.context("Error retrieving review preferences")
.unwrap();
Ok(row.into())
}
32 changes: 32 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::github::PullRequestDetails;
use anyhow::Context;
use handlers::HandlerError;
use interactions::ErrorComment;
use serde::Serialize;
use std::fmt;
use tracing as log;

Expand Down Expand Up @@ -125,6 +126,37 @@ impl From<anyhow::Error> for WebhookError {
}
}

#[derive(Debug, Serialize)]
pub struct ReviewPrefs {
pub id: uuid::Uuid,
pub username: String,
pub user_id: i64,
pub assigned_prs: Vec<i32>,
}

impl ReviewPrefs {
fn to_string(&self) -> String {
let prs = self
.assigned_prs
.iter()
.map(|pr| format!("#{}", pr))
.collect::<Vec<String>>()
.join(", ");
format!("Username: {}\nAssigned PRs: {}", self.username, prs)
}
}

impl From<tokio_postgres::row::Row> for ReviewPrefs {
fn from(row: tokio_postgres::row::Row) -> Self {
Self {
id: row.get("id"),
username: row.get("username"),
user_id: row.get("user_id"),
assigned_prs: row.get("assigned_prs"),
}
}
}

pub fn deserialize_payload<T: serde::de::DeserializeOwned>(v: &str) -> anyhow::Result<T> {
let mut deserializer = serde_json::Deserializer::from_str(&v);
let res: Result<T, _> = serde_path_to_error::deserialize(&mut deserializer);
Expand Down
25 changes: 24 additions & 1 deletion src/zulip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ use crate::db::notifications::add_metadata;
use crate::db::notifications::{self, delete_ping, move_indices, record_ping, Identifier};
use crate::github::{self, GithubClient};
use crate::handlers::docs_update::docs_update;
use crate::handlers::pull_requests_assignment_update::get_review_prefs;
use crate::handlers::Context;
use anyhow::{format_err, Context as _};
use std::convert::TryInto;
Expand Down Expand Up @@ -155,7 +156,9 @@ fn handle_command<'a>(
Some("move") => move_notification(&ctx, gh_id, words).await
.map_err(|e| format_err!("Failed to parse movement, expected `move <from> <to>`: {e:?}.")),
Some("meta") => add_meta_notification(&ctx, gh_id, words).await
.map_err(|e| format_err!("Failed to parse movement, expected `move <idx> <meta...>`: {e:?}.")),
.map_err(|e| format_err!("Failed to parse `meta` command. Synopsis: meta <num> <text>: Add <text> to your notification identified by <num> (>0)\n\nError: {e:?}")),
Some("work") => query_pr_assignments(&ctx, gh_id, words).await
.map_err(|e| format_err!("Failed to parse `work` command. Synopsis: work <show>: shows your current PRs assignment\n\nError: {e:?}")),
_ => {
while let Some(word) = next {
if word == "@**triagebot**" {
Expand Down Expand Up @@ -199,6 +202,26 @@ fn handle_command<'a>(
})
}

async fn query_pr_assignments(
ctx: &&Context,
gh_id: u64,
mut words: impl Iterator<Item = &str>,
) -> anyhow::Result<Option<String>> {
let subcommand = match words.next() {
Some(subcommand) => subcommand,
None => anyhow::bail!("no subcommand provided"),
};

let db_client = ctx.db.get().await;

let record = match subcommand {
"show" => get_review_prefs(&db_client, gh_id).await?,
_ => anyhow::bail!("Invalid subcommand."),
};

Ok(Some(record.to_string()))
}

// This does two things:
// * execute the command for the other user
// * tell the user executed for that a command was run as them by the user
Expand Down

0 comments on commit 4f833ca

Please sign in to comment.