diff --git a/.gitignore b/.gitignore
index 54e7505..8c42e23 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
/targets
/results
/db.sqlite*
+/.envrc
diff --git a/Cargo.lock b/Cargo.lock
index b99fb9a..d8fd4ed 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -32,6 +32,21 @@ version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
+[[package]]
+name = "arc-swap"
+version = "1.7.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
+
[[package]]
name = "askama"
version = "0.14.0"
@@ -74,6 +89,17 @@ dependencies = [
"winnow",
]
+[[package]]
+name = "async-trait"
+version = "0.1.89"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "atoi"
version = "2.0.0"
@@ -253,6 +279,20 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
+[[package]]
+name = "chrono"
+version = "0.4.42"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
+dependencies = [
+ "iana-time-zone",
+ "js-sys",
+ "num-traits",
+ "serde",
+ "wasm-bindgen",
+ "windows-link",
+]
+
[[package]]
name = "color-eyre"
version = "0.6.5"
@@ -295,6 +335,22 @@ version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+[[package]]
+name = "core-foundation"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+
[[package]]
name = "cpufeatures"
version = "0.2.17"
@@ -395,6 +451,8 @@ dependencies = [
"axum",
"color-eyre",
"futures",
+ "jsonwebtoken",
+ "octocrab",
"reqwest",
"serde",
"sqlx",
@@ -797,7 +855,9 @@ dependencies = [
"http",
"hyper",
"hyper-util",
+ "log",
"rustls",
+ "rustls-native-certs",
"rustls-pki-types",
"tokio",
"tokio-rustls",
@@ -805,6 +865,19 @@ dependencies = [
"webpki-roots",
]
+[[package]]
+name = "hyper-timeout"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
+dependencies = [
+ "hyper",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
[[package]]
name = "hyper-util"
version = "0.1.17"
@@ -829,6 +902,30 @@ dependencies = [
"tracing",
]
+[[package]]
+name = "iana-time-zone"
+version = "0.1.64"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "log",
+ "wasm-bindgen",
+ "windows-core",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
+dependencies = [
+ "cc",
+]
+
[[package]]
name = "icu_collections"
version = "2.1.1"
@@ -979,6 +1076,21 @@ dependencies = [
"wasm-bindgen",
]
+[[package]]
+name = "jsonwebtoken"
+version = "9.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde"
+dependencies = [
+ "base64",
+ "js-sys",
+ "pem",
+ "ring",
+ "serde",
+ "serde_json",
+ "simple_asn1",
+]
+
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -1121,6 +1233,16 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "num-bigint"
+version = "0.4.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
+dependencies = [
+ "num-integer",
+ "num-traits",
+]
+
[[package]]
name = "num-bigint-dig"
version = "0.8.5"
@@ -1182,12 +1304,58 @@ dependencies = [
"memchr",
]
+[[package]]
+name = "octocrab"
+version = "0.47.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "76f50b2657b7e31c849c612c4ca71527861631fe3c392f931fb28990b045f972"
+dependencies = [
+ "arc-swap",
+ "async-trait",
+ "base64",
+ "bytes",
+ "cfg-if",
+ "chrono",
+ "either",
+ "futures",
+ "futures-util",
+ "http",
+ "http-body",
+ "http-body-util",
+ "hyper",
+ "hyper-rustls",
+ "hyper-timeout",
+ "hyper-util",
+ "jsonwebtoken",
+ "once_cell",
+ "percent-encoding",
+ "pin-project",
+ "secrecy",
+ "serde",
+ "serde_json",
+ "serde_path_to_error",
+ "serde_urlencoded",
+ "snafu",
+ "tokio",
+ "tower",
+ "tower-http",
+ "tracing",
+ "url",
+ "web-time",
+]
+
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+[[package]]
+name = "openssl-probe"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+
[[package]]
name = "owo-colors"
version = "4.2.3"
@@ -1223,6 +1391,16 @@ dependencies = [
"windows-link",
]
+[[package]]
+name = "pem"
+version = "3.0.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be"
+dependencies = [
+ "base64",
+ "serde_core",
+]
+
[[package]]
name = "pem-rfc7468"
version = "0.7.0"
@@ -1238,6 +1416,26 @@ version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
+[[package]]
+name = "pin-project"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
+dependencies = [
+ "pin-project-internal",
+]
+
+[[package]]
+name = "pin-project-internal"
+version = "1.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "pin-project-lite"
version = "0.2.16"
@@ -1568,6 +1766,7 @@ version = "0.23.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a9586e9ee2b4f8fab52a0048ca7334d7024eef48e2cb9407e3497bb7cab7fa7"
dependencies = [
+ "log",
"once_cell",
"ring",
"rustls-pki-types",
@@ -1576,6 +1775,18 @@ dependencies = [
"zeroize",
]
+[[package]]
+name = "rustls-native-certs"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9980d917ebb0c0536119ba501e90834767bffc3d60641457fd84a1f3fd337923"
+dependencies = [
+ "openssl-probe",
+ "rustls-pki-types",
+ "schannel",
+ "security-framework",
+]
+
[[package]]
name = "rustls-pki-types"
version = "1.13.0"
@@ -1609,12 +1820,53 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+[[package]]
+name = "schannel"
+version = "0.1.28"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
+dependencies = [
+ "windows-sys 0.61.2",
+]
+
[[package]]
name = "scopeguard"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+[[package]]
+name = "secrecy"
+version = "0.10.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a"
+dependencies = [
+ "zeroize",
+]
+
+[[package]]
+name = "security-framework"
+version = "3.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
+dependencies = [
+ "bitflags",
+ "core-foundation",
+ "core-foundation-sys",
+ "libc",
+ "security-framework-sys",
+]
+
+[[package]]
+name = "security-framework-sys"
+version = "2.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
+dependencies = [
+ "core-foundation-sys",
+ "libc",
+]
+
[[package]]
name = "serde"
version = "1.0.228"
@@ -1737,6 +1989,18 @@ dependencies = [
"rand_core 0.6.4",
]
+[[package]]
+name = "simple_asn1"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb"
+dependencies = [
+ "num-bigint",
+ "num-traits",
+ "thiserror",
+ "time",
+]
+
[[package]]
name = "slab"
version = "0.4.11"
@@ -1752,6 +2016,27 @@ dependencies = [
"serde",
]
+[[package]]
+name = "snafu"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2"
+dependencies = [
+ "snafu-derive",
+]
+
+[[package]]
+name = "snafu-derive"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "socket2"
version = "0.6.1"
@@ -2170,6 +2455,19 @@ dependencies = [
"tokio",
]
+[[package]]
+name = "tokio-util"
+version = "0.7.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "futures-sink",
+ "pin-project-lite",
+ "tokio",
+]
+
[[package]]
name = "tower"
version = "0.5.2"
@@ -2181,6 +2479,7 @@ dependencies = [
"pin-project-lite",
"sync_wrapper",
"tokio",
+ "tokio-util",
"tower-layer",
"tower-service",
"tracing",
@@ -2202,6 +2501,7 @@ dependencies = [
"tower",
"tower-layer",
"tower-service",
+ "tracing",
]
[[package]]
@@ -2474,6 +2774,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
dependencies = [
"js-sys",
+ "serde",
"wasm-bindgen",
]
@@ -2496,12 +2797,65 @@ dependencies = [
"wasite",
]
+[[package]]
+name = "windows-core"
+version = "0.62.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
+dependencies = [
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
+]
+
+[[package]]
+name = "windows-implement"
+version = "0.60.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "windows-interface"
+version = "0.59.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
[[package]]
name = "windows-link"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
+[[package]]
+name = "windows-result"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+dependencies = [
+ "windows-link",
+]
+
+[[package]]
+name = "windows-strings"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+dependencies = [
+ "windows-link",
+]
+
[[package]]
name = "windows-sys"
version = "0.48.0"
diff --git a/Cargo.toml b/Cargo.toml
index da744c8..4227ae4 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,8 @@ askama = "0.14.0"
axum = { version = "0.8.6", features = ["macros"] }
color-eyre = "0.6.3"
futures = "0.3.30"
+jsonwebtoken = { version = "9.3.1", features = [] }
+octocrab = "0.47.1"
reqwest = { version = "0.12.7", features = [
"rustls-tls",
], default-features = false }
diff --git a/migrations/20251110170025_notifications.sql b/migrations/20251110170025_notifications.sql
new file mode 100644
index 0000000..ac3e4ae
--- /dev/null
+++ b/migrations/20251110170025_notifications.sql
@@ -0,0 +1,10 @@
+-- Add migration script here
+
+CREATE TABLE notification_issues(
+ "issue_number" INTEGER PRIMARY KEY,
+ "status" TEXT NOT NULL, -- open/closed
+ "first_failed_nightly" TEXT NOT NULL,
+ "target" TEXT NOT NULL
+) STRICT;
+
+CREATE INDEX notification_issues_target on notification_issues("target", "status");
diff --git a/src/build.rs b/src/build.rs
index 6bded12..48adaf1 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -17,6 +17,7 @@ use tracing::{debug, error, info};
use crate::{
db::{BuildMode, Db, FullBuildInfo, Status},
nightlies::Nightlies,
+ notification::GitHubClient,
};
struct CustomBuildFlags {
@@ -52,7 +53,7 @@ impl Display for Toolchain {
}
}
-pub async fn background_builder(db: Db) -> Result<()> {
+pub async fn background_builder(db: Db, github_client: GitHubClient) -> Result<()> {
if concurrent_jobs() == 0 {
info!("Suspending background thread since DOES_IT_BUILD_PARALLEL_JOBS=0");
loop {
@@ -61,7 +62,7 @@ pub async fn background_builder(db: Db) -> Result<()> {
}
loop {
- if let Err(err) = background_builder_inner(&db).await {
+ if let Err(err) = background_builder_inner(&db, &github_client).await {
error!(
?err,
"error in background builder, waiting for an hour before retrying: {err}"
@@ -71,7 +72,7 @@ pub async fn background_builder(db: Db) -> Result<()> {
}
}
-async fn background_builder_inner(db: &Db) -> Result<()> {
+async fn background_builder_inner(db: &Db, github_client: &GitHubClient) -> Result<()> {
let nightlies = Nightlies::fetch().await.wrap_err("fetching nightlies")?;
let already_finished = db
.finished_nightlies()
@@ -82,7 +83,7 @@ async fn background_builder_inner(db: &Db) -> Result<()> {
match next {
Some((nightly, mode)) => {
info!(%nightly, %mode, "Building next nightly");
- let result = build_every_target_for_toolchain(db, &nightly, mode)
+ let result = build_every_target_for_toolchain(db, &nightly, mode, &github_client)
.await
.wrap_err_with(|| format!("building targets for toolchain {nightly}"));
if let Err(err) = result {
@@ -178,6 +179,7 @@ pub async fn build_every_target_for_toolchain(
db: &Db,
nightly: &str,
mode: BuildMode,
+ github_client: &GitHubClient,
) -> Result<()> {
if db.is_nightly_finished(nightly, mode).await? {
debug!("Nightly is already finished, not trying again");
@@ -194,7 +196,7 @@ pub async fn build_every_target_for_toolchain(
let results = futures::stream::iter(
targets
.iter()
- .map(|target| build_single_target(db, nightly, target, mode)),
+ .map(|target| build_single_target(db, nightly, target, mode, github_client)),
)
.buffer_unordered(concurrent_jobs())
.collect::
+ 🔔 does-it-build supports sending notifications to target maintainers via GitHub issues. + You can add yourself with a PR. +
+ {% if let Some(maintainers) = maintainers %} ++ Maintainers that will receive pings for this target: + {% for maintainer in maintainers %} + {{maintainer}} + {% endfor %} +
+ {% endif %} {% if showing_failures %}