mirror of
https://github.com/Noratrieb/does-it-build.git
synced 2026-01-14 10:25:01 +01:00
Only send notification update after a month of inactivity
A lower cadence was requested in https://github.com/Noratrieb/does-it-build/pull/10#issuecomment-3514228933
This commit is contained in:
parent
b244cf05b4
commit
491eb1604f
6 changed files with 115 additions and 54 deletions
57
Cargo.lock
generated
57
Cargo.lock
generated
|
|
@ -451,6 +451,7 @@ dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
"futures",
|
"futures",
|
||||||
|
"jiff",
|
||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
"octocrab",
|
"octocrab",
|
||||||
"reqwest",
|
"reqwest",
|
||||||
|
|
@ -1066,6 +1067,47 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49cce2b81f2098e7e3efc35bc2e0a6b7abec9d34128283d7a26fa8f32a6dbb35"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-static",
|
||||||
|
"jiff-tzdb-platform",
|
||||||
|
"log",
|
||||||
|
"portable-atomic",
|
||||||
|
"portable-atomic-util",
|
||||||
|
"serde_core",
|
||||||
|
"windows-sys 0.61.2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-static"
|
||||||
|
version = "0.2.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "980af8b43c3ad5d8d349ace167ec8170839f753a42d233ba19e08afe1850fa69"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1283705eb0a21404d2bfd6eef2a7593d240bc42a0bdb39db0ad6fa2ec026524"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jiff-tzdb-platform"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "875a5a69ac2bab1a891711cf5eccbec1ce0341ea805560dcd90b7a2e925132e8"
|
||||||
|
dependencies = [
|
||||||
|
"jiff-tzdb",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.82"
|
version = "0.3.82"
|
||||||
|
|
@ -1475,6 +1517,21 @@ version = "0.3.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic"
|
||||||
|
version = "1.11.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "portable-atomic-util"
|
||||||
|
version = "0.2.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
|
||||||
|
dependencies = [
|
||||||
|
"portable-atomic",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "potential_utf"
|
name = "potential_utf"
|
||||||
version = "0.1.4"
|
version = "0.1.4"
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ askama = "0.14.0"
|
||||||
axum = { version = "0.8.6", features = ["macros"] }
|
axum = { version = "0.8.6", features = ["macros"] }
|
||||||
color-eyre = "0.6.3"
|
color-eyre = "0.6.3"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
|
jiff = "0.2.16"
|
||||||
jsonwebtoken = { version = "9.3.1", features = [] }
|
jsonwebtoken = { version = "9.3.1", features = [] }
|
||||||
octocrab = "0.47.1"
|
octocrab = "0.47.1"
|
||||||
reqwest = { version = "0.12.7", features = [
|
reqwest = { version = "0.12.7", features = [
|
||||||
|
|
|
||||||
4
migrations/20251111165945_notifications_last_update.sql
Normal file
4
migrations/20251111165945_notifications_last_update.sql
Normal file
|
|
@ -0,0 +1,4 @@
|
||||||
|
-- Add migration script here
|
||||||
|
|
||||||
|
ALTER TABLE notification_issues
|
||||||
|
ADD COLUMN "last_update_date" INTEGER NULL;
|
||||||
20
src/db.rs
20
src/db.rs
|
|
@ -106,6 +106,7 @@ pub struct NotificationIssue {
|
||||||
pub status: NotificationStatus,
|
pub status: NotificationStatus,
|
||||||
pub first_failed_nightly: String,
|
pub first_failed_nightly: String,
|
||||||
pub target: String,
|
pub target: String,
|
||||||
|
pub last_update_date: Option<i64>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Db {
|
impl Db {
|
||||||
|
|
@ -314,13 +315,14 @@ impl Db {
|
||||||
pub async fn insert_notification(&self, notification: NotificationIssue) -> Result<()> {
|
pub async fn insert_notification(&self, notification: NotificationIssue) -> Result<()> {
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO notification_issues\
|
"INSERT INTO notification_issues\
|
||||||
(issue_number, status, first_failed_nightly, target)\
|
(issue_number, status, first_failed_nightly, target, last_update_date)\
|
||||||
VALUES (?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?, ?)",
|
||||||
)
|
)
|
||||||
.bind(notification.issue_number)
|
.bind(notification.issue_number)
|
||||||
.bind(notification.status)
|
.bind(notification.status)
|
||||||
.bind(notification.first_failed_nightly)
|
.bind(notification.first_failed_nightly)
|
||||||
.bind(notification.target)
|
.bind(notification.target)
|
||||||
|
.bind(notification.last_update_date)
|
||||||
.execute(&self.conn)
|
.execute(&self.conn)
|
||||||
.await
|
.await
|
||||||
.wrap_err("inserting new notification")?;
|
.wrap_err("inserting new notification")?;
|
||||||
|
|
@ -336,4 +338,18 @@ impl Db {
|
||||||
.wrap_err("marking notification as closed")?;
|
.wrap_err("marking notification as closed")?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn set_notification_last_update(
|
||||||
|
&self,
|
||||||
|
issue_number: i64,
|
||||||
|
last_update: jiff::Timestamp,
|
||||||
|
) -> Result<()> {
|
||||||
|
sqlx::query("UPDATE notification_issues SET last_update_date = ? WHERE issue_number = ?")
|
||||||
|
.bind(last_update.as_millisecond())
|
||||||
|
.bind(issue_number)
|
||||||
|
.execute(&self.conn)
|
||||||
|
.await
|
||||||
|
.wrap_err("marking notification as closed")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,39 +0,0 @@
|
||||||
use color_eyre::{eyre::Context, Result};
|
|
||||||
use octocrab::issues;
|
|
||||||
|
|
||||||
pub struct GitHubClient {
|
|
||||||
pub send_pings: bool,
|
|
||||||
owner: String,
|
|
||||||
repo: String,
|
|
||||||
pub client: octocrab::Octocrab,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GitHubClient {
|
|
||||||
pub async fn new(
|
|
||||||
send_pings: bool,
|
|
||||||
client: octocrab::Octocrab,
|
|
||||||
owner: String,
|
|
||||||
repo: String,
|
|
||||||
) -> Result<Self> {
|
|
||||||
let installation = client
|
|
||||||
.apps()
|
|
||||||
.get_repository_installation(&owner, &repo)
|
|
||||||
.await
|
|
||||||
.wrap_err_with(|| format!("getting installation for {owner}/{repo}"))?;
|
|
||||||
|
|
||||||
let client = client
|
|
||||||
.installation(installation.id)
|
|
||||||
.wrap_err("getting client for installation")?;
|
|
||||||
|
|
||||||
Ok(Self {
|
|
||||||
send_pings,
|
|
||||||
owner,
|
|
||||||
repo,
|
|
||||||
client,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn issues(&self) -> issues::IssueHandler<'_> {
|
|
||||||
self.client.issues(&self.owner, &self.repo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -84,8 +84,6 @@ pub async fn notify_build_failure(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("Creating issue for target {target}, notifying {notify_usernames:?}");
|
|
||||||
|
|
||||||
let issue = db.find_existing_notification(target).await?;
|
let issue = db.find_existing_notification(target).await?;
|
||||||
|
|
||||||
let url = format!(
|
let url = format!(
|
||||||
|
|
@ -93,14 +91,25 @@ pub async fn notify_build_failure(
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some(issue) = issue {
|
if let Some(issue) = issue {
|
||||||
// An existing issue, send a comment.
|
// An existing issue, send a comment if it's been a month since the last update.
|
||||||
|
|
||||||
github_client
|
if issue.last_update_date.is_none_or(|last_update_date| {
|
||||||
.issues()
|
jiff::Timestamp::from_millisecond(last_update_date).is_ok_and(|last_update_date| {
|
||||||
.create_comment(
|
jiff::Timestamp::now()
|
||||||
issue.issue_number as u64,
|
.since(last_update_date)
|
||||||
format!(
|
.is_ok_and(|diff| diff.get_months() > 0)
|
||||||
"💥 The target {target} still fails to build on the nightly {nightly}!
|
})
|
||||||
|
}) {
|
||||||
|
info!(
|
||||||
|
"Sending update for {target}, since enough time has elapsed since the last update"
|
||||||
|
);
|
||||||
|
|
||||||
|
github_client
|
||||||
|
.issues()
|
||||||
|
.create_comment(
|
||||||
|
issue.issue_number as u64,
|
||||||
|
format!(
|
||||||
|
"💥 The target {target} still fails to build on the nightly {nightly}!
|
||||||
|
|
||||||
<{url}>
|
<{url}>
|
||||||
|
|
||||||
|
|
@ -111,14 +120,26 @@ pub async fn notify_build_failure(
|
||||||
```
|
```
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
|
This update is sent after a month of inactivity.
|
||||||
"
|
"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.wrap_err("creating update comment")?;
|
.wrap_err("creating update comment")?;
|
||||||
|
|
||||||
|
db.set_notification_last_update(issue.issue_number, jiff::Timestamp::now())
|
||||||
|
.await
|
||||||
|
.wrap_err("updating last_update_date in DB")?;
|
||||||
|
} else {
|
||||||
|
info!("Not sending update for {target}, since not enough time has elapsed since the last one");
|
||||||
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
info!("Creating issue for target {target}, notifying {notify_usernames:?}");
|
||||||
|
|
||||||
// Ensure the labels exist.
|
// Ensure the labels exist.
|
||||||
let label = github_client.issues().get_label(target).await;
|
let label = github_client.issues().get_label(target).await;
|
||||||
match label {
|
match label {
|
||||||
|
|
@ -176,6 +197,7 @@ This issue will be closed automatically when this target works again!"
|
||||||
issue_number: issue.number as i64,
|
issue_number: issue.number as i64,
|
||||||
status: NotificationStatus::Open,
|
status: NotificationStatus::Open,
|
||||||
target: target.into(),
|
target: target.into(),
|
||||||
|
last_update_date: Some(jiff::Timestamp::now().as_millisecond()),
|
||||||
})
|
})
|
||||||
.await
|
.await
|
||||||
.wrap_err("inserting issue into DB")?;
|
.wrap_err("inserting issue into DB")?;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue