Przeglądaj źródła

get initializing comment content

chaz-kiker 3 lat temu
rodzic
commit
851ac34719
5 zmienionych plików z 201 dodań i 54 usunięć
  1. 16 24
      src/actions.rs
  2. 92 22
      src/github.rs
  3. 2 0
      src/github/graphql.rs
  4. 89 6
      src/rfcbot.rs
  5. 2 2
      templates/_issues_fcps.tt

+ 16 - 24
src/actions.rs

@@ -44,6 +44,16 @@ pub struct IssueDecorator {
     pub labels: String,
     pub assignees: String,
     pub updated_at: String,
+
+    pub fcp_details: Option<FCPDetails>,
+}
+
+#[derive(Serialize, Deserialize, Debug)]
+pub struct FCPDetails {
+    pub bot_tracking_comment_html_url: String,
+    pub bot_tracking_comment_content: String,
+    pub initiating_comment_html_url: String,
+    pub initiating_comment_content: String,
 }
 
 #[derive(Serialize, Deserialize, Debug)]
@@ -99,7 +109,7 @@ impl<'a> Action for Step<'a> {
                 };
 
                 for QueryMap { name, kind, query } in queries {
-                    let issues = query.query(&repository, &gh).await;
+                    let issues = query.query(&repository, name == &"proposed_fcp", &gh).await;
 
                     match issues {
                         Ok(issues_decorator) => match kind {
@@ -133,30 +143,12 @@ impl<'a> Action for Step<'a> {
         }
 
         for (name, issues) in &results {
-            if name == &"proposed_fcp" {
-                let fcp_map = crate::rfcbot::get_all_fcps().await.unwrap();
-
-                let fcp_results = issues
-                    .into_iter()
-                    .filter_map(|issue_decorator| {
-                        let key = format!(
-                            "rust-lang/{}:{}:{}",
-                            issue_decorator.repo_name.clone(),
-                            issue_decorator.number.clone(),
-                            issue_decorator.title.clone(),
-                        );
-                        if let Some(fcp) = fcp_map.get(&key) {
-                            Some(FCPDecorator::from_issue_fcp(&fcp, &issue_decorator))
-                        } else {
-                            None
-                        }
-                    })
-                    .collect::<Vec<_>>();
+            // if name == &"proposed_fcp" {
 
-                context.insert(*name, &fcp_results);
-            } else {
-                context.insert(*name, issues);
-            }
+            //     context.insert(*name, &fcp_results);
+            // } else {
+            // }
+            context.insert(*name, issues);
         }
 
         TEMPLATES

+ 92 - 22
src/github.rs

@@ -1,17 +1,18 @@
 use anyhow::Context;
-use tracing as log;
-
 use async_trait::async_trait;
 use chrono::{DateTime, FixedOffset, Utc};
+use futures::future::try_join_all;
 use futures::{future::BoxFuture, FutureExt};
 use hyper::header::HeaderValue;
 use once_cell::sync::OnceCell;
 use reqwest::header::{AUTHORIZATION, USER_AGENT};
 use reqwest::{Client, Request, RequestBuilder, Response, StatusCode};
+use std::convert::TryInto;
 use std::{
     fmt,
     time::{Duration, SystemTime},
 };
+use tracing as log;
 
 pub mod graphql;
 
@@ -1044,11 +1045,20 @@ pub struct Query<'a> {
     pub exclude_labels: Vec<&'a str>,
 }
 
+fn quote_reply(markdown: &str) -> String {
+    if markdown.is_empty() {
+        String::from("*No content*")
+    } else {
+        format!("\n\t> {}", markdown.replace("\n", "\n\t> "))
+    }
+}
+
 #[async_trait]
 impl<'q> IssuesQuery for Query<'q> {
     async fn query<'a>(
         &'a self,
         repo: &'a Repository,
+        include_fcp_details: bool,
         client: &'a GithubClient,
     ) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> {
         let issues = repo
@@ -1056,30 +1066,89 @@ impl<'q> IssuesQuery for Query<'q> {
             .await
             .with_context(|| "Unable to get issues.")?;
 
+        // let fcp_collection = crate::rfcbot::FCPCollectionBox {};
+        // fcp_collection.get_all_fcps().await?;
+
+        // let fcp_map = crate::rfcbot::get_all_fcps().await?;
+
         let issues_decorator: Vec<_> = issues
-            .iter()
-            .map(|issue| crate::actions::IssueDecorator {
-                title: issue.title.clone(),
-                number: issue.number,
-                html_url: issue.html_url.clone(),
-                repo_name: repo.name().to_owned(),
-                labels: issue
-                    .labels
-                    .iter()
-                    .map(|l| l.name.as_ref())
-                    .collect::<Vec<_>>()
-                    .join(", "),
-                assignees: issue
-                    .assignees
-                    .iter()
-                    .map(|u| u.login.as_ref())
-                    .collect::<Vec<_>>()
-                    .join(", "),
-                updated_at: crate::actions::to_human(issue.updated_at),
+            .into_iter()
+            .map(|issue| async move {
+                // TODO: seems like a *really* bad approach but not sure how to make it better
+                let fcp_map = crate::rfcbot::get_all_fcps().await?;
+                let fcp_details = if include_fcp_details {
+                    let repository_name = if let Some(repo) = issue.repository.get() {
+                        repo.repository.clone()
+                    } else {
+                        let re = regex::Regex::new("https://github.com/rust-lang/|/").unwrap();
+                        let split = re.split(&issue.html_url).collect::<Vec<&str>>();
+                        split[1].to_string()
+                    };
+                    let key = format!(
+                        "rust-lang/{}:{}:{}",
+                        repository_name, issue.number, issue.title,
+                    );
+
+                    if let Some(fcp) = fcp_map.get(&key) {
+                        let bot_tracking_comment_html_url = format!(
+                            "{}#issuecomment-{}",
+                            issue.html_url, fcp.fcp.fk_bot_tracking_comment
+                        );
+                        let bot_tracking_comment_content = quote_reply(&fcp.status_comment.body);
+                        let fk_initiating_comment = fcp.fcp.fk_initiating_comment;
+                        let initiating_comment_html_url =
+                            format!("{}#issuecomment-{}", issue.html_url, fk_initiating_comment,);
+                        // TODO: get from GitHub
+                        // let url = format!(
+                        //     "{}/repos/rust-lang/{}/issues/comments/{}",
+                        //     Repository::GITHUB_API_URL,
+                        //     repository_name,
+                        //     fk_initiating_comment
+                        // );
+                        let init_comment = issue
+                            .get_comment(&client, fk_initiating_comment.try_into().unwrap())
+                            .await?;
+                        // let init_comment_content = init_comment.body;
+                        // client.json::<String>(client.get(&url)).await.unwrap();
+                        let initiating_comment_content = quote_reply(&init_comment.body);
+
+                        Some(crate::actions::FCPDetails {
+                            // additional properties from FullFCP (from rfcbot)
+                            bot_tracking_comment_html_url,
+                            bot_tracking_comment_content,
+                            initiating_comment_html_url,
+                            initiating_comment_content,
+                        })
+                    } else {
+                        None
+                    }
+                } else {
+                    None
+                };
+                Ok(crate::actions::IssueDecorator {
+                    title: issue.title.clone(),
+                    number: issue.number,
+                    html_url: issue.html_url.clone(),
+                    repo_name: repo.name().to_owned(),
+                    labels: issue
+                        .labels
+                        .iter()
+                        .map(|l| l.name.as_ref())
+                        .collect::<Vec<_>>()
+                        .join(", "),
+                    assignees: issue
+                        .assignees
+                        .iter()
+                        .map(|u| u.login.as_ref())
+                        .collect::<Vec<_>>()
+                        .join(", "),
+                    updated_at: crate::actions::to_human(issue.updated_at),
+                    fcp_details,
+                })
             })
             .collect();
 
-        Ok(issues_decorator)
+        try_join_all(issues_decorator).await
     }
 }
 
@@ -1372,6 +1441,7 @@ pub trait IssuesQuery {
     async fn query<'a>(
         &'a self,
         repo: &'a Repository,
+        include_fcp_details: bool,
         client: &'a GithubClient,
     ) -> anyhow::Result<Vec<crate::actions::IssueDecorator>>;
 }

+ 2 - 0
src/github/graphql.rs

@@ -164,6 +164,7 @@ impl super::IssuesQuery for LeastRecentlyReviewedPullRequests {
     async fn query<'a>(
         &'a self,
         repo: &'a super::Repository,
+        _include_fcp_details: bool,
         client: &'a super::GithubClient,
     ) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> {
         use cynic::QueryBuilder;
@@ -317,6 +318,7 @@ impl super::IssuesQuery for LeastRecentlyReviewedPullRequests {
                         labels,
                         assignees,
                         updated_at,
+                        fcp_details: None,
                     }
                 },
             )

+ 89 - 6
src/rfcbot.rs

@@ -3,7 +3,7 @@ use reqwest::Url;
 use serde::{Deserialize, Serialize};
 use std::collections::HashMap;
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 pub struct FCP {
     pub id: u32,
     pub fk_issue: u32,
@@ -14,17 +14,17 @@ pub struct FCP {
     pub fcp_start: Option<String>,
     pub fcp_closed: bool,
 }
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 pub struct Reviewer {
     pub id: u32,
     pub login: String,
 }
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 pub struct Review {
     pub reviewer: Reviewer,
     pub approved: bool,
 }
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 pub struct FCPIssue {
     pub id: u32,
     pub number: u32,
@@ -43,7 +43,7 @@ pub struct FCPIssue {
     pub repository: String,
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 pub struct StatusComment {
     pub id: u64,
     pub fk_issue: u32,
@@ -54,7 +54,7 @@ pub struct StatusComment {
     pub repository: String,
 }
 
-#[derive(Serialize, Deserialize, Debug)]
+#[derive(Serialize, Deserialize, Debug, Clone)]
 pub struct FullFCP {
     pub fcp: FCP,
     pub reviews: Vec<Review>,
@@ -70,6 +70,59 @@ fn quote_reply(markdown: &str) -> String {
     }
 }
 
+// #[async_trait]
+// pub trait IssueToFCP {
+//     async fn from_issue_fcp<'a>(
+//         full_fcp: &FullFCP,
+//         issue_decorator: &crate::actions::IssueDecorator,
+//         client: &'a GithubClient,
+//     ) -> anyhow::Result<Self>;
+// }
+
+// #[async_trait]
+// impl<'q> IssueToFCP for FCPDecorator {
+//     async fn from_issue_fcp<'a>(
+//         full_fcp: &FullFCP,
+//         issue_decorator: &crate::actions::IssueDecorator,
+//         client: &'a GithubClient,
+//     ) -> anyhow::Result<Self> {
+//         let bot_tracking_comment_html_url = format!(
+//             "{}#issuecomment-{}",
+//             issue_decorator.html_url, full_fcp.fcp.fk_bot_tracking_comment
+//         );
+//         let bot_tracking_comment_content = quote_reply(&full_fcp.status_comment.body);
+//         let fk_initiating_comment = full_fcp.fcp.fk_initiating_comment;
+//         let initiating_comment_html_url = format!(
+//             "{}#issuecomment-{}",
+//             issue_decorator.html_url, fk_initiating_comment,
+//         );
+//         // TODO: get from GitHub
+//         let url = format!(
+//             "{}/issues/comments/{}",
+//             issue_decorator.html_url, fk_initiating_comment
+//         );
+//         let init_comment_content = client._send_req(client.get(&url)).await?.json().await?;
+//         let initiating_comment_content = quote_reply(&init_comment_content);
+
+//         Self {
+//             // shared properties with IssueDecorator
+//             number: issue_decorator.number.clone(),
+//             title: issue_decorator.title.clone(),
+//             html_url: issue_decorator.html_url.clone(),
+//             repo_name: issue_decorator.repo_name.clone(),
+//             labels: issue_decorator.labels.clone(),
+//             assignees: issue_decorator.assignees.clone(),
+//             updated_at: issue_decorator.updated_at.clone(),
+
+//             // additional properties from FullFCP (from rfcbot)
+//             bot_tracking_comment_html_url,
+//             bot_tracking_comment_content,
+//             initiating_comment_html_url,
+//             initiating_comment_content,
+//         }
+//     }
+// }
+
 impl FCPDecorator {
     pub fn from_issue_fcp(
         full_fcp: &FullFCP,
@@ -106,6 +159,36 @@ impl FCPDecorator {
     }
 }
 
+// pub struct FCPCollection {
+//     pub fcps: Box<dyn HashMap<String, FullFCP> + Send + Sync>,
+// }
+
+// // pub trait FCPQuery {
+// //     pub fn get<'a>(&'a self) -> anyhow::Result<HashMap<String, FullFCP>>;
+// // }
+
+// impl FCPCollection {
+//     pub async fn get_all_fcps(&self) -> anyhow::Result<()> {
+//         let url = Url::parse(&"https://rfcbot.rs/api/all")?;
+//         let res = reqwest::get(url).await?.json::<Vec<FullFCP>>().await?;
+//         let mut map: HashMap<String, FullFCP> = HashMap::new();
+//         for full_fcp in res.into_iter() {
+//             map.insert(
+//                 format!(
+//                     "{}:{}:{}",
+//                     full_fcp.issue.repository.clone(),
+//                     full_fcp.issue.number.clone(),
+//                     full_fcp.issue.title.clone(),
+//                 ),
+//                 full_fcp,
+//             );
+//         }
+
+//         self.fcps = Box::new(map);
+//         Ok(())
+//     }
+// }
+
 pub async fn get_all_fcps() -> anyhow::Result<HashMap<String, FullFCP>> {
     let url = Url::parse(&"https://rfcbot.rs/api/all")?;
     let res = reqwest::get(url).await?.json::<Vec<FullFCP>>().await?;

+ 2 - 2
templates/_issues_fcps.tt

@@ -5,8 +5,8 @@
 {{heading}} "{{issue.title}}" {{issue.repo_name}}#{{issue.number}}
 
 - **Link:** {{issue.html_url}}
-- [**Tracking Comment**]({{issue.bot_tracking_comment_html_url}}): {{issue.bot_tracking_comment_content}}
-- [**Initiating Comment**]({{issue.initiating_comment_html_url}}): {{issue.initiating_comment_content}}
+- [**Tracking Comment**]({{issue.fcp_details.bot_tracking_comment_html_url}}): {{issue.fcp_details.bot_tracking_comment_content}}
+- [**Initiating Comment**]({{issue.fcp_details.initiating_comment_html_url}}): {{issue.fcp_details.initiating_comment_content}}