import { WebSiteManagementModels } from '@azure/arm-appservice' ; import * as vscode from 'vscode' ; import { ParsedSite } from 'vscode-azureappservice' ; import { IActionContext } from 'vscode-azureextensionui' ; import { extensionVersionKey , ProjectLanguage , runFromPackageKey , workerRuntimeKey } from '../../constants' ; import { ext } from '../../extensionVariables' ; import { FuncVersion , tryParseFuncVersion } from '../../FuncVersion' ; import { localize } from '../../localize' ; import { SlotTreeItemBase } from '../../tree/SlotTreeItemBase' ; import { isKnownWorkerRuntime , tryGetFunctionsWorkerRuntimeForProject } from '../../vsCodeConfig/settings' ; /**
 * Just putting a few booleans in an object to avoid ordering mistakes if we passed them as individual params
 */ type VerifyAppSettingBooleans = { doRemoteBuild : boolean | undefined ; isConsumption : boolean ; } ; export async function verifyAppSettings ( context , node , projectPath , version , language , bools ) { const client = await node . site . createClient ( context ) ; const appSettings = await client . listApplicationSettings ( ) ; if ( appSettings . properties ) { await verifyVersionAndLanguage ( context , projectPath , node . site . fullName , version , language , appSettings . properties ) ; let updateAppSettings = false ; if ( node . site . isLinux ) { const remoteBuildSettingsChanged = verifyLinuxRemoteBuildSettings ( context , appSettings . properties , bools ) ; updateAppSettings = updateAppSettings || remoteBuildSettingsChanged ; } else { updateAppSettings = verifyRunFromPackage ( context , node . site , appSettings . properties ) ; } if ( updateAppSettings ) { await client . updateApplicationSettings ( appSettings ) ; await node . appSettingsTreeItem . refresh ( context ) ; } } } export async function verifyVersionAndLanguage ( context , projectPath , siteName , localVersion , localLanguage , remoteProperties ) { const rawAzureVersion = remoteProperties [ extensionVersionKey ] ; const azureVersion = tryParseFuncVersion ( rawAzureVersion ) ; const azureWorkerRuntime = remoteProperties [ workerRuntimeKey ] ; context . telemetry . properties . remoteVersion = azureVersion || 'Unknown' ; context . telemetry . properties . remoteRuntimeV2 = isKnownWorkerRuntime ( azureWorkerRuntime ) ? azureWorkerRuntime : 'Unknown' ; const localWorkerRuntime = await tryGetFunctionsWorkerRuntimeForProject ( context , localLanguage , projectPath ) ; if ( localVersion !== FuncVersion . v1 && isKnownWorkerRuntime ( azureWorkerRuntime ) && isKnownWorkerRuntime ( localWorkerRuntime ) && azureWorkerRuntime !== localWorkerRuntime ) { throw new Error ( localize ( 'incompatibleRuntime' , 'The remote runtime "{0}" for function app "{1}" does not match your local runtime "{2}".' , azureWorkerRuntime , siteName , localWorkerRuntime ) ) ; } if ( ! ! rawAzureVersion && azureVersion !== localVersion ) { const message = localize ( 'incompatibleVersion' , 'The remote version "{0}" for function app "{1}" does not match your local version "{2}".' , rawAzureVersion , siteName , localVersion ) ; const deployAnyway = { title : localize ( 'deployAnyway' , 'Deploy Anyway' ) } ; const learnMoreLink = 'https://aka.ms/azFuncRuntime' ; await context . ui . showWarningMessage ( message , { modal : true , learnMoreLink , stepName : 'incompatibleVersion' } , deployAnyway ) ; } } /**
 * Automatically set to 1 on windows plans because it has significant perf improvements
 * https://github.com/microsoft/vscode-azurefunctions/issues/1465
 */ function verifyRunFromPackage ( context , site , remoteProperties ) { const shouldAddSetting = ! remoteProperties [ runFromPackageKey ] ; if ( shouldAddSetting ) { remoteProperties [ runFromPackageKey ] = '1' ; ext . outputChannel . appendLog ( localize ( 'addedRunFromPackage' , 'Added app setting "{0}" to improve performance of function app. Learn more here: https://aka.ms/AA8vxc0' , runFromPackageKey ) , { resourceName : site . fullName } ) ; } context . telemetry . properties . addedRunFromPackage = String ( shouldAddSetting ) ; return shouldAddSetting ; } function verifyLinuxRemoteBuildSettings ( context , remoteProperties , bools ) { let hasChanged = false ; const keysToRemove = [ ] ; if ( bools . doRemoteBuild ) { keysToRemove . push ( 'WEBSITE_RUN_FROM_ZIP' , 'WEBSITE_RUN_FROM_PACKAGE' ) ; } if ( ! bools . isConsumption ) { const dedicatedBuildSettings = [ [ 'ENABLE_ORYX_BUILD' , 'true' ] , [ 'SCM_DO_BUILD_DURING_DEPLOYMENT' , '1' ] , [ 'BUILD_FLAGS' , 'UseExpressBuild' ] , [ 'XDG_CACHE_HOME' , '/tmp/.cache' ] ] ; for ( const [ key , value ] of dedicatedBuildSettings ) { if ( ! bools . doRemoteBuild ) { keysToRemove . push ( key ) ; } else if ( remoteProperties [ key ] !== value ) { remoteProperties [ key ] = value ; hasChanged = true ; } } } for ( const key of keysToRemove ) { if ( remoteProperties [ key ] ) { delete remoteProperties [ key ] ; hasChanged = true ; } } context . telemetry . properties . linuxBuildSettingsChanged = String ( hasChanged ) ; return hasChanged ; }