Skip to content

Commit

Permalink
Merge pull request #1836 from nikomatsakis/project-goals-3
Browse files Browse the repository at this point in the history
add more parameters to the project goals message
  • Loading branch information
jackh726 committed Aug 30, 2024
2 parents 49024fc + 18167d0 commit 330e790
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 24 deletions.
93 changes: 90 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ ignore = "0.4.18"
postgres-types = { version = "0.2.4", features = ["derive"] }
cron = { version = "0.12.0" }
bytes = "1.1.0"
structopt = "0.3.26"

[dependencies.serde]
version = "1"
Expand Down
36 changes: 23 additions & 13 deletions src/bin/project_goals.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
use structopt::StructOpt;
use triagebot::{github::GithubClient, handlers::project_goals};

/// A basic example
#[derive(StructOpt, Debug)]
struct Opt {
/// If specified, no messages are sent.
#[structopt(long)]
dry_run: bool,

/// Goals with an updated within this threshold will not be pinged.
days_threshold: i64,

/// A string like "on Sep-5" when the update blog post will be written.
next_meeting_date: String,
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> anyhow::Result<()> {
dotenv::dotenv().ok();
tracing_subscriber::fmt::init();

let mut dry_run = false;

for arg in std::env::args().skip(1) {
match arg.as_str() {
"--dry-run" => dry_run = true,
_ => {
eprintln!("Usage: project_goals [--dry-run]");
std::process::exit(1);
}
}
}

let opt = Opt::from_args();
let gh = GithubClient::new_from_env();
project_goals::ping_project_goals_owners(&gh, dry_run).await?;
project_goals::ping_project_goals_owners(
&gh,
opt.dry_run,
opt.days_threshold,
&opt.next_meeting_date,
)
.await?;

Ok(())
}
54 changes: 47 additions & 7 deletions src/handlers/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::jobs::Job;
use crate::zulip::to_zulip_id;
use anyhow::Context as _;
use async_trait::async_trait;
use chrono::Utc;
use chrono::{Datelike, NaiveDate, Utc};
use tracing::{self as log};

use super::Context;
Expand All @@ -17,7 +17,11 @@ const GOALS_STREAM: u64 = 435869; // #project-goals
const C_TRACKING_ISSUE: &str = "C-tracking-issue";

const MESSAGE: &str = r#"
Dear $OWNERS, it's been $DAYS days since the last update to your goal *$GOAL*. Please comment on the github tracking issue goals#$GOALNUM with an update at your earliest convenience. Thanks! <3
Dear $OWNERS, it's been $DAYS days since the last update to your goal *$GOAL*.
We will begin drafting the next blog post collecting goal updates $NEXT_UPDATE.
Please comment on the github tracking issue goals#$GOALNUM before then. Thanks! <3
Here is a suggested template for updates (feel free to drop the items that don't apply):
Expand All @@ -35,7 +39,7 @@ impl Job for ProjectGoalsUpdateJob {
}

async fn run(&self, ctx: &super::Context, _metadata: &serde_json::Value) -> anyhow::Result<()> {
ping_project_goals_owners(&ctx.github, false).await
ping_project_goals_owners_automatically(&ctx.github).await
}
}

Expand All @@ -51,7 +55,40 @@ pub async fn check_project_goal_acl(_gh: &GithubClient, gh_id: u64) -> anyhow::R
Ok(gh_id == GOAL_OWNER_GH_ID)
}

pub async fn ping_project_goals_owners(gh: &GithubClient, dry_run: bool) -> anyhow::Result<()> {
async fn ping_project_goals_owners_automatically(gh: &GithubClient) -> anyhow::Result<()> {
// Predicted schedule is to author a blog post on the 3rd week of the month.
// We start pinging when the month starts until we see an update in this month
// or the last 7 days of previous month.
//
// Therefore, we compute:
// * Days since start of this month -- threshold will be this number of days + 7.
// * Date of the 3rd Monday in the month -- this will be the next update (e.g., `on Sep-5`).
let now = Utc::now();

// We want to ping people unless they've written an update since the last week of the previous month.
let days_threshold = now.day() + 7;

// Format the 3rd Monday of the month, e.g. "on Sep-5", for inclusion.
let third_monday =
NaiveDate::from_weekday_of_month_opt(now.year(), now.month(), chrono::Weekday::Mon, 3)
.unwrap()
.format("on %b-%d")
.to_string();

ping_project_goals_owners(gh, false, days_threshold as i64, &third_monday).await
}

/// Sends a ping message to all project goal owners if
/// they have not posted an update in the last `days_threshold` days.
///
/// `next_update` is a human readable description of when the next update
/// will be drafted (e.g., `"on Sep 5"`).
pub async fn ping_project_goals_owners(
gh: &GithubClient,
dry_run: bool,
days_threshold: i64,
next_update: &str,
) -> anyhow::Result<()> {
let goals_repo = gh.repository(&RUST_PROJECT_GOALS_REPO).await?;

let tracking_issues_query = github::Query {
Expand All @@ -78,7 +115,7 @@ pub async fn ping_project_goals_owners(gh: &GithubClient, dry_run: bool) -> anyh
days_since_last_comment,
comments,
);
if days_since_last_comment < 21 && comments > 1 {
if days_since_last_comment < days_threshold && comments > 1 {
continue;
}

Expand All @@ -99,7 +136,8 @@ pub async fn ping_project_goals_owners(gh: &GithubClient, dry_run: bool) -> anyh
},
)
.replace("$GOALNUM", &issue.number.to_string())
.replace("$GOAL", &issue.title);
.replace("$GOAL", &issue.title)
.replace("$NEXT_UPDATE", next_update);

let zulip_req = crate::zulip::MessageApiRequest {
recipient: crate::zulip::Recipient::Stream {
Expand All @@ -115,7 +153,9 @@ pub async fn ping_project_goals_owners(gh: &GithubClient, dry_run: bool) -> anyh
if !dry_run {
zulip_req.send(&gh.raw()).await?;
} else {
log::debug!("skipping zulip send because dry run");
eprintln!();
eprintln!("-- Dry Run ------------------------------------");
eprintln!("Would send to {zulip_topic_name}: {}", zulip_req.content);
}
}

Expand Down
24 changes: 23 additions & 1 deletion src/zulip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use crate::handlers::Context;
use anyhow::{format_err, Context as _};
use std::env;
use std::fmt::Write as _;
use std::str::FromStr;
use tracing as log;

#[derive(Debug, serde::Deserialize)]
Expand Down Expand Up @@ -190,8 +191,29 @@ fn handle_command<'a>(
.map_err(|e| format_err!("Failed to await at this time: {e:?}"))
}
Some("ping-goals") => {
let usage_err = |description: &str| Err(format_err!(
"Error: {description}\n\
\n\
Usage: triagebot ping-goals D N, where:\n\
\n\
* D is the number of days before an update is considered stale\n\
* N is the date of next update, like \"Sep-5\"\n",
));

let Some(threshold) = words.next() else {
return usage_err("expected number of days");
};
let threshold = match i64::from_str(threshold) {
Ok(v) => v,
Err(e) => return usage_err(&format!("ill-formed number of days, {e}")),
};

let Some(next_update) = words.next() else {
return usage_err("expected date of next update");
};

if project_goals::check_project_goal_acl(&ctx.github, gh_id).await? {
ping_project_goals_owners(&ctx.github, false)
ping_project_goals_owners(&ctx.github, false, threshold, &format!("on {next_update}"))
.await
.map_err(|e| format_err!("Failed to await at this time: {e:?}"))?;
return Ok(None);
Expand Down

0 comments on commit 330e790

Please sign in to comment.