Skip to content

Commit 3ae50ca

Browse files
committed
Use project field for proposed design meetings status
1 parent d39cd93 commit 3ae50ca

File tree

3 files changed

+183
-6
lines changed

3 files changed

+183
-6
lines changed

github-graphql/src/lib.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,3 +270,92 @@ pub mod docs_update_queries {
270270
mod schema {
271271
cynic::use_schema!("src/github.graphql");
272272
}
273+
274+
#[cynic::schema_for_derives(file = "src/github.graphql", module = "schema")]
275+
pub mod project_items_by_status {
276+
use super::queries::{PageInfo, Uri};
277+
use super::schema;
278+
279+
#[derive(cynic::QueryVariables, Debug, Clone)]
280+
pub struct Arguments {
281+
pub project_number: i32,
282+
pub after: Option<String>,
283+
}
284+
285+
#[derive(cynic::QueryFragment, Debug)]
286+
#[cynic(variables = "Arguments")]
287+
pub struct Query {
288+
#[arguments(login: "rust-lang")]
289+
pub organization: Option<Organization>,
290+
}
291+
292+
#[derive(cynic::QueryFragment, Debug)]
293+
#[cynic(variables = "Arguments")]
294+
pub struct Organization {
295+
#[arguments(number: $project_number)]
296+
pub project_v2: Option<ProjectV2>,
297+
}
298+
299+
#[derive(cynic::QueryFragment, Debug)]
300+
#[cynic(variables = "Arguments")]
301+
pub struct ProjectV2 {
302+
#[arguments(first: 100, after: $after)]
303+
pub items: ProjectV2ItemConnection,
304+
}
305+
306+
#[derive(cynic::QueryFragment, Debug)]
307+
pub struct ProjectV2ItemConnection {
308+
pub nodes: Option<Vec<Option<ProjectV2Item>>>,
309+
pub page_info: PageInfo,
310+
}
311+
312+
#[derive(cynic::QueryFragment, Debug)]
313+
pub struct ProjectV2Item {
314+
pub content: Option<ProjectV2ItemContent>,
315+
#[arguments(name = "Status")]
316+
pub field_value_by_name: Option<ProjectV2ItemFieldValue>,
317+
}
318+
319+
impl ProjectV2Item {
320+
pub fn status(&self) -> &Option<ProjectV2ItemFieldValue> {
321+
&self.field_value_by_name
322+
}
323+
}
324+
325+
#[derive(cynic::InlineFragments, Debug)]
326+
pub enum ProjectV2ItemContent {
327+
Issue(Issue),
328+
329+
#[cynic(fallback)]
330+
Other,
331+
}
332+
333+
#[derive(cynic::InlineFragments, Debug)]
334+
pub enum ProjectV2ItemFieldValue {
335+
ProjectV2ItemFieldSingleSelectValue(ProjectV2ItemFieldSingleSelectValue),
336+
337+
#[cynic(fallback)]
338+
Other,
339+
}
340+
341+
impl ProjectV2ItemFieldValue {
342+
pub fn as_str(&self) -> Option<&str> {
343+
Some(match self {
344+
Self::ProjectV2ItemFieldSingleSelectValue(val) => val.name.as_deref()?,
345+
_ => return None,
346+
})
347+
}
348+
}
349+
350+
#[derive(cynic::QueryFragment, Debug)]
351+
pub struct Issue {
352+
pub title: String,
353+
pub url: Uri,
354+
pub number: i32,
355+
}
356+
357+
#[derive(cynic::QueryFragment, Debug)]
358+
pub struct ProjectV2ItemFieldSingleSelectValue {
359+
pub name: Option<String>,
360+
}
361+
}

src/agenda.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -587,11 +587,7 @@ pub fn lang_planning<'a>() -> Box<dyn Action + Send + Sync> {
587587
QueryMap {
588588
name: "proposed_meetings",
589589
kind: QueryKind::List,
590-
query: Arc::new(github::Query {
591-
filters: vec![("state", "open"), ("is", "issue")],
592-
include_labels: vec!["meeting-proposal"],
593-
exclude_labels: vec!["meeting-scheduled"],
594-
}),
590+
query: Arc::new(github::ProposedDesignMeetings),
595591
},
596592
],
597593
},

src/github.rs

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use anyhow::Context;
1+
use anyhow::{anyhow, Context};
22
use async_trait::async_trait;
33
use chrono::{DateTime, FixedOffset, Utc};
44
use futures::{future::BoxFuture, FutureExt};
@@ -2128,6 +2128,98 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests {
21282128
}
21292129
}
21302130

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+
21312223
#[derive(Debug, serde::Deserialize)]
21322224
pub struct GitReference {
21332225
#[serde(rename = "ref")]

0 commit comments

Comments
 (0)