Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
5 changes: 5 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -1088,6 +1088,11 @@
"type": "boolean",
"description": "%azureFunctions.enableFlexConsumption%",
"default": false
},
"azureFunctions.showFlexEventGridWarning": {
"type": "boolean",
"description": "%azureFunctions.showFlexEventGridWarning%",
"default": true
}
}
}
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"azureFunctions.showDeprecatedStacks": "Show deprecated runtime stacks when creating a Function App in Azure. WARNING: These stacks may be removed at any time and may not be available in all regions.",
"azureFunctions.showExplorer": "Show or hide the Azure Functions Explorer",
"azureFunctions.showExtensionsCsprojWarning": "Show a warning when an Azure Functions project was detected that has mismatched \"extensions.csproj\" configuration.",
"%azureFunctions.showFlexEventGridWarning%": "Show a warning when deploying a Azure Blob Storage Trigger (using Event Grid) to a Flex Consumption Function App.",
"azureFunctions.showHiddenStacks": "Show hidden runtime stacks when creating a Function App in Azure. WARNING: These stacks may be in preview or may not be available in all regions.",
"azureFunctions.showMultiCoreToolsWarning": "Show a warning if multiple installs of Azure Functions Core Tools are detected.",
"azureFunctions.showProjectWarning": "Show a warning when an Azure Functions project was detected that has not been initialized for use in VS Code.",
Expand Down
2 changes: 1 addition & 1 deletion src/commands/createFunctionApp/FunctionAppCreateStep.ts
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ export class FunctionAppCreateStep extends AzureWizardExecuteStep<IFunctionAppWi
version: sku.functionAppConfigProperties.runtime.version
},
scaleAndConcurrency: {
maximumInstanceCount: context.newFlexInstanceMemoryMB ?? sku.maximumInstanceCount.defaultValue,
maximumInstanceCount: context.newFlexMaximumInstanceCount ?? sku.maximumInstanceCount.defaultValue,
instanceMemoryMB: context.newFlexInstanceMemoryMB ?? sku.instanceMemoryMB.find(im => im.isDefault)?.size ?? 2048,
alwaysReady: [],
triggers: null
Expand Down
2 changes: 1 addition & 1 deletion src/commands/deploy/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ async function deploy(actionContext: IActionContext, arg1: vscode.Uri | string |
}
);

await notifyDeployComplete(context, node, context.workspaceFolder);
await notifyDeployComplete(context, node, context.workspaceFolder, isFlexConsumption);
}

async function updateWorkerProcessTo64BitIfRequired(context: IDeployContext, siteConfig: SiteConfigResource, node: SlotTreeItem, language: ProjectLanguage, durableStorageType: DurableBackendValues | undefined): Promise<void> {
Expand Down
12 changes: 11 additions & 1 deletion src/commands/deploy/notifyDeployComplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,23 @@ import { RemoteFunctionsTreeItem } from '../../tree/remoteProject/RemoteFunction
import { nonNullValue } from '../../utils/nonNull';
import { uploadAppSettings } from '../appSettings/uploadAppSettings';
import { startStreamingLogs } from '../logstream/startStreamingLogs';
import { hasRemoteEventGridBlobTrigger, promptForEventGrid } from './promptForEventGrid';

export async function notifyDeployComplete(context: IActionContext, node: SlotTreeItem, workspaceFolder: WorkspaceFolder): Promise<void> {
export async function notifyDeployComplete(context: IActionContext, node: SlotTreeItem, workspaceFolder: WorkspaceFolder, isFlexConsumption?: boolean): Promise<void> {
const deployComplete: string = localize('deployComplete', 'Deployment to "{0}" completed.', node.site.fullName);
const viewOutput: MessageItem = { title: localize('viewOutput', 'View output') };
const streamLogs: MessageItem = { title: localize('streamLogs', 'Stream logs') };
const uploadSettings: MessageItem = { title: localize('uploadAppSettings', 'Upload settings') };

try {
const shouldCheckEventSystemTopics = isFlexConsumption && await hasRemoteEventGridBlobTrigger(context, node);
if (shouldCheckEventSystemTopics) {
await promptForEventGrid(context, workspaceFolder);
}
} catch (err) {
// ignore this error, don't block deploy for this check
}

// Don't wait
void window.showInformationMessage(deployComplete, streamLogs, uploadSettings, viewOutput).then(async result => {
await callWithTelemetryAndErrorHandling('postDeploy', async (postDeployContext: IActionContext) => {
Expand Down
57 changes: 57 additions & 0 deletions src/commands/deploy/promptForEventGrid.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { type FunctionEnvelope } from "@azure/arm-appservice";
import { DialogResponses, type IActionContext, type IAzureMessageOptions } from "@microsoft/vscode-azext-utils";
import * as retry from 'p-retry';
import { type WorkspaceFolder } from "vscode";
import { localize } from "../../localize";
import { type IBindingTemplate } from "../../templates/IBindingTemplate";
import { type SlotTreeItem } from "../../tree/SlotTreeItem";
import { getWorkspaceSetting, updateWorkspaceSetting } from "../../vsCodeConfig/settings";

export async function hasRemoteEventGridBlobTrigger(context: IActionContext, node: SlotTreeItem): Promise<boolean> {
const retries = 3;
const client = await node.site.createClient(context);

const funcs = await retry<FunctionEnvelope[]>(
async () => {
// Load more currently broken https://github.com/Azure/azure-sdk-for-js/issues/20380
const response = await client.listFunctions();
const failedToList = localize('failedToList', 'Failed to list functions.');

// https://github.com/Azure/azure-functions-host/issues/3502
if (!Array.isArray(response)) {
throw new Error(failedToList);
}

return response;
},
{ retries, minTimeout: 10 * 1000 }
);

return funcs.some(f => {
const bindings = (f.config as { bindings: IBindingTemplate[] }).bindings;
return bindings.some(b => b.type === 'blobTrigger');
});
}

export async function promptForEventGrid(context: IActionContext, workspaceFolder: WorkspaceFolder): Promise<void> {
const showFlexEventGridWarning = await getWorkspaceSetting('showFlexEventGridWarning');
if (!showFlexEventGridWarning) {
return;
}

const eventGridWarning = localize(
'eventGridWarning',
`Usage of an Event Grid based blob trigger requires an Event Grid subscription created on an Azure Storage v2 account. If you haven't already, you need to create a Event Grid subscription to complete your deployment.`);
const options: IAzureMessageOptions = { learnMoreLink: 'https://aka.ms/learnMoreEventGridSubscription' };
// need to add don't show again
Copy link
Contributor

@MicroFish91 MicroFish91 May 17, 2024

Choose a reason for hiding this comment

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

Was this a todo comment?

const result = await context.ui.showWarningMessage(eventGridWarning, options, { title: 'Close' }, DialogResponses.dontWarnAgain);
if (result === DialogResponses.dontWarnAgain) {
await updateWorkspaceSetting('showFlexEventGridWarning', false, workspaceFolder);
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Nit: Extra new line

}