Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,12 @@
},
"enablement": "!virtualWorkspace"
},
{
"command": "azureFunctions.createNewProjectWithDockerfile",
"title": "%azureFunctions.createNewProjectWithDockerfile%",
"category": "Azure Functions",
"enablement": "!virtualWorkspace"
},
{
"command": "azureFunctions.createSlot",
"title": "%azureFunctions.createSlot%",
Expand Down Expand Up @@ -381,6 +387,10 @@
"command": "azureFunctions.createNewProject",
"group": "1_projects@2"
},
{
"command": "azureFunctions.createNewProjectWithDockerfile",
"group": "1_projects@3"
},
{
"command": "azureFunctions.deploy",
"group": "2_deploy@1"
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"azureFunctions.createFunctionAppAdvanced": "Create Function App in Azure... (Advanced)",
"azureFunctions.createFunctionAppDetail": "For serverless, event driven apps and automation.",
"azureFunctions.createNewProject": "Create New Project...",
"azureFunctions.createNewProjectWithDockerfile": "Create New Project With Dockerfile...",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should call it Create New Containerized Project...?

I don't have a strong preference, but the learn document does refer to it as a containerized function app.

https://learn.microsoft.com/en-us/azure/azure-functions/functions-deploy-container?tabs=acr%2Cbash%2Cazure-cli&pivots=programming-language-javascript

"azureFunctions.createPythonVenv": "Create a virtual environment when creating a new Python project.",
"azureFunctions.createSlot": "Create Slot...",
"azureFunctions.createServiceConnector": "Create connection...",
Expand Down
2 changes: 2 additions & 0 deletions src/commands/createNewProject/IProjectWizardContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export interface IProjectWizardContext extends IActionContext {
openApiSpecificationFile?: Uri[];

targetFramework?: string | string[];

dockerfile?: boolean;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Property name is a bit odd for a boolean. If I see dockerfile, I think it's the dockerfile path or Uri. I would have called it addDockerfile or something like that.

But that being said, I don't think you need this property anymore. I'm assuming it used to be used to determine whether or not to add the CreateDockerfileProjectStep but we've covered that in another way.

}

export type OpenBehavior = 'AddToWorkspace' | 'OpenInNewWindow' | 'OpenInCurrentWindow' | 'AlreadyOpen' | 'DontOpen';
6 changes: 6 additions & 0 deletions src/commands/createNewProject/createNewProject.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FolderListStep } from './FolderListStep';
import { NewProjectLanguageStep } from './NewProjectLanguageStep';
import { OpenBehaviorStep } from './OpenBehaviorStep';
import { OpenFolderStep } from './OpenFolderStep';
import { CreateDockerfileProjectStep } from './dockerfileSteps/CreateDockerfileProjectStep';

/**
* @deprecated Use AzureFunctionsExtensionApi.createFunction instead
Expand Down Expand Up @@ -54,6 +55,10 @@ export async function createNewProjectInternal(context: IActionContext, options:
const wizardContext: Partial<IFunctionWizardContext> & IActionContext = Object.assign(context, options, { language, version: tryParseFuncVersion(version), projectTemplateKey });
const optionalExecuteStep = options.executeStep;

if (optionalExecuteStep instanceof CreateDockerfileProjectStep) {
wizardContext.dockerfile = true;
}

if (options.folderPath) {
FolderListStep.setProjectPath(wizardContext, options.folderPath);
}
Expand All @@ -70,6 +75,7 @@ export async function createNewProjectInternal(context: IActionContext, options:
promptSteps: [new FolderListStep(), new NewProjectLanguageStep(options.templateId, options.functionSettings), new OpenBehaviorStep()],
executeSteps: optionalExecuteStep ? [optionalExecuteStep, new OpenFolderStep()] : [new OpenFolderStep()]
});

await wizard.prompt();
await wizard.execute();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.md in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { ext } from "@microsoft/vscode-azext-serviceconnector";
import { AzureWizardExecuteStep, UserCancelledError, nonNullValueAndProp } from "@microsoft/vscode-azext-utils";
import { validateFuncCoreToolsInstalled } from "../../../funcCoreTools/validateFuncCoreToolsInstalled";
import { localize } from "../../../localize";
import { cpUtils } from "../../../utils/cpUtils";
import { type IFunctionWizardContext } from "../../createFunction/IFunctionWizardContext";

export class CreateDockerfileProjectStep extends AzureWizardExecuteStep<IFunctionWizardContext>{
public priority: number = 100;

public async execute(context: IFunctionWizardContext): Promise<void> {
const message: string = localize('installFuncTools', 'You must have the Azure Functions Core Tools installed to run this command.');
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mentioned this in another PR, but you should front-load this error. Nothing more annoying than going through a project wizard and then having it fail right at the end.

if (!await validateFuncCoreToolsInstalled(context, message, context.workspacePath)) {
throw new UserCancelledError('validateFuncCoreToolsInstalled');
}

let language = nonNullValueAndProp(context, 'language').toLowerCase();
if (language === 'c#') {
language = 'csharp';
}

await cpUtils.executeCommand(ext.outputChannel, nonNullValueAndProp(context, 'projectPath'), "func", "init", "--worker-runtime", language, "--docker");
}

public shouldExecute(): boolean {
return true;
}
}
4 changes: 3 additions & 1 deletion src/commands/registerCommands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ import { copyFunctionUrl } from './copyFunctionUrl';
import { createChildNode } from './createChildNode';
import { createFunctionFromCommand } from './createFunction/createFunction';
import { createFunctionApp, createFunctionAppAdvanced } from './createFunctionApp/createFunctionApp';
import { createNewProjectFromCommand } from './createNewProject/createNewProject';
import { createNewProjectFromCommand, createNewProjectInternal } from './createNewProject/createNewProject';
import { CreateDockerfileProjectStep } from './createNewProject/dockerfileSteps/CreateDockerfileProjectStep';
import { createSlot } from './createSlot';
import { deleteFunction } from './deleteFunction';
import { deleteFunctionApp } from './deleteFunctionApp';
Expand Down Expand Up @@ -75,6 +76,7 @@ export function registerCommands(): void {
registerCommandWithTreeNodeUnwrapping('azureFunctions.createFunctionApp', createFunctionApp);
registerCommandWithTreeNodeUnwrapping('azureFunctions.createFunctionAppAdvanced', createFunctionAppAdvanced);
registerCommand('azureFunctions.createNewProject', createNewProjectFromCommand);
registerCommandWithTreeNodeUnwrapping('azureFunctions.createNewProjectWithDockerfile', async (context: IActionContext) => await createNewProjectInternal(context, { executeStep: new CreateDockerfileProjectStep(), languageFilter: /Python|C\#|(Java|Type)Script|PowerShell$/i }));
registerCommandWithTreeNodeUnwrapping('azureFunctions.createSlot', createSlot);
registerCommandWithTreeNodeUnwrapping('azureFunctions.deleteFunction', deleteFunction);
registerCommandWithTreeNodeUnwrapping('azureFunctions.deleteFunctionApp', deleteFunctionApp);
Expand Down