diff --git a/src/commands/deploy/deploy.ts b/src/commands/deploy/deploy.ts index 604874a9f..cf7b3e4d2 100644 --- a/src/commands/deploy/deploy.ts +++ b/src/commands/deploy/deploy.ts @@ -60,7 +60,7 @@ async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string | expectedChildContextValue: expectedContextValue })); - const { language, version } = await verifyInitForVSCode(context, context.effectiveDeployFsPath); + const { language, languageModel, version } = await verifyInitForVSCode(context, context.effectiveDeployFsPath); context.telemetry.properties.projectLanguage = language; context.telemetry.properties.projectRuntime = version; @@ -121,7 +121,16 @@ async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string | } if (isZipDeploy) { - await verifyAppSettings(context, node, context.projectPath, version, language, { doRemoteBuild, isConsumption }, durableStorageType); + await verifyAppSettings({ + context, + node, + projectPath: context.projectPath, + version, + language, + languageModel, + bools: { doRemoteBuild, isConsumption }, + durableStorageType + }); } await node.runWithTemporaryDescription( diff --git a/src/commands/deploy/verifyAppSettings.ts b/src/commands/deploy/verifyAppSettings.ts index fa4403ead..ec869a1b7 100644 --- a/src/commands/deploy/verifyAppSettings.ts +++ b/src/commands/deploy/verifyAppSettings.ts @@ -7,11 +7,12 @@ import type { StringDictionary } from '@azure/arm-appservice'; import type { ParsedSite } from '@microsoft/vscode-azext-azureappservice'; import { IActionContext } from '@microsoft/vscode-azext-utils'; import * as vscode from 'vscode'; -import { ConnectionKey, ConnectionKeyValues, DurableBackend, DurableBackendValues, extensionVersionKey, ProjectLanguage, runFromPackageKey, workerRuntimeKey } from '../../constants'; +import { azureWebJobsFeatureFlags, ConnectionKey, ConnectionKeyValues, DurableBackend, DurableBackendValues, extensionVersionKey, ProjectLanguage, runFromPackageKey, workerRuntimeKey } from '../../constants'; import { ext } from '../../extensionVariables'; import { FuncVersion, tryParseFuncVersion } from '../../FuncVersion'; import { localize } from '../../localize'; import { SlotTreeItem } from '../../tree/SlotTreeItem'; +import { isNodeV4Plus, isPythonV2Plus } from '../../utils/programmingModelUtils'; import { isKnownWorkerRuntime, promptToUpdateDotnetRuntime, tryGetFunctionsWorkerRuntimeForProject } from '../../vsCodeConfig/settings'; import { ISetConnectionSettingContext } from '../appSettings/connectionSettings/ISetConnectionSettingContext'; @@ -20,7 +21,18 @@ import { ISetConnectionSettingContext } from '../appSettings/connectionSettings/ */ type VerifyAppSettingBooleans = { doRemoteBuild: boolean | undefined; isConsumption: boolean }; -export async function verifyAppSettings(context: IActionContext, node: SlotTreeItem, projectPath: string | undefined, version: FuncVersion, language: ProjectLanguage, bools: VerifyAppSettingBooleans, durableStorageType: DurableBackendValues | undefined): Promise { +export async function verifyAppSettings(options: { + context: IActionContext, + node: SlotTreeItem, + projectPath: string | undefined, + version: FuncVersion, + language: ProjectLanguage, + languageModel: number | undefined, + bools: VerifyAppSettingBooleans, + durableStorageType: DurableBackendValues | undefined +}): Promise { + + const { context, node, projectPath, version, language, bools, durableStorageType } = options; const client = await node.site.createClient(context); const appSettings: StringDictionary = await client.listApplicationSettings(); if (appSettings.properties) { @@ -36,6 +48,10 @@ export async function verifyAppSettings(context: IActionContext, node: SlotTreeI updateAppSettings ||= verifyRunFromPackage(context, node.site, appSettings.properties); } + if (isNodeV4Plus(options) || isPythonV2Plus(options.language, options.languageModel)) { + updateAppSettings ||= verifyFeatureFlagSetting(context, node.site, appSettings.properties); + } + const updatedRemoteConnection: boolean = await verifyAndUpdateAppConnectionStrings(context, durableStorageType, appSettings.properties); updateAppSettings ||= updatedRemoteConnection; @@ -168,3 +184,21 @@ function verifyLinuxRemoteBuildSettings(context: IActionContext, remotePropertie return hasChanged; } +function verifyFeatureFlagSetting(context: IActionContext, site: ParsedSite, remoteProperties: { [propertyName: string]: string }): boolean { + const featureFlagString = remoteProperties[azureWebJobsFeatureFlags] || ''; + + // Feature flags are comma-delimited lists of beta features + // https://learn.microsoft.com/en-us/azure/azure-functions/functions-app-settings#azurewebjobsfeatureflags + const featureFlagArray = !featureFlagString ? [] : featureFlagString.split(','); + const enableWorkerIndexingValue = 'EnableWorkerIndexing'; + const shouldAddSetting: boolean = !featureFlagArray.includes(enableWorkerIndexingValue); + + if (shouldAddSetting) { + featureFlagArray.push(enableWorkerIndexingValue); + ext.outputChannel.appendLog(localize('addedFeatureFlag', 'Added feature flag "{0}" because it is required for the new programming model', enableWorkerIndexingValue), { resourceName: site.fullName }); + remoteProperties[azureWebJobsFeatureFlags] = featureFlagArray.join(','); + } + + context.telemetry.properties.addedFeatureFlagSetting = String(shouldAddSetting); + return shouldAddSetting; +} diff --git a/src/constants.ts b/src/constants.ts index a73267922..9d8037627 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -151,6 +151,7 @@ export const extensionVersionKey: string = 'FUNCTIONS_EXTENSION_VERSION'; export const runFromPackageKey: string = 'WEBSITE_RUN_FROM_PACKAGE'; export const contentConnectionStringKey: string = 'WEBSITE_CONTENTAZUREFILECONNECTIONSTRING'; export const contentShareKey: string = 'WEBSITE_CONTENTSHARE'; +export const azureWebJobsFeatureFlags: string = 'AzureWebJobsFeatureFlags'; /** * The "current" Node.js model is 3 (and assumed, if the number is omitted).