@@ -3,25 +3,31 @@ use std::{
33 collections:: HashMap ,
44 env, fs,
55 path:: { Path , PathBuf } ,
6- time:: SystemTime ,
6+ time:: { Duration , SystemTime } ,
77} ;
88
99use api:: { client:: ApiClient , message} ;
1010use bundle:: BundleMetaDebugProps ;
1111use bundle:: Test ;
1212use chrono:: prelude:: * ;
1313use codeowners:: CodeOwners ;
14+ use constants:: TRUNK_API_TOKEN_ENV ;
1415use context:: repo:: { BundleRepo , RepoUrlParts } ;
16+ use http:: { header:: HeaderMap , HeaderValue } ;
1517#[ cfg( feature = "ruby" ) ]
1618use magnus:: { value:: ReprValue , Module , Object } ;
1719use prost_wkt_types:: Timestamp ;
1820use proto:: test_context:: test_run:: {
1921 CodeOwner , TestCaseRun , TestCaseRunStatus , TestReport as TestReportProto , TestResult ,
2022 UploaderMetadata ,
2123} ;
24+ use reqwest:: blocking:: Client ;
25+ use reqwest:: header;
26+ use reqwest:: StatusCode ;
2227use third_party:: sentry;
2328use tracing_subscriber:: { filter:: FilterFn , prelude:: * } ;
2429use trunk_analytics_cli:: { context:: gather_initial_test_context, upload_command:: run_upload} ;
30+ use url:: Url ;
2531#[ cfg( feature = "wasm" ) ]
2632use wasm_bindgen:: prelude:: wasm_bindgen;
2733
@@ -311,12 +317,8 @@ impl MutTestReport {
311317 repo : repo. clone ( ) ,
312318 } ;
313319 loop {
314- let response = tokio:: runtime:: Builder :: new_multi_thread ( )
315- . enable_all ( )
316- . max_blocking_threads ( 512 )
317- . build ( )
318- . unwrap ( )
319- . block_on ( api_client. list_quarantined_tests ( & request) ) ;
320+ let response =
321+ Self :: list_quarantined_tests_blocking ( api_client, & request, & org_url_slug) ;
320322 match response {
321323 Ok ( response) => {
322324 for test in response. quarantined_tests . iter ( ) {
@@ -341,18 +343,106 @@ impl MutTestReport {
341343 }
342344 Err ( err) => {
343345 tracing:: warn!( "Unable to fetch quarantined tests" ) ;
344- tracing:: error!(
345- hidden_in_console = true ,
346- "Error fetching quarantined tests: {:?}" ,
347- err
348- ) ;
346+ tracing:: error!( "Error fetching quarantined tests: {:?}" , err) ;
349347 break ;
350348 }
351349 }
352350 }
353351 self . 0 . borrow_mut ( ) . quarantined_tests = Some ( quarantined_tests) ;
354352 }
355353
354+ fn list_quarantined_tests_blocking (
355+ api_client : & ApiClient ,
356+ request : & message:: ListQuarantinedTestsRequest ,
357+ org_url_slug : & str ,
358+ ) -> anyhow:: Result < message:: ListQuarantinedTestsResponse > {
359+ let api_token = env:: var ( TRUNK_API_TOKEN_ENV )
360+ . map_err ( |_| anyhow:: anyhow!( "Trunk API token is required." ) ) ?;
361+ if api_token. trim ( ) . is_empty ( ) {
362+ return Err ( anyhow:: anyhow!( "Trunk API token is required." ) ) ;
363+ }
364+
365+ let api_token_header_value = HeaderValue :: from_str ( & api_token)
366+ . map_err ( |_| anyhow:: Error :: msg ( "Trunk API token is not ASCII" ) ) ?;
367+
368+ let version_path_prefix = if env:: var ( "DEBUG_STRIP_VERSION_PREFIX" ) . is_ok ( ) {
369+ String :: from ( "" )
370+ } else {
371+ String :: from ( "/v1" )
372+ } ;
373+
374+ let mut default_headers = HeaderMap :: new ( ) ;
375+ default_headers. append (
376+ header:: CONTENT_TYPE ,
377+ HeaderValue :: from_static ( "application/json" ) ,
378+ ) ;
379+ default_headers. append ( "x-api-token" , api_token_header_value) ;
380+
381+ let client = Client :: builder ( )
382+ . timeout ( Duration :: from_secs ( 30 ) )
383+ . default_headers ( default_headers)
384+ . build ( ) ?;
385+
386+ let url = format ! ( "https://api.trunk-staging.io/v1/flaky-tests/list-quarantined-tests" ) ;
387+
388+ let response = client. post ( & url) . json ( request) . send ( ) ?;
389+ println ! ( "response: {:?}" , response) ;
390+ println ! ( "url: {:?}" , url) ;
391+ println ! ( "request: {:?}" , request) ;
392+
393+ // Handle status codes similar to status_code_help
394+ let response = if !response. status ( ) . is_client_error ( ) {
395+ response. error_for_status ( ) ?
396+ } else {
397+ let status = response. status ( ) ;
398+ let error_message = match status {
399+ StatusCode :: UNAUTHORIZED => {
400+ let domain = Url :: parse ( & api_client. api_host )
401+ . ok ( )
402+ . and_then ( |url| url. domain ( ) . map ( String :: from) ) ;
403+ let context = "Your Trunk token may be incorrect - find it on the Trunk app (Settings -> Manage Organization -> Organization API Token -> View)." ;
404+ if let Some ( present_domain) = domain {
405+ let settings_url = format ! (
406+ "https://{}/{}/settings" ,
407+ present_domain. replace( "api" , "app" ) ,
408+ org_url_slug
409+ ) ;
410+ format ! (
411+ "{}\n Hint - Your settings page can be found at: {}" ,
412+ context, settings_url
413+ )
414+ } else {
415+ String :: from ( context)
416+ }
417+ }
418+ StatusCode :: NOT_FOUND => {
419+ let domain = Url :: parse ( & api_client. api_host )
420+ . ok ( )
421+ . and_then ( |url| url. domain ( ) . map ( String :: from) ) ;
422+ let context = "Your Trunk organization URL slug may be incorrect - find it on the Trunk app (Settings -> Manage Organization -> Organization Slug)." ;
423+ if let Some ( present_domain) = domain {
424+ let settings_url = format ! (
425+ "https://{}/{}/settings" ,
426+ present_domain. replace( "api" , "app" ) ,
427+ org_url_slug
428+ ) ;
429+ format ! (
430+ "{}\n Hint - Your settings page can be found at: {}" ,
431+ context, settings_url
432+ )
433+ } else {
434+ String :: from ( context)
435+ }
436+ }
437+ _ => format ! ( "Failed to list quarantined tests." ) ,
438+ } ;
439+ return Err ( anyhow:: Error :: msg ( error_message) ) ;
440+ } ;
441+
442+ let deserialized: message:: ListQuarantinedTestsResponse = response. json ( ) ?;
443+ Ok ( deserialized)
444+ }
445+
356446 fn get_org_url_slug ( & self ) -> String {
357447 env:: var ( constants:: TRUNK_ORG_URL_SLUG_ENV ) . unwrap_or_default ( )
358448 }
0 commit comments