diff --git a/tools/automator/src/announcement.rs b/tools/automator/src/announcement.rs index b1df1029d..b214808d5 100644 --- a/tools/automator/src/announcement.rs +++ b/tools/automator/src/announcement.rs @@ -9,7 +9,10 @@ use tokio::{ io::AsyncWriteExt, }; -use crate::pull_requests::{Author, PullRequest, PullRequestsSinceLastRelease}; +use crate::{ + pull_requests::{Author, PullRequest, PullRequestsSinceLastRelease}, + sponsors::Sponsors, +}; pub async fn create_release_announcement( octocrab: &Octocrab, @@ -33,11 +36,18 @@ pub async fn create_release_announcement( let mut version = pull_requests_since_last_release.version_of_last_release; version.minor += 1; + let min_dollars = 32; + let for_readme = false; + let sponsors = Sponsors::query(octocrab) + .await? + .as_markdown(min_dollars, for_readme)?; + let mut file = create_file(year, week).await?; generate_announcement( week, date, version.to_string(), + sponsors, pull_requests, &mut file, ) @@ -65,6 +75,7 @@ async fn generate_announcement( week: u32, date: String, version: String, + sponsors: String, pull_requests: impl IntoIterator, file: &mut File, ) -> anyhow::Result<()> { @@ -121,6 +132,9 @@ title = \"Weekly Release - 2022-W{week}\" # TASK: Uncomment this date, once the announcement is ready to be published. # date = {date} +# TASK: Uncomment to generate the HTML for the email newsletter. +# template = \"newsletter/weekly-release.html\" + [extra] version = \"{version}\" +++ @@ -130,7 +144,7 @@ version = \"{version}\" ### Sponsors -Fornjot is supported by [@webtrax-oz](https://github.com/webtrax-oz), [@lthiery](https://github.com/lthiery), [@Yatekii](https://github.com/Yatekii), [@martindederer](https://github.com/martindederer), [@hobofan](https://github.com/hobofan), [@ahdinosaur](https://github.com/ahdinosaur), [@thawkins](https://github.com/thawkins), [@bollian](https://github.com/bollian), [@rozgo](https://github.com/rozgo), [@reivilibre](https://github.com/reivilibre), and [my other awesome sponsors](https://github.com/sponsors/hannobraun). Thank you! +{sponsors}

diff --git a/tools/automator/src/args.rs b/tools/automator/src/args.rs index 46a0995b8..8420ea122 100644 --- a/tools/automator/src/args.rs +++ b/tools/automator/src/args.rs @@ -1,7 +1,7 @@ #[derive(clap::Parser)] pub enum Args { Announcement, - Sponsors, + Sponsors(Sponsors), } impl Args { @@ -9,3 +9,9 @@ impl Args { ::parse() } } + +#[derive(clap::Parser)] +pub struct Sponsors { + #[clap(short, long)] + pub for_readme: bool, +} diff --git a/tools/automator/src/run.rs b/tools/automator/src/run.rs index 68eea9494..a5fe2f271 100644 --- a/tools/automator/src/run.rs +++ b/tools/automator/src/run.rs @@ -4,8 +4,7 @@ use anyhow::Context; use octocrab::Octocrab; use crate::{ - announcement::create_release_announcement, args::Args, - sponsors::query_sponsors, + announcement::create_release_announcement, args::Args, sponsors::Sponsors, }; pub async fn run() -> anyhow::Result<()> { @@ -19,14 +18,14 @@ pub async fn run() -> anyhow::Result<()> { .await .context("Failed to create release announcement")?; } - Args::Sponsors => { - let sponsors = query_sponsors(&octocrab) + Args::Sponsors(args) => { + let sponsors = Sponsors::query(&octocrab) .await - .context("Failed to query sponsors")?; + .context("Failed to query sponsors")? + .as_markdown(8, args.for_readme) + .context("Failed to format sponsors")?; - println!("{sponsors:#?}"); - - todo!("Querying sponsors is not supported yet.") + println!("{sponsors}"); } } diff --git a/tools/automator/src/sponsors.rs b/tools/automator/src/sponsors.rs index ecd9501af..2376efbac 100644 --- a/tools/automator/src/sponsors.rs +++ b/tools/automator/src/sponsors.rs @@ -1,8 +1,113 @@ -use std::cmp::Ordering; +use std::{cmp::Ordering, fmt::Write}; use chrono::{DateTime, Utc}; use octocrab::Octocrab; +#[derive(Debug)] +pub struct Sponsors { + pub inner: Vec, +} + +impl Sponsors { + pub async fn query(octocrab: &Octocrab) -> anyhow::Result { + let response: QueryResult = octocrab + .graphql( + "query { + viewer { + sponsors(first: 100) { + nodes { + __typename + ... on User { + login + sponsorshipForViewerAsSponsorable { + createdAt + tier { + monthlyPriceInDollars + } + } + } + ... on Organization { + login + sponsorshipForViewerAsSponsorable { + createdAt + tier { + monthlyPriceInDollars + } + } + } + } + } + } + }", + ) + .await?; + + let mut 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::>(); + + if sponsors.len() >= 100 { + todo!( + "Number of sponsors has reached max page size, but query does \ + not support pagination." + ) + } + + sponsors.sort(); + + Ok(Sponsors { inner: sponsors }) + } + + pub fn as_markdown( + &self, + min_dollars: u32, + for_readme: bool, + ) -> anyhow::Result { + let mut output = String::from("Fornjot is supported by "); + + for sponsor in &self.inner { + if sponsor.dollars < min_dollars { + continue; + } + + let login = &sponsor.login; + let name = if for_readme { + format!("**@{login}**") + } else { + format!("@{login}") + }; + let url = format!("https://github.com/{login}"); + + write!(output, "[{name}]({url}), ")?; + } + + output.push_str( + "and [my other awesome sponsors](https://github.com/sponsors/hannobraun). Thank you!" + ); + + Ok(output) + } +} + #[derive(Debug, Eq, PartialEq)] pub struct Sponsor { pub login: String, @@ -34,75 +139,6 @@ impl PartialOrd for Sponsor { } } -pub async fn query_sponsors( - octocrab: &Octocrab, -) -> anyhow::Result> { - let response: QueryResult = octocrab - .graphql( - "query { - viewer { - sponsors(first: 100) { - nodes { - __typename - ... on User { - login - sponsorshipForViewerAsSponsorable { - createdAt - tier { - monthlyPriceInDollars - } - } - } - ... on Organization { - login - sponsorshipForViewerAsSponsorable { - createdAt - tier { - monthlyPriceInDollars - } - } - } - } - } - } - }", - ) - .await?; - - let mut 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::>(); - - if sponsors.len() >= 100 { - todo!( - "Number of sponsors has reached max page size, but query does not \ - support pagination." - ) - } - - sponsors.sort(); - - Ok(sponsors) -} - #[derive(Debug, serde::Deserialize)] pub struct QueryResult { pub data: QueryResultData,