mirror of
https://github.com/Noratrieb/does-it-build.git
synced 2026-01-14 10:25:01 +01:00
support github pings
This commit is contained in:
parent
112420d224
commit
b71f565e5b
11 changed files with 772 additions and 13 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -2,3 +2,4 @@
|
|||
/targets
|
||||
/results
|
||||
/db.sqlite*
|
||||
/.envrc
|
||||
|
|
|
|||
354
Cargo.lock
generated
354
Cargo.lock
generated
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
10
migrations/20251110170025_notifications.sql
Normal file
10
migrations/20251110170025_notifications.sql
Normal file
|
|
@ -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");
|
||||
36
src/build.rs
36
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::<Vec<Result<()>>>()
|
||||
|
|
@ -204,7 +206,7 @@ pub async fn build_every_target_for_toolchain(
|
|||
}
|
||||
|
||||
for target in targets {
|
||||
build_single_target(db, nightly, &target, mode)
|
||||
build_single_target(db, nightly, &target, mode, github_client)
|
||||
.await
|
||||
.wrap_err_with(|| format!("building target {target} for toolchain {toolchain}"))?;
|
||||
}
|
||||
|
|
@ -217,8 +219,14 @@ pub async fn build_every_target_for_toolchain(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip(db))]
|
||||
async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMode) -> Result<()> {
|
||||
#[tracing::instrument(skip(db, github_client))]
|
||||
async fn build_single_target(
|
||||
db: &Db,
|
||||
nightly: &str,
|
||||
target: &str,
|
||||
mode: BuildMode,
|
||||
github_client: &GitHubClient,
|
||||
) -> Result<()> {
|
||||
let existing = db
|
||||
.build_status_full(nightly, target, mode)
|
||||
.await
|
||||
|
|
@ -238,7 +246,7 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo
|
|||
.await
|
||||
.wrap_err("running build")?;
|
||||
|
||||
db.insert(FullBuildInfo {
|
||||
let full_build_info = FullBuildInfo {
|
||||
nightly: nightly.into(),
|
||||
target: target.into(),
|
||||
status: result.status,
|
||||
|
|
@ -255,8 +263,14 @@ async fn build_single_target(db: &Db, nightly: &str, target: &str, mode: BuildMo
|
|||
),
|
||||
does_it_build_version: Some(crate::VERSION_SHORT.into()),
|
||||
build_duration_ms: Some(start_time.elapsed().as_millis().try_into().unwrap()),
|
||||
})
|
||||
.await?;
|
||||
};
|
||||
|
||||
let result = crate::notification::notify_build(github_client, db, &full_build_info).await;
|
||||
if let Err(err) = result {
|
||||
error!(?err, "Failed to send build notification");
|
||||
}
|
||||
|
||||
db.insert(full_build_info).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
55
src/db.rs
55
src/db.rs
|
|
@ -92,6 +92,22 @@ impl BuildStats {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy, sqlx::Type, Serialize, Deserialize)]
|
||||
#[sqlx(rename_all = "snake_case")]
|
||||
#[serde(rename_all = "lowercase")]
|
||||
pub enum NotificationStatus {
|
||||
Open,
|
||||
Closed,
|
||||
}
|
||||
|
||||
#[derive(Debug, sqlx::FromRow)]
|
||||
pub struct NotificationIssue {
|
||||
pub issue_number: i64,
|
||||
pub status: NotificationStatus,
|
||||
pub first_failed_nightly: String,
|
||||
pub target: String,
|
||||
}
|
||||
|
||||
impl Db {
|
||||
pub async fn open(path: &str) -> Result<Self> {
|
||||
let db_opts = SqliteConnectOptions::from_str(path)
|
||||
|
|
@ -281,4 +297,43 @@ impl Db {
|
|||
.wrap_err("inserting finished broken nightly")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn find_existing_notification(
|
||||
&self,
|
||||
target: &str,
|
||||
) -> Result<Option<NotificationIssue>> {
|
||||
sqlx::query_as::<_, NotificationIssue>(
|
||||
"SELECT * FROM notification_issues WHERE status = 'open' AND target = ?",
|
||||
)
|
||||
.bind(target)
|
||||
.fetch_optional(&self.conn)
|
||||
.await
|
||||
.wrap_err("finding existing notification")
|
||||
}
|
||||
|
||||
pub async fn insert_notification(&self, notification: NotificationIssue) -> Result<()> {
|
||||
sqlx::query(
|
||||
"INSERT INTO notification_issues\
|
||||
(issue_number, status, first_failed_nightly, target)\
|
||||
VALUES (?, ?, ?, ?)",
|
||||
)
|
||||
.bind(notification.issue_number)
|
||||
.bind(notification.status)
|
||||
.bind(notification.first_failed_nightly)
|
||||
.bind(notification.target)
|
||||
.execute(&self.conn)
|
||||
.await
|
||||
.wrap_err("inserting new notification")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn finish_notification(&self, issue_number: i64) -> Result<()> {
|
||||
sqlx::query("UPDATE notification_issues SET status = ? WHERE issue_number = ?")
|
||||
.bind(NotificationStatus::Closed)
|
||||
.bind(issue_number)
|
||||
.execute(&self.conn)
|
||||
.await
|
||||
.wrap_err("marking notification as closed")?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
39
src/github.rs
Normal file
39
src/github.rs
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
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)
|
||||
}
|
||||
}
|
||||
33
src/main.rs
33
src/main.rs
|
|
@ -1,6 +1,7 @@
|
|||
mod build;
|
||||
mod db;
|
||||
mod nightlies;
|
||||
mod notification;
|
||||
mod web;
|
||||
|
||||
use color_eyre::{eyre::WrapErr, Result};
|
||||
|
|
@ -12,6 +13,10 @@ const VERSION_SHORT: &str = env!("GIT_COMMIT_SHORT");
|
|||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<()> {
|
||||
main_inner().await
|
||||
}
|
||||
|
||||
async fn main_inner() -> Result<()> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new("info")))
|
||||
.init();
|
||||
|
|
@ -22,7 +27,33 @@ async fn main() -> Result<()> {
|
|||
.await
|
||||
.wrap_err("running migrations")?;
|
||||
|
||||
let builder = build::background_builder(db.clone());
|
||||
let send_pings = std::env::var("GITHUB_SEND_PINGS")
|
||||
.map(|_| true)
|
||||
.unwrap_or(false);
|
||||
let github_owner = std::env::var("GITHUB_OWNER").wrap_err("missing GITHUB_OWNER env var")?;
|
||||
let github_repo = std::env::var("GITHUB_REPO").wrap_err("missing GITHUB_REPO env var")?;
|
||||
let app_id = std::env::var("GITHUB_APP_ID")
|
||||
.wrap_err("missing GITHUB_APP_ID env var")?
|
||||
.parse::<u64>()
|
||||
.wrap_err("invalid GITHUB_APP_ID")?;
|
||||
let key = std::env::var("GITHUB_APP_PRIVATE_KEY")
|
||||
.wrap_err("missing GITHUB_APP_PRIVATE_KEY env var")?;
|
||||
let key = jsonwebtoken::EncodingKey::from_rsa_pem(key.as_bytes()).unwrap();
|
||||
|
||||
let github_client = octocrab::Octocrab::builder()
|
||||
.app(app_id.into(), key)
|
||||
.build()
|
||||
.wrap_err("failed to create client")?;
|
||||
|
||||
let github_client = notification::GitHubClient::new(
|
||||
send_pings,
|
||||
github_client,
|
||||
github_owner.clone(),
|
||||
github_repo.clone(),
|
||||
)
|
||||
.await?;
|
||||
|
||||
let builder = build::background_builder(db.clone(), github_client);
|
||||
let server = web::webserver(db);
|
||||
|
||||
tokio::select! {
|
||||
|
|
|
|||
232
src/notification.rs
Normal file
232
src/notification.rs
Normal file
|
|
@ -0,0 +1,232 @@
|
|||
use color_eyre::eyre::{Context, Result};
|
||||
use octocrab::models::issues::IssueStateReason;
|
||||
use octocrab::models::IssueState;
|
||||
use tracing::info;
|
||||
|
||||
use crate::db::{Db, FullBuildInfo, NotificationIssue, NotificationStatus, Status};
|
||||
|
||||
pub const TABLE_FILE: &str = file!();
|
||||
pub const TABLE_LINE: u32 = line!() + 1;
|
||||
const TARGET_NOTIFICATIONS: &[(&str, &[&str])] = &[("armv7-sony-vita-newlibeabihf", &["pheki"])];
|
||||
|
||||
pub fn notification_pr_url() -> String {
|
||||
format!("https://github.com/Noratrieb/does-it-build/blob/main/{TABLE_FILE}#L{TABLE_LINE}")
|
||||
}
|
||||
|
||||
pub fn maintainers_for_target(target: &str) -> Option<&'static [&'static str]> {
|
||||
TARGET_NOTIFICATIONS
|
||||
.iter()
|
||||
.find(|(target_name, _)| *target_name == target)
|
||||
.map(|(_, maintainers)| *maintainers)
|
||||
}
|
||||
|
||||
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) -> octocrab::issues::IssueHandler<'_> {
|
||||
self.client.issues(&self.owner, &self.repo)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn notify_build(
|
||||
github_client: &GitHubClient,
|
||||
db: &Db,
|
||||
build_info: &FullBuildInfo,
|
||||
) -> Result<()> {
|
||||
match build_info.status {
|
||||
Status::Error => notify_build_failure(github_client, db, build_info).await,
|
||||
Status::Pass => notify_build_pass(github_client, db, build_info).await,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn notify_build_failure(
|
||||
github_client: &GitHubClient,
|
||||
db: &Db,
|
||||
build_info: &FullBuildInfo,
|
||||
) -> Result<()> {
|
||||
let FullBuildInfo {
|
||||
target,
|
||||
nightly,
|
||||
stderr,
|
||||
..
|
||||
} = build_info;
|
||||
|
||||
let Some(notify_usernames) = maintainers_for_target(target) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
info!("Creating issue for target {target}, notifying {notify_usernames:?}");
|
||||
|
||||
let issue = db.find_existing_notification(target).await?;
|
||||
|
||||
let url = format!(
|
||||
"https://does-it-build.noratrieb.dev/build?nightly={nightly}&target={target}&mode=std"
|
||||
);
|
||||
|
||||
if let Some(issue) = issue {
|
||||
// An existing issue, send a comment.
|
||||
|
||||
github_client
|
||||
.issues()
|
||||
.create_comment(
|
||||
issue.issue_number as u64,
|
||||
format!(
|
||||
"💥 The target {target} still fails to build on the nightly {nightly}!
|
||||
|
||||
<{url}>
|
||||
|
||||
<details><summary>full logs</summary>
|
||||
|
||||
```
|
||||
{stderr}
|
||||
```
|
||||
|
||||
</details>
|
||||
"
|
||||
),
|
||||
)
|
||||
.await
|
||||
.wrap_err("creating update comment")?;
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Ensure the labels exist.
|
||||
let label = github_client.issues().get_label(target).await;
|
||||
match label {
|
||||
Ok(_) => {}
|
||||
Err(octocrab::Error::GitHub { source, .. }) if source.status_code.as_u16() == 404 => {
|
||||
github_client
|
||||
.issues()
|
||||
.create_label(target, "d73a4a", format!("Target: {target}"))
|
||||
.await
|
||||
.wrap_err("creating label")?;
|
||||
}
|
||||
Err(err) => return Err(err).wrap_err("failed to fetch label label"),
|
||||
}
|
||||
|
||||
let pings = notify_usernames
|
||||
.iter()
|
||||
.map(|name| {
|
||||
if github_client.send_pings {
|
||||
format!("@{name}")
|
||||
} else {
|
||||
format!("@\\{name}")
|
||||
}
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
let issue = github_client
|
||||
.issues()
|
||||
.create(format!("{target} fails to build on {nightly}"))
|
||||
.labels(Some(vec![target.to_owned()]))
|
||||
.body(format!(
|
||||
"💥 The target {target} fails to build on the nightly {nightly}!
|
||||
|
||||
<{url}>
|
||||
|
||||
<details>
|
||||
<summary>full logs</summary>
|
||||
|
||||
```
|
||||
{stderr}
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
{pings}
|
||||
|
||||
This issue will be closed automatically when this target works again!"
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.wrap_err("failed to create issue")?;
|
||||
|
||||
db.insert_notification(NotificationIssue {
|
||||
first_failed_nightly: nightly.into(),
|
||||
issue_number: issue.number as i64,
|
||||
status: NotificationStatus::Open,
|
||||
target: target.into(),
|
||||
})
|
||||
.await
|
||||
.wrap_err("inserting issue into DB")?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn notify_build_pass(
|
||||
github_client: &GitHubClient,
|
||||
db: &Db,
|
||||
build_info: &FullBuildInfo,
|
||||
) -> Result<()> {
|
||||
let FullBuildInfo {
|
||||
target, nightly, ..
|
||||
} = build_info;
|
||||
|
||||
let issue = db.find_existing_notification(target).await?;
|
||||
|
||||
if let Some(issue) = issue {
|
||||
info!(
|
||||
"Closing issue {} for {target}, since {nightly} builds again",
|
||||
issue.issue_number
|
||||
);
|
||||
|
||||
let url = format!(
|
||||
"https://does-it-build.noratrieb.dev/build?nightly={nightly}&target={target}&mode=std"
|
||||
);
|
||||
|
||||
// An existing issue, send a comment.
|
||||
|
||||
github_client
|
||||
.issues()
|
||||
.create_comment(
|
||||
issue.issue_number as u64,
|
||||
format!("✅ The target {target} successfully builds on nightly {nightly}, \
|
||||
thanks for playing this round of Tier 3 rustc target breakage fixing! See y'all next time :3!\n\n<{url}>"),
|
||||
)
|
||||
.await
|
||||
.wrap_err("creating update comment")?;
|
||||
|
||||
github_client
|
||||
.issues()
|
||||
.update(issue.issue_number as u64)
|
||||
.state(IssueState::Closed)
|
||||
.state_reason(IssueStateReason::Completed)
|
||||
.send()
|
||||
.await
|
||||
.wrap_err("closing issue")?;
|
||||
|
||||
db.finish_notification(issue.issue_number as i64).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
11
src/web.rs
11
src/web.rs
|
|
@ -11,7 +11,10 @@ use color_eyre::{eyre::Context, Result};
|
|||
use serde::Deserialize;
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::db::{BuildInfo, BuildMode, BuildStats, Db, Status};
|
||||
use crate::{
|
||||
db::{BuildInfo, BuildMode, BuildStats, Db, Status},
|
||||
notification,
|
||||
};
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AppState {
|
||||
|
|
@ -138,6 +141,8 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
|
|||
version: &'static str,
|
||||
builds: Vec<(String, Option<BuildInfo>, Option<BuildInfo>)>,
|
||||
showing_failures: bool,
|
||||
notification_pr_url: String,
|
||||
maintainers: Option<&'static [&'static str]>,
|
||||
}
|
||||
|
||||
let filter_failures = query.failures.unwrap_or(false);
|
||||
|
|
@ -173,12 +178,16 @@ async fn web_target(State(state): State<AppState>, Query(query): Query<TargetQue
|
|||
.collect::<Vec<_>>();
|
||||
builds.sort_by_cached_key(|build| Reverse(build.0.clone()));
|
||||
|
||||
let maintainers = notification::maintainers_for_target(&query.target);
|
||||
|
||||
let page = TargetPage {
|
||||
status,
|
||||
target: query.target,
|
||||
version: crate::VERSION,
|
||||
builds,
|
||||
showing_failures: filter_failures,
|
||||
notification_pr_url: notification::notification_pr_url(),
|
||||
maintainers,
|
||||
};
|
||||
|
||||
Html(page.render().unwrap()).into_response()
|
||||
|
|
|
|||
|
|
@ -31,6 +31,18 @@
|
|||
older targets (older than November 2024) this does not always work
|
||||
reliably, so some failed std builds there are simply no-std targets.
|
||||
</p>
|
||||
<p>
|
||||
🔔 does-it-build supports sending notifications to target maintainers via GitHub issues.
|
||||
You can add yourself with <a href="{{notification_pr_url}}">a PR</a>.
|
||||
</p>
|
||||
{% if let Some(maintainers) = maintainers %}
|
||||
<p>
|
||||
Maintainers that will receive pings for this target:
|
||||
{% for maintainer in maintainers %}
|
||||
<a href="https://github.com/{{maintainer}}">{{maintainer}}</a>
|
||||
{% endfor %}
|
||||
</p>
|
||||
{% endif %}
|
||||
{% if showing_failures %}
|
||||
<p>
|
||||
<a href="/target?target={{target}}">show all</a>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue