Merge remote-tracking branch 'origin/main'

This commit is contained in:
Bryan Helmkamp 2026-04-05 00:20:53 -04:00
commit 41f0f367b3
No known key found for this signature in database
12 changed files with 143 additions and 90 deletions

View file

@ -394,10 +394,21 @@ impl HookExecutorImpl {
/// Build a reqwest client for the given TLS mode.
fn build_http_client(tls: TlsMode) -> reqwest::Client {
let accept_invalid = matches!(tls, TlsMode::NoVerify | TlsMode::Off);
reqwest::Client::builder()
.danger_accept_invalid_certs(accept_invalid)
.build()
.unwrap_or_default()
#[cfg(test)]
{
return reqwest::Client::builder()
.danger_accept_invalid_certs(accept_invalid)
.no_proxy()
.build()
.unwrap_or_default();
}
#[cfg(not(test))]
{
reqwest::Client::builder()
.danger_accept_invalid_certs(accept_invalid)
.build()
.unwrap_or_default()
}
}
/// Execute an HTTP hook: POST context JSON and parse the response.

View file

@ -1413,6 +1413,10 @@ async fn test_models(
mod tests {
use super::*;
fn test_http_client() -> reqwest::Client {
reqwest::Client::builder().no_proxy().build().unwrap()
}
// --- parse_option ---
#[test]
@ -1618,7 +1622,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let resp = test_model_via_server(&client, &server.url(""), "test-model")
.await
.unwrap();
@ -1646,7 +1650,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let resp = test_model_via_server(&client, &server.url(""), "test-model")
.await
.unwrap();
@ -1669,7 +1673,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let result = test_model_via_server(&client, &server.url(""), "bad-model").await;
assert!(result.is_err());
}
@ -1701,7 +1705,7 @@ mod tests {
}).to_string());
}).await;
let client = reqwest::Client::new();
let client = test_http_client();
let models = fetch_models_from_server(&client, &server.url(""), None)
.await
.unwrap();
@ -1753,7 +1757,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let models = fetch_models_from_server(&client, &server.url(""), Some("anthropic"))
.await
.unwrap();
@ -1772,7 +1776,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let result = fetch_models_from_server(&client, &server.url(""), None).await;
assert!(result.is_err());
}
@ -1801,7 +1805,7 @@ mod tests {
.await;
let server = ServerConnection {
client: reqwest::Client::new(),
client: test_http_client(),
base_url: mock_server.url(""),
};
@ -1841,7 +1845,7 @@ data: {\"type\":\"finish\",\"finish_reason\":\"stop\",\"usage\":{\"input_tokens\
.await;
let server = ServerConnection {
client: reqwest::Client::new(),
client: test_http_client(),
base_url: mock_server.url(""),
};

View file

@ -2201,7 +2201,6 @@ mod tests {
"beta header should contain fast-mode header, got: {beta}"
);
}
#[test]
fn beta_header_includes_both_cache_and_fast_mode() {
let result = build_beta_header(None, true, true, false);

View file

@ -229,6 +229,10 @@ mod tests {
use futures::StreamExt;
use httpmock::prelude::*;
fn test_http_client() -> reqwest::Client {
reqwest::Client::builder().no_proxy().build().unwrap()
}
fn make_request() -> Request {
Request {
model: "test-model".to_string(),
@ -270,7 +274,7 @@ data: {\"type\":\"text_delta\",\"delta\":\" world\",\"text_id\":null}\n\
.body(sse_body);
});
let adapter = Adapter::new(reqwest::Client::new(), server.base_url(), "test-provider");
let adapter = Adapter::new(test_http_client(), server.base_url(), "test-provider");
let mut stream = adapter.stream(&make_request()).await.unwrap();
@ -323,7 +327,7 @@ data: {\"type\":\"text_delta\",\"delta\":\" world\",\"text_id\":null}\n\
.json_body(response_json);
});
let adapter = Adapter::new(reqwest::Client::new(), server.base_url(), "test-provider");
let adapter = Adapter::new(test_http_client(), server.base_url(), "test-provider");
let response = adapter.complete(&make_request()).await.unwrap();
@ -346,7 +350,7 @@ data: {\"type\":\"text_delta\",\"delta\":\" world\",\"text_id\":null}\n\
then.status(502).body("Bad Gateway");
});
let adapter = Adapter::new(reqwest::Client::new(), server.base_url(), "test-provider");
let adapter = Adapter::new(test_http_client(), server.base_url(), "test-provider");
let err = adapter.complete(&make_request()).await.unwrap_err();
match &err {
@ -367,7 +371,7 @@ data: {\"type\":\"text_delta\",\"delta\":\" world\",\"text_id\":null}\n\
then.status(502).body("Bad Gateway");
});
let adapter = Adapter::new(reqwest::Client::new(), server.base_url(), "test-provider");
let adapter = Adapter::new(test_http_client(), server.base_url(), "test-provider");
let result = adapter.stream(&make_request()).await;
let Err(err) = result else {
@ -401,7 +405,7 @@ data: {\"type\":\"stream_start\"}\n\
.body(sse_body);
});
let adapter = Adapter::new(reqwest::Client::new(), server.base_url(), "test-provider");
let adapter = Adapter::new(test_http_client(), server.base_url(), "test-provider");
let mut stream = adapter.stream(&make_request()).await.unwrap();
@ -447,7 +451,7 @@ data: {\"type\":\"stream_start\"}\n\
#[test]
fn adapter_name() {
let adapter = Adapter::new(reqwest::Client::new(), "http://localhost", "anthropic");
let adapter = Adapter::new(test_http_client(), "http://localhost", "anthropic");
assert_eq!(adapter.name(), "anthropic");
}
}

View file

@ -18,13 +18,28 @@ pub struct HttpApi {
}
impl HttpApi {
fn build_client(timeout: AdapterTimeout) -> reqwest::Client {
#[cfg(test)]
{
return reqwest::Client::builder()
.connect_timeout(Duration::from_secs_f64(timeout.connect))
.no_proxy()
.build()
.unwrap_or_default();
}
#[cfg(not(test))]
{
reqwest::Client::builder()
.connect_timeout(Duration::from_secs_f64(timeout.connect))
.build()
.unwrap_or_default()
}
}
#[must_use]
pub fn new(api_key: impl Into<String>, base_url: impl Into<String>) -> Self {
let timeout = AdapterTimeout::default();
let client = reqwest::Client::builder()
.connect_timeout(Duration::from_secs_f64(timeout.connect))
.build()
.unwrap_or_default();
let client = Self::build_client(timeout);
Self {
api_key: api_key.into(),
base_url: base_url.into(),
@ -37,10 +52,7 @@ impl HttpApi {
#[must_use]
pub fn with_timeout(mut self, timeout: AdapterTimeout) -> Self {
self.client = reqwest::Client::builder()
.connect_timeout(Duration::from_secs_f64(timeout.connect))
.build()
.unwrap_or_default();
self.client = Self::build_client(timeout);
self.request_timeout = timeout.request.map(Duration::from_secs_f64);
self.stream_read_timeout = timeout.stream_read.map(Duration::from_secs_f64);
self

View file

@ -1223,7 +1223,6 @@ mod tests {
assert!(adapter.project_id.is_none());
assert!(adapter.http.default_headers.is_empty());
}
#[test]
fn audio_content_produces_text_fallback() {
let msg = Message {

View file

@ -224,7 +224,7 @@ fn validate_callback_path(path: &str) -> Result<(), String> {
}
fn build_redirect_uri(port: u16, path: &str) -> String {
format!("http://localhost:{port}{path}")
format!("http://127.0.0.1:{port}{path}")
}
pub async fn start_callback_server(
@ -234,7 +234,7 @@ pub async fn start_callback_server(
) -> Result<(u16, oneshot::Receiver<Result<String, String>>), String> {
validate_callback_path(path)?;
let listener = TcpListener::bind(format!("localhost:{port}"))
let listener = TcpListener::bind(("127.0.0.1", port))
.await
.map_err(|e| format!("Failed to bind callback server: {e}"))?;
let actual_port = listener
@ -414,6 +414,10 @@ pub async fn run_browser_flow(
mod tests {
use super::*;
fn test_http_client() -> reqwest::Client {
reqwest::Client::builder().no_proxy().build().unwrap()
}
// -----------------------------------------------------------------------
// Phase 1: PKCE
// -----------------------------------------------------------------------
@ -554,13 +558,13 @@ mod tests {
fn build_redirect_uri_constructs_expected_uri() {
assert_eq!(
build_redirect_uri(1455, "/auth/callback"),
"http://localhost:1455/auth/callback"
"http://127.0.0.1:1455/auth/callback"
);
assert_eq!(
build_redirect_uri(8080, "/oauth/done"),
"http://localhost:8080/oauth/done"
"http://127.0.0.1:8080/oauth/done"
);
assert_eq!(build_redirect_uri(1, "/"), "http://localhost:1/");
assert_eq!(build_redirect_uri(1, "/"), "http://127.0.0.1:1/");
}
// -----------------------------------------------------------------------
@ -595,7 +599,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let tokens = exchange_code_for_tokens(
&client,
&server.url(""),
@ -633,7 +637,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let tokens = exchange_code_for_tokens(
&client,
&server.url(""),
@ -662,7 +666,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = exchange_code_for_tokens(
&client,
&server.url(""),
@ -706,7 +710,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let tokens =
refresh_access_token(&client, &server.url(""), "test-client", "old-refresh-tok")
.await
@ -731,7 +735,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = refresh_access_token(&client, &server.url(""), "test-client", "expired-tok")
.await
.unwrap_err();
@ -752,10 +756,10 @@ mod tests {
assert_ne!(port, 0);
let client = reqwest::Client::new();
let client = test_http_client();
client
.get(format!(
"http://localhost:{port}{callback_path}?code=abc&state=test-state"
"http://127.0.0.1:{port}{callback_path}?code=abc&state=test-state"
))
.send()
.await
@ -772,10 +776,10 @@ mod tests {
.await
.unwrap();
let client = reqwest::Client::new();
let client = test_http_client();
let resp = client
.get(format!(
"http://localhost:{port}{callback_path}?code=abc&state=test-state"
"http://127.0.0.1:{port}{callback_path}?code=abc&state=test-state"
))
.send()
.await
@ -791,10 +795,10 @@ mod tests {
.await
.unwrap();
let client = reqwest::Client::new();
let client = test_http_client();
let resp = client
.get(format!(
"http://localhost:{port}{callback_path}?code=abc&state=wrong-state"
"http://127.0.0.1:{port}{callback_path}?code=abc&state=wrong-state"
))
.send()
.await
@ -810,10 +814,10 @@ mod tests {
.await
.unwrap();
let client = reqwest::Client::new();
let client = test_http_client();
let resp = client
.get(format!(
"http://localhost:{port}{callback_path}?code=abc&state=test-state"
"http://127.0.0.1:{port}{callback_path}?code=abc&state=test-state"
))
.send()
.await

View file

@ -286,6 +286,10 @@ mod tests {
use axum::http::Request;
use tower::ServiceExt;
fn test_http_client() -> reqwest::Client {
reqwest::Client::builder().no_proxy().build().unwrap()
}
// -----------------------------------------------------------------------
// verify_signature
// -----------------------------------------------------------------------
@ -407,7 +411,7 @@ mod tests {
let body = b"{}";
let sig = compute_signature(secret, body);
let client = reqwest::Client::new();
let client = test_http_client();
let resp = client
.post(format!("http://127.0.0.1:{port}/webhooks/github"))
.header("x-hub-signature-256", sig)

View file

@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDLrOym7SsuLj2K
yFR9UC3jhPUDgCVC1yWa2XF7Hl2LoCGuUIyxFJwUyoWGFgkWpQKCKmNqp1AEyJI3
LEOQTBT9wqLBImuZ2J7vtDCYhMWyzMH0vLatAqcDTvPfDcdu9B27VVU1TGfiNe7t
EXP5jfjNvi7AZKdwEYnZUeE4rC4fmraQy4XY9jSm/l9hEq4/RgNg6Pnjr8EJMpxM
L8CJGLnYcJA7k4wD6VwpCQoI2vOPjfEiffkAK7Ul264/ex+hWDLycqvpeL4dJ8ZM
PGOpjuG2z9dElP50pTTycAO5wXkm+luTDVYXgtSQAs5qA4mdMMvsWUCfvV0hxer6
aaa0EVBlAgMBAAECggEAKBjFBh/OzmqgBwBlUb5FKnN0YNoLe9srNg70vk4+EEzY
FJ8a84mhKJ6uJrWT2HdnxQRfShHiOO7bii0WqAOyZjq5G9iQ4lq4/2uz3XLWENsq
m+nC9NB+3LHgZNsrlfZNHCIygimmkewYO2eiM1D12FtGjO3D4NYzEyuBcUzET8gl
k0ZbBCYee6D0cRhABlg8c35ZYQ7CGeP5eUnlPMXxh/GR3VTXs5ZXeuX2G0na6COT
t3AM0xia9FJiCw73sCb3M5xVhu+61UHXQFU2gqbUZq51B/7wiEhVmIqxoU9IUIgd
UIVGUAGfPkOmZcEhIF4Kv3tEzU+hgX9aReF7hNKXAQKBgQDq6Qy9s9HdThiu2hGV
sUF7g4uglYSPQBwddNdO+x/EgvIoij91Qh44/XF5DbHy2hUVMLJivBaO9g0xjBEL
ZAhFzYEZuKTvGEYzZw9T2K1WE0lSbk+z3kp6+nasOxrtrk63oAPTB71yiGi44S2r
eqov19s6519Qpji1W8ApW063oQKBgQDd9gDFKKa6wpYVH+6KmBeaUrGUhnoujujz
fIWX4DapGoqhpx2fTOJe8vlyPbXqfG/akzvEjd21voXHeeR9GfsOOqjtW9v89Aq3
Pfqli6VdLcRFxT81kgL87/3m6WvmT6sq0mfIuIwiVul6bCdIBWoYOGffiGu5NCS6
BSFi3yCSRQKBgQCLwWbRHcBHl4Tb0eUQV8qLfzF8sjeROiT/6VmHJaQ6t2T2dXlX
e6SbZz0xNdKeltxgJP6b+ya4mu4yghBJ5JN/Y8ng0Zden+R0BGZ8DbbiNMs0fWhx
rFhHXedohCl7Km6ulEZyMHKnRzx2cZFIKcxCdnt5SdnNE3c9fn6OnEHywQKBgQC0
RBk4Bt3yjBqsKXTopsF0mniS8ezFZ1eWeKlfQb/i8yVoSHtsZ1rqVld1Ct12BX4q
fK1r4vQPqR6pdTu2xqT5V3be3135QJJ7ZCDu1k2FMahYKew+K8m1d4w0P5tcP5P6
gUu83vUg5olU3gXBHnSeGyFxkDA9CDZTxdrpm+GuKQKBgQCHPw1CBsijUwrSOEqu
4U4DkvrchEHiix3BMv6rYrDBFYu+NbDJEEkLORjN0uIV5Iq++zwewCYq1QzIdX/a
ZRBsajgkhzM5Cw8BtsRz0NgT0wsw2gk4NnViy/pLUzXWfwVpFsMTgNpJ/ya3/giU
imhV/k13UHJZzwEx/cR3JiK1uQ==
-----END PRIVATE KEY-----

View file

@ -498,21 +498,12 @@ mod tests {
use crate::Issue;
use fabro_github::GitHubAppCredentials;
fn test_http_client() -> reqwest::Client {
reqwest::Client::builder().no_proxy().build().unwrap()
}
fn test_rsa_key() -> String {
use std::process::Command;
let output = Command::new("openssl")
.args([
"genpkey",
"-algorithm",
"RSA",
"-pkeyopt",
"rsa_keygen_bits:2048",
])
.output()
.expect("openssl should be available");
assert!(output.status.success(), "openssl keygen failed");
String::from_utf8(output.stdout).unwrap()
include_str!("fixtures/github-app-test-key.pem").to_string()
}
// -----------------------------------------------------------------------
@ -535,7 +526,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let result = execute_github_graphql(
&client,
"test-token",
@ -561,7 +552,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = execute_github_graphql(
&client,
"bad-token",
@ -587,7 +578,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = execute_github_graphql(
&client,
"token",
@ -616,7 +607,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
execute_github_graphql(
&client,
"my-token",
@ -640,7 +631,7 @@ mod tests {
app_id: "test-app".to_string(),
private_key_pem: pem,
},
reqwest::Client::new(),
test_http_client(),
"owner".to_string(),
"repo".to_string(),
1,
@ -768,7 +759,6 @@ mod tests {
then.status(201).body(r#"{"token": "ghs_test"}"#);
})
.await;
// Org query returns null → fall back to user
server
.mock_async(|when, then| {
when.method("POST")
@ -777,7 +767,6 @@ mod tests {
then.status(200).body(r#"{"data": {"organization": null}}"#);
})
.await;
// User query succeeds
server
.mock_async(|when, then| {
when.method("POST")
@ -787,7 +776,6 @@ mod tests {
.body(r#"{"data": {"user": {"projectV2": {"id": "PVT_user1"}}}}"#);
})
.await;
// Items page (empty)
server
.mock_async(|when, then| {
when.method("POST")
@ -894,7 +882,6 @@ mod tests {
then.status(201).body(r#"{"token": "ghs_test"}"#);
})
.await;
// Resolve project node ID (org path)
server
.mock_async(|when, then| {
when.method("POST")
@ -908,7 +895,6 @@ mod tests {
when.method("POST").path("/graphql").body_includes("field(name:");
then.status(200).body(r#"{"data": {"node": {"field": {"id": "FLD_1", "options": [{"id": "opt-done", "name": "Done"}, {"id": "opt-todo", "name": "Todo"}]}}}}"#);
}).await;
// Update mutation
server.mock_async(|when, then| {
when.method("POST").path("/graphql").body_includes("updateProjectV2ItemFieldValue");
then.status(200).body(r#"{"data": {"updateProjectV2ItemFieldValue": {"projectV2Item": {"id": "PVTI_item1"}}}}"#);
@ -937,7 +923,6 @@ mod tests {
then.status(201).body(r#"{"token": "ghs_test"}"#);
})
.await;
// Resolve project node ID
server
.mock_async(|when, then| {
when.method("POST")

View file

@ -355,6 +355,9 @@ impl Tracker for LinearTracker {
#[cfg(test)]
mod tests {
use super::*;
fn test_http_client() -> reqwest::Client {
reqwest::Client::builder().no_proxy().build().unwrap()
}
fn mock_config(server_url: &str) -> LinearOptions {
LinearOptions {
@ -591,7 +594,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let result = execute_graphql(
&client,
&config,
@ -617,7 +620,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = execute_graphql(
&client,
&config,
@ -642,7 +645,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = execute_graphql(
&client,
&config,
@ -668,7 +671,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
let err = execute_graphql(&client, &config, "query { bad }", serde_json::json!({}))
.await
.unwrap_err();
@ -691,7 +694,7 @@ mod tests {
})
.await;
let client = reqwest::Client::new();
let client = test_http_client();
execute_graphql(
&client,
&config,
@ -721,7 +724,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let id = tracker.fetch_viewer_id().await.unwrap();
assert_eq!(id, "user-abc");
}
@ -738,7 +741,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let err = tracker.fetch_viewer_id().await.unwrap_err();
assert!(err.contains("401"), "got: {err}");
}
@ -760,7 +763,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issue = make_test_issue();
tracker.create_comment(&issue, "Hello world").await.unwrap();
}
@ -778,7 +781,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issue = make_test_issue();
let err = tracker.create_comment(&issue, "Hello").await.unwrap_err();
assert!(err.contains("success: false"), "got: {err}");
@ -811,7 +814,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issue = make_test_issue();
tracker.update_issue_state(&issue, "Done").await.unwrap();
@ -832,7 +835,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issue = make_test_issue();
let err = tracker
.update_issue_state(&issue, "Nonexistent")
@ -868,7 +871,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "my-project".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "my-project".to_string());
let issues = tracker
.fetch_candidate_issues(&["In Progress"])
.await
@ -929,7 +932,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issues = tracker.fetch_candidate_issues(&["Todo"]).await.unwrap();
assert_eq!(issues.len(), 2);
@ -958,7 +961,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issues = tracker.fetch_candidate_issues(&["Todo"]).await.unwrap();
assert!(issues.is_empty());
@ -1000,7 +1003,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issues = tracker
.fetch_issues_by_ids(&["id-a", "id-b"])
.await
@ -1060,7 +1063,7 @@ mod tests {
})
.await;
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issues = tracker.fetch_issues_by_ids(&id_refs).await.unwrap();
assert_eq!(issues.len(), 51);
@ -1071,7 +1074,7 @@ mod tests {
#[tokio::test]
async fn fetch_issues_by_ids_empty() {
let config = LinearOptions::new("unused".to_string());
let tracker = LinearTracker::new(config, reqwest::Client::new(), "proj".to_string());
let tracker = LinearTracker::new(config, test_http_client(), "proj".to_string());
let issues = tracker.fetch_issues_by_ids(&[]).await.unwrap();
assert!(issues.is_empty());
}

View file

@ -12139,8 +12139,8 @@ async fn e2e_stall_watchdog_triggers_from_dot_parsed_pipeline() {
// Verify the canonical watchdog timeout envelope was emitted.
let collected = events.lock().unwrap();
assert!(
collected.iter().any(|e| e.contains("watchdog.timeout")),
"expected watchdog.timeout event in: {collected:?}"
collected.iter().any(|e| e.contains("StallWatchdogTimeout")),
"expected StallWatchdogTimeout event in: {collected:?}"
);
}