Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vscode): Import Logic Apps from Cloud to Local VSCode #5693

Draft
wants to merge 39 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
ffc6834
feat(vscode): Add cloud to local gesture (#4878)
Jaden-Codes Jun 27, 2024
8535e9b
feat(vscode): Developing Cloud to Local feature (#5046)
Jaden-Codes Jul 19, 2024
95920db
converts auth parameters to MSI when deploying
JoaquimMalcampo Aug 20, 2024
77ef2ba
initial changes to include connection resolution
Sep 9, 2024
d518977
Revert "converts auth parameters to MSI when deploying"
Sep 9, 2024
995aec8
feat(vscode): Add cloud to local gesture (#4878)
Jaden-Codes Jun 27, 2024
688281f
feat(vscode): Developing Cloud to Local feature (#5046)
Jaden-Codes Jul 19, 2024
710fd14
initial changes to include connection resolution
Sep 9, 2024
1185b19
destructuring fix
Sep 9, 2024
f9fcd28
Merge branch 'jmalcampo/cloud_to_local' of https://github.com/Azure/L…
Sep 9, 2024
1f7a669
reformatting and adding parameterize setting handling
Sep 11, 2024
8d0d717
added LA type prompt and added helper functions
Sep 11, 2024
ce44ac2
Merge branch 'main' into jmalcampo/cloud_to_local
Sep 16, 2024
00811ea
happy path working
Sep 16, 2024
9dc0834
Merge branch 'main' into jmalcampo/cloud_to_local
Sep 16, 2024
62aa172
Merge branch 'main' into jmalcampo/cloud_to_local
Sep 20, 2024
6a82685
resolving comments
Sep 23, 2024
865ef10
cleaned up zipFileStep and cleanLocalSettings
Sep 23, 2024
a585261
Merge branch 'main' into jmalcampo/cloud_to_local
Sep 23, 2024
2663bb2
added telemetry
Sep 23, 2024
835a0d2
does not parameterize if setting is null
Sep 24, 2024
d4982fb
moved logic to execution step
Sep 26, 2024
3fc9a5e
Merge branch 'main' into jmalcampo/cloud_to_local
Sep 26, 2024
cb2de83
added telemetry to execution step
Sep 26, 2024
a4bf794
Merge branch 'main' into jmalcampo/cloud_to_local
Oct 29, 2024
1f16e1b
Merge branch 'main' into jmalcampo/cloud_to_local
Oct 30, 2024
56eb504
Wizard and local setting logic changes
Nov 2, 2024
db0925d
Merge branch 'main' into jmalcampo/cloud_to_local
Nov 2, 2024
86f1502
changed logic to excluding files and rename select folder step
Nov 4, 2024
3c1baa2
Merge branch 'main' into jmalcampo/cloud_to_local
Nov 5, 2024
b4561d5
Merge branch 'main' into jmalcampo/cloud_to_local
Nov 11, 2024
ab3713a
add read me placeholder and open after import
Nov 12, 2024
5e5ffb7
Merge branch 'main' into jmalcampo/cloud_to_local
Nov 12, 2024
532c421
changed test
Nov 12, 2024
4bb4def
added comments to steps
Nov 12, 2024
736bf7f
reverted bundleFeed changes and add more param setting support
Nov 14, 2024
264013a
moved readme to assets and add check for param setting
Nov 19, 2024
4e2f433
Merge branch 'main' into jmalcampo/cloud_to_local
Nov 19, 2024
f719b99
add import read me
Dec 18, 2024
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
3 changes: 2 additions & 1 deletion .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"recommendations": [
"biomejs.biome",
"dbaeumer.vscode-eslint"
"dbaeumer.vscode-eslint",
"ms-vscode.azure-account"
JoaquimMalcampo marked this conversation as resolved.
Show resolved Hide resolved
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,22 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
public hideStepCount = true;
private readonly templateId?: string;
private readonly functionSettings?: { [key: string]: string | undefined };
private readonly skipWorkflowStateTypeStep?: boolean;

/**
* The constructor initializes the NewCodeProjectTypeStep object with optional templateId and functionSettings parameters.
* @param templateId - The ID of the template for the code project.
* @param functionSettings - The settings for the functions in the code project.
*/
public constructor(templateId: string | undefined, functionSettings: { [key: string]: string | undefined } | undefined) {
public constructor(
templateId: string | undefined,
functionSettings: { [key: string]: string | undefined } | undefined,
skipWorkflowStateTypeStep: any
) {
super();
this.templateId = templateId;
this.functionSettings = functionSettings;
this.skipWorkflowStateTypeStep = skipWorkflowStateTypeStep;
}

/**
Expand Down Expand Up @@ -153,13 +159,15 @@ export class NewCodeProjectTypeStep extends AzureWizardPromptStep<IProjectWizard
executeSteps.push(new WorkflowProjectCreateStep());
await addInitVSCodeSteps(context, executeSteps, false);

promptSteps.push(
await WorkflowStateTypeStep.create(context, {
isProjectWizard: true,
templateId: this.templateId,
triggerSettings: this.functionSettings,
})
);
if (!this.skipWorkflowStateTypeStep) {
promptSteps.push(
await WorkflowStateTypeStep.create(context, {
isProjectWizard: true,
templateId: this.templateId,
triggerSettings: this.functionSettings,
})
);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { extractConnectionDetails, changeAuthTypeToRaw } from '../cloudToLocalHelper';
import type { ConnectionReferenceModel } from '@microsoft/vscode-extension-logic-apps';
import { describe, it, expect, vi } from 'vitest';
import { beforeEach } from 'vitest';

vi.mock('fs');
describe('extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal.', () => {
beforeEach(() => {
vi.clearAllMocks();
});

describe('extractConnectionDetails for ConnectionReferenceModel', () => {
it('should extract connection details correctly', () => {
let connectionObject = {
managedApiConnections: {
connKey: {
api: {
id: '/subscriptions/346751b2-0de1-405c-ad29-acb7ba73797f/providers/Microsoft.Web/locations/eastus2/managedApis/applicationinsights',
},
connection: {
id: '/subscriptions/346751b2-0de1-405c-ad29-acb7ba73797f/resourceGroups/vs-code-debug/providers/Microsoft.Web/connections/applicationinsights',
},
authentication: {
type: 'ManagedServiceIdentity',
},
connectionRuntimeUrl: 'runtime-url',
},
},
};
const newconnection = JSON.stringify(connectionObject);
const parsedconnection: ConnectionReferenceModel = JSON.parse(newconnection);

const details = extractConnectionDetails(parsedconnection);

const expectedDetails = [
{
WORKFLOWS_LOCATION_NAME: 'eastus2',
WORKFLOWS_RESOURCE_GROUP_NAME: 'vs-code-debug',
WORKFLOWS_SUBSCRIPTION_ID: '346751b2-0de1-405c-ad29-acb7ba73797f',
},
];

expect(details).toEqual(expectedDetails);

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / pr-coverage

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / pr-coverage

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / pr-coverage

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / pr-coverage

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / build (22.x)

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / build (22.x)

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / build (22.x)

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23

Check failure on line 43 in apps/vs-code-designer/src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts

View workflow job for this annotation

GitHub Actions / build (22.x)

src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts > extractConnectionDetails and ChangAuthToRaw are being tested for cloudToLocal. > extractConnectionDetails for ConnectionReferenceModel > should extract connection details correctly

AssertionError: expected Promise{…} to deeply equal [ { …(3) } ] - Expected: Array [ Object { "WORKFLOWS_LOCATION_NAME": "eastus2", "WORKFLOWS_RESOURCE_GROUP_NAME": "vs-code-debug", "WORKFLOWS_SUBSCRIPTION_ID": "346751b2-0de1-405c-ad29-acb7ba73797f", }, ] + Received: Promise {} ❯ src/app/commands/createNewCodeProject/__test__/cloudToLocal.test.ts:43:23
});
});

describe('ChangeAuthToRaw for ConnectionReferenceModel', () => {
it('should change authentication type to Raw', () => {
// Setup
let connectionsJsonContent = {
managedApiConnections: {
applicationinsights: {
api: {
id: '/subscriptions/346751b2-0de1-405c-ad29-acb7ba73797f/providers/Microsoft.Web/locations/eastus2/managedApis/applicationinsights',
},
connection: {
id: '/subscriptions/346751b2-0de1-405c-ad29-acb7ba73797f/resourceGroups/vs-code-debug/providers/Microsoft.Web/connections/applicationinsights',
},
authentication: {
type: 'ManagedServiceIdentity',
},
},
},
};
const jsonString = JSON.stringify(connectionsJsonContent);
const connection: ConnectionReferenceModel = JSON.parse(jsonString);

changeAuthTypeToRaw(connection);

const expectedConnection = JSON.stringify({
managedApiConnections: {
applicationinsights: {
api: {
id: '/subscriptions/346751b2-0de1-405c-ad29-acb7ba73797f/providers/Microsoft.Web/locations/eastus2/managedApis/applicationinsights',
},
connection: {
id: '/subscriptions/346751b2-0de1-405c-ad29-acb7ba73797f/resourceGroups/vs-code-debug/providers/Microsoft.Web/connections/applicationinsights',
},
authentication: {
type: 'Raw',
scheme: 'Key',
parameter: "@appsetting('applicationinsights-connectionKey')",
},
},
},
});
expect(JSON.stringify(connection)).toEqual(expectedConnection);
JoaquimMalcampo marked this conversation as resolved.
Show resolved Hide resolved
});
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
// Used createNewCodeProject.ts as a template to create this file
// This file is used to take a zipped Logic App from the desktop and unzip to the local workspace
// Reorganized file with constants at the top, grouped functions, and a main cloudToLocalInternal to call everything
import {
extensionCommand,
funcVersionSetting,
projectLanguageSetting,
projectOpenBehaviorSetting,
projectTemplateKeySetting,
parameterizeConnectionsInProjectLoadSetting,
} from '../../../constants';
import { localize } from '../../../localize';
import { addLocalFuncTelemetry, tryGetLocalFuncVersion, tryParseFuncVersion } from '../../utils/funcCoreTools/funcVersion';
import { showPreviewWarning } from '../../utils/taskUtils';
import { getGlobalSetting, getWorkspaceSetting } from '../../utils/vsCodeConfig/settings';
import { OpenBehaviorStep } from '../createNewProject/OpenBehaviorStep';
import { FolderListStep } from '../createNewProject/createProjectSteps/FolderListStep';
import { NewCodeProjectTypeStep } from './CodeProjectBase/NewCodeProjectTypeStep';
import { ZipFileStep } from '../createNewProject/createProjectSteps/ZipFileStep';
import { OpenFolderStepCodeProject } from './CodeProjectBase/OpenFolderStepCodeProject';
import { SetLogicAppName } from './CodeProjectBase/SetLogicAppNameStep';
import { setWorkspaceName } from './CodeProjectBase/SetWorkspaceName';
import { extend } from '@microsoft/logic-apps-shared';
import { AzureWizard } from '@microsoft/vscode-azext-utils';
import type { IActionContext } from '@microsoft/vscode-azext-utils';
import { latestGAVersion, OpenBehavior } from '@microsoft/vscode-extension-logic-apps';
import { extractConnectionDetails, changeAuthTypeToRaw, updateConnectionKeys, getConnectionsJsonContent } from './cloudToLocalHelper';
import type { ICreateFunctionOptions, IFunctionWizardContext, ProjectLanguage } from '@microsoft/vscode-extension-logic-apps';
import { window } from 'vscode';
import * as path from 'path';
import AdmZip = require('adm-zip');
import * as fs from 'fs';
import { SetLogicAppType } from './CodeProjectBase/setLogicAppType';
import { writeFormattedJson } from '../../utils/fs';

// Constants
const openFolder = true;

// Function to create an AdmZip instance
function createAdmZipInstance(zipFilePath: string) {
return new AdmZip(zipFilePath);
}

// Function to get zip entries
function getZipEntries(zipFilePath: string) {
const zip = createAdmZipInstance(zipFilePath);
return zip.getEntries();
}

async function cleanLocalSettings(localSettingsPath: string) {
const localSettings = JSON.parse(fs.readFileSync(localSettingsPath, 'utf8'));
JoaquimMalcampo marked this conversation as resolved.
Show resolved Hide resolved

if (localSettings.Values) {
Object.keys(localSettings.Values).forEach((key) => {
JoaquimMalcampo marked this conversation as resolved.
Show resolved Hide resolved
if (
key === 'WEBSITE_SITE_NAME' ||
key === 'WEBSITE_AUTH_ENABLED' ||
key === 'WEBSITE_SLOT_NAME' ||
key === 'ScmType' ||
key === 'FUNCTIONS_RUNTIME_SCALE_MONITORING_ENABLED'
) {
delete localSettings.Values[key];
} else if (key === 'AzureWebJobsStorage') {
localSettings.Values[key] = 'UseDevelopmentStorage=true';
}
});

await writeFormattedJson(localSettingsPath, localSettings);
}
}

// Main function to orchestrate the cloud to local process
export async function cloudToLocalInternal(
context: IActionContext,
options: ICreateFunctionOptions = {
folderPath: undefined,
language: undefined,
version: undefined,
templateId: undefined,
functionName: undefined,
functionSettings: undefined,
suppressOpenFolder: !openFolder,
}
): Promise<void> {
addLocalFuncTelemetry(context);
showPreviewWarning(extensionCommand.cloudToLocal);

const language: ProjectLanguage | string = (options.language as ProjectLanguage) || getGlobalSetting(projectLanguageSetting);
const version: string = options.version || getGlobalSetting(funcVersionSetting) || (await tryGetLocalFuncVersion()) || latestGAVersion;
const projectTemplateKey: string | undefined = getGlobalSetting(projectTemplateKeySetting);
const wizardContext: Partial<IFunctionWizardContext> & IActionContext = Object.assign(context, options, {
language,
version: tryParseFuncVersion(version),
projectTemplateKey,
projectPath: options.folderPath,
});

if (options.suppressOpenFolder) {
wizardContext.openBehavior = OpenBehavior.dontOpen;
} else if (!wizardContext.openBehavior) {
wizardContext.openBehavior = getWorkspaceSetting(projectOpenBehaviorSetting);
context.telemetry.properties.openBehaviorFromSetting = String(!!wizardContext.openBehavior);
}

const wizard: AzureWizard<IFunctionWizardContext> = new AzureWizard(wizardContext, {
title: localize('cloudToLocal', 'Import zip into new Workspace'),
JoaquimMalcampo marked this conversation as resolved.
Show resolved Hide resolved
promptSteps: [
new FolderListStep(),
new setWorkspaceName(),
new SetLogicAppType(), // is it only supporting one type?
new SetLogicAppName(),
new ZipFileStep(),
new NewCodeProjectTypeStep(options.templateId, options.functionSettings, true),
new OpenBehaviorStep(),
],
executeSteps: [new OpenFolderStepCodeProject()],
hideStepCount: true,
});
try {
await wizard.prompt();
await wizard.execute();
} catch (error) {
console.error('Error during wizard execution:', error);
}
const zipFilePath = ZipFileStep.zipFilePath;
const zipEntries = getZipEntries(zipFilePath);
const connectionspath = path.join(wizardContext.workspacePath, 'connections.json');
const localSettingsEntry = zipEntries.find((entry) => entry.entryName === 'local.settings.json');
const localSettingsPath = path.join(wizardContext.workspacePath, 'local.settings.json');
let localSettings: { Values?: any } = {};
let zipSettings = {};
const parametersEntry = zipEntries.find((entry) => entry.entryName === 'parameters.json');
const parametersPath = path.join(wizardContext.workspacePath, 'parameters.json');
let localParameters: any = {};
let zipParameters: any = {};
const connectionsData = await getConnectionsJsonContent(wizardContext as IFunctionWizardContext);
const parameterizeConnectionsSetting = getGlobalSetting(parameterizeConnectionsInProjectLoadSetting);

if (localSettingsEntry) {
const zipSettingsContent = localSettingsEntry.getData().toString('utf8');
zipSettings = JSON.parse(zipSettingsContent);
}

if (fs.existsSync(localSettingsPath)) {
const localSettingsContent = fs.readFileSync(localSettingsPath, 'utf8');
localSettings = JSON.parse(localSettingsContent);
}

if (parametersEntry) {
const parametersContent = parametersEntry.getData().toString('utf8');
zipParameters = JSON.parse(parametersContent);
}

if (fs.existsSync(parametersPath)) {
const localParametersContent = fs.readFileSync(parametersPath, 'utf8');
localParameters = JSON.parse(localParametersContent);
}

async function mergeSettings(): Promise<Record<string, any>> {
try {
const connectionsValues = await extractConnectionDetails(connectionsData);
const connectionDetail = connectionsValues[0];
const newValues = {
...connectionDetail,
...localSettings.Values,
};
const settings = {
...localSettings,
Values: newValues,
};

return settings;
} catch (error) {
console.error('Error writing file:', error);
}
}

extend(localParameters, zipParameters);
extend(localSettings, zipSettings);

if (connectionsData.managedApiConnections) {
const [convertedConnections, convertedParameters] = await changeAuthTypeToRaw(
connectionsData,
localParameters,
parameterizeConnectionsSetting
);
const mergedSettings = await mergeSettings();

await writeFormattedJson(connectionspath, convertedConnections);
await writeFormattedJson(parametersPath, convertedParameters);
await writeFormattedJson(localSettingsPath, mergedSettings);

await updateConnectionKeys(wizardContext as IFunctionWizardContext);
}

await cleanLocalSettings(localSettingsPath);

window.showInformationMessage(localize('finishedCreating', 'Finished creating project.'));
}
Loading
Loading