mirror of
https://github.com/hannobraun/Fornjot
synced 2025-02-28 18:15:53 +00:00
Merge pull request #1920 from hannobraun/automation
Add automation for generating blog posts on sponsor updates
This commit is contained in:
commit
2b037770c7
@ -1,6 +1,7 @@
|
||||
#[derive(clap::Parser)]
|
||||
pub enum Args {
|
||||
Announcement,
|
||||
#[command(subcommand)]
|
||||
Blog(Blog),
|
||||
Sponsors(Sponsors),
|
||||
}
|
||||
|
||||
@ -10,6 +11,12 @@ impl Args {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(clap::Subcommand)]
|
||||
pub enum Blog {
|
||||
Release,
|
||||
SponsorUpdate,
|
||||
}
|
||||
|
||||
#[derive(clap::Parser)]
|
||||
pub struct Sponsors {
|
||||
#[clap(short, long)]
|
||||
|
7
tools/automator/src/blog/mod.rs
Normal file
7
tools/automator/src/blog/mod.rs
Normal file
@ -0,0 +1,7 @@
|
||||
mod release;
|
||||
mod sponsors;
|
||||
mod util;
|
||||
|
||||
pub use self::{
|
||||
release::create_release_announcement, sponsors::create_sponsor_update,
|
||||
};
|
@ -1,26 +1,20 @@
|
||||
use std::{collections::HashSet, fmt::Write, path::PathBuf};
|
||||
use std::{collections::HashSet, fmt::Write};
|
||||
|
||||
use anyhow::Context;
|
||||
use chrono::{Datelike, Utc};
|
||||
use map_macro::hash_set;
|
||||
use octocrab::Octocrab;
|
||||
use tokio::{
|
||||
fs::{self, File},
|
||||
io::AsyncWriteExt,
|
||||
};
|
||||
use tokio::{fs::File, io::AsyncWriteExt};
|
||||
|
||||
use crate::{
|
||||
pull_requests::{Author, PullRequest, PullRequestsSinceLastRelease},
|
||||
sponsors::Sponsors,
|
||||
};
|
||||
|
||||
use super::util;
|
||||
|
||||
pub async fn create_release_announcement(
|
||||
octocrab: &Octocrab,
|
||||
) -> anyhow::Result<()> {
|
||||
let now = Utc::now();
|
||||
|
||||
let year = now.year();
|
||||
let date = format!("{year}-{:02}-{:02}", now.month(), now.day());
|
||||
let date = util::now_ymd();
|
||||
|
||||
let pull_requests_since_last_release =
|
||||
PullRequestsSinceLastRelease::fetch(octocrab).await?;
|
||||
@ -42,31 +36,13 @@ pub async fn create_release_announcement(
|
||||
.await?
|
||||
.as_markdown(min_dollars, for_readme)?;
|
||||
|
||||
let mut file = create_file(&version).await?;
|
||||
let mut file = util::create_blog_post_file("release", &version).await?;
|
||||
generate_announcement(date, version, sponsors, pull_requests, &mut file)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_file(version: &str) -> anyhow::Result<File> {
|
||||
let dir = PathBuf::from(format!("content/blog/release/{version}"));
|
||||
let file = dir.join("index.md");
|
||||
|
||||
// VS Code (and probably other editors/IDEs) renders the path in the output
|
||||
// as a clickable link, so the user can open the file easily.
|
||||
println!("Generating release announcement at {}", file.display());
|
||||
|
||||
fs::create_dir_all(&dir).await.with_context(|| {
|
||||
format!("Failed to create directory `{}`", dir.display())
|
||||
})?;
|
||||
let file = File::create(&file).await.with_context(|| {
|
||||
format!("Failed to create file `{}`", file.display())
|
||||
})?;
|
||||
|
||||
Ok(file)
|
||||
}
|
||||
|
||||
async fn generate_announcement(
|
||||
date: String,
|
||||
version: String,
|
58
tools/automator/src/blog/sponsors.rs
Normal file
58
tools/automator/src/blog/sponsors.rs
Normal file
@ -0,0 +1,58 @@
|
||||
use std::fmt::Write;
|
||||
|
||||
use tokio::{fs::File, io::AsyncWriteExt};
|
||||
|
||||
use super::util;
|
||||
|
||||
pub async fn create_sponsor_update() -> anyhow::Result<()> {
|
||||
let month = util::now_ym();
|
||||
let date = util::now_ymd();
|
||||
|
||||
let mut file = util::create_blog_post_file("sponsors", &month).await?;
|
||||
generate_update(date, month, &mut file).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn generate_update(
|
||||
date: String,
|
||||
month: String,
|
||||
file: &mut File,
|
||||
) -> anyhow::Result<()> {
|
||||
let mut buf = String::new();
|
||||
write!(
|
||||
buf,
|
||||
"\
|
||||
+++
|
||||
title = \"Sponsor Update - {month}\"
|
||||
date = {date}
|
||||
|
||||
# Uncomment to generate the HTML for the email newsletter.
|
||||
# template = \"newsletter/email.html\"
|
||||
+++
|
||||
|
||||
Hey folks!
|
||||
|
||||
I just sent out the new sponsor update! Topics this month include:
|
||||
|
||||
- **TASK: Summarize sponsor update.**
|
||||
|
||||
If you want to receive monthly behind-the-scenes updates too, why not support Fornjot by [becoming a sponsor](https://github.com/sponsors/hannobraun)? You can start with as little as $2 a month. More substantial contributions are also welcome, of course 😁
|
||||
|
||||
I dedicate a substantial chunk of my week to working on Fornjot. Your contribution can help make that more sustainable.
|
||||
|
||||
|
||||
### Not receiving these updates?
|
||||
|
||||
I've been sending out an update every month since February 2022. If you are a sponsor and haven't received those updates, maybe you are not opted in? Update your sponsorship over at GitHub, and make sure you check `Receive email updates from hannobraun`. Also make sure to check the spam folder in your email client.
|
||||
|
||||
If you still haven't received an update, [please contact me](mailto:hanno@braun-odw.eu). I'm happy to send you a copy directly.
|
||||
|
||||
I'm sorry for any inconvenience! Unfortunately, GitHub gives me no control over, or insight into, who is receiving those updates.
|
||||
"
|
||||
)?;
|
||||
|
||||
file.write_all(buf.as_bytes()).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
36
tools/automator/src/blog/util.rs
Normal file
36
tools/automator/src/blog/util.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use std::path::PathBuf;
|
||||
|
||||
use anyhow::Context;
|
||||
use chrono::{Datelike, Utc};
|
||||
use tokio::fs::{self, File};
|
||||
|
||||
pub fn now_ym() -> String {
|
||||
let now = Utc::now();
|
||||
format!("{}-{:02}", now.year(), now.month())
|
||||
}
|
||||
|
||||
pub fn now_ymd() -> String {
|
||||
let now = Utc::now();
|
||||
format!("{}-{:02}-{:02}", now.year(), now.month(), now.day())
|
||||
}
|
||||
|
||||
pub async fn create_blog_post_file(
|
||||
category: &str,
|
||||
title: &str,
|
||||
) -> anyhow::Result<File> {
|
||||
let dir = PathBuf::from(format!("content/blog/{category}/{title}"));
|
||||
let file = dir.join("index.md");
|
||||
|
||||
// VS Code (and probably other editors/IDEs) renders the path in the output
|
||||
// as a clickable link, so the user can open the file easily.
|
||||
println!("Generating `{category}` blog post at {}", file.display());
|
||||
|
||||
fs::create_dir_all(&dir).await.with_context(|| {
|
||||
format!("Failed to create directory `{}`", dir.display())
|
||||
})?;
|
||||
let file = File::create(&file).await.with_context(|| {
|
||||
format!("Failed to create file `{}`", file.display())
|
||||
})?;
|
||||
|
||||
Ok(file)
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
mod announcement;
|
||||
mod args;
|
||||
mod blog;
|
||||
mod pull_requests;
|
||||
mod run;
|
||||
mod sponsors;
|
||||
|
@ -4,7 +4,9 @@ use anyhow::Context;
|
||||
use octocrab::Octocrab;
|
||||
|
||||
use crate::{
|
||||
announcement::create_release_announcement, args::Args, sponsors::Sponsors,
|
||||
args::{Args, Blog},
|
||||
blog,
|
||||
sponsors::Sponsors,
|
||||
};
|
||||
|
||||
pub async fn run() -> anyhow::Result<()> {
|
||||
@ -13,16 +15,22 @@ pub async fn run() -> anyhow::Result<()> {
|
||||
let octocrab = Octocrab::builder().personal_token(token).build()?;
|
||||
|
||||
match Args::parse() {
|
||||
Args::Announcement => {
|
||||
create_release_announcement(&octocrab)
|
||||
Args::Blog(Blog::Release) => {
|
||||
blog::create_release_announcement(&octocrab)
|
||||
.await
|
||||
.context("Failed to create release announcement")?;
|
||||
}
|
||||
Args::Blog(Blog::SponsorUpdate) => {
|
||||
blog::create_sponsor_update()
|
||||
.await
|
||||
.context("Failed to create sponsor update")?;
|
||||
}
|
||||
Args::Sponsors(args) => {
|
||||
let min_dollars = 8;
|
||||
let sponsors = Sponsors::query(&octocrab)
|
||||
.await
|
||||
.context("Failed to query sponsors")?
|
||||
.as_markdown(8, args.for_readme)
|
||||
.as_markdown(min_dollars, args.for_readme)
|
||||
.context("Failed to format sponsors")?;
|
||||
|
||||
println!("{sponsors}");
|
||||
|
Loading…
Reference in New Issue
Block a user