Skip to content

Commit

Permalink
Add an API command to start a func task and to check if CLI tools is …
Browse files Browse the repository at this point in the history
…installed
  • Loading branch information
nturinski committed Oct 9, 2024
1 parent e1dc3df commit 2dc3517
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 8 deletions.
43 changes: 41 additions & 2 deletions src/commands/pickFuncProcess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/

import { sendRequestWithTimeout, type AzExtRequestPrepareOptions } from '@microsoft/vscode-azext-azureutils';
import { UserCancelledError, type IActionContext } from '@microsoft/vscode-azext-utils';
import { callWithTelemetryAndErrorHandling, parseError, UserCancelledError, type IActionContext } from '@microsoft/vscode-azext-utils';
import * as unixPsTree from 'ps-tree';
import * as vscode from 'vscode';
import { hostStartTaskName } from '../constants';
Expand All @@ -15,12 +15,51 @@ import { localize } from '../localize';
import { delay } from '../utils/delay';
import { requestUtils } from '../utils/requestUtils';
import { taskUtils } from '../utils/taskUtils';
import { ProcessDataFlag, getWindowsProcessTree, type IProcessInfo, type IWindowsProcessTree } from '../utils/windowsProcessTree';
import { getWindowsProcessTree, ProcessDataFlag, type IProcessInfo, type IWindowsProcessTree } from '../utils/windowsProcessTree';
import { getWorkspaceSetting } from '../vsCodeConfig/settings';
import path = require('path');

const funcTaskReadyEmitter = new vscode.EventEmitter<vscode.WorkspaceFolder>();
export const onDotnetFuncTaskReady = funcTaskReadyEmitter.event;

export async function startFuncProcessFromApi(
workspaceFolder: vscode.WorkspaceFolder,
buildPath: string,
args?: string[]
): Promise<{ processId: string; success: boolean; error: string }> {
const result = {
processId: '',
success: false,
error: ''
};

let funcHostStartCmd: string = 'func host start';
if (args) {
funcHostStartCmd += ` ${args.join(' ')}`;
}

await callWithTelemetryAndErrorHandling('startFuncProcessFromApi', async (context: IActionContext) => {
try {
await waitForPrevFuncTaskToStop(workspaceFolder);
const funcTask = new vscode.Task({ type: 'func' },
workspaceFolder,
hostStartTaskName, 'func',
new vscode.ShellExecution(funcHostStartCmd, {
cwd: path.posix.join('${workspaceFolder}', buildPath),
}));

const taskInfo = await startFuncTask(context, workspaceFolder, funcTask);
result.processId = await pickChildProcess(taskInfo);
result.success = true;
} catch (err) {
const pError = parseError(err);
result.error = pError.message;
}
});

return result
}

export async function pickFuncProcess(context: IActionContext, debugConfig: vscode.DebugConfiguration): Promise<string | undefined> {
const result: IPreDebugValidateResult = await preDebugValidate(context, debugConfig);
if (!result.shouldContinue) {
Expand Down
6 changes: 6 additions & 0 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { downloadAppSettingsFromApi } from './commands/api/downloadAppSettingsFr
import { revealTreeItem } from './commands/api/revealTreeItem';
import { uploadAppSettingsFromApi } from './commands/api/uploadAppSettingsFromApi';
import { runPostFunctionCreateStepsFromCache } from './commands/createFunction/FunctionCreateStepBase';
import { startFuncProcessFromApi } from './commands/pickFuncProcess';
import { registerCommands } from './commands/registerCommands';
import { func } from './constants';
import { BallerinaDebugProvider } from './debug/BallerinaDebugProvider';
Expand All @@ -28,6 +29,7 @@ import { PythonDebugProvider } from './debug/PythonDebugProvider';
import { handleUri } from './downloadAzureProject/handleUri';
import { ext } from './extensionVariables';
import { registerFuncHostTaskEvents } from './funcCoreTools/funcHostTask';
import { validateFuncCoreToolsInstalled } from './funcCoreTools/validateFuncCoreToolsInstalled';
import { validateFuncCoreToolsIsLatest } from './funcCoreTools/validateFuncCoreToolsIsLatest';
import { getResourceGroupsApi } from './getExtensionApi';
import { CentralTemplateProvider } from './templates/CentralTemplateProvider';
Expand Down Expand Up @@ -111,6 +113,10 @@ export async function activateInternal(context: vscode.ExtensionContext, perfSta
uploadAppSettings: uploadAppSettingsFromApi,
listLocalProjects: listLocalProjects,
listLocalFunctions: listLocalFunctions,
isFuncCoreToolsInstalled: async (context: IActionContext) => {
return await validateFuncCoreToolsInstalled(context, '', undefined);
},
startFuncProcess: startFuncProcessFromApi,
apiVersion: '1.9.0'
}]);
}
Expand Down
4 changes: 2 additions & 2 deletions src/funcCoreTools/funcHostTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,8 @@ export function stopFuncTaskIfRunning(workspaceFolder: vscode.WorkspaceFolder):
export async function getFuncPortFromTaskOrProject(context: IActionContext, funcTask: vscode.Task | undefined, projectPathOrTaskScope: string | vscode.WorkspaceFolder | vscode.TaskScope): Promise<string> {
try {
// First, check the task itself
if (funcTask && typeof funcTask.definition.command === 'string') {
const match = funcTask.definition.command.match(/\s+(?:"|'|)(?:-p|--port)(?:"|'|)\s+(?:"|'|)([0-9]+)/i);
if (funcTask && funcTask.execution instanceof vscode.ShellExecution) {
const match = funcTask.execution?.commandLine?.match(/\s+(?:"|'|)(?:-p|--port)(?:"|'|)\s+(?:"|'|)([0-9]+)/i);
if (match) {
return match[1];
}
Expand Down
19 changes: 15 additions & 4 deletions src/vscode-azurefunctions.api.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@

import { type AzureWizardExecuteStep, type IActionContext } from "@microsoft/vscode-azext-utils";
import type * as vscode from 'vscode';
import { type JobType } from "./templates/script/parseScriptTemplatesV2";

export interface ILocalFunction {
name: string;
Expand Down Expand Up @@ -67,6 +66,21 @@ export interface AzureFunctionsExtensionApi {

listLocalProjects(): Promise<ListLocalProjectsResult>;
listLocalFunctions(localProject: WorkspaceProject): Promise<ListLocalFunctionsResult>;

isFuncCoreToolsInstalled(context: IActionContext): Promise<boolean>;
/**
* Starts a new function process and returns the process id of the new process. This is for .NET projects only.
*
* @param {vscode.WorkspaceFolder} workspaceFolder - The workspace folder of the root of the project.
* @param {string} buildPath - The relative path to the project's build output.
* @param {string[]} args - A list of command-line arguments to pass to the process.
*
* @returns {Promise<{ processId: string; success: boolean; error: string }>} -
* - `processId` {string}: The ID of the started process.
* - `success` {boolean}: Whether the process started successfully.
* - `error` {string}: Error message in case the process fails to start, otherwise an empty string.
*/
startFuncProcess(workspaceFolder: vscode.WorkspaceFolder, buildPath: string, args: string[]): Promise<{ processId: string; success: boolean; error: string }>;
}

export type ProjectLanguage = 'JavaScript' | 'TypeScript' | 'C#' | 'Python' | 'PowerShell' | 'Java';
Expand All @@ -82,7 +96,6 @@ interface IStringDictionary {
properties?: { [propertyName: string]: string };
}


/**
* The options to use when creating a function. If an option is not specified, the default will be used or the user will be prompted
*/
Expand All @@ -109,8 +122,6 @@ export interface ICreateFunctionOptions {

languageModel?: number;

jobType?: JobType;

/**
* The version of the project. Defaults to the latest GA version
*/
Expand Down

0 comments on commit 2dc3517

Please sign in to comment.