import { HttpOperationResponse } from '@azure/ms-rest-js' ; import * as semver from 'semver' ; import * as vscode from 'vscode' ; import { callWithTelemetryAndErrorHandling , DialogResponses , IActionContext , parseError } from 'vscode-azureextensionui' ; import { PackageManager } from '../constants' ; import { FuncVersion , tryParseFuncVersion } from '../FuncVersion' ; import { localize } from '../localize' ; import { nonNullProp } from '../utils/nonNull' ; import { openUrl } from '../utils/openUrl' ; import { requestUtils } from '../utils/requestUtils' ; import { getWorkspaceSetting , updateGlobalSetting } from '../vsCodeConfig/settings' ; import { getBrewPackageName } from './getBrewPackageName' ; import { validateNoFuncCliSetting } from './getFuncCliPath' ; import { getFuncPackageManagers } from './getFuncPackageManagers' ; import { getLocalFuncCoreToolsVersion } from './getLocalFuncCoreToolsVersion' ; import { getNpmDistTag } from "./getNpmDistTag" ; import { uninstallFuncCoreTools } from './uninstallFuncCoreTools' ; import { updateFuncCoreTools } from './updateFuncCoreTools' ; export async function validateFuncCoreToolsIsLatest ( ) { await callWithTelemetryAndErrorHandling ( 'azureFunctions.validateFuncCoreToolsIsLatest' , async ( context ) => { context . errorHandling . suppressDisplay = true ; context . telemetry . properties . isActivationEvent = 'true' ; const showMultiCoreToolsWarningKey = 'showMultiCoreToolsWarning' ; const showMultiCoreToolsWarning = ! ! getWorkspaceSetting < boolean > ( showMultiCoreToolsWarningKey ) ; const showCoreToolsWarningKey = 'showCoreToolsWarning' ; const showCoreToolsWarning = ! ! getWorkspaceSetting < boolean > ( showCoreToolsWarningKey ) ; if ( showCoreToolsWarning || showMultiCoreToolsWarning ) { validateNoFuncCliSetting ( ) ; const packageManagers = await getFuncPackageManagers ( true ) ; let packageManager ; if ( packageManagers . length === 0 ) { return ; } else if ( packageManagers . length === 1 ) { packageManager = packageManagers [ 0 ] ; context . telemetry . properties . packageManager = packageManager ; } else { context . telemetry . properties . multiFunc = 'true' ; if ( showMultiCoreToolsWarning ) { const message = localize ( 'multipleInstalls' , 'Detected multiple installs of the func cli.' ) ; const selectUninstall = { title : localize ( 'selectUninstall' , 'Select version to uninstall' ) } ; const result = await context . ui . showWarningMessage ( message , selectUninstall , DialogResponses . dontWarnAgain ) ; if ( result === selectUninstall ) { await uninstallFuncCoreTools ( context , packageManagers ) ; } else if ( result === DialogResponses . dontWarnAgain ) { await updateGlobalSetting ( showMultiCoreToolsWarningKey , false ) ; } } return ; } if ( showCoreToolsWarning ) { const localVersion = await getLocalFuncCoreToolsVersion ( context , undefined ) ; if ( ! localVersion ) { return ; } context . telemetry . properties . localVersion = localVersion ; const versionFromSetting = tryParseFuncVersion ( localVersion ) ; if ( versionFromSetting === undefined ) { return ; } const newestVersion = await getNewestFunctionRuntimeVersion ( packageManager , versionFromSetting , context ) ; if ( ! newestVersion ) { return ; } if ( semver . major ( newestVersion ) === semver . major ( localVersion ) && semver . gt ( newestVersion , localVersion ) ) { context . telemetry . properties . outOfDateFunc = 'true' ; const message = localize ( 'outdatedFunctionRuntime' , 'Update your Azure Functions Core Tools ({0}) to the latest ({1}) for the best experience.' , localVersion , newestVersion ) ; const update = { title : 'Update' } ; let result ; do { result = packageManager !== undefined ? await context . ui . showWarningMessage ( message , update , DialogResponses . learnMore , DialogResponses . dontWarnAgain ) : await context . ui . showWarningMessage ( message , DialogResponses . learnMore , DialogResponses . dontWarnAgain ) ; if ( result === DialogResponses . learnMore ) { await openUrl ( 'https://aka.ms/azFuncOutdated' ) ; } else if ( result === update ) { await updateFuncCoreTools ( context , packageManager , versionFromSetting ) ; } else if ( result === DialogResponses . dontWarnAgain ) { await updateGlobalSetting ( showCoreToolsWarningKey , false ) ; } } while ( result === DialogResponses . learnMore ) ; } } } } ) ; } async function getNewestFunctionRuntimeVersion ( packageManager , versionFromSetting , context ) { try { if ( packageManager === PackageManager . brew ) { const packageName = getBrewPackageName ( versionFromSetting ) ; const url = `https://raw.githubusercontent.com/Azure/homebrew-functions/master/Formula/${ packageName }.rb` ; const response = await requestUtils . sendRequestWithExtTimeout ( context , { method : 'GET' , url } ) ; const brewInfo = nonNullProp ( response , 'bodyAsText' ) ; const matches = brewInfo . match ( /version\s+["']([^"']+)["']/i ) ; if ( matches && matches . length > 1 ) { return matches [ 1 ] ; } } else { return ( await getNpmDistTag ( context , versionFromSetting ) ) . value ; } } catch ( error ) { context . telemetry . properties . latestRuntimeError = parseError ( error ) . message ; } return undefined ; }