44 *--------------------------------------------------------------------------------------------*/
55
66import { type Site , type SiteConfigResource , type StringDictionary } from '@azure/arm-appservice' ;
7- import { getDeployFsPath , getDeployNode , deploy as innerDeploy , showDeployConfirmation , type IDeployContext , type IDeployPaths , type ParsedSite } from '@microsoft/vscode-azext-azureappservice' ;
7+ import { getDeployFsPath , getDeployNode , deploy as innerDeploy , showDeployConfirmation , type IDeployContext , type IDeployPaths , type InnerDeployContext , type ParsedSite } from '@microsoft/vscode-azext-azureappservice' ;
88import { ResourceGroupListStep } from '@microsoft/vscode-azext-azureutils' ;
9- import { DialogResponses , subscriptionExperience , type ExecuteActivityContext , type IActionContext , type ISubscriptionContext } from '@microsoft/vscode-azext-utils' ;
9+ import { AzureWizard , DialogResponses , subscriptionExperience , type ExecuteActivityContext , type IActionContext , type ISubscriptionContext } from '@microsoft/vscode-azext-utils' ;
1010import { type AzureSubscription } from '@microsoft/vscode-azureresources-api' ;
1111import type * as vscode from 'vscode' ;
1212import { CodeAction , deploySubpathSetting , DurableBackend , hostFileName , ProjectLanguage , remoteBuildSetting , ScmType , stackUpgradeLearnMoreLink } from '../../constants' ;
1313import { ext } from '../../extensionVariables' ;
1414import { addLocalFuncTelemetry } from '../../funcCoreTools/getLocalFuncCoreToolsVersion' ;
15+ import { funcToolsInstalled , validateFuncCoreToolsInstalled } from '../../funcCoreTools/validateFuncCoreToolsInstalled' ;
1516import { localize } from '../../localize' ;
1617import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource' ;
1718import { type SlotTreeItem } from '../../tree/SlotTreeItem' ;
@@ -30,6 +31,7 @@ import { getNetheriteConnectionIfNeeded } from '../appSettings/connectionSetting
3031import { getSQLConnectionIfNeeded } from '../appSettings/connectionSettings/sqlDatabase/getSQLConnection' ;
3132import { getEolWarningMessages } from '../createFunctionApp/stacks/getStackPicks' ;
3233import { tryGetFunctionProjectRoot } from '../createNewProject/verifyIsProject' ;
34+ import { DeployFunctionCoreToolsStep } from './DeployFunctionCoreToolsStep' ;
3335import { getOrCreateFunctionApp } from './getOrCreateFunctionApp' ;
3436import { getWarningsForConnectionSettings } from './getWarningsForConnectionSettings' ;
3537import { notifyDeployComplete } from './notifyDeployComplete' ;
@@ -218,54 +220,81 @@ async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string |
218220 eolWarningMessage ? stackUpgradeLearnMoreLink : undefined ) ;
219221 }
220222
221- await runPreDeployTask ( context , context . effectiveDeployFsPath , siteConfig . scmType ) ;
222-
223- if ( isZipDeploy ) {
224- void validateGlobSettings ( context , context . effectiveDeployFsPath ) ;
223+ let isFuncToolsInstalled : boolean = await funcToolsInstalled ( context , context . workspaceFolder . uri . fsPath ) ;
224+ if ( language === ProjectLanguage . Custom && ! isFuncToolsInstalled ) {
225+ await validateFuncCoreToolsInstalled ( context , localize ( 'validateFuncCoreToolsCustom' , 'The Functions Core Tools are required to deploy to a custom runtime function app.' ) ) ;
226+ isFuncToolsInstalled = true ;
225227 }
226228
227- if ( language === ProjectLanguage . CSharp && ! site . isLinux || durableStorageType ) {
228- await updateWorkerProcessTo64BitIfRequired ( context , siteConfig , site , language , durableStorageType ) ;
229- }
230229
231- // app settings shouldn't be checked with flex consumption plans
232- if ( isZipDeploy && ! isFlexConsumption ) {
233- await verifyAppSettings ( {
234- context,
235- node,
236- projectPath : context . projectPath ,
237- version,
238- language,
239- languageModel,
240- bools : { doRemoteBuild, isConsumption } ,
241- durableStorageType,
242- appSettings
243- } ) ;
244- }
230+ if ( ! isFuncToolsInstalled ) {
231+ await runPreDeployTask ( context , context . effectiveDeployFsPath , siteConfig . scmType ) ;
232+
233+ if ( isZipDeploy ) {
234+ void validateGlobSettings ( context , context . effectiveDeployFsPath ) ;
235+ }
236+
237+ if ( language === ProjectLanguage . CSharp && ! site . isLinux || durableStorageType ) {
238+ await updateWorkerProcessTo64BitIfRequired ( context , siteConfig , site , language , durableStorageType ) ;
239+ }
245240
241+ // app settings shouldn't be checked with flex consumption plans
242+ if ( isZipDeploy && ! isFlexConsumption ) {
243+ await verifyAppSettings ( {
244+ context,
245+ node,
246+ projectPath : context . projectPath ,
247+ version,
248+ language,
249+ languageModel,
250+ bools : { doRemoteBuild, isConsumption } ,
251+ durableStorageType,
252+ appSettings
253+ } ) ;
254+ }
255+ }
256+ let deployedWithFuncCli = false ;
246257 await node . runWithTemporaryDescription (
247258 context ,
248259 localize ( 'deploying' , 'Deploying...' ) ,
249260 async ( ) => {
250- // Stop function app here to avoid *.jar file in use on server side.
251- // More details can be found: https://github.com/Microsoft/vscode-azurefunctions/issues/106
252- context . stopAppBeforeDeploy = language === ProjectLanguage . Java ;
253-
254- // preDeploy tasks are only required for zipdeploy so subpath may not exist
255- let deployFsPath : string = context . effectiveDeployFsPath ;
256-
257- if ( ! isZipDeploy && ! isPathEqual ( context . effectiveDeployFsPath , context . originalDeployFsPath ) ) {
258- deployFsPath = context . originalDeployFsPath ;
259- const noSubpathWarning : string = `WARNING: Ignoring deploySubPath "${ getWorkspaceSetting ( deploySubpathSetting , context . originalDeployFsPath ) } " for non-zip deploy.` ;
260- ext . outputChannel . appendLog ( noSubpathWarning ) ;
261+ // prioritize func cli deployment if installed
262+ if ( isFuncToolsInstalled ) {
263+ context . telemetry . properties . funcCoreToolsInstalled = 'true' ;
264+ context . telemetry . properties . deployMethod = 'funccli' ;
265+ const deployContext = Object . assign ( context , await createActivityContext ( ) , { site } ) as unknown as InnerDeployContext ;
266+ deployContext . activityChildren = [ ] ;
267+ const wizard = new AzureWizard ( deployContext , {
268+ executeSteps : [ new DeployFunctionCoreToolsStep ( ) ] ,
269+ } ) ;
270+
271+ deployContext . activityTitle = site . isSlot
272+ ? localize ( 'deploySlot' , 'Deploy to slot "{0}"' , site . fullName )
273+ : localize ( 'deployApp' , 'Deploy to app "{0}"' , site . fullName ) ;
274+ await wizard . execute ( ) ;
275+ deployedWithFuncCli = true ;
276+ return ;
277+ } else {
278+ // Stop function app here to avoid *.jar file in use on server side.
279+ // More details can be found: https://github.com/Microsoft/vscode-azurefunctions/issues/106
280+ context . stopAppBeforeDeploy = language === ProjectLanguage . Java ;
281+
282+ // preDeploy tasks are only required for zipdeploy so subpath may not exist
283+ let deployFsPath : string = context . effectiveDeployFsPath ;
284+
285+ if ( ! isZipDeploy && ! isPathEqual ( context . effectiveDeployFsPath , context . originalDeployFsPath ) ) {
286+ deployFsPath = context . originalDeployFsPath ;
287+ const noSubpathWarning : string = `WARNING: Ignoring deploySubPath "${ getWorkspaceSetting ( deploySubpathSetting , context . originalDeployFsPath ) } " for non-zip deploy.` ;
288+ ext . outputChannel . appendLog ( noSubpathWarning ) ;
289+ }
290+ const deployContext = Object . assign ( context , await createActivityContext ( ) ) ;
291+ deployContext . activityChildren = [ ] ;
292+ await innerDeploy ( site , deployFsPath , deployContext ) ;
261293 }
262- const deployContext = Object . assign ( context , await createActivityContext ( ) ) ;
263- deployContext . activityChildren = [ ] ;
264- await innerDeploy ( site , deployFsPath , deployContext ) ;
265294 }
266295 ) ;
267296
268- await notifyDeployComplete ( context , node , context . workspaceFolder , isFlexConsumption ) ;
297+ await notifyDeployComplete ( context , node , context . workspaceFolder , isFlexConsumption , deployedWithFuncCli ) ;
269298}
270299
271300async function updateWorkerProcessTo64BitIfRequired ( context : IDeployContext , siteConfig : SiteConfigResource , site : ParsedSite , language : ProjectLanguage , durableStorageType : DurableBackend | undefined ) : Promise < void > {
@@ -310,3 +339,4 @@ async function validateGlobSettings(context: IActionContext, fsPath: string): Pr
310339 await context . ui . showWarningMessage ( message , { stepName : 'globSettingRemoved' } ) ;
311340 }
312341}
342+
0 commit comments