diff --git a/DotNetWorker.sln b/DotNetWorker.sln index 0fc5bb848..e8aca308b 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -140,6 +140,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.Extensions.Shared.Te EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http.AspNetCore.Analyzers", "extensions\Worker.Extensions.Http.AspNetCore.Analyzers\Worker.Extensions.Http.AspNetCore.Analyzers.csproj", "{7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net7Worker", "samples\Net7Worker\Net7Worker.csproj", "{BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DependentAssemblyWithFunctions.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{198DA072-F94F-4585-A744-97B3DAC21686}" EndProject Global @@ -344,6 +346,10 @@ Global {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}.Debug|Any CPU.Build.0 = Debug|Any CPU {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}.Release|Any CPU.ActiveCfg = Release|Any CPU {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}.Release|Any CPU.Build.0 = Release|Any CPU + {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}.Release|Any CPU.Build.0 = Release|Any CPU {B6342174-5436-4846-B43C-39D8E34AE5CF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6342174-5436-4846-B43C-39D8E34AE5CF}.Debug|Any CPU.Build.0 = Debug|Any CPU {B6342174-5436-4846-B43C-39D8E34AE5CF}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -417,6 +423,7 @@ Global {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} {B6342174-5436-4846-B43C-39D8E34AE5CF} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {198DA072-F94F-4585-A744-97B3DAC21686} = {B5821230-6E0A-4535-88A9-ED31B6F07596} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/sdk/Sdk/ExtensionsCsprojGenerator.cs b/sdk/Sdk/ExtensionsCsprojGenerator.cs index e73f3012e..c11097cb2 100644 --- a/sdk/Sdk/ExtensionsCsprojGenerator.cs +++ b/sdk/Sdk/ExtensionsCsprojGenerator.cs @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Functions.Worker.Sdk { internal class ExtensionsCsprojGenerator { - private const string ExtensionsProjectName = "WorkerExtensions.csproj"; + internal const string ExtensionsProjectName = "WorkerExtensions.csproj"; private readonly IDictionary _extensions; private readonly string _outputPath; @@ -31,9 +31,20 @@ public void Generate() { var extensionsCsprojFilePath = Path.Combine(_outputPath, ExtensionsProjectName); - RecreateDirectory(_outputPath); + string csproj = GetCsProjContent(); + if (File.Exists(extensionsCsprojFilePath)) + { + string existing = File.ReadAllText(extensionsCsprojFilePath); + if (string.Equals(csproj, existing, StringComparison.Ordinal)) + { + // If contents are the same, only touch the file to update timestamp. + File.SetLastWriteTimeUtc(extensionsCsprojFilePath, DateTime.UtcNow); + return; + } + } - WriteExtensionsCsProj(extensionsCsprojFilePath); + RecreateDirectory(_outputPath); + File.WriteAllText(extensionsCsprojFilePath, csproj); } private void RecreateDirectory(string directoryPath) @@ -46,13 +57,6 @@ private void RecreateDirectory(string directoryPath) Directory.CreateDirectory(directoryPath); } - private void WriteExtensionsCsProj(string filePath) - { - string csprojContent = GetCsProjContent(); - - File.WriteAllText(filePath, csprojContent); - } - internal string GetCsProjContent() { string extensionReferences = GetExtensionReferences(); diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index a80cae752..c61be03ff 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -1,8 +1,8 @@  - 16 - 4 + 17 + -preview1 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 7ad914b23..2dd2abd39 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -8,437 +8,215 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and *********************************************************************************************** --> - - - <_ToolingSuffix> - <_AzureFunctionsNotSet Condition="'$(AzureFunctionsVersion)' == ''">true - v3 - <_ToolingSuffix Condition="($(AzureFunctionsVersion.StartsWith('v3',StringComparison.OrdinalIgnoreCase)) Or $(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase))) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v5.0'">net5-isolated - <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v6.0'">net6-isolated - <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v7.0'">net7-isolated - <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v8.0'">net8-isolated - <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETFramework'">netfx-isolated - $(_ToolingSuffix) - <_FunctionsTaskFramework Condition=" '$(MSBuildRuntimeType)' == 'Core'">netstandard2.0 - <_FunctionsTaskFramework Condition=" '$(_FunctionsTaskFramework)' == ''">net472 - <_FunctionsTasksDir Condition=" '$(_FunctionsTasksDir)'=='' ">$(MSBuildThisFileDirectory)..\tools\$(_FunctionsTaskFramework)\ - <_FunctionsTaskAssemblyFullPath Condition=" '$(_FunctionsTaskAssemblyFullPath)'=='' ">$(_FunctionsTasksDir)\Microsoft.Azure.Functions.Worker.Sdk.dll - - <_FunctionsWorkerConfigInputFile>$(MSBuildThisFileDirectory)\..\tools\worker.config.json - - <_FunctionsMetadataLoaderExtensionFile>$(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll - <_FunctionsExtensionsDirectory>.azurefunctions - <_FunctionsExtensionsJsonName>extensions.json - <_FunctionsExtensionsFullPublish Condition="$(NoBuild) == '' And $(_FunctionsExtensionsFullPublish) == ''">True - <_FunctionsExtensionsFullPublish Condition="$(_FunctionsExtensionsFullPublish) == ''">!$(NoBuild) - $(MSBuildExtensionsPath)\Microsoft\VisualStudio\Managed.Functions\ - - false - true - $(FunctionsEnableWorkerIndexing) - $(FunctionsEnableWorkerIndexing) - true - true - true - $(RootNamespace.Replace("-", "_")) - - - - - + + + <_ToolingSuffix> + <_AzureFunctionsNotSet Condition="'$(AzureFunctionsVersion)' == ''">true + v3 + <_ToolingSuffix Condition="($(AzureFunctionsVersion.StartsWith('v3',StringComparison.OrdinalIgnoreCase)) Or $(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase))) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v5.0'">net5-isolated + <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v6.0'">net6-isolated + <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v7.0'">net7-isolated + <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v8.0'">net8-isolated + <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETFramework'">netfx-isolated + $(_ToolingSuffix) + <_FunctionsTaskFramework Condition="'$(MSBuildRuntimeType)' == 'Core'">netstandard2.0 + <_FunctionsTaskFramework Condition="'$(_FunctionsTaskFramework)' == ''">net472 + <_FunctionsTasksDir Condition="'$(_FunctionsTasksDir)'==''">$(MSBuildThisFileDirectory)..\tools\$(_FunctionsTaskFramework)\ + <_FunctionsTaskAssemblyFullPath Condition=" '$(_FunctionsTaskAssemblyFullPath)'=='' ">$(_FunctionsTasksDir)\Microsoft.Azure.Functions.Worker.Sdk.dll + + <_FunctionsExtensionCommonProps>ImportDirectoryBuildProps=false;ImportDirectoryBuildTargets=false;ImportDirectoryPackagesProps=false + <_FunctionsExtensionRemoveProps>TargetFramework;Platform;RuntimeIdentifier;SelfContained;PublishSingleFile;PublishReadyToRun;UseCurrentRuntimeIdentifier;WebPublishMethod;PublishProfile;DeployOnBuild;PublishDir + <_FunctionsWorkerConfigInputFile>$(MSBuildThisFileDirectory)\..\tools\worker.config.json + + <_FunctionsMetadataLoaderExtensionFile>$(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll + <_FunctionsExtensionsDirectory>.azurefunctions + <_FunctionsExtensionsJsonName>extensions.json + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\Managed.Functions\ + + false + true + $(FunctionsEnableWorkerIndexing) + $(FunctionsEnableWorkerIndexing) + + true + true + + <_FunctionsGenerateExtensionProject Condition="'$(DesignTimeBuild)' != 'true'">true + $(RootNamespace.Replace("-", "_")) + + + + + + + + + + + + + + + + + + - + + - + + - - - - - - - - + + - - <_FunctionsWorkerExecutableFileName >$(TargetName)$(TargetExt) - - - - <_FunctionsNativeExecutableExtension Condition="($(RuntimeIdentifier.StartsWith('win')) or $(DefaultAppHostRuntimeIdentifier.StartsWith('win')))">.exe - <_FunctionsWorkerExecutableFileName Condition="'$(PublishAot)' != 'true'">$(TargetName).dll - <_FunctionsWorkerExecutableFileName Condition="'$(PublishAot)' == 'true'">$(TargetName)$(_FunctionsNativeExecutableExtension) + + + + <_FunctionsMetadataPath>$(IntermediateOutputPath)functions.metadata + <_FunctionsWorkerConfigPath>$(IntermediateOutputPath)worker.config.json + $(IntermediateOutputPath)WorkerExtensions + $([System.IO.Path]::GetFullPath($(ExtensionsCsProjDirectory))) + $([System.IO.Path]::Combine($(ExtensionsCsProjDirectory), WorkerExtensions.csproj)) + <_FunctionsIntermediateExtensionJsonPath>$(ExtensionsCsProjDirectory)\buildout\bin\$(_FunctionsExtensionsJsonName) + <_FunctionsIntermediateExtensionUpdatedJsonPath>$(IntermediateOutputPath)$(_FunctionsExtensionsJsonName) - - - - - - $(TargetDir)\worker.config.json - $([System.IO.Path]::Combine($([System.IO.Path]::GetTempPath()), $([System.IO.Path]::GetRandomFileName()))) - - - - - - - - - - - - - - $(TargetDir)\worker.config.json - $([System.IO.Path]::Combine($([System.IO.Path]::GetTempPath()), $([System.IO.Path]::GetRandomFileName()))) - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - <_FilesInTargetDir Include="$(TargetDir)**\*" /> - - - - - - - - - - - - - - - - - $(FunctionsDir) - $(PublishDir)\ - $(PublishDir)bin\$(TargetFileName) - $(FunctionsDir) - - - - - - - - - - - - $(PublishIntermediateOutputPath) - $(PublishDir)\ - $(PublishDir)bin\$(TargetFileName) - $(PublishIntermediateOutputPath) - - - - - <_PublishTempFiles Include="$(PublishIntermediateOutputPath)**\*.*" /> - - - - - - - - - - - - - - + + + + + + - ============================================================ - --> + + + + + + - - _InitializeDeployOnBuildProperties; - Publish; - $(_DotNetPublishFiles); - + <_FunctionsExecutable>dotnet + + + <_FunctionsExecutable Condition="'$(SelfContained)' == 'true' AND '%(Identity)' == '$(AppHostIntermediatePath)'">{WorkerRoot}%(None.Link) + <_FunctionsExecutable Condition="$(TargetFrameworkIdentifier) == '.NETFramework'">{WorkerRoot}$(TargetName)$(TargetExt) - - - - - - $(PublishDir)\worker.config.json - $([System.IO.Path]::Combine($([System.IO.Path]::GetTempPath()), $([System.IO.Path]::GetRandomFileName()))) - - - - - - - - - - - - - $(PublishDir)\worker.config.json - $([System.IO.Path]::Combine($([System.IO.Path]::GetTempPath()), $([System.IO.Path]::GetRandomFileName()))) - - - - - - - + - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - _GenerateFunctionsAndCopyContentFiles; - _WorkerExtensionsRestorePublish; - _WorkerExtensionsFullPublish; - _WorkerExtensionsPublishCopy; - _EnhanceFunctionsExtensionsMetadataPostPublish - - - _GenerateFunctionsAndCopyContentFiles; - _WorkerExtensionsPublishCopyNoBuild - - + + + + + + + + + <_ExtensionBinaries Include="$(ExtensionsCsProjDirectory)\buildout\bin\**" + Exclude="$(ExtensionsCsProjDirectory)\buildout\bin\runtimes\**;$(_FunctionsIntermediateExtensionJsonPath)" + CopyToOutputDirectory="PreserveNewest" + CopyToPublishDirectory="PreserveNewest" /> + <_ExtensionRuntimeBinaries Include="$(ExtensionsCsProjDirectory)\buildout\runtimes\**" + CopyToOutputDirectory="PreserveNewest" + CopyToPublishDirectory="PreserveNewest" /> + + + + + + + + + + + + + + <_NoneWithTargetPath Include="@(_ExtensionFilesWithTargetPath)" TargetPath="$(_FunctionsExtensionsDirectory)/%(_ExtensionFilesWithTargetPath.TargetPath)" /> + + + + + + <_WorkerExtFilesToClean Include="$(ExtensionsCsProjDirectory)\**" Condition="'$(ExtensionsCsProjDirectory)' != ''" /> + <_WorkerExtFilesToClean Include="$(TargetDir)$(_FunctionsExtensionsDirectory)\**" /> + <_WorkerExtFilesToClean Include="$(_FunctionsMetadataPath)" /> + <_WorkerExtFilesToClean Include="$(_FunctionsWorkerConfigPath)" /> + <_WorkerExtFilesToClean Include="$(TargetDir)worker.config.json" /> + <_WorkerExtFilesToClean Include="$(TargetDir)extensions.json" /> + <_WorkerExtFilesToClean Include="$(TargetDir)functions.metadata" /> + <_WorkerExtFilesToClean Include="$(_FunctionsIntermediateExtensionUpdatedJsonPath)" /> + + + + + + - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs b/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs index 8fbaf5c13..c76bb4871 100644 --- a/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs +++ b/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs @@ -34,8 +34,6 @@ public override bool Execute() string newJson = JsonSerializer.Serialize(extensionsMetadata, _serializerOptions); File.WriteAllText(OutputPath, newJson); - File.Delete(ExtensionsJsonPath); - return true; } } diff --git a/sdk/release_notes.md b/sdk/release_notes.md index d61770f66..391d4c80d 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,10 +4,12 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 1.16.4 (meta package) -- Update Microsoft.Azure.Functions.Worker.Sdk.Generators dependency to 1.1.6 +### Microsoft.Azure.Functions.Worker.Sdk 1.17.0-preview1 (meta package) -### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.1.6 - -- Avoid executing source generators outside of an Azure Functions project. (#2119) +- Improve incremental build support for worker extension project inner build (https://github.com/Azure/azure-functions-dotnet-worker/pull/1749) + - Now builds to intermediate output path +- Resolve and pass nuget restore sources as explicit property to inner build (https://github.com/Azure/azure-functions-dotnet-worker/pull/1937) +- Integrate inner build with existing .NET SDK targets (https://github.com/Azure/azure-functions-dotnet-worker/pull/1861) + - Targets have been refactored to participate with `CopyToOutputDirectory` and `CopyToPublishDirectory` instead of manually copying + - Incremental build support further improved diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs index 1c2014785..3af598ce7 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs @@ -1,7 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System; using System.Collections.Generic; +using System.IO; using Microsoft.Azure.Functions.Worker.Sdk; using Xunit; @@ -9,8 +11,48 @@ namespace Microsoft.Azure.Functions.SdkTests { public class ExtensionsCsProjGeneratorTests { - [Fact] - public void GetCsProjContent_Succeeds_functions_v3() + public enum FuncVersion + { + V3, + V4, + } + + [Theory] + [InlineData(FuncVersion.V3)] + [InlineData(FuncVersion.V4)] + public void GetCsProjContent_Succeeds(FuncVersion version) + { + var generator = GetGenerator(version); + string actual = generator.GetCsProjContent().Replace("\r\n", "\n"); + string expected = ExpectedCsproj(version).Replace("\r\n", "\n"); + Assert.Equal(expected, actual); + } + + [Theory] + [InlineData(FuncVersion.V3)] + [InlineData(FuncVersion.V4)] + public void GetCsProjContent_IncrementalSupport(FuncVersion version) + { + DateTime RunGenerate(string subPath, out string contents) + { + var generator = GetGenerator(version, subPath); + generator.Generate(); + + string path = Path.Combine(subPath, ExtensionsCsprojGenerator.ExtensionsProjectName); + contents = File.ReadAllText(path); + var csproj = new FileInfo(Path.Combine(subPath, ExtensionsCsprojGenerator.ExtensionsProjectName)); + return csproj.LastWriteTimeUtc; + } + + string subPath = Guid.NewGuid().ToString(); + DateTime firstRun = RunGenerate(subPath, out string first); + DateTime secondRun = RunGenerate(subPath, out string second); + + Assert.NotEqual(firstRun, secondRun); + Assert.Equal(first, second); + } + + static ExtensionsCsprojGenerator GetGenerator(FuncVersion version, string subPath = "") { IDictionary extensions = new Dictionary { @@ -19,13 +61,22 @@ public void GetCsProjContent_Succeeds_functions_v3() { "Microsoft.Azure.WebJobs.Extensions", "2.0.0" }, }; - var generator = new ExtensionsCsprojGenerator(extensions, "", "v3", Constants.NetCoreApp, Constants.NetCoreVersion31); - - string actualCsproj = generator.GetCsProjContent().Replace("\r\n", "\n"); - - Assert.Equal(ExpectedCsProjV3(), actualCsproj); + return version switch + { + FuncVersion.V3 => new ExtensionsCsprojGenerator(extensions, subPath, "v3", Constants.NetCoreApp, Constants.NetCoreVersion31), + FuncVersion.V4 => new ExtensionsCsprojGenerator(extensions, subPath, "v4", Constants.NetCoreApp, Constants.NetCoreVersion6), + _ => throw new ArgumentOutOfRangeException(nameof(version)), + }; } + private static string ExpectedCsproj(FuncVersion version) + => version switch + { + FuncVersion.V3 => ExpectedCsProjV3(), + FuncVersion.V4 => ExpectedCsProjV4(), + _ => throw new ArgumentOutOfRangeException(nameof(version)), + }; + private static string ExpectedCsProjV3() { return @" @@ -52,27 +103,10 @@ private static string ExpectedCsProjV3() "; - } - - [Fact] - public void GetCsProjContent_Succeeds_functions_v4() - { - IDictionary extensions = new Dictionary - { - { "Microsoft.Azure.WebJobs.Extensions.Storage", "4.0.3" }, - { "Microsoft.Azure.WebJobs.Extensions.Http", "3.0.0" }, - { "Microsoft.Azure.WebJobs.Extensions", "2.0.0" }, - }; - - var generator = new ExtensionsCsprojGenerator(extensions, "", "v4", Constants.NetCoreApp, Constants.NetCoreVersion6); - - string actualCsproj = generator.GetCsProjContent().Replace("\r\n", "\n"); - - Assert.Equal(ExpectedCsProjV4(), actualCsproj); - } - - private static string ExpectedCsProjV4() - { + } + + private static string ExpectedCsProjV4() + { return @" @@ -96,7 +130,7 @@ private static string ExpectedCsProjV4() -"; - } +"; + } } }