@@ -60,14 +60,6 @@ export class GitHubAuthProvider implements vscode.AuthenticationProvider {
6060 this . deviceAuthentication = deviceAuthentication ;
6161 }
6262
63- async notifyExistingSessions ( ) : Promise < void > {
64- const sessions = await this . sessionsPromise ;
65- if ( sessions . length > 0 ) {
66- this . logger . info ( `GitHubAuthProvider: notifying about ${ sessions . length } existing session(s)` ) ;
67- this . sessionChangeEmitter . fire ( { added : sessions , removed : [ ] , changed : [ ] } ) ;
68- }
69- }
70-
7163 async hydrateFromK8sToken ( ) : Promise < void > {
7264 let sessions = await this . sessionsPromise ;
7365 if ( sessions . length > 0 ) {
@@ -96,51 +88,60 @@ export class GitHubAuthProvider implements vscode.AuthenticationProvider {
9688 }
9789 }
9890
99- await this . tryHydrate ( 3 , 500 ) ;
91+ await this . doHydrate ( ) ;
10092 }
10193
102- private async tryHydrate ( maxAttempts : number , delayMs : number ) : Promise < void > {
103- for ( let attempt = 1 ; attempt <= maxAttempts ; attempt ++ ) {
94+ private async waitForToken ( timeoutMs : number , intervalMs : number ) : Promise < string | undefined > {
95+ const deadline = Date . now ( ) + timeoutMs ;
96+ while ( Date . now ( ) < deadline ) {
10497 try {
105- const token = await this . githubService . getToken ( ) ;
106- const tokenScopes = await this . githubService . getTokenScopes ( token ) ;
107- if ( tokenScopes . length === 0 ) {
108- this . logger . info ( 'GitHubAuthProvider: hydrate skipped, token has no scopes' ) ;
109- return ;
110- }
98+ return await this . githubService . getToken ( ) ;
99+ } catch {
100+ await new Promise ( resolve => setTimeout ( resolve , intervalMs ) ) ;
101+ }
102+ }
103+ return undefined ;
104+ }
111105
112- const githubUser = await this . githubService . getUser ( ) ;
113- const matchingBundles = getMatchingHydrationScopeBundles ( tokenScopes ) ;
114- if ( matchingBundles . length === 0 ) {
115- this . logger . info ( 'GitHubAuthProvider: hydrate skipped , token scopes match no known bundle ' ) ;
116- return ;
117- }
106+ private async doHydrate ( ) : Promise < void > {
107+ const token = await this . waitForToken ( 30000 , 500 ) ;
108+ if ( ! token ) {
109+ this . logger . warn ( 'GitHubAuthProvider: hydrate failed , token not available after 30s ' ) ;
110+ return ;
111+ }
118112
119- const isDeviceAuthToken = await this . githubService . isDeviceAuthToken ( ) ;
120- const account = { label : githubUser . login , id : githubUser . id . toString ( ) } ;
121- const hydratedSessions = matchingBundles . map ( scopes => ( {
122- id : v4 ( ) ,
123- accessToken : token ,
124- account,
125- scopes : isDeviceAuthToken ? scopes : [ ...scopes , WORKSPACE_PAT_SCOPE ] ,
126- } ) ) ;
127-
128- await this . storeSessions ( hydratedSessions ) ;
129- this . sessionChangeEmitter . fire ( { added : hydratedSessions , removed : [ ] , changed : [ ] } ) ;
130- const tokenSource = isDeviceAuthToken ? 'device authentication' : 'workspace PAT' ;
131- this . logger . info ( `GitHubAuthProvider: hydrated ${ hydratedSessions . length } session(s) from K8s ${ tokenSource } ` ) ;
113+ try {
114+ const tokenScopes = await this . githubService . getTokenScopes ( token ) ;
115+ if ( tokenScopes . length === 0 ) {
116+ this . logger . info ( 'GitHubAuthProvider: hydrate skipped, token has no scopes' ) ;
132117 return ;
133- } catch ( error ) {
134- if ( isUnauthorizedError ( error ) ) {
135- this . logger . warn ( 'GitHubAuthProvider: hydrate failed, token is not valid' ) ;
136- return ;
137- }
138- if ( attempt < maxAttempts ) {
139- this . logger . info ( `GitHubAuthProvider: hydrate attempt ${ attempt } /${ maxAttempts } failed: ${ ( error as Error ) . message } , retrying in ${ delayMs } ms` ) ;
140- await new Promise ( resolve => setTimeout ( resolve , delayMs ) ) ;
141- } else {
142- this . logger . warn ( `GitHubAuthProvider: hydrate failed after ${ maxAttempts } attempts: ${ ( error as Error ) . message } ` ) ;
143- }
118+ }
119+
120+ const githubUser = await this . githubService . getUser ( ) ;
121+ const matchingBundles = getMatchingHydrationScopeBundles ( tokenScopes ) ;
122+ if ( matchingBundles . length === 0 ) {
123+ this . logger . info ( 'GitHubAuthProvider: hydrate skipped, token scopes match no known bundle' ) ;
124+ return ;
125+ }
126+
127+ const isDeviceAuthToken = await this . githubService . isDeviceAuthToken ( ) ;
128+ const account = { label : githubUser . login , id : githubUser . id . toString ( ) } ;
129+ const hydratedSessions = matchingBundles . map ( scopes => ( {
130+ id : v4 ( ) ,
131+ accessToken : token ,
132+ account,
133+ scopes : isDeviceAuthToken ? scopes : [ ...scopes , WORKSPACE_PAT_SCOPE ] ,
134+ } ) ) ;
135+
136+ await this . storeSessions ( hydratedSessions ) ;
137+ this . sessionChangeEmitter . fire ( { added : hydratedSessions , removed : [ ] , changed : [ ] } ) ;
138+ const tokenSource = isDeviceAuthToken ? 'device authentication' : 'workspace PAT' ;
139+ this . logger . info ( `GitHubAuthProvider: hydrated ${ hydratedSessions . length } session(s) from K8s ${ tokenSource } ` ) ;
140+ } catch ( error ) {
141+ if ( isUnauthorizedError ( error ) ) {
142+ this . logger . warn ( 'GitHubAuthProvider: hydrate failed, token is not valid' ) ;
143+ } else {
144+ this . logger . warn ( `GitHubAuthProvider: hydrate failed: ${ ( error as Error ) . message } ` ) ;
144145 }
145146 }
146147 }
0 commit comments