From cf6171dc5c600ba0c7a4463e38ba57eb51a5b1aa Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 12:05:23 +0200 Subject: [PATCH 01/10] Remove unused code --- tools/automator/src/args.rs | 5 +---- tools/automator/src/run.rs | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/tools/automator/src/args.rs b/tools/automator/src/args.rs index 780cf5f992..a3d0041354 100644 --- a/tools/automator/src/args.rs +++ b/tools/automator/src/args.rs @@ -1,6 +1,6 @@ #[derive(clap::Parser)] pub enum Args { - CreateReleaseAnnouncement(CreateReleaseAnnouncement), + CreateReleaseAnnouncement, Sponsors, } @@ -9,6 +9,3 @@ impl Args { ::parse() } } - -#[derive(clap::Parser)] -pub struct CreateReleaseAnnouncement {} diff --git a/tools/automator/src/run.rs b/tools/automator/src/run.rs index 70c6db1604..a5cafba456 100644 --- a/tools/automator/src/run.rs +++ b/tools/automator/src/run.rs @@ -11,7 +11,7 @@ pub async fn run() -> anyhow::Result<()> { let octocrab = Octocrab::builder().personal_token(token).build()?; match Args::parse() { - Args::CreateReleaseAnnouncement(_) => { + Args::CreateReleaseAnnouncement => { create_release_announcement(&octocrab) .await .context("Failed to create release announcement")?; From 33dc1d332d45bbb9e86c4c0c3c3df9e2071694d1 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 12:05:39 +0200 Subject: [PATCH 02/10] Shorten `automator` command --- tools/automator/src/args.rs | 2 +- tools/automator/src/run.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/automator/src/args.rs b/tools/automator/src/args.rs index a3d0041354..46a0995b80 100644 --- a/tools/automator/src/args.rs +++ b/tools/automator/src/args.rs @@ -1,6 +1,6 @@ #[derive(clap::Parser)] pub enum Args { - CreateReleaseAnnouncement, + Announcement, Sponsors, } diff --git a/tools/automator/src/run.rs b/tools/automator/src/run.rs index a5cafba456..3f8e5ff42a 100644 --- a/tools/automator/src/run.rs +++ b/tools/automator/src/run.rs @@ -11,7 +11,7 @@ pub async fn run() -> anyhow::Result<()> { let octocrab = Octocrab::builder().personal_token(token).build()?; match Args::parse() { - Args::CreateReleaseAnnouncement => { + Args::Announcement => { create_release_announcement(&octocrab) .await .context("Failed to create release announcement")?; From 3718664d957326527d108f9e059f73b25a4d8022 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 12:44:56 +0200 Subject: [PATCH 03/10] Add GraphQL query for sponsors --- tools/automator/src/run.rs | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/tools/automator/src/run.rs b/tools/automator/src/run.rs index 3f8e5ff42a..b53791a022 100644 --- a/tools/automator/src/run.rs +++ b/tools/automator/src/run.rs @@ -17,8 +17,37 @@ pub async fn run() -> anyhow::Result<()> { .context("Failed to create release announcement")?; } Args::Sponsors => { - let response: serde_json::Value = - octocrab.graphql("query { viewer { login }}").await?; + let response: serde_json::Value = octocrab + .graphql( + "query { + viewer { + sponsors(first: 100) { + nodes { + __typename + ... on User { + login + sponsorshipForViewerAsSponsorable { + createdAt + tier { + monthlyPriceInDollars + } + } + } + ... on Organization { + login + sponsorshipForViewerAsSponsorable { + createdAt + tier { + monthlyPriceInDollars + } + } + } + } + } + } + }", + ) + .await?; println!("{response}"); todo!("Querying sponsors is not supported yet.") From dca1cc990721e2eebfdc964089e5b52d46db9ecf Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 12:47:22 +0200 Subject: [PATCH 04/10] Move sponsor querying code to dedicated module --- tools/automator/src/main.rs | 1 + tools/automator/src/run.rs | 41 ++++++--------------------------- tools/automator/src/sponsors.rs | 39 +++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 34 deletions(-) create mode 100644 tools/automator/src/sponsors.rs diff --git a/tools/automator/src/main.rs b/tools/automator/src/main.rs index de47bdcbab..b94f4c1a84 100644 --- a/tools/automator/src/main.rs +++ b/tools/automator/src/main.rs @@ -2,6 +2,7 @@ mod announcement; mod args; mod pull_requests; mod run; +mod sponsors; #[tokio::main] async fn main() -> anyhow::Result<()> { diff --git a/tools/automator/src/run.rs b/tools/automator/src/run.rs index b53791a022..f9eeac94f3 100644 --- a/tools/automator/src/run.rs +++ b/tools/automator/src/run.rs @@ -3,7 +3,10 @@ use std::env; use anyhow::Context; use octocrab::Octocrab; -use crate::{announcement::create_release_announcement, args::Args}; +use crate::{ + announcement::create_release_announcement, args::Args, + sponsors::query_sponsors, +}; pub async fn run() -> anyhow::Result<()> { let token = env::var("GITHUB_TOKEN") @@ -17,39 +20,9 @@ pub async fn run() -> anyhow::Result<()> { .context("Failed to create release announcement")?; } Args::Sponsors => { - let response: serde_json::Value = octocrab - .graphql( - "query { - viewer { - sponsors(first: 100) { - nodes { - __typename - ... on User { - login - sponsorshipForViewerAsSponsorable { - createdAt - tier { - monthlyPriceInDollars - } - } - } - ... on Organization { - login - sponsorshipForViewerAsSponsorable { - createdAt - tier { - monthlyPriceInDollars - } - } - } - } - } - } - }", - ) - .await?; - println!("{response}"); - + query_sponsors(&octocrab) + .await + .context("Failed to query sponsors")?; todo!("Querying sponsors is not supported yet.") } } diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs new file mode 100644 index 0000000000..3835c5f4c4 --- /dev/null +++ b/tools/automator/src/sponsors.rs @@ -0,0 +1,39 @@ +use octocrab::Octocrab; + +pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { + let response: serde_json::Value = octocrab + .graphql( + "query { + viewer { + sponsors(first: 100) { + nodes { + __typename + ... on User { + login + sponsorshipForViewerAsSponsorable { + createdAt + tier { + monthlyPriceInDollars + } + } + } + ... on Organization { + login + sponsorshipForViewerAsSponsorable { + createdAt + tier { + monthlyPriceInDollars + } + } + } + } + } + } + }", + ) + .await?; + + println!("{response}"); + + Ok(()) +} From 335a49eb10a935d8b07c2166b44a2e00902941f4 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 12:50:18 +0200 Subject: [PATCH 05/10] Add depenency on Serde to `automator` --- Cargo.lock | 1 + tools/automator/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 0bcdbde3a5..bcfe59d0ad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,6 +221,7 @@ dependencies = [ "map-macro", "octocrab", "semver", + "serde", "serde_json", "tokio", "url", diff --git a/tools/automator/Cargo.toml b/tools/automator/Cargo.toml index a653067172..536ceb0022 100644 --- a/tools/automator/Cargo.toml +++ b/tools/automator/Cargo.toml @@ -10,6 +10,7 @@ chrono = "0.4.22" map-macro = "0.2.4" octocrab = "0.17.0" semver = "1.0.14" +serde = "1.0.144" serde_json = "1.0.85" url = "2.3.0" From a90ee271131d22cdb05708800864b25cfac8461f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 13:03:50 +0200 Subject: [PATCH 06/10] Add types to encode query result --- tools/automator/src/sponsors.rs | 47 +++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs index 3835c5f4c4..3006989824 100644 --- a/tools/automator/src/sponsors.rs +++ b/tools/automator/src/sponsors.rs @@ -1,7 +1,8 @@ +use chrono::{DateTime, Utc}; use octocrab::Octocrab; pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { - let response: serde_json::Value = octocrab + let response: QueryResult = octocrab .graphql( "query { viewer { @@ -33,7 +34,49 @@ pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { ) .await?; - println!("{response}"); + println!("{:#?}", response.data.viewer.sponsors.nodes); Ok(()) } + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResult { + pub data: QueryResultData, +} + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResultData { + pub viewer: QueryResultViewer, +} + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResultViewer { + pub sponsors: QueryResultSponsorsNodes, +} + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResultSponsorsNodes { + pub nodes: Vec, +} + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResultSponsorsNode { + pub login: String, + + #[serde(rename = "sponsorshipForViewerAsSponsorable")] + pub sponsorship_for_viewer_as_sponsorable: QueryResultSponsorable, +} + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResultSponsorable { + #[serde(rename = "createdAt")] + pub created_at: DateTime, + + pub tier: QueryResultSponsorableTier, +} + +#[derive(Debug, serde::Deserialize)] +pub struct QueryResultSponsorableTier { + #[serde(rename = "monthlyPriceInDollars")] + pub monthly_price_in_dollars: u32, +} From 9237b0f7da9a7d7d045d73db5f3bf875a6eb6988 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 13:07:47 +0200 Subject: [PATCH 07/10] Add `Sponsor` --- tools/automator/src/sponsors.rs | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs index 3006989824..fb7a27193c 100644 --- a/tools/automator/src/sponsors.rs +++ b/tools/automator/src/sponsors.rs @@ -1,6 +1,13 @@ use chrono::{DateTime, Utc}; use octocrab::Octocrab; +#[derive(Debug)] +pub struct Sponsor { + pub login: String, + pub since: DateTime, + pub dollars: u32, +} + pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { let response: QueryResult = octocrab .graphql( @@ -34,7 +41,29 @@ pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { ) .await?; - println!("{:#?}", response.data.viewer.sponsors.nodes); + let sponsors = response + .data + .viewer + .sponsors + .nodes + .into_iter() + .map(|node| { + let login = node.login; + let since = node.sponsorship_for_viewer_as_sponsorable.created_at; + let dollars = node + .sponsorship_for_viewer_as_sponsorable + .tier + .monthly_price_in_dollars; + + Sponsor { + login, + since, + dollars, + } + }) + .collect::>(); + + println!("{sponsors:#?}"); Ok(()) } From 413f933829d719746d11ef3655b8d4bfda6d3807 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 13:10:20 +0200 Subject: [PATCH 08/10] Sort sponsors --- tools/automator/src/sponsors.rs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs index fb7a27193c..bdc33dbcee 100644 --- a/tools/automator/src/sponsors.rs +++ b/tools/automator/src/sponsors.rs @@ -1,13 +1,39 @@ +use std::cmp::Ordering; + use chrono::{DateTime, Utc}; use octocrab::Octocrab; -#[derive(Debug)] +#[derive(Debug, Eq, PartialEq)] pub struct Sponsor { pub login: String, pub since: DateTime, pub dollars: u32, } +impl Ord for Sponsor { + fn cmp(&self, other: &Self) -> Ordering { + let by_dollars = other.dollars.cmp(&self.dollars); + let by_date = self.since.cmp(&other.since); + let by_login = self.login.cmp(&other.login); + + if by_dollars.is_ne() { + return by_dollars; + } + + if by_date.is_ne() { + return by_date; + } + + by_login + } +} + +impl PartialOrd for Sponsor { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { let response: QueryResult = octocrab .graphql( @@ -41,7 +67,7 @@ pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { ) .await?; - let sponsors = response + let mut sponsors = response .data .viewer .sponsors @@ -63,6 +89,8 @@ pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { }) .collect::>(); + sponsors.sort(); + println!("{sponsors:#?}"); Ok(()) From 08f045052219cd93b393b9f97a6bd5f0c9d9b747 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 13:17:51 +0200 Subject: [PATCH 09/10] Refactor --- tools/automator/src/run.rs | 5 ++++- tools/automator/src/sponsors.rs | 8 ++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/automator/src/run.rs b/tools/automator/src/run.rs index f9eeac94f3..68eea94948 100644 --- a/tools/automator/src/run.rs +++ b/tools/automator/src/run.rs @@ -20,9 +20,12 @@ pub async fn run() -> anyhow::Result<()> { .context("Failed to create release announcement")?; } Args::Sponsors => { - query_sponsors(&octocrab) + let sponsors = query_sponsors(&octocrab) .await .context("Failed to query sponsors")?; + + println!("{sponsors:#?}"); + todo!("Querying sponsors is not supported yet.") } } diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs index bdc33dbcee..42534873c5 100644 --- a/tools/automator/src/sponsors.rs +++ b/tools/automator/src/sponsors.rs @@ -34,7 +34,9 @@ impl PartialOrd for Sponsor { } } -pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { +pub async fn query_sponsors( + octocrab: &Octocrab, +) -> anyhow::Result> { let response: QueryResult = octocrab .graphql( "query { @@ -91,9 +93,7 @@ pub async fn query_sponsors(octocrab: &Octocrab) -> anyhow::Result<()> { sponsors.sort(); - println!("{sponsors:#?}"); - - Ok(()) + Ok(sponsors) } #[derive(Debug, serde::Deserialize)] From 54a07900e722de2dd45f2748adc1420d2d5312d6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Tue, 20 Sep 2022 13:19:26 +0200 Subject: [PATCH 10/10] Detect unhandled edge case --- tools/automator/src/sponsors.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs index 42534873c5..ecd9501af4 100644 --- a/tools/automator/src/sponsors.rs +++ b/tools/automator/src/sponsors.rs @@ -91,6 +91,13 @@ pub async fn query_sponsors( }) .collect::>(); + if sponsors.len() >= 100 { + todo!( + "Number of sponsors has reached max page size, but query does not \ + support pagination." + ) + } + sponsors.sort(); Ok(sponsors)