@@ -37,6 +37,11 @@ public interface IHostContext : IDisposable
37
37
void ShutdownRunner ( ShutdownReason reason ) ;
38
38
void WritePerfCounter ( string counter ) ;
39
39
void LoadDefaultUserAgents ( ) ;
40
+
41
+ bool AllowAuthMigration { get ; }
42
+ void EnableAuthMigration ( string trace ) ;
43
+ void DeferAuthMigration ( TimeSpan deferred , string trace ) ;
44
+ event EventHandler < AuthMigrationEventArgs > AuthMigrationChanged ;
40
45
}
41
46
42
47
public enum StartupType
@@ -70,12 +75,21 @@ public sealed class HostContext : EventListener, IObserver<DiagnosticListener>,
70
75
private RunnerWebProxy _webProxy = new ( ) ;
71
76
private string _hostType = string . Empty ;
72
77
78
+ // disable auth migration by default
79
+ private readonly ManualResetEventSlim _allowAuthMigration = new ManualResetEventSlim ( false ) ;
80
+ private DateTime _deferredAuthMigrationTime = DateTime . MaxValue ;
81
+ private readonly object _authMigrationLock = new object ( ) ;
82
+ private CancellationTokenSource _authMigrationAutoReenableTaskCancellationTokenSource = new ( ) ;
83
+ private Task _authMigrationAutoReenableTask ;
84
+
73
85
public event EventHandler Unloading ;
86
+ public event EventHandler < AuthMigrationEventArgs > AuthMigrationChanged ;
74
87
public CancellationToken RunnerShutdownToken => _runnerShutdownTokenSource . Token ;
75
88
public ShutdownReason RunnerShutdownReason { get ; private set ; }
76
89
public ISecretMasker SecretMasker => _secretMasker ;
77
90
public List < ProductInfoHeaderValue > UserAgents => _userAgents ;
78
91
public RunnerWebProxy WebProxy => _webProxy ;
92
+ public bool AllowAuthMigration => _allowAuthMigration . IsSet ;
79
93
public HostContext ( string hostType , string logFile = null )
80
94
{
81
95
// Validate args.
@@ -207,6 +221,71 @@ public HostContext(string hostType, string logFile = null)
207
221
LoadDefaultUserAgents ( ) ;
208
222
}
209
223
224
+ // marked as internal for testing
225
+ internal async Task AuthMigrationAuthReenableAsync ( TimeSpan refreshInterval , CancellationToken token )
226
+ {
227
+ try
228
+ {
229
+ while ( ! token . IsCancellationRequested )
230
+ {
231
+ _trace . Verbose ( $ "Auth migration defer timer is set to expire at { _deferredAuthMigrationTime . ToString ( "O" ) } . AllowAuthMigration: { _allowAuthMigration . IsSet } .") ;
232
+ await Task . Delay ( refreshInterval , token ) ;
233
+ if ( ! _allowAuthMigration . IsSet && DateTime . UtcNow > _deferredAuthMigrationTime )
234
+ {
235
+ _trace . Info ( $ "Auth migration defer timer expired. Allowing auth migration.") ;
236
+ EnableAuthMigration ( "Auth migration defer timer expired." ) ;
237
+ }
238
+ }
239
+ }
240
+ catch ( TaskCanceledException )
241
+ {
242
+ // Task was cancelled, exit the loop.
243
+ }
244
+ catch ( Exception ex )
245
+ {
246
+ _trace . Info ( "Error in auth migration reenable task." ) ;
247
+ _trace . Error ( ex ) ;
248
+ }
249
+ }
250
+
251
+ public void EnableAuthMigration ( string trace )
252
+ {
253
+ _allowAuthMigration . Set ( ) ;
254
+
255
+ lock ( _authMigrationLock )
256
+ {
257
+ if ( _authMigrationAutoReenableTask == null )
258
+ {
259
+ var refreshIntervalInMS = 60 * 1000 ;
260
+ #if DEBUG
261
+ // For L0, we will refresh faster
262
+ if ( ! string . IsNullOrEmpty ( Environment . GetEnvironmentVariable ( "_GITHUB_ACTION_AUTH_MIGRATION_REFRESH_INTERVAL" ) ) )
263
+ {
264
+ refreshIntervalInMS = int . Parse ( Environment . GetEnvironmentVariable ( "_GITHUB_ACTION_AUTH_MIGRATION_REFRESH_INTERVAL" ) ) ;
265
+ }
266
+ #endif
267
+ _authMigrationAutoReenableTask = AuthMigrationAuthReenableAsync ( TimeSpan . FromMilliseconds ( refreshIntervalInMS ) , _authMigrationAutoReenableTaskCancellationTokenSource . Token ) ;
268
+ }
269
+ }
270
+
271
+ _trace . Info ( $ "Enable auth migration at { _deferredAuthMigrationTime . ToString ( "O" ) } .") ;
272
+ AuthMigrationChanged ? . Invoke ( this , new AuthMigrationEventArgs ( trace ) ) ;
273
+ }
274
+
275
+ public void DeferAuthMigration ( TimeSpan deferred , string trace )
276
+ {
277
+ _allowAuthMigration . Reset ( ) ;
278
+
279
+ // defer migration for a while
280
+ lock ( _authMigrationLock )
281
+ {
282
+ _deferredAuthMigrationTime = DateTime . UtcNow . Add ( deferred ) ;
283
+ }
284
+
285
+ _trace . Info ( $ "Disabled auth migration until { _deferredAuthMigrationTime . ToString ( "O" ) } .") ;
286
+ AuthMigrationChanged ? . Invoke ( this , new AuthMigrationEventArgs ( trace ) ) ;
287
+ }
288
+
210
289
public void LoadDefaultUserAgents ( )
211
290
{
212
291
if ( string . IsNullOrEmpty ( WebProxy . HttpProxyAddress ) && string . IsNullOrEmpty ( WebProxy . HttpsProxyAddress ) )
@@ -549,6 +628,18 @@ private void Dispose(bool disposing)
549
628
_loadContext . Unloading -= LoadContext_Unloading ;
550
629
_loadContext = null ;
551
630
}
631
+
632
+ if ( _authMigrationAutoReenableTask != null )
633
+ {
634
+ _authMigrationAutoReenableTaskCancellationTokenSource ? . Cancel ( ) ;
635
+ }
636
+
637
+ if ( _authMigrationAutoReenableTaskCancellationTokenSource != null )
638
+ {
639
+ _authMigrationAutoReenableTaskCancellationTokenSource ? . Dispose ( ) ;
640
+ _authMigrationAutoReenableTaskCancellationTokenSource = null ;
641
+ }
642
+
552
643
_httpTraceSubscription ? . Dispose ( ) ;
553
644
_diagListenerSubscription ? . Dispose ( ) ;
554
645
_traceManager ? . Dispose ( ) ;
0 commit comments