|
1 | | -use anyhow::Context; |
| 1 | +use anyhow::{anyhow, Context}; |
2 | 2 | use async_trait::async_trait; |
3 | 3 | use chrono::{DateTime, FixedOffset, Utc}; |
4 | 4 | use futures::{future::BoxFuture, FutureExt}; |
@@ -2128,6 +2128,98 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests { |
2128 | 2128 | } |
2129 | 2129 | } |
2130 | 2130 |
|
| 2131 | +async fn project_items_by_status( |
| 2132 | + client: &GithubClient, |
| 2133 | + status_filter: impl Fn(Option<&str>) -> bool, |
| 2134 | +) -> anyhow::Result<Vec<github_graphql::project_items_by_status::ProjectV2ItemContent>> { |
| 2135 | + use cynic::QueryBuilder; |
| 2136 | + use github_graphql::project_items_by_status; |
| 2137 | + |
| 2138 | + const DESIGN_MEETING_PROJECT: i32 = 31; |
| 2139 | + let mut args = project_items_by_status::Arguments { |
| 2140 | + project_number: DESIGN_MEETING_PROJECT, |
| 2141 | + after: None, |
| 2142 | + }; |
| 2143 | + |
| 2144 | + let mut all_items = vec![]; |
| 2145 | + loop { |
| 2146 | + let query = project_items_by_status::Query::build(args.clone()); |
| 2147 | + let req = client.post(Repository::GITHUB_GRAPHQL_API_URL); |
| 2148 | + let req = req.json(&query); |
| 2149 | + |
| 2150 | + let (resp, req_dbg) = client._send_req(req).await?; |
| 2151 | + let data = resp |
| 2152 | + .json::<cynic::GraphQlResponse<project_items_by_status::Query>>() |
| 2153 | + .await |
| 2154 | + .context(req_dbg)?; |
| 2155 | + if let Some(errors) = data.errors { |
| 2156 | + anyhow::bail!("There were graphql errors. {:?}", errors); |
| 2157 | + } |
| 2158 | + let items = data |
| 2159 | + .data |
| 2160 | + .ok_or_else(|| anyhow!("No data returned."))? |
| 2161 | + .organization |
| 2162 | + .ok_or_else(|| anyhow!("Organization not found."))? |
| 2163 | + .project_v2 |
| 2164 | + .ok_or_else(|| anyhow!("Project not found."))? |
| 2165 | + .items; |
| 2166 | + let filtered = items |
| 2167 | + .nodes |
| 2168 | + .ok_or_else(|| anyhow!("Malformed response."))? |
| 2169 | + .into_iter() |
| 2170 | + .flatten() |
| 2171 | + .filter(|item| { |
| 2172 | + status_filter( |
| 2173 | + item.field_value_by_name |
| 2174 | + .as_ref() |
| 2175 | + .and_then(|status| status.as_str()), |
| 2176 | + ) |
| 2177 | + }) |
| 2178 | + .flat_map(|item| item.content); |
| 2179 | + all_items.extend(filtered); |
| 2180 | + |
| 2181 | + let page_info = items.page_info; |
| 2182 | + if !page_info.has_next_page || page_info.end_cursor.is_none() { |
| 2183 | + break; |
| 2184 | + } |
| 2185 | + args.after = page_info.end_cursor; |
| 2186 | + } |
| 2187 | + |
| 2188 | + Ok(all_items) |
| 2189 | +} |
| 2190 | + |
| 2191 | +pub struct ProposedDesignMeetings; |
| 2192 | +#[async_trait] |
| 2193 | +impl IssuesQuery for ProposedDesignMeetings { |
| 2194 | + async fn query<'a>( |
| 2195 | + &'a self, |
| 2196 | + _repo: &'a Repository, |
| 2197 | + _include_fcp_details: bool, |
| 2198 | + client: &'a GithubClient, |
| 2199 | + ) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> { |
| 2200 | + use github_graphql::project_items_by_status::ProjectV2ItemContent; |
| 2201 | + |
| 2202 | + let items = |
| 2203 | + project_items_by_status(client, |status| status == Some("Needs triage")).await?; |
| 2204 | + Ok(items |
| 2205 | + .into_iter() |
| 2206 | + .flat_map(|item| match item { |
| 2207 | + ProjectV2ItemContent::Issue(issue) => Some(crate::actions::IssueDecorator { |
| 2208 | + assignees: String::new(), |
| 2209 | + number: issue.number.try_into().unwrap(), |
| 2210 | + fcp_details: None, |
| 2211 | + html_url: issue.url.0, |
| 2212 | + title: issue.title, |
| 2213 | + repo_name: String::new(), |
| 2214 | + labels: String::new(), |
| 2215 | + updated_at_hts: String::new(), |
| 2216 | + }), |
| 2217 | + _ => None, |
| 2218 | + }) |
| 2219 | + .collect()) |
| 2220 | + } |
| 2221 | +} |
| 2222 | + |
2131 | 2223 | #[derive(Debug, serde::Deserialize)] |
2132 | 2224 | pub struct GitReference { |
2133 | 2225 | #[serde(rename = "ref")] |
|
0 commit comments