diff --git a/packages/fx-core/src/plugins/resource/function/index.ts b/packages/fx-core/src/plugins/resource/function/index.ts index 6bd8d33a02..48060c8b83 100644 --- a/packages/fx-core/src/plugins/resource/function/index.ts +++ b/packages/fx-core/src/plugins/resource/function/index.ts @@ -10,6 +10,7 @@ import { FxResult, FunctionPluginResultFactory as ResultFactory } from "./result import { LifeCycle } from "./enums"; import { Logger } from "./utils/logger"; import { telemetryHelper } from "./utils/telemetry-helper"; +import { setFeatureFlag } from "./utils/depsChecker/checkerAdapter"; // This layer tries to provide a uniform exception handling for function plugin. export class FunctionPlugin implements Plugin { @@ -78,6 +79,7 @@ export class FunctionPlugin implements Plugin { public async preDeploy(ctx: PluginContext): Promise { Logger.setLogger(ctx.logProvider); + setFeatureFlag(ctx.answers); await StepHelperFactory.preDeployStepHelper.start( Object.entries(PreDeploySteps).length, ctx.dialog); const res = await this.runWithErrorWrapper(ctx, LifeCycle.preDeploy, @@ -89,6 +91,7 @@ export class FunctionPlugin implements Plugin { public async deploy(ctx: PluginContext): Promise { Logger.setLogger(ctx.logProvider); + setFeatureFlag(ctx.answers); await StepHelperFactory.deployStepHelper.start( Object.entries(DeploySteps).length, ctx.dialog); const res = await this.runWithErrorWrapper(ctx, LifeCycle.deploy, diff --git a/packages/fx-core/src/plugins/resource/function/plugin.ts b/packages/fx-core/src/plugins/resource/function/plugin.ts index 87f48e1089..01fdc4000b 100644 --- a/packages/fx-core/src/plugins/resource/function/plugin.ts +++ b/packages/fx-core/src/plugins/resource/function/plugin.ts @@ -38,6 +38,11 @@ import { FxResult, FunctionPluginResultFactory as ResultFactory } from "./result import { Logger } from "./utils/logger"; import { PostProvisionSteps, PreDeploySteps, ProvisionSteps, StepGroup, step } from "./resources/steps"; import { functionNameQuestion, nodeVersionQuestion } from "./questions"; +import { dotnetHelpLink, Messages } from "./utils/depsChecker/common"; +import { DotnetChecker } from "./utils/depsChecker/dotnetChecker"; +import { handleDotnetError } from "./utils/depsChecker/checkerAdapter"; +import { isLinux } from "./utils/depsChecker/common"; +import { DepsCheckerError } from "./utils/depsChecker/errors"; type Site = WebSiteManagementModels.Site; type AppServicePlan = WebSiteManagementModels.AppServicePlan; @@ -446,7 +451,8 @@ export class FunctionPluginImpl { return ResultFactory.Success(); } - await FunctionDeploy.checkDotNetVersion(ctx, workingPath); + // NOTE: make sure this step is before using `dotnet` command if you refactor this code. + await this.handleDotnetChecker(); await runWithErrorCatchAndThrow(new InstallTeamsfxBindingError(), async () => await step(StepGroup.PreDeployStepGroup, PreDeploySteps.installTeamsfxBinding, async () => @@ -594,4 +600,30 @@ export class FunctionPluginImpl { return undefined; } + + private async handleDotnetChecker(): Promise { + await step(StepGroup.PreDeployStepGroup, PreDeploySteps.dotnetInstall, async () => { + const dotnetChecker = new DotnetChecker(); + try { + if (await dotnetChecker.isInstalled()) { + return; + } + } catch (error) { + handleDotnetError(error); + return; + } + + if (isLinux()) { + // TODO: handle linux installation + handleDotnetError(new DepsCheckerError(Messages.defaultErrorMessage, dotnetHelpLink)); + return; + } + + try { + await dotnetChecker.install(); + } catch (error) { + handleDotnetError(error); + } + }); + } } diff --git a/packages/fx-core/src/plugins/resource/function/resources/steps.ts b/packages/fx-core/src/plugins/resource/function/resources/steps.ts index 0c6d557214..8e25e927cf 100644 --- a/packages/fx-core/src/plugins/resource/function/resources/steps.ts +++ b/packages/fx-core/src/plugins/resource/function/resources/steps.ts @@ -22,6 +22,7 @@ export enum PostProvisionSteps { } export enum PreDeploySteps { + dotnetInstall = "Install .NET Core SDK if needed.", installTeamsfxBinding = "Install TeamsFX Binding.", npmPrepare = "Install/Build js files." } diff --git a/packages/fx-core/src/plugins/resource/function/utils/depsChecker/checkerAdapter.ts b/packages/fx-core/src/plugins/resource/function/utils/depsChecker/checkerAdapter.ts index 5cb3ddfd61..a93778aa38 100644 --- a/packages/fx-core/src/plugins/resource/function/utils/depsChecker/checkerAdapter.ts +++ b/packages/fx-core/src/plugins/resource/function/utils/depsChecker/checkerAdapter.ts @@ -3,8 +3,10 @@ import * as path from "path"; import { Logger } from "../logger"; +import { DepsCheckerError } from "./errors"; import { dotnetChecker, DotnetChecker } from "./dotnetChecker"; -import { ConfigMap } from "fx-api"; +import { ConfigMap, PluginContext, returnUserError } from "fx-api"; +import { Messages, dotnetHelpLink } from "./common"; export { cpUtils } from "./cpUtils"; export const logger = Logger; @@ -74,3 +76,11 @@ export async function getDotnetForShell(): Promise { const execPath = await dotnetChecker.getDotnetExecPath(); return DotnetChecker.escapeFilePath(execPath); } + +export function handleDotnetError(error: Error): void { + if (error instanceof DepsCheckerError) { + throw returnUserError(error, "function", "DepsCheckerError", error.helpLink, error); + } else { + throw returnUserError(new Error(Messages.defaultErrorMessage), "function", "DepsCheckerError", dotnetHelpLink, error); + } +}