@@ -529,6 +529,12 @@ private void LookupForMatchingGitHubRepository(BuildIdentity buildIdentity)
529529 string repoIdentity = string . Empty ;
530530 string gitHubHost = "github.com" ;
531531
532+ if ( Environment . GetEnvironmentVariable ( "GITHUB_TOKEN" ) is string envGitHubToken )
533+ {
534+ client . DefaultRequestHeaders . Authorization =
535+ new System . Net . Http . Headers . AuthenticationHeaderValue ( "Bearer" , envGitHubToken ) ;
536+ }
537+
532538 if ( ! Uri . TryCreate ( buildIdentity . AzureDevOpsRepository , UriKind . Absolute , out Uri repoAddr ) )
533539 {
534540 throw new Exception ( $ "Can't parse the repository URL: { buildIdentity . AzureDevOpsRepository } ") ;
@@ -550,26 +556,20 @@ private void LookupForMatchingGitHubRepository(BuildIdentity buildIdentity)
550556 HttpResponseMessage response = client . GetAsync ( url ) . Result ;
551557
552558 const int MaxRetries = 5 ;
553- for ( int retry = 1 ; retry <= MaxRetries && response . StatusCode == System . Net . HttpStatusCode . TooManyRequests ; retry ++ )
559+ for ( int retry = 1 ;
560+ retry <= MaxRetries && ( response . StatusCode == System . Net . HttpStatusCode . TooManyRequests || response . StatusCode == System . Net . HttpStatusCode . Forbidden ) ;
561+ retry ++ )
554562 {
555- TimeSpan timeSpan ;
556- if ( response . Headers . RetryAfter ? . Delta != null )
557- {
558- timeSpan = response . Headers . RetryAfter . Delta . Value ;
559- }
560- else if ( response . Headers . RetryAfter ? . Date != null )
561- {
562- timeSpan = response . Headers . RetryAfter . Date . Value - DateTimeOffset . UtcNow ;
563- }
564- else
563+ TimeSpan ? timeSpan = GetTimeToWait ( response ) ;
564+
565+ if ( ! timeSpan . HasValue )
565566 {
566- const int defaultRetryAfterSeconds = 10 ;
567- timeSpan = TimeSpan . FromSeconds ( defaultRetryAfterSeconds ) ;
567+ break ;
568568 }
569569
570570 Log . LogMessage ( MessageImportance . High ,
571- $ "API rate limit exceeded, retrying in { timeSpan . TotalSeconds } seconds. Retry attempt: { retry } ") ;
572- Thread . Sleep ( timeSpan ) ;
571+ $ "API rate limit exceeded, retrying in { timeSpan . Value . TotalSeconds } seconds. Retry attempt: { retry } ") ;
572+ Thread . Sleep ( timeSpan . Value ) ;
573573 response = client . GetAsync ( url ) . Result ;
574574 }
575575
@@ -594,6 +594,37 @@ private void LookupForMatchingGitHubRepository(BuildIdentity buildIdentity)
594594 }
595595 }
596596
597+ public static TimeSpan ? GetTimeToWait ( HttpResponseMessage response )
598+ {
599+ if ( response . Headers . RetryAfter != null )
600+ {
601+ if ( response . Headers . RetryAfter . Delta . HasValue )
602+ {
603+ return response . Headers . RetryAfter . Delta . Value ;
604+ }
605+ else if ( response . Headers . RetryAfter . Date . HasValue )
606+ {
607+ return response . Headers . RetryAfter . Date . Value - DateTimeOffset . Now ;
608+ }
609+ }
610+
611+ if ( response . Headers . TryGetValues ( "X-RateLimit-Remaining" , out var values ) )
612+ {
613+ if ( values . FirstOrDefault ( ) != "0" )
614+ {
615+ // apparently not rate limited, so no need to wait
616+ return null ;
617+ }
618+
619+ values = response . Headers . GetValues ( "X-RateLimit-Reset" ) ;
620+ if ( long . TryParse ( values . FirstOrDefault ( ) , out long resetTime ) )
621+ {
622+ return DateTimeOffset . FromUnixTimeSeconds ( resetTime ) - DateTimeOffset . Now ;
623+ }
624+ }
625+ return null ;
626+ }
627+
597628 public static string GetRepoName ( string repoUrl )
598629 {
599630 // In case the URL comes in ending with a '/', prevent an indexing exception
0 commit comments