From 03d86344ddb7641b7a99f2c37b3774299044c3a3 Mon Sep 17 00:00:00 2001 From: Sergei Shmakov Date: Fri, 24 Jan 2025 15:41:02 +0100 Subject: [PATCH] Conects and syncs to AzureDevOps (#3976) --- src/constants.integrations.ts | 7 ++ .../authentication/azureDevOps.ts | 117 +----------------- 2 files changed, 11 insertions(+), 113 deletions(-) diff --git a/src/constants.integrations.ts b/src/constants.integrations.ts index 89770d71ba757..afc5b4fc98352 100644 --- a/src/constants.integrations.ts +++ b/src/constants.integrations.ts @@ -29,6 +29,7 @@ export const supportedOrderedCloudIntegrationIds = [ SelfHostedIntegrationId.CloudGitHubEnterprise, HostingIntegrationId.GitLab, SelfHostedIntegrationId.CloudGitLabSelfHosted, + HostingIntegrationId.AzureDevOps, IssueIntegrationId.Jira, ]; @@ -71,6 +72,12 @@ export const supportedCloudIntegrationDescriptors: IntegrationDescriptor[] = [ icon: 'gl-provider-gitlab', supports: ['prs', 'issues'], }, + { + id: HostingIntegrationId.AzureDevOps, + name: 'Azure DevOps', + icon: 'gl-provider-azdo', + supports: ['prs', 'issues'], + }, { id: IssueIntegrationId.Jira, name: 'Jira', diff --git a/src/plus/integrations/authentication/azureDevOps.ts b/src/plus/integrations/authentication/azureDevOps.ts index d4db11b71d4b4..bc75c3a16298e 100644 --- a/src/plus/integrations/authentication/azureDevOps.ts +++ b/src/plus/integrations/authentication/azureDevOps.ts @@ -1,121 +1,12 @@ -import type { Disposable, QuickInputButton } from 'vscode'; -import { env, ThemeIcon, Uri, window } from 'vscode'; import { HostingIntegrationId } from '../../../constants.integrations'; -import { base64 } from '../../../system/string'; -import type { IntegrationAuthenticationSessionDescriptor } from './integrationAuthenticationProvider'; -import { LocalIntegrationAuthenticationProvider } from './integrationAuthenticationProvider'; -import type { ProviderAuthenticationSession } from './models'; +import { CloudIntegrationAuthenticationProvider } from './integrationAuthenticationProvider'; -export class AzureDevOpsAuthenticationProvider extends LocalIntegrationAuthenticationProvider { +export class AzureDevOpsAuthenticationProvider extends CloudIntegrationAuthenticationProvider { protected override get authProviderId(): HostingIntegrationId.AzureDevOps { return HostingIntegrationId.AzureDevOps; } - override async createSession( - descriptor?: IntegrationAuthenticationSessionDescriptor, - ): Promise { - let azureOrganization: string | undefined = descriptor?.organization as string | undefined; - if (!azureOrganization) { - const orgInput = window.createInputBox(); - orgInput.ignoreFocusOut = true; - const orgInputDisposables: Disposable[] = []; - try { - azureOrganization = await new Promise(resolve => { - orgInputDisposables.push( - orgInput.onDidHide(() => resolve(undefined)), - orgInput.onDidChangeValue(() => (orgInput.validationMessage = undefined)), - orgInput.onDidAccept(() => { - const value = orgInput.value.trim(); - if (!value) { - orgInput.validationMessage = 'An organization is required'; - return; - } - - resolve(value); - }), - ); - - orgInput.title = `Azure DevOps Authentication${ - descriptor?.domain ? ` \u2022 ${descriptor.domain}` : '' - }`; - orgInput.placeholder = 'Organization'; - orgInput.prompt = 'Enter your Azure DevOps organization'; - orgInput.show(); - }); - } finally { - orgInput.dispose(); - orgInputDisposables.forEach(d => void d.dispose()); - } - } - - if (!azureOrganization) return undefined; - - const tokenInput = window.createInputBox(); - tokenInput.ignoreFocusOut = true; - - const disposables: Disposable[] = []; - - let token; - try { - const infoButton: QuickInputButton = { - iconPath: new ThemeIcon(`link-external`), - tooltip: 'Open the Azure DevOps Access Tokens Page', - }; - - token = await new Promise(resolve => { - disposables.push( - tokenInput.onDidHide(() => resolve(undefined)), - tokenInput.onDidChangeValue(() => (tokenInput.validationMessage = undefined)), - tokenInput.onDidAccept(() => { - const value = tokenInput.value.trim(); - if (!value) { - tokenInput.validationMessage = 'A personal access token is required'; - return; - } - - resolve(value); - }), - tokenInput.onDidTriggerButton(e => { - if (e === infoButton) { - void env.openExternal( - Uri.parse( - `https://${ - descriptor?.domain ?? 'dev.azure.com' - }/${azureOrganization}/_usersSettings/tokens`, - ), - ); - } - }), - ); - - tokenInput.password = true; - tokenInput.title = `Azure DevOps Authentication${ - descriptor?.domain ? ` \u2022 ${descriptor.domain}` : '' - }`; - tokenInput.placeholder = `Requires ${descriptor?.scopes.join(', ') ?? 'all'} scopes`; - tokenInput.prompt = `Paste your [Azure DevOps Personal Access Token](https://${ - descriptor?.domain ?? 'dev.azure.com' - }/${azureOrganization}/_usersSettings/tokens "Get your Azure DevOps Access Token")`; - tokenInput.buttons = [infoButton]; - - tokenInput.show(); - }); - } finally { - tokenInput.dispose(); - disposables.forEach(d => void d.dispose()); - } - - if (!token) return undefined; - - return { - id: this.getSessionId(descriptor), - accessToken: base64(`:${token}`), - scopes: descriptor?.scopes ?? [], - account: { - id: '', - label: '', - }, - cloud: false, - }; + protected override getCompletionInputTitle(): string { + return 'Connect to Azure Dev Ops'; } }