Move getting auth token into GithubCodeSearchService (#673)

This hides the implementation a bit better and should let us find the correct token for different repos
This commit is contained in:
Matt Bierner
2025-08-19 13:40:15 -07:00
committed by GitHub
parent 1bd6430980
commit 88cbaa304d
6 changed files with 82 additions and 68 deletions
@@ -14,6 +14,7 @@ import { env } from '../../../util/vs/base/common/process';
import { URI } from '../../../util/vs/base/common/uri';
import { Range } from '../../../util/vs/editor/common/core/range';
import { createDecorator } from '../../../util/vs/platform/instantiation/common/instantiation';
import { IAuthenticationService } from '../../authentication/common/authentication';
import { FileChunkAndScore } from '../../chunking/common/chunk';
import { getGithubMetadataHeaders } from '../../chunking/common/chunkingEndpointClientImpl';
import { stripChunkTextMetadata, truncateToMaxUtf8Length } from '../../chunking/common/chunkingStringUtils';
@@ -27,7 +28,7 @@ import { ILogService } from '../../log/common/logService';
import { IFetcherService, Response } from '../../networking/common/fetcherService';
import { postRequest } from '../../networking/common/networking';
import { ITelemetryService } from '../../telemetry/common/telemetry';
import { CodeSearchOptions, CodeSearchResult, RemoteCodeSearchIndexState, RemoteCodeSearchIndexStatus } from './remoteCodeSearch';
import { CodeSearchOptions, CodeSearchResult, RemoteCodeSearchError, RemoteCodeSearchIndexState, RemoteCodeSearchIndexStatus } from './remoteCodeSearch';
interface ResponseShape {
@@ -70,16 +71,16 @@ export interface IGithubCodeSearchService {
* Gets the state of the remote index for a given repo.
*/
getRemoteIndexState(
authToken: string,
authOptions: { readonly silent: boolean },
githubRepoId: GithubRepoId,
token: CancellationToken,
): Promise<Result<RemoteCodeSearchIndexState, Error>>;
): Promise<Result<RemoteCodeSearchIndexState, RemoteCodeSearchError>>;
/**
* Requests that a given repo be indexed.
*/
triggerIndexing(
authToken: string,
authOptions: { readonly silent: boolean },
triggerReason: 'auto' | 'manual' | 'tool',
githubRepoId: GithubRepoId,
telemetryInfo: TelemetryCorrelationId,
@@ -91,7 +92,7 @@ export interface IGithubCodeSearchService {
* The repo must have been indexed first. Make sure to check {@link getRemoteIndexState} or call {@link triggerIndexing}.
*/
searchRepo(
authToken: string,
authOptions: { readonly silent: boolean },
embeddingType: EmbeddingType,
repo: GithubCodeSearchRepoInfo,
query: string,
@@ -107,6 +108,7 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
declare readonly _serviceBrand: undefined;
constructor(
@IAuthenticationService private readonly _authenticationService: IAuthenticationService,
@IDomainService private readonly _domainService: IDomainService,
@ICAPIClientService private readonly _capiClientService: ICAPIClientService,
@IEnvService private readonly _envService: IEnvService,
@@ -116,13 +118,19 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
@ITelemetryService private readonly _telemetryService: ITelemetryService,
) { }
async getRemoteIndexState(authToken: string, githubRepoId: GithubRepoId, token: CancellationToken): Promise<Result<RemoteCodeSearchIndexState, Error>> {
async getRemoteIndexState(auth: { readonly silent: boolean }, githubRepoId: GithubRepoId, token: CancellationToken): Promise<Result<RemoteCodeSearchIndexState, RemoteCodeSearchError>> {
const repoNwo = toGithubNwo(githubRepoId);
if (repoNwo.startsWith('microsoft/simuluation-test-')) {
return Result.ok({ status: RemoteCodeSearchIndexStatus.NotYetIndexed });
}
const authToken = await this.getGithubAccessToken(auth.silent);
if (!authToken) {
this._logService.error(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). Failed to fetch indexing status. No valid github auth token.`);
return Result.error<RemoteCodeSearchError>({ type: 'not-authorized' });
}
try {
const statusRequest = await raceCancellationError(this._capiClientService.makeRequest<Response>({
method: 'GET',
@@ -142,14 +150,14 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
statusCode: statusRequest.status,
});
this._logService.error(`GithubCodeSearchService.getRemoteIndexState(${repoNwo}). Failed to fetch indexing status. Response: ${statusRequest.status}. ${await statusRequest.text()}`);
return Result.error(new Error(`Failed to fetch indexing status. Response: ${statusRequest.status}.`));
this._logService.error(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). Failed to fetch indexing status. Response: ${statusRequest.status}. ${await statusRequest.text()}`);
return Result.error<RemoteCodeSearchError>({ type: 'generic-error', error: new Error(`Failed to fetch indexing status. Response: ${statusRequest.status}.`) });
}
const preCheckResult = await raceCancellationError(statusRequest.json(), token);
if (preCheckResult.semantic_code_search_ok && preCheckResult.semantic_commit_sha) {
const indexedCommit = preCheckResult.semantic_commit_sha;
this._logService.trace(`GithubCodeSearchService.getRemoteIndexState(${repoNwo}). Found indexed commit: ${indexedCommit}.`);
this._logService.trace(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). Found indexed commit: ${indexedCommit}.`);
return Result.ok({
status: RemoteCodeSearchIndexStatus.Ready,
indexedCommit,
@@ -158,36 +166,41 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
if (preCheckResult.semantic_indexing_enabled) {
if (await raceCancellationError(this.isEmptyRepo(authToken, githubRepoId, token), token)) {
this._logService.trace(`GithubCodeSearchService.getRemoteIndexState(${repoNwo}). Semantic indexing enabled but repo is empty.`);
this._logService.trace(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). Semantic indexing enabled but repo is empty.`);
return Result.ok({
status: RemoteCodeSearchIndexStatus.Ready,
indexedCommit: undefined
});
}
this._logService.trace(`GithubCodeSearchService.getRemoteIndexState(${repoNwo}). Semantic indexing enabled but not yet indexed.`);
this._logService.trace(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). Semantic indexing enabled but not yet indexed.`);
return Result.ok({ status: RemoteCodeSearchIndexStatus.BuildingIndex });
} else {
this._logService.trace(`GithubCodeSearchService.getRemoteIndexState(${repoNwo}). semantic_indexing_enabled was false. Repo not yet indexed but possibly can be.`);
this._logService.trace(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). semantic_indexing_enabled was false. Repo not yet indexed but possibly can be.`);
return Result.ok({ status: RemoteCodeSearchIndexStatus.NotYetIndexed });
}
} catch (e) {
} catch (e: unknown) {
if (isCancellationError(e)) {
throw e;
}
this._logService.error(`GithubCodeSearchService.getRemoteIndexState(${repoNwo}). Error: ${e}`);
return Result.error(e);
this._logService.error(`GithubCodeSearchService::getRemoteIndexState(${repoNwo}). Error: ${e}`);
return Result.error<RemoteCodeSearchError>({ type: 'generic-error', error: e instanceof Error ? e : new Error(String(e)) });
}
}
public async triggerIndexing(
authToken: string,
auth: { readonly silent: boolean },
triggerReason: 'auto' | 'manual' | 'tool',
githubRepoId: GithubRepoId,
telemetryInfo: TelemetryCorrelationId,
): Promise<boolean> {
const authToken = await this.getGithubAccessToken(auth.silent);
if (!authToken) {
return false;
}
const response = await this._capiClientService.makeRequest<Response>({
method: 'POST',
headers: {
@@ -241,7 +254,7 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
}
async searchRepo(
authToken: string,
auth: { readonly silent: boolean },
embeddingType: EmbeddingType,
repo: GithubCodeSearchRepoInfo,
searchQuery: string,
@@ -250,6 +263,11 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
telemetryInfo: TelemetryCorrelationId,
token: CancellationToken
): Promise<CodeSearchResult> {
const authToken = await this.getGithubAccessToken(auth.silent);
if (!authToken) {
throw new Error('No valid auth token');
}
const response = await raceCancellationError(
postRequest(
this._fetcherService,
@@ -330,6 +348,12 @@ export class GithubCodeSearchService implements IGithubCodeSearchService {
return result;
}
private async getGithubAccessToken(silent: boolean) {
return (await this._authenticationService.getPermissiveGitHubSession({ silent }))?.accessToken
?? (await this._authenticationService.getAnyGitHubSession({ silent }))?.accessToken;
}
private async isEmptyRepo(authToken: string, githubRepoId: GithubRepoId, token: CancellationToken): Promise<boolean> {
const response = await raceCancellationError(fetch(this._capiClientService.dotcomAPIURL + `/repos/${toGithubNwo(githubRepoId)}`, {
headers: {