Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 32 additions & 5 deletions github-graphql/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
pub mod queries {
use super::schema;

pub type Date = chrono::NaiveDate;
pub type DateTime = chrono::DateTime<chrono::Utc>;

cynic::impl_scalar!(Date, schema::Date);
cynic::impl_scalar!(DateTime, schema::DateTime);

#[derive(cynic::QueryVariables, Debug, Clone)]
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -312,13 +314,25 @@ pub mod project_items_by_status {
#[derive(cynic::QueryFragment, Debug)]
pub struct ProjectV2Item {
pub content: Option<ProjectV2ItemContent>,

// Currently we hard code the field names we care about here.
#[cynic(rename = "fieldValueByName")]
#[arguments(name = "Status")]
pub field_value_by_name: Option<ProjectV2ItemFieldValue>,
pub status: Option<ProjectV2ItemFieldValue>,
#[cynic(rename = "fieldValueByName")]
#[arguments(name = "Date")]
pub date: Option<ProjectV2ItemFieldValue>,
}

impl ProjectV2Item {
pub fn status(&self) -> &Option<ProjectV2ItemFieldValue> {
&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<Date> {
let Some(ref date) = self.date else { return None };
date.as_date()
}
}

Expand All @@ -333,6 +347,7 @@ pub mod project_items_by_status {
#[derive(cynic::InlineFragments, Debug)]
pub enum ProjectV2ItemFieldValue {
ProjectV2ItemFieldSingleSelectValue(ProjectV2ItemFieldSingleSelectValue),
ProjectV2ItemFieldDateValue(ProjectV2ItemFieldDateValue),

#[cynic(fallback)]
Other,
Expand All @@ -345,6 +360,13 @@ pub mod project_items_by_status {
_ => return None,
})
}

pub fn as_date(&self) -> Option<Date> {
match self {
Self::ProjectV2ItemFieldDateValue(val) => val.date,
_ => None,
}
}
}

#[derive(cynic::QueryFragment, Debug)]
Expand All @@ -358,4 +380,9 @@ pub mod project_items_by_status {
pub struct ProjectV2ItemFieldSingleSelectValue {
pub name: Option<String>,
}

#[derive(cynic::QueryFragment, Debug)]
pub struct ProjectV2ItemFieldDateValue {
pub date: Option<Date>,
}
}
10 changes: 5 additions & 5 deletions src/agenda.rs
Original file line number Diff line number Diff line change
Expand Up @@ -475,10 +475,8 @@ pub fn lang<'a>() -> Box<dyn Action + Send + Sync> {
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,
}),
},
],
Expand Down Expand Up @@ -596,7 +594,9 @@ pub fn lang_planning<'a>() -> Box<dyn Action + Send + Sync> {
QueryMap {
name: "proposed_meetings",
kind: QueryKind::List,
query: Arc::new(github::ProposedDesignMeetings),
query: Arc::new(github::DesignMeetings {
with_status: github::DesignMeetingStatus::Proposed,
}),
},
],
},
Expand Down
54 changes: 35 additions & 19 deletions src/github.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<Vec<github_graphql::project_items_by_status::ProjectV2ItemContent>> {
) -> anyhow::Result<Vec<github_graphql::project_items::ProjectV2Item>> {
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<project_items_by_status::Query> = client.json(req).await?;
let data: cynic::GraphQlResponse<project_items::Query> = client.json(req).await?;
if let Some(errors) = data.errors {
anyhow::bail!("There were graphql errors. {:?}", errors);
}
Expand All @@ -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;
Expand All @@ -2166,26 +2159,49 @@ async fn project_items_by_status(
args.after = page_info.end_cursor;
}

all_items.sort_by_key(|item| item.date());
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,
_include_fcp_details: bool,
client: &'a GithubClient,
) -> anyhow::Result<Vec<crate::actions::IssueDecorator>> {
use github_graphql::project_items_by_status::ProjectV2ItemContent;
use github_graphql::project_items::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 {
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,
Expand Down
2 changes: 2 additions & 0 deletions templates/lang_agenda.tt
Original file line number Diff line number Diff line change
Expand Up @@ -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!)
Expand Down