Skip to content

Commit 3dd678d

Browse files
authored
GitHub - update authentication flow for branch protection (microsoft#181924)
* GitHub - tweak authentication request * Add tracing messages
1 parent d4632bb commit 3dd678d

File tree

2 files changed

+41
-20
lines changed

2 files changed

+41
-20
lines changed

extensions/github/src/auth.ts

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { Octokit } from '@octokit/rest';
1010
import { httpsOverHttp } from 'tunnel';
1111
import { URL } from 'url';
1212

13+
export class AuthenticationError extends Error { }
14+
1315
function getAgent(url: string | undefined = process.env.HTTPS_PROXY): Agent {
1416
if (!url) {
1517
return globalAgent;
@@ -57,25 +59,30 @@ export function getOctokit(): Promise<Octokit> {
5759

5860
let _octokitGraphql: Promise<graphql> | undefined;
5961

60-
export function getOctokitGraphql(): Promise<graphql> {
62+
export async function getOctokitGraphql(): Promise<graphql> {
6163
if (!_octokitGraphql) {
62-
_octokitGraphql = getSession()
63-
.then(async session => {
64-
const token = session.accessToken;
65-
const { graphql } = await import('@octokit/graphql');
66-
67-
return graphql.defaults({
68-
headers: {
69-
authorization: `token ${token}`
70-
},
71-
request: {
72-
agent: getAgent()
73-
}
74-
});
75-
}).then(null, async err => {
76-
_octokitGraphql = undefined;
77-
throw err;
64+
try {
65+
const session = await authentication.getSession('github', scopes, { createIfNone: false });
66+
67+
if (!session) {
68+
throw new AuthenticationError('No GitHub authentication session available.');
69+
}
70+
71+
const token = session.accessToken;
72+
const { graphql } = await import('@octokit/graphql');
73+
74+
return graphql.defaults({
75+
headers: {
76+
authorization: `token ${token}`
77+
},
78+
request: {
79+
agent: getAgent()
80+
}
7881
});
82+
} catch (err) {
83+
_octokitGraphql = undefined;
84+
throw err;
85+
}
7986
}
8087

8188
return _octokitGraphql;

extensions/github/src/branchProtection.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { EventEmitter, LogOutputChannel, Memento, Uri, workspace } from 'vscode';
6+
import { authentication, EventEmitter, LogOutputChannel, Memento, Uri, workspace } from 'vscode';
77
import { Repository as GitHubRepository, RepositoryRuleset } from '@octokit/graphql-schema';
8-
import { getOctokitGraphql } from './auth';
8+
import { AuthenticationError, getOctokitGraphql } from './auth';
99
import { API, BranchProtection, BranchProtectionProvider, BranchProtectionRule, Repository } from './typings/git';
1010
import { DisposableStore, getRepositoryFromUrl } from './util';
1111

@@ -163,10 +163,12 @@ export class GithubBranchProtectionProvider implements BranchProtectionProvider
163163
}
164164

165165
// Repository details
166+
this.logger.trace(`Fetching repository details for "${repository.owner}/${repository.repo}".`);
166167
const repositoryDetails = await this.getRepositoryDetails(repository.owner, repository.repo);
167168

168169
// Check repository write permission
169170
if (repositoryDetails.viewerPermission !== 'ADMIN' && repositoryDetails.viewerPermission !== 'MAINTAIN' && repositoryDetails.viewerPermission !== 'WRITE') {
171+
this.logger.trace(`Skipping branch protection for "${repository.owner}/${repository.repo}" due to missing repository write permission.`);
170172
continue;
171173
}
172174

@@ -189,8 +191,20 @@ export class GithubBranchProtectionProvider implements BranchProtectionProvider
189191

190192
// Save branch protection to global state
191193
await this.globalState.update(this.globalStateKey, branchProtection);
194+
this.logger.trace(`Branch protection for "${this.repository.rootUri.toString()}": ${JSON.stringify(branchProtection)}.`);
192195
} catch (err) {
193-
// noop
196+
if (err instanceof AuthenticationError) {
197+
// Since there is no GitHub authentication session available we need to wait
198+
// until the user signs in with their GitHub account so that we can query the
199+
// repository rulesets
200+
const disposable = authentication.onDidChangeSessions(e => {
201+
if (e.provider.id === 'github') {
202+
disposable.dispose();
203+
this.updateRepositoryBranchProtection();
204+
}
205+
});
206+
}
207+
194208
this.logger.warn(`Failed to update repository branch protection: ${err.message}`);
195209
}
196210
}

0 commit comments

Comments
 (0)