4
4
*--------------------------------------------------------------------------------------------*/
5
5
6
6
import { 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' ;
8
8
import { 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' ;
10
10
import { type AzureSubscription } from '@microsoft/vscode-azureresources-api' ;
11
11
import type * as vscode from 'vscode' ;
12
12
import { CodeAction , deploySubpathSetting , DurableBackend , hostFileName , ProjectLanguage , remoteBuildSetting , ScmType , stackUpgradeLearnMoreLink } from '../../constants' ;
13
13
import { ext } from '../../extensionVariables' ;
14
14
import { addLocalFuncTelemetry } from '../../funcCoreTools/getLocalFuncCoreToolsVersion' ;
15
+ import { funcToolsInstalled , validateFuncCoreToolsInstalled } from '../../funcCoreTools/validateFuncCoreToolsInstalled' ;
15
16
import { localize } from '../../localize' ;
16
17
import { ResolvedFunctionAppResource } from '../../tree/ResolvedFunctionAppResource' ;
17
18
import { type SlotTreeItem } from '../../tree/SlotTreeItem' ;
@@ -30,6 +31,7 @@ import { getNetheriteConnectionIfNeeded } from '../appSettings/connectionSetting
30
31
import { getSQLConnectionIfNeeded } from '../appSettings/connectionSettings/sqlDatabase/getSQLConnection' ;
31
32
import { getEolWarningMessages } from '../createFunctionApp/stacks/getStackPicks' ;
32
33
import { tryGetFunctionProjectRoot } from '../createNewProject/verifyIsProject' ;
34
+ import { DeployFunctionCoreToolsStep } from './DeployFunctionCoreToolsStep' ;
33
35
import { getOrCreateFunctionApp } from './getOrCreateFunctionApp' ;
34
36
import { getWarningsForConnectionSettings } from './getWarningsForConnectionSettings' ;
35
37
import { notifyDeployComplete } from './notifyDeployComplete' ;
@@ -218,54 +220,81 @@ async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string |
218
220
eolWarningMessage ? stackUpgradeLearnMoreLink : undefined ) ;
219
221
}
220
222
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 ;
225
227
}
226
228
227
- if ( language === ProjectLanguage . CSharp && ! site . isLinux || durableStorageType ) {
228
- await updateWorkerProcessTo64BitIfRequired ( context , siteConfig , site , language , durableStorageType ) ;
229
- }
230
229
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
+ }
245
240
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 ;
246
257
await node . runWithTemporaryDescription (
247
258
context ,
248
259
localize ( 'deploying' , 'Deploying...' ) ,
249
260
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 ) ;
261
293
}
262
- const deployContext = Object . assign ( context , await createActivityContext ( ) ) ;
263
- deployContext . activityChildren = [ ] ;
264
- await innerDeploy ( site , deployFsPath , deployContext ) ;
265
294
}
266
295
) ;
267
296
268
- await notifyDeployComplete ( context , node , context . workspaceFolder , isFlexConsumption ) ;
297
+ await notifyDeployComplete ( context , node , context . workspaceFolder , isFlexConsumption , deployedWithFuncCli ) ;
269
298
}
270
299
271
300
async 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
310
339
await context . ui . showWarningMessage ( message , { stepName : 'globSettingRemoved' } ) ;
311
340
}
312
341
}
342
+
0 commit comments