azure-functions-powershell-.../tools/helper.psm1

302 строки
10 KiB
PowerShell

#
# Copyright (c) Microsoft. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for full license information.
#
using namespace System.Runtime.InteropServices
$IsWindowsEnv = [RuntimeInformation]::IsOSPlatform([OSPlatform]::Windows)
$RepoRoot = (Resolve-Path "$PSScriptRoot/..").Path
$DotnetSDKVersionRequirements = @{
# .NET SDK 3.1 is required by the Microsoft.ManifestTool.dll tool
'3.1' = @{
MinimalPatch = '426'
DefaultPatch = '426'
}
'8.0' = @{
MinimalPatch = '100-preview.7.23376.3'
DefaultPatch = '100-preview.7.23376.3'
}
}
$GrpcToolsVersion = '2.50.0' # grpc.tools
$GoogleProtobufToolsVersion = '3.21.9' # google.protobuf.tools
function Find-Dotnet
{
$listSdksOutput = dotnet --list-sdks
$installedDotnetSdks = $listSdksOutput | ForEach-Object { $_.Split(" ")[0] }
Write-Log "Detected dotnet SDKs: $($installedDotnetSdks -join ', ')"
foreach ($majorMinorVersion in $DotnetSDKVersionRequirements.Keys) {
$minimalVersion = "$majorMinorVersion.$($DotnetSDKVersionRequirements[$majorMinorVersion].MinimalPatch)"
$firstAcceptable = $installedDotnetSdks |
Where-Object { $_.StartsWith("$majorMinorVersion.") } |
Where-Object { [System.Management.Automation.SemanticVersion]::new($_) -ge [System.Management.Automation.SemanticVersion]::new($minimalVersion) } |
Select-Object -First 1
if (-not $firstAcceptable) {
throw "Cannot find the dotnet SDK for .NET Core $majorMinorVersion. Version $minimalVersion or higher is required. Please specify '-Bootstrap' to install build dependencies."
}
}
}
function Install-Dotnet {
[CmdletBinding()]
param(
[string]$Channel = 'release'
)
try {
Find-Dotnet
return # Simply return if we find dotnet SDk with the correct version
} catch { }
$obtainUrl = "https://raw.githubusercontent.com/dotnet/install-scripts/main/src"
try {
$installScript = if ($IsWindowsEnv) { "dotnet-install.ps1" } else { "dotnet-install.sh" }
Invoke-WebRequest -Uri $obtainUrl/$installScript -OutFile $installScript
foreach ($majorMinorVersion in $DotnetSDKVersionRequirements.Keys) {
$version = "$majorMinorVersion.$($DotnetSDKVersionRequirements[$majorMinorVersion].DefaultPatch)"
Write-Log "Installing dotnet SDK version $version" -Warning
if ($IsWindowsEnv) {
& .\$installScript -Channel $Channel -Version $Version -InstallDir "$env:ProgramFiles/dotnet"
} else {
bash ./$installScript -c $Channel -v $Version --install-dir /usr/share/dotnet
}
}
}
finally {
Remove-Item $installScript -Force -ErrorAction SilentlyContinue
}
}
function New-gRPCAutoGenCode
{
[CmdletBinding()]
param(
[switch] $Force
)
if ($Force -or -not (Test-Path "$RepoRoot/src/Messaging/protobuf/FunctionRpc.cs") -or
-not (Test-Path "$RepoRoot/src/Messaging/protobuf/FunctionRpcGrpc.cs"))
{
Write-Log "Generate the CSharp code for gRPC communication from protobuf"
Resolve-ProtoBufToolPath
$outputDir = "$RepoRoot/src/Messaging/protobuf"
Remove-Item $outputDir -Recurse -Force -ErrorAction SilentlyContinue
New-Item $outputDir -ItemType Directory -Force -ErrorAction Stop > $null
$allProtoFiles = Get-ChildItem -Path $Script:protobuf_dir_Path -Filter "*.proto" -Recurse
$fileList = $allProtoFiles.FullName
& $Script:protoc_Path $fileList `
--csharp_out $outputDir `
--grpc_out=$outputDir `
--plugin=protoc-gen-grpc=$Script:grpc_csharp_plugin_Path `
--proto_path=$Script:protobuf_dir_Path `
--proto_path=$Script:google_protobuf_tools_Path
if ($LASTEXITCODE -ne 0) {
throw "Failed to generate the CSharp code for gRPC communication."
}
}
}
function Resolve-ProtoBufToolPath
{
if (-not $Script:protoc_Path) {
Write-Log "Resolve the protobuf tools for auto-generating code"
$nugetPath = Get-NugetPackagesPath
$toolsPath = "$RepoRoot/tools"
if (-not (Test-Path "$toolsPath/obj/project.assets.json") -or
-not (Test-Path "$nugetPath/grpc.tools/$GrpcToolsVersion")) {
dotnet restore $toolsPath --verbosity quiet
if ($LASTEXITCODE -ne 0) {
throw "Cannot resolve protobuf tools. 'dotnet restore $toolsPath' failed."
}
}
if ($IsWindowsEnv) {
$plat_arch_Name = "windows_x64"
$protoc_Name = "protoc.exe"
$grpc_csharp_plugin_Name = "grpc_csharp_plugin.exe"
} else {
$plat_arch_Name = if ($IsLinux) { "linux_x64" } else { "macosx_x64" }
$protoc_Name = "protoc"
$grpc_csharp_plugin_Name = "grpc_csharp_plugin"
}
$Script:protoc_Path =
Resolve-Path "$nugetPath/grpc.tools/$GrpcToolsVersion/tools/$plat_arch_Name/$protoc_Name" |
ForEach-Object Path
if (-not $Script:protoc_Path) {
throw "Couldn't find the executable 'protoc'. Check if the package 'grpc.tools' has been restored."
}
$Script:grpc_csharp_plugin_Path =
Resolve-Path "$nugetPath/grpc.tools/$GrpcToolsVersion/tools/$plat_arch_Name/$grpc_csharp_plugin_Name" |
ForEach-Object Path
if (-not $Script:grpc_csharp_plugin_Path) {
throw "Couldn't find the executable 'grpc_csharp_plugin'. Check if the package 'grpc.tools' has been restored."
}
$Script:google_protobuf_tools_Path =
Resolve-Path "$nugetPath/google.protobuf.tools/$GoogleProtobufToolsVersion/tools" |
ForEach-Object Path
if (-not $Script:google_protobuf_tools_Path) {
throw "Couldn't find the protobuf tools. Check if the package 'google.protobuf.tools' has been restored."
}
$Script:protobuf_dir_Path = "$RepoRoot/protobuf/src/proto"
}
}
function Write-Log
{
param(
[string] $Message,
[switch] $Warning,
[switch] $Indent
)
$foregroundColor = if ($Warning) { "Yellow" } else { "Green" }
$indentPrefix = if ($Indent) { " " } else { "" }
Write-Host -ForegroundColor $foregroundColor "${indentPrefix}${Message}"
}
function Get-NugetPackagesPath
{
if ($env:NUGET_PACKAGES)
{
return $env:NUGET_PACKAGES
}
if ($IsWindowsEnv)
{
return "${env:USERPROFILE}\.nuget\packages"
}
else
{
return "${env:HOME}/.nuget/packages"
}
}
#region Start-ResGen
$generated_code_template = @'
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a running 'Start-ResGen' from tools\helper.psm1.
// To add or remove a member, edit your .resx file then rerun 'Start-ResGen'.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
internal class {0} {{
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {{
get {{
if (object.ReferenceEquals(resourceMan, null)) {{
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.Azure.Functions.PowerShellWorker.resources.{0}", typeof({0}).Assembly);
resourceMan = temp;
}}
return resourceMan;
}}
}}
/// <summary>
/// Overrides the current threads CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {{
get {{ return resourceCulture; }}
set {{ resourceCulture = value; }}
}}
{1}
}}
'@
$individual_resource_string_proprety = @'
/// <summary>
/// Looks up a localized string similar to
/// {0}
/// </summary>
internal static string {1} {{
get {{
return ResourceManager.GetString("{1}", resourceCulture);
}}
}}
'@
function Start-ResGen
{
param([switch] $Force)
$sourceDir = (Resolve-Path -Path "$PSScriptRoot/../src").Path
$genDir = Join-Path -Path $sourceDir -ChildPath gen
if (Test-Path -Path $genDir -PathType Container) {
if ($Force) {
Remove-Item -Path $genDir -Recurse -Force
} else {
return
}
}
$resourceDir = Join-Path -Path $sourceDir -ChildPath resources
$resxFiles = Get-ChildItem -Path $resourceDir -Filter *.resx
$null = New-Item -Path $genDir -ItemType Directory -Force
foreach ($resx in $resxFiles) {
$typeName = [System.IO.Path]::GetFileNameWithoutExtension($resx.FullName)
$resXml = [xml] (Get-Content $resx.FullName)
$properties = [System.Text.StringBuilder]::new()
foreach ($data in $resXml.root.data) {
$name = $data.name
$value = $data.value -replace "`n","\n"
$property = $individual_resource_string_proprety -f $value, $name
$null = $properties.Append($property)
}
$typeCode = $generated_code_template -f $typeName, $properties.ToString()
$typeFile = Join-Path -Path $genDir "$typeName.cs"
Set-Content -Path $typeFile -Value $typeCode
}
}
#endregion Start-ResGen