From e5cd6aecbd59eeee9792e3b2675536dbe06e7b1c Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Mon, 13 Jul 2026 11:22:01 -0400 Subject: [PATCH 1/3] Revert "fix(vscode): Disable MSI option in connector setup (#9364)" This reverts commit 78d8ddbd1f84251dc9facf779c43aa6c8c0f8325. --- .../__test__/authenticationMethodStep.test.ts | 13 ++----------- .../commands/workflows/authenticationMethodStep.ts | 7 +------ 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts b/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts index 13b3420f3ca..ab9c5950efd 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts @@ -52,19 +52,10 @@ describe('AuthenticationMethodSelectionStep', () => { expect(context.authenticationMethod).toBe('rawKeys'); }); - it('defaults to rawKeys without prompting when MSI is disabled', () => { - context.enabled = true; + it('does not prompt when Azure connectors are disabled', () => { + context.enabled = false; expect(new AuthenticationMethodSelectionStep().shouldPrompt(context)).toBe(false); - expect(context.authenticationMethod).toBe('rawKeys'); - }); - - it('does not override an already-set authentication method', () => { - context.enabled = true; - context.authenticationMethod = 'managedServiceIdentity'; - - expect(new AuthenticationMethodSelectionStep().shouldPrompt(context)).toBe(false); - expect(context.authenticationMethod).toBe('managedServiceIdentity'); }); it('rethrows non-cancellation errors', async () => { diff --git a/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts b/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts index b34a76742f7..b594a87b23f 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts @@ -70,13 +70,8 @@ export class AuthenticationMethodSelectionStep< /** * Determines if this step should prompt again (only if no method is selected yet). - * - * TODO: MSI option is temporarily disabled until functions extension fix deployed — always default to rawKeys. */ public shouldPrompt(context: T): boolean { - if (context.enabled === true && context.authenticationMethod === undefined) { - context.authenticationMethod = 'rawKeys'; - } - return false; + return context.enabled === true && context.authenticationMethod === undefined; } } From dce9feaab304455caa33ce3e0fd48057c2a5f642 Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Fri, 17 Jul 2026 17:41:28 -0400 Subject: [PATCH 2/3] update local.settings.json to include WORKFLOWS_AUTHENTICATION_METHOD = 'managedServiceIdentity' by default --- .../__test__/CreateLogicAppWorkspace.test.ts | 18 +++-- .../__test__/authenticationMethodStep.test.ts | 66 ---------------- .../__test__/azureConnectorWizard.test.ts | 10 +-- .../__test__/enableAzureConnectors.test.ts | 5 +- .../workflows/authenticationMethodStep.ts | 77 ------------------- .../workflows/azureConnectorWizard.ts | 15 +--- .../workflows/enableAzureConnectors.ts | 7 +- .../__test__/localSettings.test.ts | 9 ++- .../app/utils/appSettings/localSettings.ts | 2 + .../utils/codeless/__test__/common.test.ts | 12 +-- .../__test__/validateProjectArtifacts.test.ts | 7 ++ .../src/app/utils/codeless/common.ts | 8 +- apps/vs-code-designer/src/test/ui/SKILL.md | 7 +- .../test/ui/connectionPromptFallback.test.ts | 6 +- 14 files changed, 51 insertions(+), 198 deletions(-) delete mode 100644 apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts delete mode 100644 apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts diff --git a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts index 51888da9983..e364e0da816 100644 --- a/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts +++ b/apps/vs-code-designer/src/app/commands/createNewCodeProject/CodeProjectBase/__test__/CreateLogicAppWorkspace.test.ts @@ -1416,10 +1416,11 @@ describe('createLocalConfigurationFiles', () => { FUNCTIONS_WORKER_RUNTIME: 'dotnet', APP_KIND: 'workflowapp', ProjectDirectoryPath: path.join('test', 'workspace', 'TestLogicApp'), + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', }); // Verify no other properties exist - expect(Object.keys(localSettingsData.Values)).toHaveLength(5); + expect(Object.keys(localSettingsData.Values)).toHaveLength(6); }); it('should include global.json in .funcignore for custom code projects', async () => { @@ -1461,11 +1462,12 @@ describe('createLocalConfigurationFiles', () => { FUNCTIONS_WORKER_RUNTIME: 'dotnet', APP_KIND: 'workflowapp', ProjectDirectoryPath: path.join('test', 'workspace', 'TestLogicApp'), + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', AzureWebJobsFeatureFlags: 'EnableMultiLanguageWorker', }); - // Verify exactly 6 properties exist (5 standard + 1 feature flag) - expect(Object.keys(localSettingsData.Values)).toHaveLength(6); + // Verify exactly 7 properties exist (5 standard + auth method + 1 feature flag) + expect(Object.keys(localSettingsData.Values)).toHaveLength(7); }); it('should include global.json in .funcignore for rules engine projects', async () => { @@ -1507,11 +1509,12 @@ describe('createLocalConfigurationFiles', () => { FUNCTIONS_WORKER_RUNTIME: 'dotnet', APP_KIND: 'workflowapp', ProjectDirectoryPath: path.join('test', 'workspace', 'TestLogicApp'), + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', AzureWebJobsFeatureFlags: 'EnableMultiLanguageWorker', }); - // Verify exactly 6 properties exist (5 standard + 1 feature flag) - expect(Object.keys(localSettingsData.Values)).toHaveLength(6); + // Verify exactly 7 properties exist (5 standard + auth method + 1 feature flag) + expect(Object.keys(localSettingsData.Values)).toHaveLength(7); }); it('should create local.settings.json with exact required values for codeful projects', async () => { @@ -1531,12 +1534,13 @@ describe('createLocalConfigurationFiles', () => { FUNCTIONS_WORKER_RUNTIME: 'dotnet', APP_KIND: 'workflowapp', ProjectDirectoryPath: path.join('test', 'workspace', 'TestLogicApp'), + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', AzureWebJobsFeatureFlags: 'EnableMultiLanguageWorker', WORKFLOW_CODEFUL_ENABLED: 'true', }); - // Verify exactly 7 properties exist (5 standard + feature flag + codeful-enabled). - expect(Object.keys(localSettingsData.Values)).toHaveLength(7); + // Verify exactly 8 properties exist (5 standard + auth method + feature flag + codeful-enabled). + expect(Object.keys(localSettingsData.Values)).toHaveLength(8); }); it('should include extension bundle configuration in host.json', async () => { diff --git a/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts b/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts deleted file mode 100644 index ab9c5950efd..00000000000 --- a/apps/vs-code-designer/src/app/commands/workflows/__test__/authenticationMethodStep.test.ts +++ /dev/null @@ -1,66 +0,0 @@ -import { beforeEach, describe, expect, it, vi } from 'vitest'; - -vi.mock('../../../../localize', () => ({ - localize: (_key: string, defaultMessage: string) => defaultMessage, -})); - -vi.mock('@microsoft/vscode-azext-utils', () => ({ - AzureWizardPromptStep: class AzureWizardPromptStep {}, - parseError: (error: any) => ({ - isUserCancelledError: error?.isUserCancelledError === true, - message: error?.message ?? String(error), - }), -})); - -import { AuthenticationMethodSelectionStep } from '../authenticationMethodStep'; - -describe('AuthenticationMethodSelectionStep', () => { - let context: any; - - beforeEach(() => { - context = { - enabled: true, - telemetry: { properties: {}, measurements: {} }, - ui: { - showQuickPick: vi.fn(), - }, - }; - }); - - it('defaults to connection keys when the authentication prompt is cancelled', async () => { - context.ui.showQuickPick.mockRejectedValue({ isUserCancelledError: true }); - - await new AuthenticationMethodSelectionStep().prompt(context); - - expect(context.authenticationMethod).toBe('rawKeys'); - expect(context.telemetry.properties.authenticationMethodDefaulted).toBe('rawKeys'); - }); - - it('keeps explicit Managed Service Identity selections', async () => { - context.ui.showQuickPick.mockResolvedValue({ data: 'managedServiceIdentity' }); - - await new AuthenticationMethodSelectionStep().prompt(context); - - expect(context.authenticationMethod).toBe('managedServiceIdentity'); - }); - - it('keeps explicit connection-key selections', async () => { - context.ui.showQuickPick.mockResolvedValue({ data: 'rawKeys' }); - - await new AuthenticationMethodSelectionStep().prompt(context); - - expect(context.authenticationMethod).toBe('rawKeys'); - }); - - it('does not prompt when Azure connectors are disabled', () => { - context.enabled = false; - - expect(new AuthenticationMethodSelectionStep().shouldPrompt(context)).toBe(false); - }); - - it('rethrows non-cancellation errors', async () => { - context.ui.showQuickPick.mockRejectedValue(new Error('quick pick failed')); - - await expect(new AuthenticationMethodSelectionStep().prompt(context)).rejects.toThrow('quick pick failed'); - }); -}); diff --git a/apps/vs-code-designer/src/app/commands/workflows/__test__/azureConnectorWizard.test.ts b/apps/vs-code-designer/src/app/commands/workflows/__test__/azureConnectorWizard.test.ts index 13caa97434c..1418f615373 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/__test__/azureConnectorWizard.test.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/__test__/azureConnectorWizard.test.ts @@ -1,7 +1,6 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; import { defaultMsiAudience, - workflowAuthenticationMethodKey, workflowLocationKey, workflowManagementBaseURIKey, workflowResourceGroupNameKey, @@ -65,14 +64,13 @@ describe('createAzureWizard', () => { } as any; }); - it('defaults cancelled connector selection to disabled raw keys', async () => { + it('defaults cancelled connector selection to disabled', async () => { vi.mocked(context.ui.showQuickPick).mockRejectedValue({ isUserCancelledError: true }); const wizard = createAzureWizard(context, projectPath) as any; await wizard.options.promptSteps[0].prompt(context); expect(context.enabled).toBe(false); - expect(context.authenticationMethod).toBe('rawKeys'); expect(context.telemetry.properties.azureConnectorsDefaulted).toBe('rawKeys'); }); @@ -105,23 +103,20 @@ describe('createAzureWizard', () => { expect(azureConnectorStep.shouldPrompt({ ...context, enabled: false })).toBe(false); }); - it('persists disabled raw-key settings when Azure connectors are skipped', async () => { + it('persists empty subscription when Azure connectors are skipped', async () => { context.enabled = false; - context.authenticationMethod = 'rawKeys'; const wizard = createAzureWizard(context, projectPath) as any; await wizard.options.executeSteps[0].execute(context); expect(addOrUpdateLocalAppSettings).toHaveBeenCalledWith(context, projectPath, { [workflowSubscriptionIdKey]: '', - [workflowAuthenticationMethodKey]: 'rawKeys', }); }); it('persists Azure connector settings and notifies the language client when enabled', async () => { Object.assign(context, { enabled: true, - authenticationMethod: 'managedServiceIdentity', tenantId: 'tenant-id', subscriptionId: 'subscription-id', resourceGroup: { name: 'rg', location: 'westus' }, @@ -137,7 +132,6 @@ describe('createAzureWizard', () => { [workflowResourceGroupNameKey]: 'rg', [workflowLocationKey]: 'westus', [workflowManagementBaseURIKey]: 'https://management.azure.com/', - [workflowAuthenticationMethodKey]: 'managedServiceIdentity', [workflowsDynamicConnectionDefaultAuthAudienceKey]: defaultMsiAudience, }); expect(ext.languageClient.sendNotification).toHaveBeenCalledWith('custom/updateApiConfig', { diff --git a/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts b/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts index e2fa9ac9d32..eb749ce2896 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/__test__/enableAzureConnectors.test.ts @@ -1,6 +1,6 @@ import * as vscode from 'vscode'; import { beforeEach, describe, expect, it, type Mock, vi } from 'vitest'; -import { localSettingsFileName, workflowAuthenticationMethodKey, workflowSubscriptionIdKey } from '../../../../constants'; +import { localSettingsFileName, workflowSubscriptionIdKey } from '../../../../constants'; import { getLocalSettingsJson } from '../../../utils/appSettings/localSettings'; import { getAzureConnectorDetailsForLocalProject, invalidateAzureDetailsCache } from '../../../utils/codeless/common'; import { getLogicAppProjectRoot } from '../../../utils/codeless/connection'; @@ -68,11 +68,10 @@ describe('enableAzureConnectors', () => { expect(ext.outputChannel.appendLog).toHaveBeenCalledWith('Azure connectors are enabled for the workflow.'); }); - it('shows already-enabled information when subscription and auth settings exist', async () => { + it('shows already-enabled information when subscription setting exists', async () => { (getLocalSettingsJson as Mock).mockResolvedValue({ Values: { [workflowSubscriptionIdKey]: 'subscription-id', - [workflowAuthenticationMethodKey]: 'ActiveDirectoryOAuth', }, }); diff --git a/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts b/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts deleted file mode 100644 index b594a87b23f..00000000000 --- a/apps/vs-code-designer/src/app/commands/workflows/authenticationMethodStep.ts +++ /dev/null @@ -1,77 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import { AzureWizardPromptStep, parseError } from '@microsoft/vscode-azext-utils'; -import type { IActionContext, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; -import { localize } from '../../../localize'; - -/** - * String literal union for supported authentication methods. - * This replaces the enum for simpler runtime footprint. - */ -export type AuthenticationMethodType = 'managedServiceIdentity' | 'rawKeys'; - -/** - * Authentication method selection step - * This step prompts the user to select between MSI and raw keys - * and sets the `authenticationMethod` in the context. - */ -export class AuthenticationMethodSelectionStep< - T extends IActionContext & { authenticationMethod?: AuthenticationMethodType; enabled?: boolean }, -> extends AzureWizardPromptStep { - /** - * Prompts the user to select an authentication method. - * The result is stored in `context.authenticationMethod`. - */ - public async prompt(context: T): Promise { - const placeHolder: string = localize('selectAuthMethod', 'Select authentication method for Azure connectors'); - - const picks: IAzureQuickPickItem[] = [ - { - label: localize('authMethodMSI', '$(shield) Managed Service Identity'), - description: localize('authMethodMSIDesc', 'Use Azure Managed Identity'), - detail: localize( - 'authMethodMSIDetail', - 'Authenticate using Azure Managed Service Identity. More secure, no keys stored locally. Requires proper Azure RBAC configuration.' - ), - data: 'managedServiceIdentity', - }, - { - label: localize('authMethodRawKeys', '$(key) Connection Keys'), - description: localize('authMethodRawKeysDesc', 'Use connection strings and access keys (traditional method)'), - detail: localize( - 'authMethodRawKeysDetail', - 'Authenticate using connection strings, access keys, or API keys configured in your app settings.' - ), - data: 'rawKeys', - }, - ]; - - const selectedMethod = await context.ui - .showQuickPick(picks, { - placeHolder, - suppressPersistence: true, - ignoreFocusOut: true, - }) - .catch((error) => { - if (parseError(error).isUserCancelledError) { - context.telemetry.properties.authenticationMethodDefaulted = 'rawKeys'; - return { data: 'rawKeys' as AuthenticationMethodType }; - } - - throw error; - }); - - // Save the selected authentication method - context.authenticationMethod = selectedMethod.data; - } - - /** - * Determines if this step should prompt again (only if no method is selected yet). - */ - public shouldPrompt(context: T): boolean { - return context.enabled === true && context.authenticationMethod === undefined; - } -} diff --git a/apps/vs-code-designer/src/app/commands/workflows/azureConnectorWizard.ts b/apps/vs-code-designer/src/app/commands/workflows/azureConnectorWizard.ts index 95fccbf40dc..db704a59109 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/azureConnectorWizard.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/azureConnectorWizard.ts @@ -9,7 +9,6 @@ import type { IProjectWizardContext } from '@microsoft/vscode-extension-logic-ap import * as path from 'path'; import { defaultMsiAudience, - workflowAuthenticationMethodKey, workflowLocationKey, workflowManagementBaseURIKey, workflowResourceGroupNameKey, @@ -20,7 +19,6 @@ import { import { ext } from '../../../extensionVariables'; import { localize } from '../../../localize'; import { addOrUpdateLocalAppSettings } from '../../utils/appSettings/localSettings'; -import { AuthenticationMethodSelectionStep, type AuthenticationMethodType } from './authenticationMethodStep'; export interface IAzureConnectorsContext extends IActionContext, IProjectWizardContext { credentials: any; @@ -29,14 +27,13 @@ export interface IAzureConnectorsContext extends IActionContext, IProjectWizardC enabled: boolean; tenantId: any; environment: any; - authenticationMethod?: AuthenticationMethodType; MSIenabled?: boolean; } //TODO: Update to be in webview after ignite redesign is done export function createAzureWizard(wizardContext: IAzureConnectorsContext, projectPath: string): AzureWizard { return new AzureWizard(wizardContext, { - promptSteps: [new GetSubscriptionDetailsStep(projectPath), new AuthenticationMethodSelectionStep()], + promptSteps: [new GetSubscriptionDetailsStep(projectPath)], executeSteps: [new SaveAzureContext(projectPath)], }); } @@ -67,9 +64,6 @@ class GetSubscriptionDetailsStep extends AzureWizardPromptStep { const valuesToUpdateInSettings: Record = {}; if (context.enabled === false) { valuesToUpdateInSettings[workflowSubscriptionIdKey] = ''; - valuesToUpdateInSettings[workflowAuthenticationMethodKey] = 'rawKeys'; } else { const { resourceGroup, subscriptionId, tenantId, environment } = context; valuesToUpdateInSettings[workflowTenantIdKey] = tenantId; @@ -114,11 +107,7 @@ class SaveAzureContext extends AzureWizardExecuteStep { valuesToUpdateInSettings[workflowResourceGroupNameKey] = resourceGroup?.name || ''; valuesToUpdateInSettings[workflowLocationKey] = resourceGroup?.location || ''; valuesToUpdateInSettings[workflowManagementBaseURIKey] = environment.resourceManagerEndpointUrl; - // Save the authentication method to local settings - if (context.authenticationMethod) { - valuesToUpdateInSettings[workflowAuthenticationMethodKey] = context.authenticationMethod; - valuesToUpdateInSettings[workflowsDynamicConnectionDefaultAuthAudienceKey] = defaultMsiAudience; - } + valuesToUpdateInSettings[workflowsDynamicConnectionDefaultAuthAudienceKey] = defaultMsiAudience; // Then send notifications for runtime updates ext?.languageClient?.sendNotification('custom/updateApiConfig', { diff --git a/apps/vs-code-designer/src/app/commands/workflows/enableAzureConnectors.ts b/apps/vs-code-designer/src/app/commands/workflows/enableAzureConnectors.ts index 7f790344eee..c9f08503b8d 100644 --- a/apps/vs-code-designer/src/app/commands/workflows/enableAzureConnectors.ts +++ b/apps/vs-code-designer/src/app/commands/workflows/enableAzureConnectors.ts @@ -2,7 +2,7 @@ * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { localSettingsFileName, workflowAuthenticationMethodKey, workflowSubscriptionIdKey } from '../../../../src/constants'; +import { localSettingsFileName, workflowSubscriptionIdKey } from '../../../../src/constants'; import { localize } from '../../../localize'; import type { IAzureConnectorsContext } from '../../commands/workflows/azureConnectorWizard'; import { createAzureWizard } from '../../commands/workflows/azureConnectorWizard'; @@ -29,8 +29,7 @@ export async function enableAzureConnectors(context: IActionContext, node: vscod const localSettings: ILocalSettingsJson = await getLocalSettingsJson(context, localSettingsFilePath); const subscriptionId: string | undefined = localSettings.Values?.[workflowSubscriptionIdKey]; - const authenticationMethod: string | undefined = localSettings.Values?.[workflowAuthenticationMethodKey]; - if (!!subscriptionId && !!authenticationMethod) { + if (subscriptionId) { ext.outputChannel.appendLog(localize('logicapp.azureConnectorsEnabledForWorkflow', 'Azure connectors are enabled for the workflow.')); return; } @@ -43,7 +42,7 @@ export async function enableAzureConnectors(context: IActionContext, node: vscod if (connectorsContext.enabled) { invalidateAzureDetailsCache(projectPath); getAzureConnectorDetailsForLocalProject(context, projectPath).catch(() => {}); - + ext.outputChannel.appendLog(localize('logicapp.azureConnectorsEnabledForWorkflow', 'Azure connectors are enabled for the workflow.')); } } diff --git a/apps/vs-code-designer/src/app/utils/appSettings/__test__/localSettings.test.ts b/apps/vs-code-designer/src/app/utils/appSettings/__test__/localSettings.test.ts index ca596d21b0f..1909231896e 100644 --- a/apps/vs-code-designer/src/app/utils/appSettings/__test__/localSettings.test.ts +++ b/apps/vs-code-designer/src/app/utils/appSettings/__test__/localSettings.test.ts @@ -13,6 +13,7 @@ import { localEmulatorConnectionString, logicAppKind, multiLanguageWorkerSetting, + workflowAuthenticationMethodKey, workerRuntimeKey, workflowCodefulEnabledKey, } from '../../../../constants'; @@ -68,6 +69,7 @@ describe('utils/appSettings', () => { [workerRuntimeKey]: WorkerRuntime.Dotnet, [appKindSetting]: logicAppKind, [ProjectDirectoryPathKey]: projectPath, + [workflowAuthenticationMethodKey]: 'managedServiceIdentity', }; it('logicApp: 5 base keys, no feature or codeful flags', () => { @@ -114,10 +116,11 @@ describe('utils/appSettings', () => { expect(getLocalSettingsSchema(false)).toEqual({ IsEncrypted: false, Values: { - [appKindSetting]: logicAppKind, - [workerRuntimeKey]: WorkerRuntime.Dotnet, [azureWebJobsStorageKey]: localEmulatorConnectionString, [functionsInprocNet8Enabled]: functionsInprocNet8EnabledTrue, + [workerRuntimeKey]: WorkerRuntime.Dotnet, + [appKindSetting]: logicAppKind, + [workflowAuthenticationMethodKey]: 'managedServiceIdentity', }, }); }); @@ -163,6 +166,7 @@ describe('utils/appSettings', () => { workerRuntimeKey, appKindSetting, ProjectDirectoryPathKey, + workflowAuthenticationMethodKey, ]); }); @@ -174,6 +178,7 @@ describe('utils/appSettings', () => { workerRuntimeKey, appKindSetting, ProjectDirectoryPathKey, + workflowAuthenticationMethodKey, azureWebJobsFeatureFlagsKey, workflowCodefulEnabledKey, ]); diff --git a/apps/vs-code-designer/src/app/utils/appSettings/localSettings.ts b/apps/vs-code-designer/src/app/utils/appSettings/localSettings.ts index 38ff08fc2ce..9f2a19f3a68 100644 --- a/apps/vs-code-designer/src/app/utils/appSettings/localSettings.ts +++ b/apps/vs-code-designer/src/app/utils/appSettings/localSettings.ts @@ -16,6 +16,7 @@ import { azureStorageTypeSetting, functionsInprocNet8Enabled, functionsInprocNet8EnabledTrue, + workflowAuthenticationMethodKey, workflowCodefulEnabledKey, } from '../../../constants'; import { localize } from '../../../localize'; @@ -213,6 +214,7 @@ export const getLocalSettingsSchema = (isDesignTime: boolean, projectPath?: stri if (projectPath) { values[ProjectDirectoryPathKey] = projectPath; } + values[workflowAuthenticationMethodKey] = 'managedServiceIdentity'; if (logicAppType !== undefined && logicAppType !== ProjectType.logicApp) { values[azureWebJobsFeatureFlagsKey] = multiLanguageWorkerSetting; } diff --git a/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts b/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts index 68aee7e7f26..0d13eb9f058 100644 --- a/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts +++ b/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts @@ -1,5 +1,5 @@ import { beforeEach, describe, expect, it, vi } from 'vitest'; -import { workflowAuthenticationMethodKey, workflowSubscriptionIdKey } from '../../../../constants'; +import { workflowSubscriptionIdKey } from '../../../../constants'; vi.mock('../../../../localize', () => ({ localize: (_key: string, defaultMessage: string, ...args: unknown[]) => @@ -58,7 +58,7 @@ describe('getAzureConnectorDetailsForLocalProject', () => { }; }); - it('defaults cancelled Azure connector discovery to disabled raw-key settings', async () => { + it('defaults cancelled Azure connector discovery to disabled settings', async () => { vi.mocked(getLocalSettingsJson).mockResolvedValue({ Values: {} } as any); vi.mocked(createAzureWizard).mockReturnValue({ prompt: vi.fn().mockRejectedValue({ isUserCancelledError: true }), @@ -70,10 +70,9 @@ describe('getAzureConnectorDetailsForLocalProject', () => { expect(details).toEqual({ enabled: false }); expect(addOrUpdateLocalAppSettings).toHaveBeenCalledWith(context, projectPath, { [workflowSubscriptionIdKey]: '', - [workflowAuthenticationMethodKey]: 'rawKeys', }); expect(getAuthData).not.toHaveBeenCalled(); - expect(context.telemetry.properties.azureConnectorsDefaulted).toBe('rawKeys'); + expect(context.telemetry.properties.azureConnectorsDefaulted).toBe('true'); }); it('handles undefined projectPath', async () => { @@ -106,17 +105,15 @@ describe('getAzureConnectorDetailsForLocalProject', () => { expect(addOrUpdateLocalAppSettings).not.toHaveBeenCalled(); }); - it('persists raw keys when the Azure wizard explicitly skips connectors', async () => { + it('persists disabled state when the Azure wizard explicitly skips connectors', async () => { vi.mocked(getLocalSettingsJson).mockResolvedValue({ Values: {} } as any); vi.mocked(createAzureWizard).mockImplementation((wizardContext: any) => ({ prompt: vi.fn(async () => { wizardContext.enabled = false; - wizardContext.authenticationMethod = 'rawKeys'; }), execute: vi.fn(async () => { await addOrUpdateLocalAppSettings(wizardContext, projectPath, { [workflowSubscriptionIdKey]: '', - [workflowAuthenticationMethodKey]: 'rawKeys', }); }), })) as any; @@ -126,7 +123,6 @@ describe('getAzureConnectorDetailsForLocalProject', () => { expect(details.enabled).toBe(false); expect(addOrUpdateLocalAppSettings).toHaveBeenCalledWith(context, projectPath, { [workflowSubscriptionIdKey]: '', - [workflowAuthenticationMethodKey]: 'rawKeys', }); }); diff --git a/apps/vs-code-designer/src/app/utils/codeless/__test__/validateProjectArtifacts.test.ts b/apps/vs-code-designer/src/app/utils/codeless/__test__/validateProjectArtifacts.test.ts index ca76d341b55..03f18a23351 100644 --- a/apps/vs-code-designer/src/app/utils/codeless/__test__/validateProjectArtifacts.test.ts +++ b/apps/vs-code-designer/src/app/utils/codeless/__test__/validateProjectArtifacts.test.ts @@ -21,6 +21,7 @@ import { localEmulatorConnectionString, logicAppKind, multiLanguageWorkerSetting, + workflowAuthenticationMethodKey, workerRuntimeKey, workflowCodefulEnabledKey, workflowOperationDiscoveryHostModeKey, @@ -182,6 +183,7 @@ describe('validateProjectArtifacts', () => { [workerRuntimeKey]: WorkerRuntime.Dotnet, [azureWebJobsStorageKey]: localEmulatorConnectionString, [functionsInprocNet8Enabled]: functionsInprocNet8EnabledTrue, + [workflowAuthenticationMethodKey]: 'managedServiceIdentity', [azureWebJobsFeatureFlagsKey]: multiLanguageWorkerSetting, [workflowCodefulEnabledKey]: 'true', }); @@ -201,6 +203,7 @@ describe('validateProjectArtifacts', () => { ProjectDirectoryPath: projectPath, AzureWebJobsStorage: 'UseDevelopmentStorage=true', FUNCTIONS_INPROC_NET8_ENABLED: '1', + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', EXISTING_SECRET: 'super-secret', }, }); @@ -224,6 +227,7 @@ describe('validateProjectArtifacts', () => { ProjectDirectoryPath: projectPath, AzureWebJobsStorage: 'UseDevelopmentStorage=true', FUNCTIONS_INPROC_NET8_ENABLED: '1', + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', }, }); @@ -246,6 +250,7 @@ describe('validateProjectArtifacts', () => { [workerRuntimeKey]: WorkerRuntime.Dotnet, [azureWebJobsStorageKey]: localEmulatorConnectionString, [functionsInprocNet8Enabled]: functionsInprocNet8EnabledTrue, + [workflowAuthenticationMethodKey]: 'managedServiceIdentity', }; beforeEach(() => { @@ -738,6 +743,7 @@ describe('validateProjectArtifacts', () => { ProjectDirectoryPath: projectPath, AzureWebJobsStorage: 'UseDevelopmentStorage=true', FUNCTIONS_INPROC_NET8_ENABLED: '1', + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', }, }); @@ -764,6 +770,7 @@ describe('validateProjectArtifacts', () => { ProjectDirectoryPath: projectPath, AzureWebJobsStorage: 'UseDevelopmentStorage=true', FUNCTIONS_INPROC_NET8_ENABLED: '1', + WORKFLOWS_AUTHENTICATION_METHOD: 'managedServiceIdentity', }, }); diff --git a/apps/vs-code-designer/src/app/utils/codeless/common.ts b/apps/vs-code-designer/src/app/utils/codeless/common.ts index 102f4356e8f..a9d29c28379 100644 --- a/apps/vs-code-designer/src/app/utils/codeless/common.ts +++ b/apps/vs-code-designer/src/app/utils/codeless/common.ts @@ -7,7 +7,6 @@ import { workflowManagementBaseURIKey, managementApiPrefix, workflowFileName, - workflowAuthenticationMethodKey, artifactsDirectory, mapsDirectory, schemasDirectory, @@ -193,10 +192,9 @@ export async function getArtifactsPathInLocalProject(projectPath: string): Promi const azureDetailsCache = new Map(); const AZURE_DETAILS_CACHE_TTL = 300000; // 5 minutes -async function defaultAzureConnectorDetailsToRawKeys(context: IActionContext, projectPath: string): Promise { +async function defaultAzureConnectorDetails(context: IActionContext, projectPath: string): Promise { await addOrUpdateLocalAppSettings(context, projectPath, { [workflowSubscriptionIdKey]: '', - [workflowAuthenticationMethodKey]: 'rawKeys', }); return { @@ -252,8 +250,8 @@ export async function getAzureConnectorDetailsForLocalProject( throw error; } - context.telemetry.properties.azureConnectorsDefaulted = 'rawKeys'; - const defaultDetails = await defaultAzureConnectorDetailsToRawKeys(context, projectPath); + context.telemetry.properties.useDefaultAzureConnectorDetails = 'true'; + const defaultDetails = await defaultAzureConnectorDetails(context, projectPath); azureDetailsCache.set(projectPath, { timestamp: now, details: defaultDetails }); return defaultDetails; } diff --git a/apps/vs-code-designer/src/test/ui/SKILL.md b/apps/vs-code-designer/src/test/ui/SKILL.md index 85eeef0dfe1..01360602e67 100644 --- a/apps/vs-code-designer/src/test/ui/SKILL.md +++ b/apps/vs-code-designer/src/test/ui/SKILL.md @@ -327,13 +327,12 @@ await input.setText('logic app workspace'); // ❌ switches to file search ### Issue: Azure connector wizard blocks designer loading (FIXED) **Symptom**: Designer never loads for CustomCode and RulesEngine workspaces. VS Code shows QuickPick prompts that require manual intervention. -**Cause**: When `WORKFLOWS_SUBSCRIPTION_ID` is undefined in `local.settings.json`, the extension shows two blocking QuickPick prompts: +**Cause**: When `WORKFLOWS_SUBSCRIPTION_ID` is undefined in `local.settings.json`, the extension shows a blocking QuickPick prompt: 1. "Enable connectors in Azure for Logic App" → "Use connectors from Azure" / "Skip for now" - 2. "Select authentication method for Azure connectors" → "Managed Service Identity" / "Connection Keys" -**Code path**: `getAzureConnectorDetailsForLocalProject()` in `apps/vs-code-designer/src/app/utils/codeless/common.ts` triggers `azureConnectorWizard.ts` which calls `authenticationMethodStep.ts`. +**Code path**: `getAzureConnectorDetailsForLocalProject()` in `apps/vs-code-designer/src/app/utils/codeless/common.ts` triggers `azureConnectorWizard.ts`. **Fix applied (2026-02-24)**: Two-layer fix in both `designerOpen.test.ts` and `designerActions.test.ts`: 1. `ensureLocalSettingsForDesigner(appDir)` — patches `local.settings.json` with `WORKFLOWS_SUBSCRIPTION_ID: ""` before opening the designer. Setting it to empty string (not undefined) prevents the wizard from launching. - 2. `handleDesignerPrompts(workbench, driver)` — fallback safety net that polls for QuickPick dialogs and auto-selects "Skip for now" / "Connection Keys" if they still appear. + 2. `handleDesignerPrompts(workbench, driver)` — fallback safety net that polls for QuickPick dialogs and auto-selects "Skip for now" if they still appear. **Standard workspaces** already had `WORKFLOWS_SUBSCRIPTION_ID: ""` in their `local.settings.json` (set by the creation wizard), so they were unaffected. ### Issue: Command palette fails to open in designer tests (FIXED) diff --git a/apps/vs-code-designer/src/test/ui/connectionPromptFallback.test.ts b/apps/vs-code-designer/src/test/ui/connectionPromptFallback.test.ts index 1dbec0846b1..2cfed56d410 100644 --- a/apps/vs-code-designer/src/test/ui/connectionPromptFallback.test.ts +++ b/apps/vs-code-designer/src/test/ui/connectionPromptFallback.test.ts @@ -146,6 +146,10 @@ describe('Connection prompt fallback E2E', function () { await driver.switchTo().defaultContent(); const localSettings = JSON.parse(fs.readFileSync(path.join(entry.appDir, 'local.settings.json'), 'utf-8')); assert.strictEqual(localSettings.Values?.WORKFLOWS_SUBSCRIPTION_ID, '', 'Cancellation should persist Azure connectors disabled'); - assert.strictEqual(localSettings.Values?.WORKFLOWS_AUTHENTICATION_METHOD, 'rawKeys', 'Cancellation should default to connection keys'); + assert.strictEqual( + localSettings.Values?.WORKFLOWS_AUTHENTICATION_METHOD, + 'managedServiceIdentity', + 'Cancellation should default to managed service identity' + ); }); }); From af9f278ea85133c2a013bd849d330569d0899472 Mon Sep 17 00:00:00 2001 From: andrew-eldridge Date: Fri, 17 Jul 2026 17:53:16 -0400 Subject: [PATCH 3/3] fix tests --- .../src/app/utils/codeless/__test__/common.test.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts b/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts index 0d13eb9f058..98bf6746f4d 100644 --- a/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts +++ b/apps/vs-code-designer/src/app/utils/codeless/__test__/common.test.ts @@ -72,7 +72,6 @@ describe('getAzureConnectorDetailsForLocalProject', () => { [workflowSubscriptionIdKey]: '', }); expect(getAuthData).not.toHaveBeenCalled(); - expect(context.telemetry.properties.azureConnectorsDefaulted).toBe('true'); }); it('handles undefined projectPath', async () => {