From 6512f5df981e0d47089f3eab9026d4338574c61e Mon Sep 17 00:00:00 2001 From: Ubiratan Soares Date: Thu, 16 Apr 2026 10:54:12 +0200 Subject: [PATCH 1/2] github: support multiple webhook secrets --- src/github/webhook.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/github/webhook.rs b/src/github/webhook.rs index 3ff755a5a..ae79bbd0a 100644 --- a/src/github/webhook.rs +++ b/src/github/webhook.rs @@ -339,12 +339,20 @@ fn check_payload_signed(signature: &str, payload: &[u8]) -> Result<(), SignedPay } }; - let mut mac = Hmac::::new_from_slice( - std::env::var("GITHUB_WEBHOOK_SECRET") - .expect("Missing GITHUB_WEBHOOK_SECRET") - .as_bytes(), - ) - .unwrap(); - mac.update(payload); - mac.verify_slice(&signature).map_err(|_| SignedPayloadError) + // although the env var name suggests a single webhook secret passed in, + // for the sake of easing some operational tasks, internally we support + // a comma-separated list of them. + let gh_webhook_secrets = + std::env::var("GITHUB_WEBHOOK_SECRET").expect("Missing GITHUB_WEBHOOK_SECRET"); + + for secret in gh_webhook_secrets.split(',') { + let mut mac = Hmac::::new_from_slice(secret.trim().as_bytes()).unwrap(); + + mac.update(payload); + if mac.verify_slice(&signature).is_ok() { + return Ok(()); + } + } + + Err(SignedPayloadError) } From 776798a72d2b8861eedd4018951340b5204678c0 Mon Sep 17 00:00:00 2001 From: Ubiratan Soares Date: Thu, 16 Apr 2026 14:28:00 +0200 Subject: [PATCH 2/2] github: add ongoing maintenance warn --- src/main.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/main.rs b/src/main.rs index 28d40f35a..56919a541 100644 --- a/src/main.rs +++ b/src/main.rs @@ -45,6 +45,8 @@ async fn run_server(addr: SocketAddr) -> anyhow::Result<()> { .build() .expect("Failed to build octocrab."); + check_ongoing_service_maintenance(); + // Loading the workqueue takes ~10-15s on large repos, and it's annoying for local rebuilds. // Allow users to opt out of it. let skip_loading_workqueue = env::var("SKIP_WORKQUEUE").is_ok_and(|v| v == "1"); @@ -365,6 +367,17 @@ fn is_scheduled_jobs_disabled() -> bool { env::var_os("TRIAGEBOT_TEST_DISABLE_JOBS").is_some() } +/// Evaluates signals of ongoing service maintenance at startup time +/// For now we check only whether we are updating Github webhooks +fn check_ongoing_service_maintenance() { + let gh_webhook_secrets = + env::var("GITHUB_WEBHOOK_SECRET").expect("GITHUB_WEBHOOK_SECRET is required"); + + if gh_webhook_secrets.split(',').count() > 1 { + tracing::warn!("ongoing maintenance: multiple github webhooks secrets are set"); + } +} + #[tokio::main(flavor = "current_thread")] async fn main() -> anyhow::Result<()> { dotenvy::dotenv().ok();