From 213da2a506aeb4935b9178912deea04ffa63ccd1 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Mon, 5 Jun 2023 17:29:50 -0700 Subject: [PATCH 1/3] Use project to get scheduled meetings --- src/agenda.rs | 10 +++++----- src/github.rs | 28 +++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/agenda.rs b/src/agenda.rs index fe885b6d2..7e94fef34 100644 --- a/src/agenda.rs +++ b/src/agenda.rs @@ -475,10 +475,8 @@ pub fn lang<'a>() -> Box { QueryMap { name: "scheduled_meetings", kind: QueryKind::List, - query: Arc::new(github::Query { - filters: vec![("state", "open"), ("is", "issue")], - include_labels: vec!["meeting-proposal", "meeting-scheduled"], - exclude_labels: vec![], + query: Arc::new(github::DesignMeetings { + with_status: github::DesignMeetingStatus::Scheduled, }), }, ], @@ -596,7 +594,9 @@ pub fn lang_planning<'a>() -> Box { QueryMap { name: "proposed_meetings", kind: QueryKind::List, - query: Arc::new(github::ProposedDesignMeetings), + query: Arc::new(github::DesignMeetings { + with_status: github::DesignMeetingStatus::Proposed, + }), }, ], }, diff --git a/src/github.rs b/src/github.rs index 7d38ac402..d7fd8192d 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2169,9 +2169,30 @@ async fn project_items_by_status( Ok(all_items) } -pub struct ProposedDesignMeetings; +pub enum DesignMeetingStatus { + Proposed, + Scheduled, + Done, + Empty, +} + +impl DesignMeetingStatus { + fn query_str(&self) -> Option<&str> { + match self { + DesignMeetingStatus::Proposed => Some("Needs triage"), + DesignMeetingStatus::Scheduled => Some("Scheduled"), + DesignMeetingStatus::Done => Some("Done"), + DesignMeetingStatus::Empty => None, + } + } +} + +pub struct DesignMeetings { + pub with_status: DesignMeetingStatus, +} + #[async_trait] -impl IssuesQuery for ProposedDesignMeetings { +impl IssuesQuery for DesignMeetings { async fn query<'a>( &'a self, _repo: &'a Repository, @@ -2181,7 +2202,8 @@ impl IssuesQuery for ProposedDesignMeetings { use github_graphql::project_items_by_status::ProjectV2ItemContent; let items = - project_items_by_status(client, |status| status == Some("Needs triage")).await?; + project_items_by_status(client, |status| status == self.with_status.query_str()) + .await?; Ok(items .into_iter() .flat_map(|item| match item { From 70cc40ba8f78531c80c592b01400f46a4066194e Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Mon, 5 Jun 2023 17:56:34 -0700 Subject: [PATCH 2/3] Sort meetings by scheduled date --- github-graphql/src/lib.rs | 37 ++++++++++++++++++++++++++++++++----- src/github.rs | 26 ++++++++++---------------- 2 files changed, 42 insertions(+), 21 deletions(-) diff --git a/github-graphql/src/lib.rs b/github-graphql/src/lib.rs index 42ea4789b..8ab940c5e 100644 --- a/github-graphql/src/lib.rs +++ b/github-graphql/src/lib.rs @@ -7,8 +7,10 @@ pub mod queries { use super::schema; + pub type Date = chrono::NaiveDate; pub type DateTime = chrono::DateTime; + cynic::impl_scalar!(Date, schema::Date); cynic::impl_scalar!(DateTime, schema::DateTime); #[derive(cynic::QueryVariables, Debug, Clone)] @@ -272,8 +274,8 @@ mod schema { } #[cynic::schema_for_derives(file = "src/github.graphql", module = "schema")] -pub mod project_items_by_status { - use super::queries::{PageInfo, Uri}; +pub mod project_items { + use super::queries::{Date, PageInfo, Uri}; use super::schema; #[derive(cynic::QueryVariables, Debug, Clone)] @@ -312,13 +314,25 @@ pub mod project_items_by_status { #[derive(cynic::QueryFragment, Debug)] pub struct ProjectV2Item { pub content: Option, + + // Currently we hard code the field names we care about here. + #[cynic(rename = "fieldValueByName")] #[arguments(name = "Status")] - pub field_value_by_name: Option, + pub status: Option, + #[cynic(rename = "fieldValueByName")] + #[arguments(name = "Date")] + pub date: Option, } impl ProjectV2Item { - pub fn status(&self) -> &Option { - &self.field_value_by_name + pub fn status(&self) -> Option<&str> { + let Some(ref status) = self.status else { return None }; + status.as_str() + } + + pub fn date(&self) -> Option { + let Some(ref date) = self.date else { return None }; + date.as_date() } } @@ -333,6 +347,7 @@ pub mod project_items_by_status { #[derive(cynic::InlineFragments, Debug)] pub enum ProjectV2ItemFieldValue { ProjectV2ItemFieldSingleSelectValue(ProjectV2ItemFieldSingleSelectValue), + ProjectV2ItemFieldDateValue(ProjectV2ItemFieldDateValue), #[cynic(fallback)] Other, @@ -345,6 +360,13 @@ pub mod project_items_by_status { _ => return None, }) } + + pub fn as_date(&self) -> Option { + match self { + Self::ProjectV2ItemFieldDateValue(val) => val.date, + _ => None, + } + } } #[derive(cynic::QueryFragment, Debug)] @@ -358,4 +380,9 @@ pub mod project_items_by_status { pub struct ProjectV2ItemFieldSingleSelectValue { pub name: Option, } + + #[derive(cynic::QueryFragment, Debug)] + pub struct ProjectV2ItemFieldDateValue { + pub date: Option, + } } diff --git a/src/github.rs b/src/github.rs index d7fd8192d..a6e55e329 100644 --- a/src/github.rs +++ b/src/github.rs @@ -2116,23 +2116,23 @@ impl IssuesQuery for LeastRecentlyReviewedPullRequests { async fn project_items_by_status( client: &GithubClient, status_filter: impl Fn(Option<&str>) -> bool, -) -> anyhow::Result> { +) -> anyhow::Result> { use cynic::QueryBuilder; - use github_graphql::project_items_by_status; + use github_graphql::project_items; const DESIGN_MEETING_PROJECT: i32 = 31; - let mut args = project_items_by_status::Arguments { + let mut args = project_items::Arguments { project_number: DESIGN_MEETING_PROJECT, after: None, }; let mut all_items = vec![]; loop { - let query = project_items_by_status::Query::build(args.clone()); + let query = project_items::Query::build(args.clone()); let req = client.post(Repository::GITHUB_GRAPHQL_API_URL); let req = req.json(&query); - let data: cynic::GraphQlResponse = client.json(req).await?; + let data: cynic::GraphQlResponse = client.json(req).await?; if let Some(errors) = data.errors { anyhow::bail!("There were graphql errors. {:?}", errors); } @@ -2149,14 +2149,7 @@ async fn project_items_by_status( .ok_or_else(|| anyhow!("Malformed response."))? .into_iter() .flatten() - .filter(|item| { - status_filter( - item.field_value_by_name - .as_ref() - .and_then(|status| status.as_str()), - ) - }) - .flat_map(|item| item.content); + .filter(|item| status_filter(item.status())); all_items.extend(filtered); let page_info = items.page_info; @@ -2166,6 +2159,7 @@ async fn project_items_by_status( args.after = page_info.end_cursor; } + all_items.sort_by_key(|item| item.date()); Ok(all_items) } @@ -2199,15 +2193,15 @@ impl IssuesQuery for DesignMeetings { _include_fcp_details: bool, client: &'a GithubClient, ) -> anyhow::Result> { - use github_graphql::project_items_by_status::ProjectV2ItemContent; + use github_graphql::project_items::ProjectV2ItemContent; let items = project_items_by_status(client, |status| status == self.with_status.query_str()) .await?; Ok(items .into_iter() - .flat_map(|item| match item { - ProjectV2ItemContent::Issue(issue) => Some(crate::actions::IssueDecorator { + .flat_map(|item| match item.content { + Some(ProjectV2ItemContent::Issue(issue)) => Some(crate::actions::IssueDecorator { assignees: String::new(), number: issue.number.try_into().unwrap(), fcp_details: None, From d1b57f9fdb693ab350aaa056a40c48d37b2a9602 Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Mon, 5 Jun 2023 17:56:40 -0700 Subject: [PATCH 3/3] Point to meeting project --- templates/lang_agenda.tt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/lang_agenda.tt b/templates/lang_agenda.tt index f630e6f34..60fe32f6d 100644 --- a/templates/lang_agenda.tt +++ b/templates/lang_agenda.tt @@ -24,6 +24,8 @@ tags: triage-meeting {{-issues::render(issues=scheduled_meetings, indent="", empty="No pending proposals this time.")}} +Edit the schedule here: https://github.com/orgs/rust-lang/projects/31/views/7. + ## Announcements or custom items (Meeting attendees, feel free to add items here!)