Skip to content

Commit 4f833ca

Browse files
authored
Merge pull request #1778 from apiraino/query-the-assigned-prs-from-zulip
Add Zulip integration to query PRs assignment
2 parents 75dc576 + 1196b6e commit 4f833ca

File tree

3 files changed

+72
-1
lines changed

3 files changed

+72
-1
lines changed

src/handlers/pull_requests_assignment_update.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::collections::HashMap;
33
use crate::db::notifications::record_username;
44
use crate::github::retrieve_pull_requests;
55
use crate::jobs::Job;
6+
use crate::ReviewPrefs;
67
use anyhow::Context as _;
78
use async_trait::async_trait;
89
use tokio_postgres::Client as DbClient;
@@ -70,3 +71,18 @@ WHERE review_prefs.user_id=$1";
7071
.await
7172
.context("Insert DB error")
7273
}
74+
75+
/// Get pull request assignments for a team member
76+
pub async fn get_review_prefs(db: &DbClient, user_id: u64) -> anyhow::Result<ReviewPrefs> {
77+
let q = "
78+
SELECT username,r.*
79+
FROM review_prefs r
80+
JOIN users on r.user_id=users.user_id
81+
WHERE r.user_id = $1;";
82+
let row = db
83+
.query_one(q, &[&(user_id as i64)])
84+
.await
85+
.context("Error retrieving review preferences")
86+
.unwrap();
87+
Ok(row.into())
88+
}

src/lib.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crate::github::PullRequestDetails;
88
use anyhow::Context;
99
use handlers::HandlerError;
1010
use interactions::ErrorComment;
11+
use serde::Serialize;
1112
use std::fmt;
1213
use tracing as log;
1314

@@ -125,6 +126,37 @@ impl From<anyhow::Error> for WebhookError {
125126
}
126127
}
127128

129+
#[derive(Debug, Serialize)]
130+
pub struct ReviewPrefs {
131+
pub id: uuid::Uuid,
132+
pub username: String,
133+
pub user_id: i64,
134+
pub assigned_prs: Vec<i32>,
135+
}
136+
137+
impl ReviewPrefs {
138+
fn to_string(&self) -> String {
139+
let prs = self
140+
.assigned_prs
141+
.iter()
142+
.map(|pr| format!("#{}", pr))
143+
.collect::<Vec<String>>()
144+
.join(", ");
145+
format!("Username: {}\nAssigned PRs: {}", self.username, prs)
146+
}
147+
}
148+
149+
impl From<tokio_postgres::row::Row> for ReviewPrefs {
150+
fn from(row: tokio_postgres::row::Row) -> Self {
151+
Self {
152+
id: row.get("id"),
153+
username: row.get("username"),
154+
user_id: row.get("user_id"),
155+
assigned_prs: row.get("assigned_prs"),
156+
}
157+
}
158+
}
159+
128160
pub fn deserialize_payload<T: serde::de::DeserializeOwned>(v: &str) -> anyhow::Result<T> {
129161
let mut deserializer = serde_json::Deserializer::from_str(&v);
130162
let res: Result<T, _> = serde_path_to_error::deserialize(&mut deserializer);

src/zulip.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use crate::db::notifications::add_metadata;
22
use crate::db::notifications::{self, delete_ping, move_indices, record_ping, Identifier};
33
use crate::github::{self, GithubClient};
44
use crate::handlers::docs_update::docs_update;
5+
use crate::handlers::pull_requests_assignment_update::get_review_prefs;
56
use crate::handlers::Context;
67
use anyhow::{format_err, Context as _};
78
use std::convert::TryInto;
@@ -155,7 +156,9 @@ fn handle_command<'a>(
155156
Some("move") => move_notification(&ctx, gh_id, words).await
156157
.map_err(|e| format_err!("Failed to parse movement, expected `move <from> <to>`: {e:?}.")),
157158
Some("meta") => add_meta_notification(&ctx, gh_id, words).await
158-
.map_err(|e| format_err!("Failed to parse movement, expected `move <idx> <meta...>`: {e:?}.")),
159+
.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:?}")),
160+
Some("work") => query_pr_assignments(&ctx, gh_id, words).await
161+
.map_err(|e| format_err!("Failed to parse `work` command. Synopsis: work <show>: shows your current PRs assignment\n\nError: {e:?}")),
159162
_ => {
160163
while let Some(word) = next {
161164
if word == "@**triagebot**" {
@@ -199,6 +202,26 @@ fn handle_command<'a>(
199202
})
200203
}
201204

205+
async fn query_pr_assignments(
206+
ctx: &&Context,
207+
gh_id: u64,
208+
mut words: impl Iterator<Item = &str>,
209+
) -> anyhow::Result<Option<String>> {
210+
let subcommand = match words.next() {
211+
Some(subcommand) => subcommand,
212+
None => anyhow::bail!("no subcommand provided"),
213+
};
214+
215+
let db_client = ctx.db.get().await;
216+
217+
let record = match subcommand {
218+
"show" => get_review_prefs(&db_client, gh_id).await?,
219+
_ => anyhow::bail!("Invalid subcommand."),
220+
};
221+
222+
Ok(Some(record.to_string()))
223+
}
224+
202225
// This does two things:
203226
// * execute the command for the other user
204227
// * tell the user executed for that a command was run as them by the user

0 commit comments

Comments
 (0)