From 5d5513b107284e25d0fabc88cae7dc10ca9f6911 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 11 Nov 2024 14:27:07 -0800 Subject: [PATCH 001/190] Address warnings in sample projects (#2849) --- samples/Configuration/HttpFunction.cs | 8 ++++---- .../ExceptionHandlingMiddleware.cs | 2 +- samples/CustomMiddleware/HttpFunction.cs | 2 +- .../HttpTriggerWithMultipleOutputBindings.cs | 4 ++-- samples/CustomMiddleware/MyCustomMiddleware.cs | 2 +- samples/Extensions/Blob/Book.cs | 7 ++++--- samples/Extensions/CosmosDB/CosmosDBFunction.cs | 6 +++--- .../CosmosDB/CosmosInputBindingFunctions.cs | 8 ++++---- samples/Extensions/EventGrid/EventGridFunction.cs | 15 ++++++--------- samples/Extensions/MultiOutput/MultiOutput.cs | 2 +- samples/Extensions/Queue/QueueFunction.cs | 8 ++++---- samples/Extensions/SignalR/SignalRFunction.cs | 8 ++++---- samples/Extensions/Table/TableFunction.cs | 6 +++--- samples/Extensions/Timer/TimerFunction.cs | 2 +- 14 files changed, 39 insertions(+), 41 deletions(-) diff --git a/samples/Configuration/HttpFunction.cs b/samples/Configuration/HttpFunction.cs index 5129cee25..4e3d8424f 100644 --- a/samples/Configuration/HttpFunction.cs +++ b/samples/Configuration/HttpFunction.cs @@ -25,15 +25,15 @@ public static MyType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post public class MyType { - public string camelCasePropertyName { get; set; } - public string PascalCasePropertyName { get; set; } - public string NullValue { get; set; } + public string? camelCasePropertyName { get; set; } + public string? PascalCasePropertyName { get; set; } + public string? NullValue { get; set; } // This sample can use both System.Text.Json and Newtonsoft.Json, depending on which // is registered. Including both attributes here. [JsonPropertyName("Changed_Via_System_Text_Json")] [JsonProperty("Changed_Via_Newtonsoft_Json")] - public string DifferentSerializedName { get; set; } + public string? DifferentSerializedName { get; set; } } } } diff --git a/samples/CustomMiddleware/ExceptionHandlingMiddleware.cs b/samples/CustomMiddleware/ExceptionHandlingMiddleware.cs index 003c78905..d16a96191 100644 --- a/samples/CustomMiddleware/ExceptionHandlingMiddleware.cs +++ b/samples/CustomMiddleware/ExceptionHandlingMiddleware.cs @@ -60,7 +60,7 @@ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next } } - private OutputBindingData GetHttpOutputBindingFromMultipleOutputBinding(FunctionContext context) + private static OutputBindingData? GetHttpOutputBindingFromMultipleOutputBinding(FunctionContext context) { // The output binding entry name will be "$return" only when the function return type is HttpResponseData var httpOutputBinding = context.GetOutputBindings() diff --git a/samples/CustomMiddleware/HttpFunction.cs b/samples/CustomMiddleware/HttpFunction.cs index ed7f19949..5d1c9a363 100644 --- a/samples/CustomMiddleware/HttpFunction.cs +++ b/samples/CustomMiddleware/HttpFunction.cs @@ -23,7 +23,7 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g var logger = context.GetLogger(); // Get the item set by the middleware - if (context.Items.TryGetValue("middlewareitem", out object value) && value is string message) + if (context.Items.TryGetValue("middlewareitem", out object? value) && value is string message) { logger.LogInformation("From middleware: {message}", message); } diff --git a/samples/CustomMiddleware/HttpTriggerWithMultipleOutputBindings.cs b/samples/CustomMiddleware/HttpTriggerWithMultipleOutputBindings.cs index ea2e8e4ec..9645d38af 100644 --- a/samples/CustomMiddleware/HttpTriggerWithMultipleOutputBindings.cs +++ b/samples/CustomMiddleware/HttpTriggerWithMultipleOutputBindings.cs @@ -32,8 +32,8 @@ public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get") public class MyOutputType { [QueueOutput("functionstesting2", Connection = "AzureWebJobsStorage")] - public string Name { get; set; } + public string? Name { get; set; } - public HttpResponseData HttpResponse { get; set; } + public HttpResponseData? HttpResponse { get; set; } } } diff --git a/samples/CustomMiddleware/MyCustomMiddleware.cs b/samples/CustomMiddleware/MyCustomMiddleware.cs index 48c61a5bc..ffc5c58e1 100644 --- a/samples/CustomMiddleware/MyCustomMiddleware.cs +++ b/samples/CustomMiddleware/MyCustomMiddleware.cs @@ -20,7 +20,7 @@ public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next // This happens after function execution. We can inspect the context after the function // was invoked - if (context.Items.TryGetValue("functionitem", out object value) && value is string message) + if (context.Items.TryGetValue("functionitem", out object? value) && value is string message) { ILogger logger = context.GetLogger(); diff --git a/samples/Extensions/Blob/Book.cs b/samples/Extensions/Blob/Book.cs index 824e88336..383645748 100644 --- a/samples/Extensions/Blob/Book.cs +++ b/samples/Extensions/Blob/Book.cs @@ -5,7 +5,8 @@ namespace SampleApp { public class Book { - public string Id { get; set; } - public string Name { get; set; } + public string? Id { get; set; } + + public string? Name { get; set; } } -} \ No newline at end of file +} diff --git a/samples/Extensions/CosmosDB/CosmosDBFunction.cs b/samples/Extensions/CosmosDB/CosmosDBFunction.cs index d2b044aa2..17a2ec7e0 100644 --- a/samples/Extensions/CosmosDB/CosmosDBFunction.cs +++ b/samples/Extensions/CosmosDB/CosmosDBFunction.cs @@ -21,7 +21,7 @@ public CosmosDBFunction(ILogger logger) [Function(nameof(CosmosDBFunction))] [ExponentialBackoffRetry(5, "00:00:04", "00:15:00")] [CosmosDBOutput("%CosmosDb%", "%CosmosContainerOut%", Connection = "CosmosDBConnection", CreateIfNotExists = true)] - public object Run( + public object? Run( [CosmosDBTrigger( "%CosmosDb%", "%CosmosContainerIn%", @@ -48,9 +48,9 @@ public object Run( public class MyDocument { - public string Id { get; set; } + public string? Id { get; set; } - public string Text { get; set; } + public string? Text { get; set; } public int Number { get; set; } diff --git a/samples/Extensions/CosmosDB/CosmosInputBindingFunctions.cs b/samples/Extensions/CosmosDB/CosmosInputBindingFunctions.cs index 41d0317a4..62955cd8a 100644 --- a/samples/Extensions/CosmosDB/CosmosInputBindingFunctions.cs +++ b/samples/Extensions/CosmosDB/CosmosInputBindingFunctions.cs @@ -265,15 +265,15 @@ public void DocByIdFromJSON( public class ToDoItem { - public string Id { get; set; } - public string Description { get; set; } + public string? Id { get; set; } + public string? Description { get; set; } } public class ToDoItemLookup { - public string ToDoItemId { get; set; } + public string? ToDoItemId { get; set; } - public string ToDoItemPartitionKeyValue { get; set; } + public string? ToDoItemPartitionKeyValue { get; set; } } } } diff --git a/samples/Extensions/EventGrid/EventGridFunction.cs b/samples/Extensions/EventGrid/EventGridFunction.cs index aa1b6e004..18b1342ba 100644 --- a/samples/Extensions/EventGrid/EventGridFunction.cs +++ b/samples/Extensions/EventGrid/EventGridFunction.cs @@ -1,8 +1,6 @@ // 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 Microsoft.Azure.Functions.Worker; using Microsoft.Extensions.Logging; @@ -15,8 +13,7 @@ public static class EventGridFunction public static MyEventType Run([EventGridTrigger] MyEventType input, FunctionContext context) { var logger = context.GetLogger(nameof(EventGridFunction)); - - logger.LogInformation(input.Data.ToString()); + logger.LogInformation(input.Data?.ToString()); var outputEvent = new MyEventType() { @@ -34,16 +31,16 @@ public static MyEventType Run([EventGridTrigger] MyEventType input, FunctionCont public class MyEventType { - public string Id { get; set; } + public string? Id { get; set; } - public string Topic { get; set; } + public string? Topic { get; set; } - public string Subject { get; set; } + public string? Subject { get; set; } - public string EventType { get; set; } + public string? EventType { get; set; } public DateTime EventTime { get; set; } - public IDictionary Data { get; set; } + public IDictionary? Data { get; set; } } } diff --git a/samples/Extensions/MultiOutput/MultiOutput.cs b/samples/Extensions/MultiOutput/MultiOutput.cs index 025ec85ab..e56700a48 100644 --- a/samples/Extensions/MultiOutput/MultiOutput.cs +++ b/samples/Extensions/MultiOutput/MultiOutput.cs @@ -38,7 +38,7 @@ public class MyOutputType [QueueOutput("myQueue")] public string? Name { get; set; } - public HttpResponseData HttpResponse { get; set; } + public HttpResponseData? HttpResponse { get; set; } } // } diff --git a/samples/Extensions/Queue/QueueFunction.cs b/samples/Extensions/Queue/QueueFunction.cs index b9f821c58..cfa26b8b7 100644 --- a/samples/Extensions/Queue/QueueFunction.cs +++ b/samples/Extensions/Queue/QueueFunction.cs @@ -28,7 +28,7 @@ public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionCon // Use a string array to return more than one message. string[] messages = { $"Album name = {myQueueItem.Name}", - $"Album songs = {myQueueItem.Songs.ToString()}"}; + $"Album songs = {myQueueItem.Songs}"}; _logger.LogInformation("{msg1},{msg2}", messages[0], messages[1]); @@ -58,10 +58,10 @@ public void QueueBinaryDataFunction([QueueTrigger("input-queue")] BinaryData mes public class Album { - public string Id { get; set; } + public string? Id { get; set; } - public string Name { get; set; } + public string? Name { get; set; } - public List Songs { get; set; } + public List? Songs { get; set; } } } diff --git a/samples/Extensions/SignalR/SignalRFunction.cs b/samples/Extensions/SignalR/SignalRFunction.cs index b567e7928..ace3ea3e6 100644 --- a/samples/Extensions/SignalR/SignalRFunction.cs +++ b/samples/Extensions/SignalR/SignalRFunction.cs @@ -33,15 +33,15 @@ public static class SignalRFunction public class MyConnectionInfo { - public string Url { get; set; } + public string? Url { get; set; } - public string AccessToken { get; set; } + public string? AccessToken { get; set; } } public class MyMessage { - public string Target { get; set; } + public string? Target { get; set; } - public object[] Arguments { get; set; } + public object[]? Arguments { get; set; } } } diff --git a/samples/Extensions/Table/TableFunction.cs b/samples/Extensions/Table/TableFunction.cs index 95894ed68..9936538ef 100644 --- a/samples/Extensions/Table/TableFunction.cs +++ b/samples/Extensions/Table/TableFunction.cs @@ -102,10 +102,10 @@ public void TablePocoFunction( public class MyTableData { - public string PartitionKey { get; set; } + public string? PartitionKey { get; set; } - public string RowKey { get; set; } + public string? RowKey { get; set; } - public string Text { get; set; } + public string? Text { get; set; } } } diff --git a/samples/Extensions/Timer/TimerFunction.cs b/samples/Extensions/Timer/TimerFunction.cs index e94913097..1b0d405ca 100644 --- a/samples/Extensions/Timer/TimerFunction.cs +++ b/samples/Extensions/Timer/TimerFunction.cs @@ -15,7 +15,7 @@ public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo, FunctionContext context) { var logger = context.GetLogger(nameof(TimerFunction)); - logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus.Next}"); + logger.LogInformation($"Function Ran. Next timer schedule = {timerInfo.ScheduleStatus?.Next}"); } // } From 47d1a39b73a2acf0a32f8afda84f8984bcaa542b Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 11 Nov 2024 14:27:17 -0800 Subject: [PATCH 002/190] Switch durable for storage in test project (#2848) --- .../FunctionApp01/FunctionApp01.csproj | 5 +--- .../FunctionExt01/FunctionExt01.csproj | 23 +++++++++++++++++++ test/SdkE2ETests/InnerBuildTests.cs | 18 +++++++-------- 3 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 test/Resources/Projects/FunctionExt01/FunctionExt01.csproj diff --git a/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj b/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj index 48b614c1b..06a9e64f8 100644 --- a/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj +++ b/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj @@ -12,15 +12,12 @@ - - - - + diff --git a/test/Resources/Projects/FunctionExt01/FunctionExt01.csproj b/test/Resources/Projects/FunctionExt01/FunctionExt01.csproj new file mode 100644 index 000000000..904b22ce1 --- /dev/null +++ b/test/Resources/Projects/FunctionExt01/FunctionExt01.csproj @@ -0,0 +1,23 @@ + + + + net8.0 + enable + enable + + + + + + + + + + <_Parameter1>Microsoft.Azure.WebJobs.Extensions.Storage + <_Parameter2>5.3.1 + <_Parameter3>true + <_Parameter3_IsLiteral>true + + + + diff --git a/test/SdkE2ETests/InnerBuildTests.cs b/test/SdkE2ETests/InnerBuildTests.cs index 01df7d661..1f993bd24 100644 --- a/test/SdkE2ETests/InnerBuildTests.cs +++ b/test/SdkE2ETests/InnerBuildTests.cs @@ -34,19 +34,19 @@ public async Task Build_ScansReferences() JToken expectedExtensionsJson = JObject.Parse(@"{ ""extensions"": [ { - ""name"": ""SqlDurabilityProvider"", - ""typeName"": ""DurableTask.SqlServer.AzureFunctions.SqlDurabilityProviderStartup, DurableTask.SqlServer.AzureFunctions, Version=1.4.0.0, Culture=neutral, PublicKeyToken=2ea3c3a96309d850"", - ""hintPath"": ""./.azurefunctions/DurableTask.SqlServer.AzureFunctions.dll"" + ""name"": ""Startup"", + ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"", + ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"" }, { - ""name"": ""DurableTask"", - ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.DurableTask.DurableTaskWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.DurableTask, Version=2.0.0.0, Culture=neutral, PublicKeyToken=014045d636e89289"", - ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.DurableTask.dll"" + ""name"": ""AzureStorageBlobs"", + ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageBlobsWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage.Blobs, Version=5.3.1.0, Culture=neutral, PublicKeyToken=92742159e12e44c8"", + ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.Storage.Blobs.dll"" }, { - ""name"": ""Startup"", - ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"", - ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"" + ""name"": ""AzureStorageQueues"", + ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageQueuesWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage.Queues, Version=5.1.3.0, Culture=neutral, PublicKeyToken=92742159e12e44c8"", + ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.Storage.Queues.dll"" } ] }"); From 8e01d91fa8116b80717a206c7e8904ac8a89f42d Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 11 Nov 2024 14:30:59 -0800 Subject: [PATCH 003/190] update otel release_notes.md (#2845) --- src/DotNetWorker.OpenTelemetry/release_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/DotNetWorker.OpenTelemetry/release_notes.md b/src/DotNetWorker.OpenTelemetry/release_notes.md index 036d666c5..7caeb6d1c 100644 --- a/src/DotNetWorker.OpenTelemetry/release_notes.md +++ b/src/DotNetWorker.OpenTelemetry/release_notes.md @@ -1,5 +1,5 @@ ## What's Changed -### Microsoft.Azure.Functions.Worker.OpenTelemetry 1.0.0 (Preview) +### Microsoft.Azure.Functions.Worker.OpenTelemetry 1.0.0 (Preview 2) -- Initial preview release \ No newline at end of file +- `UseFunctionsWorkerDefaults` signature now uses `OpenTelemetryBuilder` (from `IOpenTelemetryBuilder`) (#2839) From 2a5812598b7d46b969c372b1237ed4cc343bd4e4 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Mon, 15 Jul 2024 17:52:54 -0700 Subject: [PATCH 004/190] Setting _ToolingSuffix for TargetFrameworkVersion v9.0 (#2597) * Setting _ToolingSuffix for V9.0 TargetFrameworkVersion (#2499) Setting `_ToolingSuffix` value to net9-isolated when the Targetframework of the function app is `net9.0`. * feature branch release notes --- sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 1 + sdk/release_notes.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index a5389f5c7..b61ae0c13 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -19,6 +19,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and <_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)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v9.0'">net9-isolated <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETFramework'">netfx-isolated $(_ToolingSuffix) <_FunctionsTaskFramework Condition="'$(MSBuildRuntimeType)' == 'Core'">netstandard2.0 diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 67afe6f17..7b7753438 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -7,6 +7,8 @@ ### Microsoft.Azure.Functions.Worker.Sdk - Changed exception handling in function invocation path to ensure fatal exceptions bubble up. +- Updated `Microsoft.Azure.Functions.Worker.Sdk.Generators` reference to 1.3.4. +- Setting _ToolingSuffix for TargetFrameworkVersion v9.0 ### Microsoft.Azure.Functions.Worker.Sdk.Generators From 0453216f7a923bd32465bc0c899b87bbb6329f4e Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Fri, 16 Aug 2024 12:41:12 -0700 Subject: [PATCH 005/190] Adding net9.0 TFM (#2615) * Adding net9.0 TFM Update build YAML to install net9 pin to preview6 in global.json * Bump SDK package version * Adding Net9 sample app. * Updating the below packages to use 9x version for net9.0 tfm - Microsoft.Extensions.Hosting - Microsoft.Extensions.Hosting.Abstractions - System.Collections.Immutable - System.Diagnostics.DiagnosticSource * Move condition to ItemGroup element instead of Choose-When pattern. * Updated ApplicationInsights package version in Sample app to latest stable (1.3.0) --- DotNetWorker.sln | 12 ++++---- global.json | 5 ++-- samples/Net9FunctionApp/HelloHttp.cs | 17 +++++++++++ .../Net9FunctionApp/Net9FunctionApp.csproj | 29 +++++++++++++++++++ samples/Net9FunctionApp/NuGet.Config | 7 +++++ samples/Net9FunctionApp/Program.cs | 14 +++++++++ samples/Net9FunctionApp/host.json | 12 ++++++++ sdk/Sdk/Sdk.csproj | 1 + .../DotNetWorker.Core.csproj | 12 +++++++- .../DotNetWorker.Grpc.csproj | 12 ++++++-- src/DotNetWorker/DotNetWorker.csproj | 10 ++++++- 11 files changed, 119 insertions(+), 12 deletions(-) create mode 100644 samples/Net9FunctionApp/HelloHttp.cs create mode 100644 samples/Net9FunctionApp/Net9FunctionApp.csproj create mode 100644 samples/Net9FunctionApp/NuGet.Config create mode 100644 samples/Net9FunctionApp/Program.cs create mode 100644 samples/Net9FunctionApp/host.json diff --git a/DotNetWorker.sln b/DotNetWorker.sln index f9615a07d..8223a5cc1 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -148,7 +148,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Timer.Tests", "test\extensions\Worker.Extensions.Timer.Tests\Worker.Extensions.Timer.Tests.csproj", "{6947034E-C97F-4F78-940F-B6A398E23C9C}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.Extensions.Http.AspNetCore.Analyzers", "extensions\Worker.Extensions.Http.AspNetCore.Analyzers\src\Worker.Extensions.Http.AspNetCore.Analyzers.csproj", "{63C70590-7F4A-4D54-9157-7FEDE0F8650D}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net9FunctionApp", "samples\Net9FunctionApp\Net9FunctionApp.csproj", "{F7F70331-CB38-47D7-9366-F8C5D934D088}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -376,10 +376,10 @@ Global {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.Build.0 = Release|Any CPU - {63C70590-7F4A-4D54-9157-7FEDE0F8650D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {63C70590-7F4A-4D54-9157-7FEDE0F8650D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {63C70590-7F4A-4D54-9157-7FEDE0F8650D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {63C70590-7F4A-4D54-9157-7FEDE0F8650D}.Release|Any CPU.Build.0 = Release|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -445,7 +445,7 @@ Global {82157559-DF60-496D-817F-84B34CFF76FD} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {9AE6E00C-5E6F-4615-9C69-464E9B208E8C} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {6947034E-C97F-4F78-940F-B6A398E23C9C} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} - {63C70590-7F4A-4D54-9157-7FEDE0F8650D} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {F7F70331-CB38-47D7-9366-F8C5D934D088} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} diff --git a/global.json b/global.json index 0d655b083..e8630fed2 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,8 @@ { "sdk": { - "version": "8.0.110", - "rollForward": "latestFeature" + "version": "9.0.100-preview.6.24328.19", + "allowPrerelease": true, + "rollForward": "latestPatch" }, "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.56", diff --git a/samples/Net9FunctionApp/HelloHttp.cs b/samples/Net9FunctionApp/HelloHttp.cs new file mode 100644 index 000000000..6ef279040 --- /dev/null +++ b/samples/Net9FunctionApp/HelloHttp.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace Net9FunctionApp +{ + public class HelloHttp(ILogger logger) + { + [Function("HelloHttp")] + public IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req) + { + logger.LogInformation("C# HTTP trigger function processed a request."); + return new OkObjectResult("Welcome to Azure Functions!"); + } + } +} diff --git a/samples/Net9FunctionApp/Net9FunctionApp.csproj b/samples/Net9FunctionApp/Net9FunctionApp.csproj new file mode 100644 index 000000000..9b6b2a4ab --- /dev/null +++ b/samples/Net9FunctionApp/Net9FunctionApp.csproj @@ -0,0 +1,29 @@ + + + net9.0 + v4 + Exe + enable + enable + + + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + \ No newline at end of file diff --git a/samples/Net9FunctionApp/NuGet.Config b/samples/Net9FunctionApp/NuGet.Config new file mode 100644 index 000000000..d8f90e261 --- /dev/null +++ b/samples/Net9FunctionApp/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/samples/Net9FunctionApp/Program.cs b/samples/Net9FunctionApp/Program.cs new file mode 100644 index 000000000..c2df7fbe4 --- /dev/null +++ b/samples/Net9FunctionApp/Program.cs @@ -0,0 +1,14 @@ +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +var host = new HostBuilder() + .ConfigureFunctionsWebApplication() + .ConfigureServices(services => + { + services.AddApplicationInsightsTelemetryWorkerService(); + services.ConfigureFunctionsApplicationInsights(); + }) + .Build(); + +host.Run(); diff --git a/samples/Net9FunctionApp/host.json b/samples/Net9FunctionApp/host.json new file mode 100644 index 000000000..ee5cf5f83 --- /dev/null +++ b/samples/Net9FunctionApp/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 1cc232248..26ce304c3 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -3,6 +3,7 @@ 18 1 + -preview1 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 3bcc803ad..cf8640040 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -2,7 +2,7 @@ Library - net5.0;netstandard2.0 + net5.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Core This library provides the core functionality to build an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker.Core @@ -22,6 +22,16 @@ + + + + + + + + + + diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index fd9d76056..befd3a8a5 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -2,7 +2,7 @@ Library - net5.0;net6.0;net7.0;netstandard2.0 + net5.0;net6.0;net7.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Grpc This library provides gRPC support for Azure Functions .NET Worker communication with the Azure Functions Host. Microsoft.Azure.Functions.Worker.Grpc @@ -10,7 +10,7 @@ true 17 0 - + -preview1 true @@ -27,6 +27,14 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + + + diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index 2ed0d2a72..4afc87937 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -2,7 +2,7 @@ Library - net5.0;net6.0;net7.0;netstandard2.0 + net5.0;net6.0;net7.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker This library enables you to create an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker @@ -17,6 +17,14 @@ + + + + + + + + From 345ce39dd6b7c9f940e475cee2e64df91a1273f1 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 26 Aug 2024 15:58:52 -0700 Subject: [PATCH 006/190] Updating project structure to fix extensions, samples and core package dependencies --- DotNetWorker.Extensions.sln | 252 ++++++++++++++++ DotNetWorker.Extensions.slnf | 46 +++ DotNetWorker.Samples.sln | 84 ++++++ DotNetWorker.sln | 283 +----------------- .../src/Worker.Extensions.CosmosDB.csproj | 10 +- .../src/Worker.Extensions.EventGrid.csproj | 4 +- .../src/Worker.Extensions.EventHubs.csproj | 4 +- .../src/Properties/AssemblyInfo.cs | 2 +- .../Worker.Extensions.Http.AspNetCore.csproj | 6 +- .../src/Worker.Extensions.Http.csproj | 5 +- .../src/Worker.Extensions.Rpc.csproj | 5 +- .../src/Worker.Extensions.ServiceBus.csproj | 1 - .../Worker.Extensions.Storage.Blobs.csproj | 7 +- .../Worker.Extensions.Storage.Queues.csproj | 2 +- .../src/Worker.Extensions.Tables.csproj | 7 +- .../src/Worker.Extensions.Timer.csproj | 5 +- .../AspNetIntegration.csproj | 15 +- samples/DotNetWorker.Samples.slnf | 15 + samples/FunctionApp/FunctionApp.csproj | 25 +- samples/Net7Worker/.vscode/extensions.json | 5 - .../Net7Worker/EventHubCancellationToken.cs | 65 ---- samples/Net7Worker/HttpFunction.cs | 34 --- samples/Net7Worker/Net7Worker.csproj | 16 - samples/Net7Worker/Program.cs | 10 - .../Net7Worker/Properties/launchSettings.json | 9 - samples/Net7Worker/README.md | 28 -- samples/Net7Worker/host.json | 11 - samples/Net7Worker/local.settings.json | 8 - sdk/Sdk.Generators/Sdk.Generators.csproj | 4 +- .../DotNetWorker.ApplicationInsights.csproj | 2 +- .../DotNetWorker.Core.csproj | 22 +- .../DotNetWorker.Grpc.csproj | 18 +- src/DotNetWorker/DotNetWorker.csproj | 12 +- .../DotNetWorker.OpenTelemetry.Tests.csproj | 3 - .../DotNetWorkerTests.csproj | 8 +- test/E2ETests/E2EApps/E2EApp/E2EApp.csproj | 3 +- test/E2ETests/E2ETests/E2ETests.csproj | 2 +- .../SdkTests.csproj | 2 - .../Sdk.Analyzers.Tests.csproj | 1 - .../Sdk.Generator.Tests.csproj | 3 +- test/SdkE2ETests/SdkE2ETests.csproj | 4 - .../Worker.Extensions.Shared.Tests.csproj | 2 +- .../FunctionsEndpointDataSourceTests.cs | 0 .../FunctionsHttpProxyingMiddlewareTests.cs | 3 + .../WorkerRequestServicesMiddlewareTests.cs | 2 + .../TestBindingMetadata.cs | 21 ++ .../TestConverterContext.cs | 27 ++ .../Worker.Extensions.Tests.csproj | 4 +- .../AspNetCoreHttpRequestDataTests.cs | 87 +++--- ...er.Extensions.Http.AspNetCore.Tests.csproj | 1 - 50 files changed, 575 insertions(+), 620 deletions(-) create mode 100644 DotNetWorker.Extensions.sln create mode 100644 DotNetWorker.Extensions.slnf create mode 100644 DotNetWorker.Samples.sln create mode 100644 samples/DotNetWorker.Samples.slnf delete mode 100644 samples/Net7Worker/.vscode/extensions.json delete mode 100644 samples/Net7Worker/EventHubCancellationToken.cs delete mode 100644 samples/Net7Worker/HttpFunction.cs delete mode 100644 samples/Net7Worker/Net7Worker.csproj delete mode 100644 samples/Net7Worker/Program.cs delete mode 100644 samples/Net7Worker/Properties/launchSettings.json delete mode 100644 samples/Net7Worker/README.md delete mode 100644 samples/Net7Worker/host.json delete mode 100644 samples/Net7Worker/local.settings.json rename test/{DotNetWorkerTests => Worker.Extensions.Tests}/AspNetCore/FunctionsEndpointDataSourceTests.cs (100%) rename test/{DotNetWorkerTests => Worker.Extensions.Tests}/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs (99%) rename test/{DotNetWorkerTests => Worker.Extensions.Tests}/AspNetCore/WorkerRequestServicesMiddlewareTests.cs (97%) create mode 100644 test/Worker.Extensions.Tests/TestBindingMetadata.cs create mode 100644 test/Worker.Extensions.Tests/TestConverterContext.cs diff --git a/DotNetWorker.Extensions.sln b/DotNetWorker.Extensions.sln new file mode 100644 index 000000000..dfc97f665 --- /dev/null +++ b/DotNetWorker.Extensions.sln @@ -0,0 +1,252 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32228.430 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{FD7243E4-BF18-43F8-8744-BA1D17ACF378}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{1B6B4B62-686E-44B4-9CEC-710DA34BC09E}" + ProjectSection(SolutionItems) = preProject + build\Common.props = build\Common.props + build\Extensions.props = build\Extensions.props + build\icon.png = build\icon.png + build\Icon.props = build\Icon.props + build\PackageInfo.props = build\PackageInfo.props + build\SharedReferences.targets = build\SharedReferences.targets + EndProjectSection +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{42CB3DE7-B070-4BA1-8A7A-ACB237BEAA4E}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtility", "test\TestUtility\TestUtility.csproj", "{C30B77A7-4085-422E-AADE-A4322989F5F8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "extensions", "extensions", "{A7B4FF1E-3DF7-4F28-9333-D0961CDDF702}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http", "extensions\Worker.Extensions.Http\src\Worker.Extensions.Http.csproj", "{1E601406-6923-4CB9-AAD7-928E08906B10}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Abstractions", "extensions\Worker.Extensions.Abstractions\src\Worker.Extensions.Abstractions.csproj", "{B5F66802-0968-4B99-8E97-E42C744CE5CE}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Storage", "extensions\Worker.Extensions.Storage\src\Worker.Extensions.Storage.csproj", "{D6EAB0C1-491C-4723-B1F3-B6F5461CD359}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Timer", "extensions\Worker.Extensions.Timer\src\Worker.Extensions.Timer.csproj", "{4DBEC557-E5CC-41E9-9319-BC02615CF228}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.CosmosDB", "extensions\Worker.Extensions.CosmosDB\src\Worker.Extensions.CosmosDB.csproj", "{37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.EventGrid", "extensions\Worker.Extensions.EventGrid\src\Worker.Extensions.EventGrid.csproj", "{9C305047-0B81-4DA1-98D4-BC8B391A2297}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.ServiceBus", "extensions\Worker.Extensions.ServiceBus\src\Worker.Extensions.ServiceBus.csproj", "{660B4D9D-081A-4DCA-BD7A-E196F4529BFD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.EventHubs", "extensions\Worker.Extensions.EventHubs\src\Worker.Extensions.EventHubs.csproj", "{4A5770BE-6BB7-448F-A818-DD1450F8CBDC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.RabbitMQ", "extensions\Worker.Extensions.RabbitMQ\src\Worker.Extensions.RabbitMQ.csproj", "{55652CF7-E58B-4564-A76B-D49DC71878DC}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.SignalRService", "extensions\Worker.Extensions.SignalRService\src\Worker.Extensions.SignalRService.csproj", "{A9802FBA-CF59-462B-88A0-1D7D0D19C748}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.SendGrid", "extensions\Worker.Extensions.SendGrid\src\Worker.Extensions.SendGrid.csproj", "{59EB5B01-4756-48BB-8B37-70D29E3BDFB6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Warmup", "extensions\Worker.Extensions.Warmup\src\Worker.Extensions.Warmup.csproj", "{BDA0BCB4-BD26-4B10-B865-87082F290B38}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Kafka", "extensions\Worker.Extensions.Kafka\src\Worker.Extensions.Kafka.csproj", "{F63A63A9-FE09-4225-A293-6A58F9C1E520}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Worker", "Worker", "{0F6B5528-642F-4C46-AB4E-15E9B6CE24F9}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{0EA6A975-2934-4837-9932-2328EFE23BFD}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2EApp", "test\E2ETests\E2EApps\E2EApp\E2EApp.csproj", "{34CB5A87-0433-4C19-9CB3-E2F58119CDE9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2ETests", "test\E2ETests\E2ETests\E2ETests.csproj", "{059C8F76-20F9-42BD-A343-64EE3ACF1AF8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Storage.Queues", "extensions\Worker.Extensions.Storage.Queues\src\Worker.Extensions.Storage.Queues.csproj", "{1D2A2B02-BFA8-4E53-9844-88359C5B2671}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Storage.Blobs", "extensions\Worker.Extensions.Storage.Blobs\src\Worker.Extensions.Storage.Blobs.csproj", "{FC352905-BD72-4049-8D32-3CBB9304FDC8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Tables", "extensions\Worker.Extensions.Tables\src\Worker.Extensions.Tables.csproj", "{004DEF24-7EBB-499D-BD1C-E940AC4E122D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Shared", "extensions\Worker.Extensions.Shared\Worker.Extensions.Shared.csproj", "{277D77B9-8915-41E3-8763-0B66328ADDDA}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Rpc", "extensions\Worker.Extensions.Rpc\src\Worker.Extensions.Rpc.csproj", "{93B64F12-EBDD-46CE-B4FB-0904701F0032}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{AA4D318D-101B-49E7-A4EC-B34165AEDB33}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Rpc.Tests", "test\Worker.Extensions.Rpc.Tests\Worker.Extensions.Rpc.Tests.csproj", "{B13C9E5F-0E4B-413E-90AE-20B84B100364}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http.AspNetCore", "extensions\Worker.Extensions.Http.AspNetCore\src\Worker.Extensions.Http.AspNetCore.csproj", "{1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.SignalRService.Tests", "test\Worker.Extensions.SignalRService.Tests\Worker.Extensions.SignalRService.Tests.csproj", "{286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Tests", "test\Worker.Extensions.Tests\Worker.Extensions.Tests.csproj", "{17BDCE12-6964-4B87-B2AC-68CE270A3E9A}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http.AspNetCore.Tests", "test\extensions\Worker.Extensions.Http.AspNetCore.Tests\Worker.Extensions.Http.AspNetCore.Tests.csproj", "{D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Shared.Tests", "test\Worker.Extensions.Shared.Tests\Worker.Extensions.Shared.Tests.csproj", "{B6342174-5436-4846-B43C-39D8E34AE5CF}" +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}") = "Worker.Extensions.Timer.Tests", "test\extensions\Worker.Extensions.Timer.Tests\Worker.Extensions.Timer.Tests.csproj", "{6947034E-C97F-4F78-940F-B6A398E23C9C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {C30B77A7-4085-422E-AADE-A4322989F5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C30B77A7-4085-422E-AADE-A4322989F5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C30B77A7-4085-422E-AADE-A4322989F5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C30B77A7-4085-422E-AADE-A4322989F5F8}.Release|Any CPU.Build.0 = Release|Any CPU + {1E601406-6923-4CB9-AAD7-928E08906B10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1E601406-6923-4CB9-AAD7-928E08906B10}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1E601406-6923-4CB9-AAD7-928E08906B10}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1E601406-6923-4CB9-AAD7-928E08906B10}.Release|Any CPU.Build.0 = Release|Any CPU + {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Release|Any CPU.Build.0 = Release|Any CPU + {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Release|Any CPU.Build.0 = Release|Any CPU + {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Release|Any CPU.Build.0 = Release|Any CPU + {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Debug|Any CPU.Build.0 = Debug|Any CPU + {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Release|Any CPU.ActiveCfg = Release|Any CPU + {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Release|Any CPU.Build.0 = Release|Any CPU + {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Release|Any CPU.Build.0 = Release|Any CPU + {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Release|Any CPU.Build.0 = Release|Any CPU + {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Release|Any CPU.Build.0 = Release|Any CPU + {55652CF7-E58B-4564-A76B-D49DC71878DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55652CF7-E58B-4564-A76B-D49DC71878DC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55652CF7-E58B-4564-A76B-D49DC71878DC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55652CF7-E58B-4564-A76B-D49DC71878DC}.Release|Any CPU.Build.0 = Release|Any CPU + {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Release|Any CPU.Build.0 = Release|Any CPU + {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Release|Any CPU.Build.0 = Release|Any CPU + {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Release|Any CPU.Build.0 = Release|Any CPU + {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Release|Any CPU.Build.0 = Release|Any CPU + {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Release|Any CPU.Build.0 = Release|Any CPU + {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Release|Any CPU.Build.0 = Release|Any CPU + {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Release|Any CPU.Build.0 = Release|Any CPU + {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Release|Any CPU.Build.0 = Release|Any CPU + {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Release|Any CPU.Build.0 = Release|Any CPU + {277D77B9-8915-41E3-8763-0B66328ADDDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {277D77B9-8915-41E3-8763-0B66328ADDDA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {277D77B9-8915-41E3-8763-0B66328ADDDA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {277D77B9-8915-41E3-8763-0B66328ADDDA}.Release|Any CPU.Build.0 = Release|Any CPU + {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Release|Any CPU.Build.0 = Release|Any CPU + {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Release|Any CPU.Build.0 = Release|Any CPU + {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Release|Any CPU.Build.0 = Release|Any CPU + {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Release|Any CPU.Build.0 = Release|Any CPU + {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Release|Any CPU.Build.0 = Release|Any CPU + {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {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 + {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 + {B6342174-5436-4846-B43C-39D8E34AE5CF}.Release|Any CPU.Build.0 = Release|Any CPU + {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Release|Any CPU.Build.0 = Release|Any CPU + {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {C30B77A7-4085-422E-AADE-A4322989F5F8} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {1E601406-6923-4CB9-AAD7-928E08906B10} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {B5F66802-0968-4B99-8E97-E42C744CE5CE} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {D6EAB0C1-491C-4723-B1F3-B6F5461CD359} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {4DBEC557-E5CC-41E9-9319-BC02615CF228} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {9C305047-0B81-4DA1-98D4-BC8B391A2297} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {660B4D9D-081A-4DCA-BD7A-E196F4529BFD} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {4A5770BE-6BB7-448F-A818-DD1450F8CBDC} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {55652CF7-E58B-4564-A76B-D49DC71878DC} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {A9802FBA-CF59-462B-88A0-1D7D0D19C748} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {59EB5B01-4756-48BB-8B37-70D29E3BDFB6} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {BDA0BCB4-BD26-4B10-B865-87082F290B38} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {F63A63A9-FE09-4225-A293-6A58F9C1E520} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {0F6B5528-642F-4C46-AB4E-15E9B6CE24F9} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {0EA6A975-2934-4837-9932-2328EFE23BFD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {34CB5A87-0433-4C19-9CB3-E2F58119CDE9} = {0EA6A975-2934-4837-9932-2328EFE23BFD} + {059C8F76-20F9-42BD-A343-64EE3ACF1AF8} = {0F6B5528-642F-4C46-AB4E-15E9B6CE24F9} + {1D2A2B02-BFA8-4E53-9844-88359C5B2671} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {FC352905-BD72-4049-8D32-3CBB9304FDC8} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {004DEF24-7EBB-499D-BD1C-E940AC4E122D} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {277D77B9-8915-41E3-8763-0B66328ADDDA} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {93B64F12-EBDD-46CE-B4FB-0904701F0032} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {AA4D318D-101B-49E7-A4EC-B34165AEDB33} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {B13C9E5F-0E4B-413E-90AE-20B84B100364} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} + {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} + {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {17BDCE12-6964-4B87-B2AC-68CE270A3E9A} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {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} + {6947034E-C97F-4F78-940F-B6A398E23C9C} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} + EndGlobalSection +EndGlobal diff --git a/DotNetWorker.Extensions.slnf b/DotNetWorker.Extensions.slnf new file mode 100644 index 000000000..809d70b50 --- /dev/null +++ b/DotNetWorker.Extensions.slnf @@ -0,0 +1,46 @@ +{ + "solution": { + "path": "DotNetWorker.sln", + "projects": [ + "extensions\\Worker.Extensions.Abstractions\\src\\Worker.Extensions.Abstractions.csproj", + "extensions\\Worker.Extensions.CosmosDB\\src\\Worker.Extensions.CosmosDB.csproj", + "extensions\\Worker.Extensions.EventGrid\\src\\Worker.Extensions.EventGrid.csproj", + "extensions\\Worker.Extensions.EventHubs\\src\\Worker.Extensions.EventHubs.csproj", + "extensions\\Worker.Extensions.Http.AspNetCore.Analyzers\\Worker.Extensions.Http.AspNetCore.Analyzers.csproj", + "extensions\\Worker.Extensions.Http.AspNetCore\\src\\Worker.Extensions.Http.AspNetCore.csproj", + "extensions\\Worker.Extensions.Http\\src\\Worker.Extensions.Http.csproj", + "extensions\\Worker.Extensions.Kafka\\src\\Worker.Extensions.Kafka.csproj", + "extensions\\Worker.Extensions.RabbitMQ\\src\\Worker.Extensions.RabbitMQ.csproj", + "extensions\\Worker.Extensions.Rpc\\src\\Worker.Extensions.Rpc.csproj", + "extensions\\Worker.Extensions.SendGrid\\src\\Worker.Extensions.SendGrid.csproj", + "extensions\\Worker.Extensions.ServiceBus\\src\\Worker.Extensions.ServiceBus.csproj", + "extensions\\Worker.Extensions.Shared\\Worker.Extensions.Shared.csproj", + "extensions\\Worker.Extensions.SignalRService\\src\\Worker.Extensions.SignalRService.csproj", + "extensions\\Worker.Extensions.Storage.Blobs\\src\\Worker.Extensions.Storage.Blobs.csproj", + "extensions\\Worker.Extensions.Storage.Queues\\src\\Worker.Extensions.Storage.Queues.csproj", + "extensions\\Worker.Extensions.Storage\\src\\Worker.Extensions.Storage.csproj", + "extensions\\Worker.Extensions.Tables\\src\\Worker.Extensions.Tables.csproj", + "extensions\\Worker.Extensions.Timer\\src\\Worker.Extensions.Timer.csproj", + "extensions\\Worker.Extensions.Warmup\\src\\Worker.Extensions.Warmup.csproj", + "samples\\Extensions\\Extensions.csproj", + "test\\DependentAssemblyWithFunctions.NetStandard\\DependentAssemblyWithFunctions.NetStandard.csproj", + "test\\DependentAssemblyWithFunctions\\DependentAssemblyWithFunctions.csproj", + "test\\DotNetWorkerTests\\DotNetWorkerTests.csproj", + "test\\E2ETests\\E2EApps\\E2EApp\\E2EApp.csproj", + "test\\E2ETests\\E2ETests\\E2ETests.csproj", + "test\\FunctionMetadataGeneratorTests\\SdkTests.csproj", + "test\\Sdk.Analyzers.Tests\\Sdk.Analyzers.Tests.csproj", + "test\\Sdk.Generator.Tests\\Sdk.Generator.Tests.csproj", + "test\\SdkE2ETests\\SdkE2ETests.csproj", + "test\\TestUtility\\TestUtility.csproj", + "test\\Worker.Extensions.Rpc.Tests\\Worker.Extensions.Rpc.Tests.csproj", + "test\\Worker.Extensions.Sample-IncorrectImplementation\\Worker.Extensions.Sample-IncorrectImplementation.csproj", + "test\\Worker.Extensions.Sample\\Worker.Extensions.Sample.csproj", + "test\\Worker.Extensions.Shared.Tests\\Worker.Extensions.Shared.Tests.csproj", + "test\\Worker.Extensions.SignalRService.Tests\\Worker.Extensions.SignalRService.Tests.csproj", + "test\\Worker.Extensions.Tests\\Worker.Extensions.Tests.csproj", + "test\\extensions\\Worker.Extensions.Http.AspNetCore.Tests\\Worker.Extensions.Http.AspNetCore.Tests.csproj", + "test\\extensions\\Worker.Extensions.Timer.Tests\\Worker.Extensions.Timer.Tests.csproj" + ] + } +} \ No newline at end of file diff --git a/DotNetWorker.Samples.sln b/DotNetWorker.Samples.sln new file mode 100644 index 000000000..0ad9f6d84 --- /dev/null +++ b/DotNetWorker.Samples.sln @@ -0,0 +1,84 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.1.32228.430 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{9D6603BD-7EA2-4D11-A69C-0D9E01317FD6}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionApp", "samples\FunctionApp\FunctionApp.csproj", "{E61EE414-3693-4C83-BDAA-17AB0024D0E6}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{42CB3DE7-B070-4BA1-8A7A-ACB237BEAA4E}" + ProjectSection(SolutionItems) = preProject + .editorconfig = .editorconfig + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions", "samples\Extensions\Extensions.csproj", "{BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomMiddleware", "samples\CustomMiddleware\CustomMiddleware.csproj", "{2A72383A-9C00-41FB-9D29-909EE5E6BFB9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFramework", "samples\EntityFramework\EntityFramework.csproj", "{C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Configuration", "samples\Configuration\Configuration.csproj", "{035AAD56-5F51-476C-8556-0F6CFD6EF1BF}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFxWorker", "samples\NetFxWorker\NetFxWorker.csproj", "{B37E6BAC-F16B-4366-94FB-8B94B52A08C9}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetIntegration", "samples\AspNetIntegration\AspNetIntegration.csproj", "{D2F67410-9933-42E8-B04A-E17634D83A30}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net9FunctionApp", "samples\Net9FunctionApp\Net9FunctionApp.csproj", "{F7F70331-CB38-47D7-9366-F8C5D934D088}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Release|Any CPU.Build.0 = Release|Any CPU + {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Release|Any CPU.Build.0 = Release|Any CPU + {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Release|Any CPU.Build.0 = Release|Any CPU + {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Release|Any CPU.Build.0 = Release|Any CPU + {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Release|Any CPU.Build.0 = Release|Any CPU + {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Release|Any CPU.Build.0 = Release|Any CPU + {D2F67410-9933-42E8-B04A-E17634D83A30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2F67410-9933-42E8-B04A-E17634D83A30}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2F67410-9933-42E8-B04A-E17634D83A30}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2F67410-9933-42E8-B04A-E17634D83A30}.Release|Any CPU.Build.0 = Release|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(NestedProjects) = preSolution + {E61EE414-3693-4C83-BDAA-17AB0024D0E6} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {2A72383A-9C00-41FB-9D29-909EE5E6BFB9} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {035AAD56-5F51-476C-8556-0F6CFD6EF1BF} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {B37E6BAC-F16B-4366-94FB-8B94B52A08C9} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {D2F67410-9933-42E8-B04A-E17634D83A30} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {F7F70331-CB38-47D7-9366-F8C5D934D088} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} + EndGlobalSection +EndGlobal diff --git a/DotNetWorker.sln b/DotNetWorker.sln index 8223a5cc1..f35602163 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -11,8 +11,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionApp", "samples\Func EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker", "src\DotNetWorker\DotNetWorker.csproj", "{2B47EC99-E383-4DFA-9130-DAF40FDA313B}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorkerTests", "test\DotNetWorkerTests\DotNetWorkerTests.csproj", "{02D1B220-3DAE-40E7-B5CC-86501756BF92}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdk", "sdk", "{4B0D77E7-FA83-4FDD-9E67-CC95EAD21348}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{1B6B4B62-686E-44B4-9CEC-710DA34BC09E}" @@ -27,12 +25,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{1B6B4B62 EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk", "sdk\Sdk\Sdk.csproj", "{E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkTests", "test\FunctionMetadataGeneratorTests\SdkTests.csproj", "{5C38C5A3-83A5-4E2F-9B32-204C2225E890}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionMetadataLoaderExtension", "sdk\FunctionMetadataLoaderExtension\FunctionMetadataLoaderExtension.csproj", "{6B64FE04-BA90-49FC-893A-DF12EF15280C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkE2ETests", "test\SdkE2ETests\SdkE2ETests.csproj", "{BFB2832E-C3AB-4F09-B285-B24E535EC858}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{42CB3DE7-B070-4BA1-8A7A-ACB237BEAA4E}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig @@ -40,50 +34,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestUtility", "test\TestUtility\TestUtility.csproj", "{C30B77A7-4085-422E-AADE-A4322989F5F8}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "extensions", "extensions", "{A7B4FF1E-3DF7-4F28-9333-D0961CDDF702}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http", "extensions\Worker.Extensions.Http\src\Worker.Extensions.Http.csproj", "{1E601406-6923-4CB9-AAD7-928E08906B10}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Abstractions", "extensions\Worker.Extensions.Abstractions\src\Worker.Extensions.Abstractions.csproj", "{B5F66802-0968-4B99-8E97-E42C744CE5CE}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Storage", "extensions\Worker.Extensions.Storage\src\Worker.Extensions.Storage.csproj", "{D6EAB0C1-491C-4723-B1F3-B6F5461CD359}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Timer", "extensions\Worker.Extensions.Timer\src\Worker.Extensions.Timer.csproj", "{4DBEC557-E5CC-41E9-9319-BC02615CF228}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.CosmosDB", "extensions\Worker.Extensions.CosmosDB\src\Worker.Extensions.CosmosDB.csproj", "{37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.EventGrid", "extensions\Worker.Extensions.EventGrid\src\Worker.Extensions.EventGrid.csproj", "{9C305047-0B81-4DA1-98D4-BC8B391A2297}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.ServiceBus", "extensions\Worker.Extensions.ServiceBus\src\Worker.Extensions.ServiceBus.csproj", "{660B4D9D-081A-4DCA-BD7A-E196F4529BFD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.EventHubs", "extensions\Worker.Extensions.EventHubs\src\Worker.Extensions.EventHubs.csproj", "{4A5770BE-6BB7-448F-A818-DD1450F8CBDC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.RabbitMQ", "extensions\Worker.Extensions.RabbitMQ\src\Worker.Extensions.RabbitMQ.csproj", "{55652CF7-E58B-4564-A76B-D49DC71878DC}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.SignalRService", "extensions\Worker.Extensions.SignalRService\src\Worker.Extensions.SignalRService.csproj", "{A9802FBA-CF59-462B-88A0-1D7D0D19C748}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.SendGrid", "extensions\Worker.Extensions.SendGrid\src\Worker.Extensions.SendGrid.csproj", "{59EB5B01-4756-48BB-8B37-70D29E3BDFB6}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Warmup", "extensions\Worker.Extensions.Warmup\src\Worker.Extensions.Warmup.csproj", "{BDA0BCB4-BD26-4B10-B865-87082F290B38}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Kafka", "extensions\Worker.Extensions.Kafka\src\Worker.Extensions.Kafka.csproj", "{F63A63A9-FE09-4225-A293-6A58F9C1E520}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Analyzers", "sdk\Sdk.Analyzers\Sdk.Analyzers.csproj", "{055D602D-D2B3-416B-AC59-1972D832032A}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Analyzers.Tests", "test\Sdk.Analyzers.Tests\Sdk.Analyzers.Tests.csproj", "{A75EA1E1-2801-460C-87C0-DE6A82D30851}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{083592CA-7DAB-44CE-8979-44FAFA46AEC3}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Worker", "Worker", "{0F6B5528-642F-4C46-AB4E-15E9B6CE24F9}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Sdk", "Sdk", "{B5821230-6E0A-4535-88A9-ED31B6F07596}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{0EA6A975-2934-4837-9932-2328EFE23BFD}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2EApp", "test\E2ETests\E2EApps\E2EApp\E2EApp.csproj", "{34CB5A87-0433-4C19-9CB3-E2F58119CDE9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "E2ETests", "test\E2ETests\E2ETests\E2ETests.csproj", "{059C8F76-20F9-42BD-A343-64EE3ACF1AF8}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.Grpc", "src\DotNetWorker.Grpc\DotNetWorker.Grpc.csproj", "{248ACC90-D4F9-432B-B7B9-341EF00FA072}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.Core", "src\DotNetWorker.Core\DotNetWorker.Core.csproj", "{23AAA8FA-5B51-49BF-8021-148C8031A321}" @@ -96,59 +50,21 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFramework", "samples\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Configuration", "samples\Configuration\Configuration.csproj", "{035AAD56-5F51-476C-8556-0F6CFD6EF1BF}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Storage.Queues", "extensions\Worker.Extensions.Storage.Queues\src\Worker.Extensions.Storage.Queues.csproj", "{1D2A2B02-BFA8-4E53-9844-88359C5B2671}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Storage.Blobs", "extensions\Worker.Extensions.Storage.Blobs\src\Worker.Extensions.Storage.Blobs.csproj", "{FC352905-BD72-4049-8D32-3CBB9304FDC8}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generators", "sdk\Sdk.Generators\Sdk.Generators.csproj", "{F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generator.Tests", "test\Sdk.Generator.Tests\Sdk.Generator.Tests.csproj", "{18A09B24-8646-40A6-BD85-2773AF567453}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Sample", "test\Worker.Extensions.Sample\Worker.Extensions.Sample.csproj", "{9E23C9B2-7C0A-4F09-987F-0E5BDC8BE28C}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleExtensions", "SampleExtensions", "{922A387F-8595-4C74-ABF1-AEFF9530950C}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Sample-IncorrectImplementation", "test\Worker.Extensions.Sample-IncorrectImplementation\Worker.Extensions.Sample-IncorrectImplementation.csproj", "{22FCE0DF-65FE-4650-8202-765832C40E6D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFxWorker", "samples\NetFxWorker\NetFxWorker.csproj", "{B37E6BAC-F16B-4366-94FB-8B94B52A08C9}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.ApplicationInsights", "src\DotNetWorker.ApplicationInsights\DotNetWorker.ApplicationInsights.csproj", "{65DE66B6-568F-46AC-8F0D-C79A02F48214}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Tables", "extensions\Worker.Extensions.Tables\src\Worker.Extensions.Tables.csproj", "{004DEF24-7EBB-499D-BD1C-E940AC4E122D}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Shared", "extensions\Worker.Extensions.Shared\Worker.Extensions.Shared.csproj", "{277D77B9-8915-41E3-8763-0B66328ADDDA}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Rpc", "extensions\Worker.Extensions.Rpc\src\Worker.Extensions.Rpc.csproj", "{93B64F12-EBDD-46CE-B4FB-0904701F0032}" -EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensions", "Extensions", "{AA4D318D-101B-49E7-A4EC-B34165AEDB33}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Rpc.Tests", "test\Worker.Extensions.Rpc.Tests\Worker.Extensions.Rpc.Tests.csproj", "{B13C9E5F-0E4B-413E-90AE-20B84B100364}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http.AspNetCore", "extensions\Worker.Extensions.Http.AspNetCore\src\Worker.Extensions.Http.AspNetCore.csproj", "{1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.SignalRService.Tests", "test\Worker.Extensions.SignalRService.Tests\Worker.Extensions.SignalRService.Tests.csproj", "{286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Tests", "test\Worker.Extensions.Tests\Worker.Extensions.Tests.csproj", "{17BDCE12-6964-4B87-B2AC-68CE270A3E9A}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetIntegration", "samples\AspNetIntegration\AspNetIntegration.csproj", "{D2F67410-9933-42E8-B04A-E17634D83A30}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions", "test\DependentAssemblyWithFunctions\DependentAssemblyWithFunctions.csproj", "{AB6E1E7A-0D2C-4086-9487-566887C1E753}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http.AspNetCore.Tests", "test\extensions\Worker.Extensions.Http.AspNetCore.Tests\Worker.Extensions.Http.AspNetCore.Tests.csproj", "{D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Shared.Tests", "test\Worker.Extensions.Shared.Tests\Worker.Extensions.Shared.Tests.csproj", "{B6342174-5436-4846-B43C-39D8E34AE5CF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net7Worker", "samples\Net7Worker\Net7Worker.csproj", "{BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{198DA072-F94F-4585-A744-97B3DAC21686}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry", "src\DotNetWorker.OpenTelemetry\DotNetWorker.OpenTelemetry.csproj", "{82157559-DF60-496D-817F-84B34CFF76FD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry.Tests", "test\DotNetWorker.OpenTelemetry.Tests\DotNetWorker.OpenTelemetry.Tests.csproj", "{9AE6E00C-5E6F-4615-9C69-464E9B208E8C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Timer.Tests", "test\extensions\Worker.Extensions.Timer.Tests\Worker.Extensions.Timer.Tests.csproj", "{6947034E-C97F-4F78-940F-B6A398E23C9C}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net9FunctionApp", "samples\Net9FunctionApp\Net9FunctionApp.csproj", "{F7F70331-CB38-47D7-9366-F8C5D934D088}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Net9FunctionApp", "samples\Net9FunctionApp\Net9FunctionApp.csproj", "{F7F70331-CB38-47D7-9366-F8C5D934D088}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorkerTests", "test\DotNetWorkerTests\DotNetWorkerTests.csproj", "{B0A6867D-2C35-4BF1-892E-CE84795525BD}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -164,98 +80,22 @@ Global {2B47EC99-E383-4DFA-9130-DAF40FDA313B}.Debug|Any CPU.Build.0 = Debug|Any CPU {2B47EC99-E383-4DFA-9130-DAF40FDA313B}.Release|Any CPU.ActiveCfg = Release|Any CPU {2B47EC99-E383-4DFA-9130-DAF40FDA313B}.Release|Any CPU.Build.0 = Release|Any CPU - {02D1B220-3DAE-40E7-B5CC-86501756BF92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {02D1B220-3DAE-40E7-B5CC-86501756BF92}.Debug|Any CPU.Build.0 = Debug|Any CPU - {02D1B220-3DAE-40E7-B5CC-86501756BF92}.Release|Any CPU.ActiveCfg = Release|Any CPU - {02D1B220-3DAE-40E7-B5CC-86501756BF92}.Release|Any CPU.Build.0 = Release|Any CPU {E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5}.Debug|Any CPU.Build.0 = Debug|Any CPU {E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5}.Release|Any CPU.ActiveCfg = Release|Any CPU {E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5}.Release|Any CPU.Build.0 = Release|Any CPU - {5C38C5A3-83A5-4E2F-9B32-204C2225E890}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5C38C5A3-83A5-4E2F-9B32-204C2225E890}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5C38C5A3-83A5-4E2F-9B32-204C2225E890}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5C38C5A3-83A5-4E2F-9B32-204C2225E890}.Release|Any CPU.Build.0 = Release|Any CPU {6B64FE04-BA90-49FC-893A-DF12EF15280C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6B64FE04-BA90-49FC-893A-DF12EF15280C}.Debug|Any CPU.Build.0 = Debug|Any CPU {6B64FE04-BA90-49FC-893A-DF12EF15280C}.Release|Any CPU.ActiveCfg = Release|Any CPU {6B64FE04-BA90-49FC-893A-DF12EF15280C}.Release|Any CPU.Build.0 = Release|Any CPU - {BFB2832E-C3AB-4F09-B285-B24E535EC858}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BFB2832E-C3AB-4F09-B285-B24E535EC858}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BFB2832E-C3AB-4F09-B285-B24E535EC858}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BFB2832E-C3AB-4F09-B285-B24E535EC858}.Release|Any CPU.Build.0 = Release|Any CPU {C30B77A7-4085-422E-AADE-A4322989F5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C30B77A7-4085-422E-AADE-A4322989F5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU {C30B77A7-4085-422E-AADE-A4322989F5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU {C30B77A7-4085-422E-AADE-A4322989F5F8}.Release|Any CPU.Build.0 = Release|Any CPU - {1E601406-6923-4CB9-AAD7-928E08906B10}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1E601406-6923-4CB9-AAD7-928E08906B10}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1E601406-6923-4CB9-AAD7-928E08906B10}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1E601406-6923-4CB9-AAD7-928E08906B10}.Release|Any CPU.Build.0 = Release|Any CPU - {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B5F66802-0968-4B99-8E97-E42C744CE5CE}.Release|Any CPU.Build.0 = Release|Any CPU - {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D6EAB0C1-491C-4723-B1F3-B6F5461CD359}.Release|Any CPU.Build.0 = Release|Any CPU - {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4DBEC557-E5CC-41E9-9319-BC02615CF228}.Release|Any CPU.Build.0 = Release|Any CPU - {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Debug|Any CPU.Build.0 = Debug|Any CPU - {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Release|Any CPU.ActiveCfg = Release|Any CPU - {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882}.Release|Any CPU.Build.0 = Release|Any CPU - {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9C305047-0B81-4DA1-98D4-BC8B391A2297}.Release|Any CPU.Build.0 = Release|Any CPU - {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {660B4D9D-081A-4DCA-BD7A-E196F4529BFD}.Release|Any CPU.Build.0 = Release|Any CPU - {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4A5770BE-6BB7-448F-A818-DD1450F8CBDC}.Release|Any CPU.Build.0 = Release|Any CPU - {55652CF7-E58B-4564-A76B-D49DC71878DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {55652CF7-E58B-4564-A76B-D49DC71878DC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {55652CF7-E58B-4564-A76B-D49DC71878DC}.Release|Any CPU.ActiveCfg = Release|Any CPU - {55652CF7-E58B-4564-A76B-D49DC71878DC}.Release|Any CPU.Build.0 = Release|Any CPU - {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A9802FBA-CF59-462B-88A0-1D7D0D19C748}.Release|Any CPU.Build.0 = Release|Any CPU - {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {59EB5B01-4756-48BB-8B37-70D29E3BDFB6}.Release|Any CPU.Build.0 = Release|Any CPU - {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BDA0BCB4-BD26-4B10-B865-87082F290B38}.Release|Any CPU.Build.0 = Release|Any CPU - {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F63A63A9-FE09-4225-A293-6A58F9C1E520}.Release|Any CPU.Build.0 = Release|Any CPU {055D602D-D2B3-416B-AC59-1972D832032A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {055D602D-D2B3-416B-AC59-1972D832032A}.Debug|Any CPU.Build.0 = Debug|Any CPU {055D602D-D2B3-416B-AC59-1972D832032A}.Release|Any CPU.ActiveCfg = Release|Any CPU {055D602D-D2B3-416B-AC59-1972D832032A}.Release|Any CPU.Build.0 = Release|Any CPU - {A75EA1E1-2801-460C-87C0-DE6A82D30851}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A75EA1E1-2801-460C-87C0-DE6A82D30851}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A75EA1E1-2801-460C-87C0-DE6A82D30851}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A75EA1E1-2801-460C-87C0-DE6A82D30851}.Release|Any CPU.Build.0 = Release|Any CPU - {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {34CB5A87-0433-4C19-9CB3-E2F58119CDE9}.Release|Any CPU.Build.0 = Release|Any CPU - {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {059C8F76-20F9-42BD-A343-64EE3ACF1AF8}.Release|Any CPU.Build.0 = Release|Any CPU {248ACC90-D4F9-432B-B7B9-341EF00FA072}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {248ACC90-D4F9-432B-B7B9-341EF00FA072}.Debug|Any CPU.Build.0 = Debug|Any CPU {248ACC90-D4F9-432B-B7B9-341EF00FA072}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -280,30 +120,10 @@ Global {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Release|Any CPU.Build.0 = Release|Any CPU - {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D2A2B02-BFA8-4E53-9844-88359C5B2671}.Release|Any CPU.Build.0 = Release|Any CPU - {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FC352905-BD72-4049-8D32-3CBB9304FDC8}.Release|Any CPU.Build.0 = Release|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Release|Any CPU.Build.0 = Release|Any CPU - {18A09B24-8646-40A6-BD85-2773AF567453}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {18A09B24-8646-40A6-BD85-2773AF567453}.Debug|Any CPU.Build.0 = Debug|Any CPU - {18A09B24-8646-40A6-BD85-2773AF567453}.Release|Any CPU.ActiveCfg = Release|Any CPU - {18A09B24-8646-40A6-BD85-2773AF567453}.Release|Any CPU.Build.0 = Release|Any CPU - {9E23C9B2-7C0A-4F09-987F-0E5BDC8BE28C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9E23C9B2-7C0A-4F09-987F-0E5BDC8BE28C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9E23C9B2-7C0A-4F09-987F-0E5BDC8BE28C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9E23C9B2-7C0A-4F09-987F-0E5BDC8BE28C}.Release|Any CPU.Build.0 = Release|Any CPU - {22FCE0DF-65FE-4650-8202-765832C40E6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {22FCE0DF-65FE-4650-8202-765832C40E6D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {22FCE0DF-65FE-4650-8202-765832C40E6D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {22FCE0DF-65FE-4650-8202-765832C40E6D}.Release|Any CPU.Build.0 = Release|Any CPU {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Debug|Any CPU.Build.0 = Debug|Any CPU {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -312,58 +132,10 @@ Global {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Debug|Any CPU.Build.0 = Debug|Any CPU {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Release|Any CPU.ActiveCfg = Release|Any CPU {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Release|Any CPU.Build.0 = Release|Any CPU - {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {004DEF24-7EBB-499D-BD1C-E940AC4E122D}.Release|Any CPU.Build.0 = Release|Any CPU - {277D77B9-8915-41E3-8763-0B66328ADDDA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {277D77B9-8915-41E3-8763-0B66328ADDDA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {277D77B9-8915-41E3-8763-0B66328ADDDA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {277D77B9-8915-41E3-8763-0B66328ADDDA}.Release|Any CPU.Build.0 = Release|Any CPU - {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Debug|Any CPU.Build.0 = Debug|Any CPU - {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Release|Any CPU.ActiveCfg = Release|Any CPU - {93B64F12-EBDD-46CE-B4FB-0904701F0032}.Release|Any CPU.Build.0 = Release|Any CPU - {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B13C9E5F-0E4B-413E-90AE-20B84B100364}.Release|Any CPU.Build.0 = Release|Any CPU - {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}.Release|Any CPU.Build.0 = Release|Any CPU - {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Release|Any CPU.ActiveCfg = Release|Any CPU - {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}.Release|Any CPU.Build.0 = Release|Any CPU - {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {17BDCE12-6964-4B87-B2AC-68CE270A3E9A}.Release|Any CPU.Build.0 = Release|Any CPU {D2F67410-9933-42E8-B04A-E17634D83A30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D2F67410-9933-42E8-B04A-E17634D83A30}.Debug|Any CPU.Build.0 = Debug|Any CPU {D2F67410-9933-42E8-B04A-E17634D83A30}.Release|Any CPU.ActiveCfg = Release|Any CPU {D2F67410-9933-42E8-B04A-E17634D83A30}.Release|Any CPU.Build.0 = Release|Any CPU - {AB6E1E7A-0D2C-4086-9487-566887C1E753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AB6E1E7A-0D2C-4086-9487-566887C1E753}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AB6E1E7A-0D2C-4086-9487-566887C1E753}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AB6E1E7A-0D2C-4086-9487-566887C1E753}.Release|Any CPU.Build.0 = Release|Any CPU - {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {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 - {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 - {B6342174-5436-4846-B43C-39D8E34AE5CF}.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 - {198DA072-F94F-4585-A744-97B3DAC21686}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {198DA072-F94F-4585-A744-97B3DAC21686}.Debug|Any CPU.Build.0 = Debug|Any CPU - {198DA072-F94F-4585-A744-97B3DAC21686}.Release|Any CPU.ActiveCfg = Release|Any CPU - {198DA072-F94F-4585-A744-97B3DAC21686}.Release|Any CPU.Build.0 = Release|Any CPU {82157559-DF60-496D-817F-84B34CFF76FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {82157559-DF60-496D-817F-84B34CFF76FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {82157559-DF60-496D-817F-84B34CFF76FD}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -372,14 +144,14 @@ Global {9AE6E00C-5E6F-4615-9C69-464E9B208E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU {9AE6E00C-5E6F-4615-9C69-464E9B208E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU {9AE6E00C-5E6F-4615-9C69-464E9B208E8C}.Release|Any CPU.Build.0 = Release|Any CPU - {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.Build.0 = Release|Any CPU {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.Build.0 = Debug|Any CPU {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.ActiveCfg = Release|Any CPU {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.Build.0 = Release|Any CPU + {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -387,65 +159,24 @@ Global GlobalSection(NestedProjects) = preSolution {E61EE414-3693-4C83-BDAA-17AB0024D0E6} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {2B47EC99-E383-4DFA-9130-DAF40FDA313B} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} - {02D1B220-3DAE-40E7-B5CC-86501756BF92} = {0F6B5528-642F-4C46-AB4E-15E9B6CE24F9} {E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} - {5C38C5A3-83A5-4E2F-9B32-204C2225E890} = {B5821230-6E0A-4535-88A9-ED31B6F07596} {6B64FE04-BA90-49FC-893A-DF12EF15280C} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} - {BFB2832E-C3AB-4F09-B285-B24E535EC858} = {B5821230-6E0A-4535-88A9-ED31B6F07596} {C30B77A7-4085-422E-AADE-A4322989F5F8} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {1E601406-6923-4CB9-AAD7-928E08906B10} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {B5F66802-0968-4B99-8E97-E42C744CE5CE} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {D6EAB0C1-491C-4723-B1F3-B6F5461CD359} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {4DBEC557-E5CC-41E9-9319-BC02615CF228} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {37F71B56-1FC7-4BEC-9AB4-FF57C6BF2882} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {9C305047-0B81-4DA1-98D4-BC8B391A2297} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {660B4D9D-081A-4DCA-BD7A-E196F4529BFD} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {4A5770BE-6BB7-448F-A818-DD1450F8CBDC} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {55652CF7-E58B-4564-A76B-D49DC71878DC} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {A9802FBA-CF59-462B-88A0-1D7D0D19C748} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {59EB5B01-4756-48BB-8B37-70D29E3BDFB6} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {BDA0BCB4-BD26-4B10-B865-87082F290B38} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {F63A63A9-FE09-4225-A293-6A58F9C1E520} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} {055D602D-D2B3-416B-AC59-1972D832032A} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} - {A75EA1E1-2801-460C-87C0-DE6A82D30851} = {B5821230-6E0A-4535-88A9-ED31B6F07596} - {0F6B5528-642F-4C46-AB4E-15E9B6CE24F9} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {B5821230-6E0A-4535-88A9-ED31B6F07596} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {0EA6A975-2934-4837-9932-2328EFE23BFD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {34CB5A87-0433-4C19-9CB3-E2F58119CDE9} = {0EA6A975-2934-4837-9932-2328EFE23BFD} - {059C8F76-20F9-42BD-A343-64EE3ACF1AF8} = {0F6B5528-642F-4C46-AB4E-15E9B6CE24F9} {248ACC90-D4F9-432B-B7B9-341EF00FA072} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {23AAA8FA-5B51-49BF-8021-148C8031A321} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {2A72383A-9C00-41FB-9D29-909EE5E6BFB9} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {035AAD56-5F51-476C-8556-0F6CFD6EF1BF} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {1D2A2B02-BFA8-4E53-9844-88359C5B2671} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {FC352905-BD72-4049-8D32-3CBB9304FDC8} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} - {18A09B24-8646-40A6-BD85-2773AF567453} = {B5821230-6E0A-4535-88A9-ED31B6F07596} - {9E23C9B2-7C0A-4F09-987F-0E5BDC8BE28C} = {922A387F-8595-4C74-ABF1-AEFF9530950C} - {922A387F-8595-4C74-ABF1-AEFF9530950C} = {B5821230-6E0A-4535-88A9-ED31B6F07596} - {22FCE0DF-65FE-4650-8202-765832C40E6D} = {922A387F-8595-4C74-ABF1-AEFF9530950C} {B37E6BAC-F16B-4366-94FB-8B94B52A08C9} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {65DE66B6-568F-46AC-8F0D-C79A02F48214} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} - {004DEF24-7EBB-499D-BD1C-E940AC4E122D} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {277D77B9-8915-41E3-8763-0B66328ADDDA} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {93B64F12-EBDD-46CE-B4FB-0904701F0032} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {AA4D318D-101B-49E7-A4EC-B34165AEDB33} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {B13C9E5F-0E4B-413E-90AE-20B84B100364} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} - {1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {17BDCE12-6964-4B87-B2AC-68CE270A3E9A} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {D2F67410-9933-42E8-B04A-E17634D83A30} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {AB6E1E7A-0D2C-4086-9487-566887C1E753} = {B5821230-6E0A-4535-88A9-ED31B6F07596} - {D8E79B53-9A44-46CC-9D7A-E9494FC8CAF4} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} - {B6342174-5436-4846-B43C-39D8E34AE5CF} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {198DA072-F94F-4585-A744-97B3DAC21686} = {B5821230-6E0A-4535-88A9-ED31B6F07596} {82157559-DF60-496D-817F-84B34CFF76FD} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {9AE6E00C-5E6F-4615-9C69-464E9B208E8C} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {6947034E-C97F-4F78-940F-B6A398E23C9C} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} {F7F70331-CB38-47D7-9366-F8C5D934D088} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} + {B0A6867D-2C35-4BF1-892E-CE84795525BD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} diff --git a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj index 93bfdf713..782383eba 100644 --- a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj +++ b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj @@ -14,18 +14,18 @@ + + + + + - - - - - diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index 35443895d..635fdf976 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -16,11 +16,11 @@ - - + + diff --git a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj index 48fc0247e..60c9ea99d 100644 --- a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj +++ b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj @@ -13,13 +13,13 @@ - - + + diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/Properties/AssemblyInfo.cs index 33f6f1705..794added6 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Properties/AssemblyInfo.cs @@ -3,6 +3,6 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index 23d89d2b3..b6d00e5ad 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -15,11 +15,15 @@ + - + + + + diff --git a/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj b/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj index 7aa205d47..28f75e8be 100644 --- a/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj +++ b/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj @@ -13,7 +13,10 @@ - + + + + diff --git a/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj b/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj index b9aa4156f..769980a07 100644 --- a/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj +++ b/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj @@ -13,9 +13,12 @@ - + + + + diff --git a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj index 38d7c0075..17878a447 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj +++ b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj @@ -25,7 +25,6 @@ - diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index cd0eb9504..fb21f5b80 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -14,15 +14,12 @@ - - - - - + + diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj index e70a7b744..380fb81ce 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj +++ b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj @@ -16,11 +16,11 @@ - + diff --git a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj index ec390ab98..f3d5596b0 100644 --- a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj +++ b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj @@ -12,16 +12,13 @@ - - - - - + + diff --git a/extensions/Worker.Extensions.Timer/src/Worker.Extensions.Timer.csproj b/extensions/Worker.Extensions.Timer/src/Worker.Extensions.Timer.csproj index 45290011c..27a6abf87 100644 --- a/extensions/Worker.Extensions.Timer/src/Worker.Extensions.Timer.csproj +++ b/extensions/Worker.Extensions.Timer/src/Worker.Extensions.Timer.csproj @@ -12,8 +12,11 @@ - + + + + \ No newline at end of file diff --git a/samples/AspNetIntegration/AspNetIntegration.csproj b/samples/AspNetIntegration/AspNetIntegration.csproj index 7f91c0385..2c27549cd 100644 --- a/samples/AspNetIntegration/AspNetIntegration.csproj +++ b/samples/AspNetIntegration/AspNetIntegration.csproj @@ -7,15 +7,12 @@ - - - - - - - - - + + + + + + \ No newline at end of file diff --git a/samples/DotNetWorker.Samples.slnf b/samples/DotNetWorker.Samples.slnf new file mode 100644 index 000000000..cff1084e3 --- /dev/null +++ b/samples/DotNetWorker.Samples.slnf @@ -0,0 +1,15 @@ +{ + "solution": { + "path": "..\\DotNetWorker.sln", + "projects": [ + "samples\\AspNetIntegration\\AspNetIntegration.csproj", + "samples\\Configuration\\Configuration.csproj", + "samples\\CustomMiddleware\\CustomMiddleware.csproj", + "samples\\EntityFramework\\EntityFramework.csproj", + "samples\\Extensions\\Extensions.csproj", + "samples\\FunctionApp\\FunctionApp.csproj", + "samples\\Net9FunctionApp\\Net9FunctionApp.csproj", + "samples\\NetFxWorker\\NetFxWorker.csproj" + ] + } +} \ No newline at end of file diff --git a/samples/FunctionApp/FunctionApp.csproj b/samples/FunctionApp/FunctionApp.csproj index 5423ca69a..1e19ac5ce 100644 --- a/samples/FunctionApp/FunctionApp.csproj +++ b/samples/FunctionApp/FunctionApp.csproj @@ -12,26 +12,11 @@ + + + + + - - - - - - - - - - - - diff --git a/samples/Net7Worker/.vscode/extensions.json b/samples/Net7Worker/.vscode/extensions.json deleted file mode 100644 index dde673dcd..000000000 --- a/samples/Net7Worker/.vscode/extensions.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "recommendations": [ - "ms-azuretools.vscode-azurefunctions" - ] -} \ No newline at end of file diff --git a/samples/Net7Worker/EventHubCancellationToken.cs b/samples/Net7Worker/EventHubCancellationToken.cs deleted file mode 100644 index fda0c3003..000000000 --- a/samples/Net7Worker/EventHubCancellationToken.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using Microsoft.Azure.Functions.Worker; -using Microsoft.Extensions.Logging; - -namespace Net7Worker -{ - public class EventHubCancellationToken - { - private readonly ILogger _logger; - - public EventHubCancellationToken(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - // Sample showing how to handle a cancellation token being received - // In this example, the function invocation status will be "Cancelled" - // - [Function(nameof(ThrowOnCancellation))] - public async Task ThrowOnCancellation( - [EventHubTrigger("sample-workitem-1", Connection = "EventHubConnection")] string[] messages, - FunctionContext context, - CancellationToken cancellationToken) - { - _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(ThrowOnCancellation)); - - foreach (var message in messages) - { - cancellationToken.ThrowIfCancellationRequested(); - await Task.Delay(6000); // task delay to simulate message processing - _logger.LogInformation("Message '{msg}' was processed.", message); - } - } - // - - // Sample showing how to take precautionary/clean up actions if a cancellation token is received - // In this example, the function invocation status will be "Successful" - // - [Function(nameof(HandleCancellationCleanup))] - public async Task HandleCancellationCleanup( - [EventHubTrigger("sample-workitem-2", Connection = "EventHubConnection")] string[] messages, - FunctionContext context, - CancellationToken cancellationToken) - { - _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(HandleCancellationCleanup)); - - foreach (var message in messages) - { - if (cancellationToken.IsCancellationRequested) - { - _logger.LogInformation("A cancellation token was received, taking precautionary actions."); - // Take precautions like noting how far along you are with processing the batch - _logger.LogInformation("Precautionary activities complete."); - break; - } - - await Task.Delay(6000); // task delay to simulate message processing - _logger.LogInformation("Message '{msg}' was processed.", message); - } - } - // - } -} diff --git a/samples/Net7Worker/HttpFunction.cs b/samples/Net7Worker/HttpFunction.cs deleted file mode 100644 index 0ffb79e62..000000000 --- a/samples/Net7Worker/HttpFunction.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using System.Net; -using Microsoft.Azure.Functions.Worker; -using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.Extensions.Logging; - -namespace Net7Worker -{ - public class HttpFunction - { - private readonly ILogger _logger; - - public HttpFunction(ILoggerFactory loggerFactory) - { - _logger = loggerFactory.CreateLogger(); - } - - [Function(nameof(HttpFunction))] - public HttpResponseData Run( - [HttpTrigger(AuthorizationLevel.Anonymous,"get", "post", Route = null)] HttpRequestData req, - FunctionContext executionContext) - { - _logger.LogInformation("C# HTTP trigger function processing a request."); - - var response = req.CreateResponse(HttpStatusCode.OK); - response.Headers.Add("Content-Type", "text/plain; charset=utf-8"); - response.WriteString("Welcome to Azure Functions - Isolated .NET 7!"); - - return response; - } - } -} diff --git a/samples/Net7Worker/Net7Worker.csproj b/samples/Net7Worker/Net7Worker.csproj deleted file mode 100644 index 4834f9247..000000000 --- a/samples/Net7Worker/Net7Worker.csproj +++ /dev/null @@ -1,16 +0,0 @@ - - - - net7.0 - v4 - Exe - - - - - - - - - - \ No newline at end of file diff --git a/samples/Net7Worker/Program.cs b/samples/Net7Worker/Program.cs deleted file mode 100644 index 332b923d1..000000000 --- a/samples/Net7Worker/Program.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -using Microsoft.Extensions.Hosting; - -var host = new HostBuilder() - .ConfigureFunctionsWorkerDefaults() - .Build(); - -host.Run(); diff --git a/samples/Net7Worker/Properties/launchSettings.json b/samples/Net7Worker/Properties/launchSettings.json deleted file mode 100644 index a0bd94b09..000000000 --- a/samples/Net7Worker/Properties/launchSettings.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "profiles": { - "Net7Worker": { - "commandName": "Project", - "commandLineArgs": "--port 7199", - "launchBrowser": false - } - } -} \ No newline at end of file diff --git a/samples/Net7Worker/README.md b/samples/Net7Worker/README.md deleted file mode 100644 index b2148c610..000000000 --- a/samples/Net7Worker/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# .NET Framework Worker - -This sample demonstrates how to create a .NET 7 project using the Isolated model. - -## Function Samples - -### HTTPFunction.cs - -Demonstrates basic HTTP trigger function. - -### EventHubCancellationToken.cs - -Demonstrates how to use the Cancellation Token parameter binding in the context of an -EventHub trigger sample where we are processing multiple messages. - -- `ThrowOnCancellation` - - shows how to throw when a cancellation token is received - - the status of the function will be "Cancelled" -- `HandleCancellationCleanup` - - shows how to take precautionary/clean up actions if a cancellation token is received - - the status of the function will be "Successful" - -Cancellation tokens are signalled by the platform, the use cases supported today are: - -1. Sudden host shutdown or host restart -2. Function timeout (where function execution has exceeded the timeout limit) - 1. You can try this out by setting function timeout to 5 seconds in - the host.json file: `"functionTimeout": "00:00:05"` diff --git a/samples/Net7Worker/host.json b/samples/Net7Worker/host.json deleted file mode 100644 index beb2e4020..000000000 --- a/samples/Net7Worker/host.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "2.0", - "logging": { - "applicationInsights": { - "samplingSettings": { - "isEnabled": true, - "excludedTypes": "Request" - } - } - } -} \ No newline at end of file diff --git a/samples/Net7Worker/local.settings.json b/samples/Net7Worker/local.settings.json deleted file mode 100644 index 9f0c231c0..000000000 --- a/samples/Net7Worker/local.settings.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "IsEncrypted": false, - "Values": { - "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", - "AzureWebJobsStorage": "UseDevelopmentStorage=true", - "EventHubConnection": "" - } -} \ No newline at end of file diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index f673aa8e9..25e8e596a 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -17,8 +17,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 9602aa2eb..917ffa1ee 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -18,7 +18,7 @@ - + diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index cf8640040..2d40db8b3 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -2,7 +2,7 @@ Library - net5.0;net9.0;netstandard2.0 + net8.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Core This library provides the core functionality to build an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker.Core @@ -21,27 +21,17 @@ - - - - + - - - - - - - - + - + - - + + diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index befd3a8a5..4f78300ba 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -2,7 +2,7 @@ Library - net5.0;net6.0;net7.0;net9.0;netstandard2.0 + net8.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Grpc This library provides gRPC support for Azure Functions .NET Worker communication with the Azure Functions Host. Microsoft.Azure.Functions.Worker.Grpc @@ -21,27 +21,19 @@ - + - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - + + + + + + - + diff --git a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj index 7269347c3..39f054fbe 100644 --- a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj +++ b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj @@ -25,7 +25,6 @@ - @@ -47,7 +46,7 @@ - + \ No newline at end of file diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index cf3d987f4..06a72fcb3 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -10,7 +10,7 @@ - + diff --git a/test/FunctionMetadataGeneratorTests/SdkTests.csproj b/test/FunctionMetadataGeneratorTests/SdkTests.csproj index da0bc2af8..460c8297f 100644 --- a/test/FunctionMetadataGeneratorTests/SdkTests.csproj +++ b/test/FunctionMetadataGeneratorTests/SdkTests.csproj @@ -38,8 +38,6 @@ - - diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index d0a849c7a..ab3f7e5a6 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -32,7 +32,6 @@ - diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index 538eb8d69..ca50a64be 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -27,7 +27,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -44,7 +44,6 @@ - diff --git a/test/SdkE2ETests/SdkE2ETests.csproj b/test/SdkE2ETests/SdkE2ETests.csproj index d048f470d..511948b36 100644 --- a/test/SdkE2ETests/SdkE2ETests.csproj +++ b/test/SdkE2ETests/SdkE2ETests.csproj @@ -27,10 +27,6 @@ - - - - Always diff --git a/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj b/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj index 8f64870f4..65fb26afc 100644 --- a/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj +++ b/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj @@ -26,4 +26,4 @@ - + \ No newline at end of file diff --git a/test/DotNetWorkerTests/AspNetCore/FunctionsEndpointDataSourceTests.cs b/test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs similarity index 100% rename from test/DotNetWorkerTests/AspNetCore/FunctionsEndpointDataSourceTests.cs rename to test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs diff --git a/test/DotNetWorkerTests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs b/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs similarity index 99% rename from test/DotNetWorkerTests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs rename to test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs index 634cdde6d..9c10358ed 100644 --- a/test/DotNetWorkerTests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs +++ b/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs @@ -17,6 +17,8 @@ namespace Microsoft.Azure.Functions.Worker.Tests.AspNetCore { + +#if false // Needs updates to shared types public class FunctionsHttpProxyingMiddlewareTests { [Fact] @@ -277,4 +279,5 @@ public async Task CompleteFunctionInvocation_RunsWhen_FunctionThrowsException() test.MockCoordinator.Verify(p => p.CompleteFunctionInvocation(It.IsAny()), Times.Once()); } } +#endif } diff --git a/test/DotNetWorkerTests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs b/test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs similarity index 97% rename from test/DotNetWorkerTests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs rename to test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs index 7f9fbed81..a23d452c1 100644 --- a/test/DotNetWorkerTests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs +++ b/test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Functions.Worker.Tests.AspNetCore { public class WorkerRequestServicesMiddlewareTests { +#if false // Needs updates to shared types [Fact] public async Task ServiceProviders_Equal() { @@ -52,6 +53,7 @@ public async Task ServiceProviders_Equal() private class MyService { } +#endif } } diff --git a/test/Worker.Extensions.Tests/TestBindingMetadata.cs b/test/Worker.Extensions.Tests/TestBindingMetadata.cs new file mode 100644 index 000000000..88b59e9b9 --- /dev/null +++ b/test/Worker.Extensions.Tests/TestBindingMetadata.cs @@ -0,0 +1,21 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker.Tests +{ + public class TestBindingMetadata : BindingMetadata + { + public TestBindingMetadata(string name, string type, BindingDirection direction) + { + Name = name; + Type = type; + Direction = direction; + } + + public override string Name { get; } + + public override string Type { get; } + + public override BindingDirection Direction { get; } + } +} diff --git a/test/Worker.Extensions.Tests/TestConverterContext.cs b/test/Worker.Extensions.Tests/TestConverterContext.cs new file mode 100644 index 000000000..c1c6d2bc3 --- /dev/null +++ b/test/Worker.Extensions.Tests/TestConverterContext.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Worker.Converters; + +namespace Microsoft.Azure.Functions.Worker.Tests.Converters +{ + internal class TestConverterContext : ConverterContext + { + public TestConverterContext(Type targetType, object source, FunctionContext context = null) + { + TargetType = targetType; + Source = source; + FunctionContext = context; //TODO: SharedTestFunctionContext ?? new TestFunctionContext(); + } + + public override object Source { get; } + + public override FunctionContext FunctionContext { get; } + + public override Type TargetType { get; } + + public override IReadOnlyDictionary Properties { get; } + } +} diff --git a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj index fffc0de38..e756ccfbb 100644 --- a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj +++ b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj @@ -12,6 +12,8 @@ + + @@ -25,10 +27,10 @@ + - diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/AspNetCoreHttpRequestDataTests.cs b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/AspNetCoreHttpRequestDataTests.cs index 908eb4b0e..d793d5bec 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/AspNetCoreHttpRequestDataTests.cs +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/AspNetCoreHttpRequestDataTests.cs @@ -5,61 +5,64 @@ using System.Text; using Microsoft.AspNetCore.Http; using Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore; -using Microsoft.Azure.Functions.Worker.Tests; +//using Microsoft.Azure.Functions.Worker.Tests; namespace Worker.Extensions.Http.AspNetCore.Tests { public class AspNetCoreHttpRequestDataTests { - [Fact] - public void RequestData_ExposesRequestProperties() - { - var uri = "http://localhost:808/test/123?query=test"; - var request = CreateRequest(uri, "POST", "Hello World"); + // Requires fix to share TestFunctionContext + + + //[Fact] + //public void RequestData_ExposesRequestProperties() + //{ + // var uri = "http://localhost:808/test/123?query=test"; + // var request = CreateRequest(uri, "POST", "Hello World"); - var testIdentity = new ClaimsIdentity(); - var testUser = new ClaimsPrincipal(testIdentity); - request.HttpContext.User = testUser; + // var testIdentity = new ClaimsIdentity(); + // var testUser = new ClaimsPrincipal(testIdentity); + // request.HttpContext.User = testUser; - var requestData = new AspNetCoreHttpRequestData(request, new TestFunctionContext()); + // var requestData = new AspNetCoreHttpRequestData(request, new TestFunctionContext()); - Assert.Equal(uri, requestData.Url.AbsoluteUri); - Assert.Same(request.Body, requestData.Body); - Assert.Same(testIdentity, requestData.Identities.Single()); - Assert.Equal(request.Method, requestData.Method); - } + // Assert.Equal(uri, requestData.Url.AbsoluteUri); + // Assert.Same(request.Body, requestData.Body); + // Assert.Same(testIdentity, requestData.Identities.Single()); + // Assert.Equal(request.Method, requestData.Method); + //} - [Fact] - public void RequestData_ExposesRequestCookies() - { - var uri = "http://localhost:808/test/123?query=test"; - var request = CreateRequest(uri, "POST", "Hello World"); - request.Cookies = new CookiesCollection - { - { "cookie1", "value1" }, - { "cookie2", "value2" } - }; + //[Fact] + //public void RequestData_ExposesRequestCookies() + //{ + // var uri = "http://localhost:808/test/123?query=test"; + // var request = CreateRequest(uri, "POST", "Hello World"); + // request.Cookies = new CookiesCollection + // { + // { "cookie1", "value1" }, + // { "cookie2", "value2" } + // }; - var requestData = new AspNetCoreHttpRequestData(request, new TestFunctionContext()); + // var requestData = new AspNetCoreHttpRequestData(request, new TestFunctionContext()); - Assert.Collection(requestData.Cookies, - c => Assert.Equal("cookie1:value1", $"{c.Name}:{c.Value}"), - c => Assert.Equal("cookie2:value2", $"{c.Name}:{c.Value}")); - } + // Assert.Collection(requestData.Cookies, + // c => Assert.Equal("cookie1:value1", $"{c.Name}:{c.Value}"), + // c => Assert.Equal("cookie2:value2", $"{c.Name}:{c.Value}")); + //} - private static HttpRequest CreateRequest(string uri, string method, string body) - { - var request = new DefaultHttpContext().Request; - var uriBuilder = new UriBuilder(uri); + //private static HttpRequest CreateRequest(string uri, string method, string body) + //{ + // var request = new DefaultHttpContext().Request; + // var uriBuilder = new UriBuilder(uri); - request.Scheme = uriBuilder.Scheme; - request.Host = new HostString(uriBuilder.Host, uriBuilder.Port); - request.Path = uriBuilder.Path; - request.Method = method; - request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body)); - request.QueryString = new QueryString(uriBuilder.Query); + // request.Scheme = uriBuilder.Scheme; + // request.Host = new HostString(uriBuilder.Host, uriBuilder.Port); + // request.Path = uriBuilder.Path; + // request.Method = method; + // request.Body = new MemoryStream(Encoding.UTF8.GetBytes(body)); + // request.QueryString = new QueryString(uriBuilder.Query); - return request; - } + // return request; + //} } } diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj index 271194538..84b0851be 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj @@ -34,7 +34,6 @@ - \ No newline at end of file From fb542ece07ba9529145b6b8d8cff341d780177b1 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Wed, 28 Aug 2024 23:29:44 -0700 Subject: [PATCH 007/190] Updates to main solution. Fixing unit tests. --- DotNetWorker.sln | 58 ------------------- .../DefaultFunctionInvokerTests.cs | 2 + 2 files changed, 2 insertions(+), 58 deletions(-) diff --git a/DotNetWorker.sln b/DotNetWorker.sln index f35602163..9b57a01a7 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -3,12 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.1.32228.430 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "samples", "samples", "{9D6603BD-7EA2-4D11-A69C-0D9E01317FD6}" -EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{FD7243E4-BF18-43F8-8744-BA1D17ACF378}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FunctionApp", "samples\FunctionApp\FunctionApp.csproj", "{E61EE414-3693-4C83-BDAA-17AB0024D0E6}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker", "src\DotNetWorker\DotNetWorker.csproj", "{2B47EC99-E383-4DFA-9130-DAF40FDA313B}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdk", "sdk", "{4B0D77E7-FA83-4FDD-9E67-CC95EAD21348}" @@ -42,28 +38,14 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.Grpc", "src\Do EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.Core", "src\DotNetWorker.Core\DotNetWorker.Core.csproj", "{23AAA8FA-5B51-49BF-8021-148C8031A321}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions", "samples\Extensions\Extensions.csproj", "{BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CustomMiddleware", "samples\CustomMiddleware\CustomMiddleware.csproj", "{2A72383A-9C00-41FB-9D29-909EE5E6BFB9}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EntityFramework", "samples\EntityFramework\EntityFramework.csproj", "{C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Configuration", "samples\Configuration\Configuration.csproj", "{035AAD56-5F51-476C-8556-0F6CFD6EF1BF}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generators", "sdk\Sdk.Generators\Sdk.Generators.csproj", "{F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NetFxWorker", "samples\NetFxWorker\NetFxWorker.csproj", "{B37E6BAC-F16B-4366-94FB-8B94B52A08C9}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.ApplicationInsights", "src\DotNetWorker.ApplicationInsights\DotNetWorker.ApplicationInsights.csproj", "{65DE66B6-568F-46AC-8F0D-C79A02F48214}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetIntegration", "samples\AspNetIntegration\AspNetIntegration.csproj", "{D2F67410-9933-42E8-B04A-E17634D83A30}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry", "src\DotNetWorker.OpenTelemetry\DotNetWorker.OpenTelemetry.csproj", "{82157559-DF60-496D-817F-84B34CFF76FD}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry.Tests", "test\DotNetWorker.OpenTelemetry.Tests\DotNetWorker.OpenTelemetry.Tests.csproj", "{9AE6E00C-5E6F-4615-9C69-464E9B208E8C}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Net9FunctionApp", "samples\Net9FunctionApp\Net9FunctionApp.csproj", "{F7F70331-CB38-47D7-9366-F8C5D934D088}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorkerTests", "test\DotNetWorkerTests\DotNetWorkerTests.csproj", "{B0A6867D-2C35-4BF1-892E-CE84795525BD}" EndProject Global @@ -72,10 +54,6 @@ Global Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution - {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E61EE414-3693-4C83-BDAA-17AB0024D0E6}.Release|Any CPU.Build.0 = Release|Any CPU {2B47EC99-E383-4DFA-9130-DAF40FDA313B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2B47EC99-E383-4DFA-9130-DAF40FDA313B}.Debug|Any CPU.Build.0 = Debug|Any CPU {2B47EC99-E383-4DFA-9130-DAF40FDA313B}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -104,38 +82,14 @@ Global {23AAA8FA-5B51-49BF-8021-148C8031A321}.Debug|Any CPU.Build.0 = Debug|Any CPU {23AAA8FA-5B51-49BF-8021-148C8031A321}.Release|Any CPU.ActiveCfg = Release|Any CPU {23AAA8FA-5B51-49BF-8021-148C8031A321}.Release|Any CPU.Build.0 = Release|Any CPU - {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4}.Release|Any CPU.Build.0 = Release|Any CPU - {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2A72383A-9C00-41FB-9D29-909EE5E6BFB9}.Release|Any CPU.Build.0 = Release|Any CPU - {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Release|Any CPU.ActiveCfg = Release|Any CPU - {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779}.Release|Any CPU.Build.0 = Release|Any CPU - {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Release|Any CPU.ActiveCfg = Release|Any CPU - {035AAD56-5F51-476C-8556-0F6CFD6EF1BF}.Release|Any CPU.Build.0 = Release|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Debug|Any CPU.Build.0 = Debug|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Release|Any CPU.ActiveCfg = Release|Any CPU {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E}.Release|Any CPU.Build.0 = Release|Any CPU - {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B37E6BAC-F16B-4366-94FB-8B94B52A08C9}.Release|Any CPU.Build.0 = Release|Any CPU {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Debug|Any CPU.Build.0 = Debug|Any CPU {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Release|Any CPU.ActiveCfg = Release|Any CPU {65DE66B6-568F-46AC-8F0D-C79A02F48214}.Release|Any CPU.Build.0 = Release|Any CPU - {D2F67410-9933-42E8-B04A-E17634D83A30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D2F67410-9933-42E8-B04A-E17634D83A30}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D2F67410-9933-42E8-B04A-E17634D83A30}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D2F67410-9933-42E8-B04A-E17634D83A30}.Release|Any CPU.Build.0 = Release|Any CPU {82157559-DF60-496D-817F-84B34CFF76FD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {82157559-DF60-496D-817F-84B34CFF76FD}.Debug|Any CPU.Build.0 = Debug|Any CPU {82157559-DF60-496D-817F-84B34CFF76FD}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -144,10 +98,6 @@ Global {9AE6E00C-5E6F-4615-9C69-464E9B208E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU {9AE6E00C-5E6F-4615-9C69-464E9B208E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU {9AE6E00C-5E6F-4615-9C69-464E9B208E8C}.Release|Any CPU.Build.0 = Release|Any CPU - {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {F7F70331-CB38-47D7-9366-F8C5D934D088}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.ActiveCfg = Release|Any CPU - {F7F70331-CB38-47D7-9366-F8C5D934D088}.Release|Any CPU.Build.0 = Release|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -157,7 +107,6 @@ Global HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution - {E61EE414-3693-4C83-BDAA-17AB0024D0E6} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {2B47EC99-E383-4DFA-9130-DAF40FDA313B} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {E28BAAEF-4E70-4CAB-8475-759ECBAF1AF5} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} {6B64FE04-BA90-49FC-893A-DF12EF15280C} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} @@ -165,17 +114,10 @@ Global {055D602D-D2B3-416B-AC59-1972D832032A} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} {248ACC90-D4F9-432B-B7B9-341EF00FA072} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {23AAA8FA-5B51-49BF-8021-148C8031A321} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} - {BC56E506-A2F7-46D4-95DC-BD97E5AF92D4} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {2A72383A-9C00-41FB-9D29-909EE5E6BFB9} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {C4C0CE7E-6A34-473E-A8FB-7D8FBA765779} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {035AAD56-5F51-476C-8556-0F6CFD6EF1BF} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {F77CCCE6-2DC3-48AA-8FE8-1B135B76B90E} = {4B0D77E7-FA83-4FDD-9E67-CC95EAD21348} - {B37E6BAC-F16B-4366-94FB-8B94B52A08C9} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {65DE66B6-568F-46AC-8F0D-C79A02F48214} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} - {D2F67410-9933-42E8-B04A-E17634D83A30} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {82157559-DF60-496D-817F-84B34CFF76FD} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {9AE6E00C-5E6F-4615-9C69-464E9B208E8C} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {F7F70331-CB38-47D7-9366-F8C5D934D088} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} {B0A6867D-2C35-4BF1-892E-CE84795525BD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution diff --git a/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs b/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs index 6be19eff6..cced17717 100644 --- a/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs +++ b/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs @@ -197,6 +197,8 @@ private FunctionContext CreateContext(FunctionDefinition definition = null, Func var mockServiceProvider = new Mock(MockBehavior.Strict); mockServiceProvider.Setup(a => a.GetService(typeof(IBindingCache))) .Returns(new DefaultBindingCache()); + mockServiceProvider.Setup(a => a.GetService(typeof(Microsoft.Extensions.DependencyInjection.IServiceProviderIsService))) + .Returns(null); return new TestFunctionContext(definition, invocation, CancellationToken.None, serviceProvider: mockServiceProvider.Object); } From d09cf7ae3776bb1aee655724dcd846ac59bad304 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 29 Aug 2024 00:21:35 -0700 Subject: [PATCH 008/190] Dependency updates --- .../FunctionMetadataLoaderExtension.csproj | 2 +- sdk/Sdk.Analyzers/Sdk.Analyzers.csproj | 4 ++-- sdk/Sdk.Generators/Sdk.Generators.csproj | 4 ++-- sdk/Sdk/Sdk.csproj | 11 +++++----- .../DotNetWorker.ApplicationInsights.csproj | 8 +++---- .../DotNetWorker.Core.csproj | 17 +++++++------- .../DotNetWorker.Grpc.csproj | 13 ++++++----- .../DotNetWorker.OpenTelemetry.csproj | 8 +++---- src/DotNetWorker/DotNetWorker.csproj | 9 ++++---- .../DotNetWorker.OpenTelemetry.Tests.csproj | 22 +++++++++---------- .../DotNetWorkerTests.csproj | 10 ++++----- test/TestUtility/TestUtility.csproj | 10 ++++----- 12 files changed, 60 insertions(+), 58 deletions(-) diff --git a/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj b/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj index 69074f8b4..d354b3127 100644 --- a/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj +++ b/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj @@ -10,7 +10,7 @@ - + diff --git a/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj b/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj index c43f14f4e..4e1e142d6 100644 --- a/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj +++ b/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj @@ -2,7 +2,7 @@ 2 - 1 + 2 Library true false @@ -19,7 +19,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index 25e8e596a..584198c46 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -19,12 +19,12 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 26ce304c3..71c20f050 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -1,8 +1,7 @@  - 18 - 1 + 2 -preview1 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk @@ -31,10 +30,10 @@ - - - - + + + + diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 917ffa1ee..6df5556a6 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -5,11 +5,11 @@ Microsoft.Azure.Functions.Worker.ApplicationInsights Microsoft.Azure.Functions.Worker.ApplicationInsights Microsoft.Azure.Functions.Worker.ApplicationInsights - 1 - 4 + 2 + 0 0 README.md - + -preview1 $(BeforePack);GetReleaseNotes @@ -18,7 +18,7 @@ - + diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 2d40db8b3..95f36f706 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -8,7 +8,8 @@ Microsoft.Azure.Functions.Worker.Core Microsoft.Azure.Functions.Worker.Core true - 19 + 2 + 0 0 @@ -22,16 +23,16 @@ - - - - + + + + - + - - + + diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 4f78300ba..39057f159 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -8,7 +8,8 @@ Microsoft.Azure.Functions.Worker.Grpc Microsoft.Azure.Functions.Worker.Grpc true - 17 + 2 + 0 0 -preview1 true @@ -17,18 +18,18 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index 952e9304d..698a5ce04 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -6,7 +6,7 @@ Microsoft.Azure.Functions.Worker.OpenTelemetry Microsoft.Azure.Functions.Worker.OpenTelemetry 1 - 0 + 1 0 -preview1 README.md @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index ad4fad5d9..244d6fb60 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -8,17 +8,18 @@ Microsoft.Azure.Functions.Worker Microsoft.Azure.Functions.Worker true - 23 + 2 + 0 0 - + -preview1 - - + + diff --git a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj index 5dc8fe350..6d0ea830a 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj +++ b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj @@ -2,22 +2,22 @@ net8.0 - false - Microsoft.Azure.Functions.Worker.Tests - Microsoft.Azure.Functions.Worker.Tests - true - preview - ..\..\key.snk - disable - true + false + Microsoft.Azure.Functions.Worker.Tests + Microsoft.Azure.Functions.Worker.Tests + true + preview + ..\..\key.snk + disable + true - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/DotNetWorkerTests/DotNetWorkerTests.csproj b/test/DotNetWorkerTests/DotNetWorkerTests.csproj index d556cba01..097257715 100644 --- a/test/DotNetWorkerTests/DotNetWorkerTests.csproj +++ b/test/DotNetWorkerTests/DotNetWorkerTests.csproj @@ -13,12 +13,12 @@ - + - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index 0cdd9efb7..7b7ceb2d1 100644 --- a/test/TestUtility/TestUtility.csproj +++ b/test/TestUtility/TestUtility.csproj @@ -10,11 +10,11 @@ - - - - - + + + + + From 62649ce0a408f016762349bd989443e5e670d3cc Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 29 Aug 2024 00:24:21 -0700 Subject: [PATCH 009/190] Test updates --- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- test/DotNetWorkerTests/DotNetWorkerTests.csproj | 9 +-------- test/TestUtility/TestUtility.csproj | 2 +- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 95f36f706..66fb674d9 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -11,7 +11,7 @@ 2 0 0 - + -preview1 diff --git a/test/DotNetWorkerTests/DotNetWorkerTests.csproj b/test/DotNetWorkerTests/DotNetWorkerTests.csproj index 097257715..967ebcfdc 100644 --- a/test/DotNetWorkerTests/DotNetWorkerTests.csproj +++ b/test/DotNetWorkerTests/DotNetWorkerTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 false Microsoft.Azure.Functions.Worker.Tests Microsoft.Azure.Functions.Worker.Tests @@ -30,13 +30,6 @@ - diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index 7b7ceb2d1..ff62c6e44 100644 --- a/test/TestUtility/TestUtility.csproj +++ b/test/TestUtility/TestUtility.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 Microsoft.Azure.Functions.Tests.TestUtility Microsoft.Azure.Functions.Tests.TestUtility disable From 8fb0b8dee3d070dfc0060efe7ad09790c0d907e2 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 29 Aug 2024 00:30:16 -0700 Subject: [PATCH 010/190] Updating samples dependencies --- samples/Configuration/Configuration.csproj | 2 +- samples/Extensions/Extensions.csproj | 2 +- samples/FunctionApp/FunctionApp.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/samples/Configuration/Configuration.csproj b/samples/Configuration/Configuration.csproj index fd487daab..7e4711ef4 100644 --- a/samples/Configuration/Configuration.csproj +++ b/samples/Configuration/Configuration.csproj @@ -10,7 +10,7 @@ - + diff --git a/samples/Extensions/Extensions.csproj b/samples/Extensions/Extensions.csproj index ccf024250..656ad9280 100644 --- a/samples/Extensions/Extensions.csproj +++ b/samples/Extensions/Extensions.csproj @@ -9,7 +9,7 @@ - + diff --git a/samples/FunctionApp/FunctionApp.csproj b/samples/FunctionApp/FunctionApp.csproj index 1e19ac5ce..23c1a738d 100644 --- a/samples/FunctionApp/FunctionApp.csproj +++ b/samples/FunctionApp/FunctionApp.csproj @@ -9,7 +9,7 @@ - + From 233dcbe888e1a427f6cb491376e4b1815619595a Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 29 Aug 2024 00:48:11 -0700 Subject: [PATCH 011/190] Fixing extension solution dependencies --- test/E2ETests/E2EApps/E2EApp/E2EApp.csproj | 4 ++-- test/E2ETests/E2ETests/E2ETests.csproj | 19 ++++++++++--------- test/TestUtility/TestUtility.csproj | 1 + .../Worker.Extensions.Rpc.Tests.csproj | 8 ++++---- .../Worker.Extensions.Shared.Tests.csproj | 6 +++--- ...ker.Extensions.SignalRService.Tests.csproj | 10 +++++----- .../Worker.Extensions.Tests.csproj | 8 ++++---- ...er.Extensions.Http.AspNetCore.Tests.csproj | 11 ++++++----- .../Worker.Extensions.Timer.Tests.csproj | 14 ++++++++++---- 9 files changed, 45 insertions(+), 36 deletions(-) diff --git a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj index 39f054fbe..45d9b700f 100644 --- a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj +++ b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj @@ -44,8 +44,8 @@ - - + + diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index 06a72fcb3..efd107a25 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -1,22 +1,23 @@  - net7.0 + net8.0 Microsoft.Azure.Functions.Worker.E2ETests Microsoft.Azure.Functions.Worker.E2ETests disable - - + + - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index ff62c6e44..0d266474e 100644 --- a/test/TestUtility/TestUtility.csproj +++ b/test/TestUtility/TestUtility.csproj @@ -14,6 +14,7 @@ + diff --git a/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj b/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj index af13311c8..136f879e4 100644 --- a/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj +++ b/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj @@ -11,10 +11,10 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj b/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj index 65fb26afc..ba37f24b5 100644 --- a/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj +++ b/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj @@ -9,10 +9,10 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj b/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj index adb646b0d..76de399d5 100644 --- a/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj +++ b/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj @@ -9,14 +9,14 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj index e756ccfbb..b9bb0519c 100644 --- a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj +++ b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj @@ -14,10 +14,10 @@ - - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj index 84b0851be..99ed1e4db 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Tests @@ -14,16 +14,17 @@ - + + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj b/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj index 8474952b5..d6a5b1726 100644 --- a/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj +++ b/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj @@ -13,10 +13,16 @@ - - - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + From 26dd8a189cfc6f496799d24628cd69aa092f5197 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 29 Aug 2024 00:52:42 -0700 Subject: [PATCH 012/190] Removing solution filter files --- DotNetWorker.Extensions.slnf | 46 ------------------------------- samples/DotNetWorker.Samples.slnf | 15 ---------- 2 files changed, 61 deletions(-) delete mode 100644 DotNetWorker.Extensions.slnf delete mode 100644 samples/DotNetWorker.Samples.slnf diff --git a/DotNetWorker.Extensions.slnf b/DotNetWorker.Extensions.slnf deleted file mode 100644 index 809d70b50..000000000 --- a/DotNetWorker.Extensions.slnf +++ /dev/null @@ -1,46 +0,0 @@ -{ - "solution": { - "path": "DotNetWorker.sln", - "projects": [ - "extensions\\Worker.Extensions.Abstractions\\src\\Worker.Extensions.Abstractions.csproj", - "extensions\\Worker.Extensions.CosmosDB\\src\\Worker.Extensions.CosmosDB.csproj", - "extensions\\Worker.Extensions.EventGrid\\src\\Worker.Extensions.EventGrid.csproj", - "extensions\\Worker.Extensions.EventHubs\\src\\Worker.Extensions.EventHubs.csproj", - "extensions\\Worker.Extensions.Http.AspNetCore.Analyzers\\Worker.Extensions.Http.AspNetCore.Analyzers.csproj", - "extensions\\Worker.Extensions.Http.AspNetCore\\src\\Worker.Extensions.Http.AspNetCore.csproj", - "extensions\\Worker.Extensions.Http\\src\\Worker.Extensions.Http.csproj", - "extensions\\Worker.Extensions.Kafka\\src\\Worker.Extensions.Kafka.csproj", - "extensions\\Worker.Extensions.RabbitMQ\\src\\Worker.Extensions.RabbitMQ.csproj", - "extensions\\Worker.Extensions.Rpc\\src\\Worker.Extensions.Rpc.csproj", - "extensions\\Worker.Extensions.SendGrid\\src\\Worker.Extensions.SendGrid.csproj", - "extensions\\Worker.Extensions.ServiceBus\\src\\Worker.Extensions.ServiceBus.csproj", - "extensions\\Worker.Extensions.Shared\\Worker.Extensions.Shared.csproj", - "extensions\\Worker.Extensions.SignalRService\\src\\Worker.Extensions.SignalRService.csproj", - "extensions\\Worker.Extensions.Storage.Blobs\\src\\Worker.Extensions.Storage.Blobs.csproj", - "extensions\\Worker.Extensions.Storage.Queues\\src\\Worker.Extensions.Storage.Queues.csproj", - "extensions\\Worker.Extensions.Storage\\src\\Worker.Extensions.Storage.csproj", - "extensions\\Worker.Extensions.Tables\\src\\Worker.Extensions.Tables.csproj", - "extensions\\Worker.Extensions.Timer\\src\\Worker.Extensions.Timer.csproj", - "extensions\\Worker.Extensions.Warmup\\src\\Worker.Extensions.Warmup.csproj", - "samples\\Extensions\\Extensions.csproj", - "test\\DependentAssemblyWithFunctions.NetStandard\\DependentAssemblyWithFunctions.NetStandard.csproj", - "test\\DependentAssemblyWithFunctions\\DependentAssemblyWithFunctions.csproj", - "test\\DotNetWorkerTests\\DotNetWorkerTests.csproj", - "test\\E2ETests\\E2EApps\\E2EApp\\E2EApp.csproj", - "test\\E2ETests\\E2ETests\\E2ETests.csproj", - "test\\FunctionMetadataGeneratorTests\\SdkTests.csproj", - "test\\Sdk.Analyzers.Tests\\Sdk.Analyzers.Tests.csproj", - "test\\Sdk.Generator.Tests\\Sdk.Generator.Tests.csproj", - "test\\SdkE2ETests\\SdkE2ETests.csproj", - "test\\TestUtility\\TestUtility.csproj", - "test\\Worker.Extensions.Rpc.Tests\\Worker.Extensions.Rpc.Tests.csproj", - "test\\Worker.Extensions.Sample-IncorrectImplementation\\Worker.Extensions.Sample-IncorrectImplementation.csproj", - "test\\Worker.Extensions.Sample\\Worker.Extensions.Sample.csproj", - "test\\Worker.Extensions.Shared.Tests\\Worker.Extensions.Shared.Tests.csproj", - "test\\Worker.Extensions.SignalRService.Tests\\Worker.Extensions.SignalRService.Tests.csproj", - "test\\Worker.Extensions.Tests\\Worker.Extensions.Tests.csproj", - "test\\extensions\\Worker.Extensions.Http.AspNetCore.Tests\\Worker.Extensions.Http.AspNetCore.Tests.csproj", - "test\\extensions\\Worker.Extensions.Timer.Tests\\Worker.Extensions.Timer.Tests.csproj" - ] - } -} \ No newline at end of file diff --git a/samples/DotNetWorker.Samples.slnf b/samples/DotNetWorker.Samples.slnf deleted file mode 100644 index cff1084e3..000000000 --- a/samples/DotNetWorker.Samples.slnf +++ /dev/null @@ -1,15 +0,0 @@ -{ - "solution": { - "path": "..\\DotNetWorker.sln", - "projects": [ - "samples\\AspNetIntegration\\AspNetIntegration.csproj", - "samples\\Configuration\\Configuration.csproj", - "samples\\CustomMiddleware\\CustomMiddleware.csproj", - "samples\\EntityFramework\\EntityFramework.csproj", - "samples\\Extensions\\Extensions.csproj", - "samples\\FunctionApp\\FunctionApp.csproj", - "samples\\Net9FunctionApp\\Net9FunctionApp.csproj", - "samples\\NetFxWorker\\NetFxWorker.csproj" - ] - } -} \ No newline at end of file From fad94da3c1e4a10914d141cbbfb8ef98c1129055 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 2 Sep 2024 21:49:35 -0700 Subject: [PATCH 013/190] Test updates to fix enum comparison issue --- test/DotNetWorkerTests/GrpcFunctionDefinitionTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/DotNetWorkerTests/GrpcFunctionDefinitionTests.cs b/test/DotNetWorkerTests/GrpcFunctionDefinitionTests.cs index 4ca86017b..dcbb124b1 100644 --- a/test/DotNetWorkerTests/GrpcFunctionDefinitionTests.cs +++ b/test/DotNetWorkerTests/GrpcFunctionDefinitionTests.cs @@ -124,7 +124,7 @@ public void GrpcFunctionDefinition_BlobInput_Creates() Assert.Equal(typeof(string), q.Type); Assert.Contains(PropertyBagKeys.ConverterFallbackBehavior, q.Properties.Keys); Assert.Contains(PropertyBagKeys.BindingAttributeSupportedConverters, q.Properties.Keys); - Assert.Equal("Default", q.Properties[PropertyBagKeys.ConverterFallbackBehavior].ToString()); + Assert.Equal("Allow", q.Properties[PropertyBagKeys.ConverterFallbackBehavior].ToString()); Assert.Contains(new Dictionary>().ToString(), q.Properties[PropertyBagKeys.BindingAttributeSupportedConverters].ToString()); }); @@ -182,7 +182,7 @@ public void GrpcFunctionDefinition_QueueTrigger_Creates() Assert.Equal(typeof(QueueMessage), q.Type); Assert.Contains(PropertyBagKeys.ConverterFallbackBehavior, q.Properties.Keys); Assert.Contains(PropertyBagKeys.BindingAttributeSupportedConverters, q.Properties.Keys); - Assert.Equal("Default", q.Properties[PropertyBagKeys.ConverterFallbackBehavior].ToString()); + Assert.Equal("Allow", q.Properties[PropertyBagKeys.ConverterFallbackBehavior].ToString()); Assert.Contains(new Dictionary>().ToString(), q.Properties[PropertyBagKeys.BindingAttributeSupportedConverters].ToString()); }); } @@ -231,7 +231,7 @@ public void GrpcFunctionDefinition_TableInput_Creates() Assert.Equal(typeof(TableClient), q.Type); Assert.Contains(PropertyBagKeys.ConverterFallbackBehavior, q.Properties.Keys); Assert.Contains(PropertyBagKeys.BindingAttributeSupportedConverters, q.Properties.Keys); - Assert.Equal("Default", q.Properties[PropertyBagKeys.ConverterFallbackBehavior].ToString()); + Assert.Equal("Allow", q.Properties[PropertyBagKeys.ConverterFallbackBehavior].ToString()); Assert.Contains(new Dictionary>().ToString(), q.Properties[PropertyBagKeys.BindingAttributeSupportedConverters].ToString()); }); From 42a7b58319f97fe8af49e082869f172b0b9ba450 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 2 Sep 2024 22:53:05 -0700 Subject: [PATCH 014/190] Fixing SDK tests --- DotNetWorker.sln | 21 +++++++++++ .../SdkTests.csproj | 36 +++++++++---------- .../Sdk.Analyzers.Tests.csproj | 19 +++++----- .../Sdk.Generator.Tests.csproj | 31 ++++++++-------- 4 files changed, 64 insertions(+), 43 deletions(-) diff --git a/DotNetWorker.sln b/DotNetWorker.sln index 9b57a01a7..c778039fa 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -48,6 +48,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorkerTests", "test\DotNetWorkerTests\DotNetWorkerTests.csproj", "{B0A6867D-2C35-4BF1-892E-CE84795525BD}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkTests", "test\FunctionMetadataGeneratorTests\SdkTests.csproj", "{75B18A32-D0EC-420E-9E7E-FF6846301C4D}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Analyzers.Tests", "test\Sdk.Analyzers.Tests\Sdk.Analyzers.Tests.csproj", "{C05499A2-0232-4F73-A6CA-043F0B26C485}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generator.Tests", "test\Sdk.Generator.Tests\Sdk.Generator.Tests.csproj", "{9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -102,6 +108,18 @@ Global {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.Build.0 = Release|Any CPU + {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Release|Any CPU.Build.0 = Release|Any CPU + {C05499A2-0232-4F73-A6CA-043F0B26C485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C05499A2-0232-4F73-A6CA-043F0B26C485}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C05499A2-0232-4F73-A6CA-043F0B26C485}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C05499A2-0232-4F73-A6CA-043F0B26C485}.Release|Any CPU.Build.0 = Release|Any CPU + {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -119,6 +137,9 @@ Global {82157559-DF60-496D-817F-84B34CFF76FD} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {9AE6E00C-5E6F-4615-9C69-464E9B208E8C} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {B0A6867D-2C35-4BF1-892E-CE84795525BD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {75B18A32-D0EC-420E-9E7E-FF6846301C4D} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {C05499A2-0232-4F73-A6CA-043F0B26C485} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} diff --git a/test/FunctionMetadataGeneratorTests/SdkTests.csproj b/test/FunctionMetadataGeneratorTests/SdkTests.csproj index 460c8297f..ba10764c8 100644 --- a/test/FunctionMetadataGeneratorTests/SdkTests.csproj +++ b/test/FunctionMetadataGeneratorTests/SdkTests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 Microsoft.Azure.Functions.SdkTests Microsoft.Azure.Functions.SdkTests true @@ -11,33 +11,31 @@ - - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + + + + + - - - - - - - + diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index ab3f7e5a6..5b0ae5c26 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -1,22 +1,24 @@  - net7.0 + net8.0 false $(NoWarn);NU1701;RS1014 - + + + - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -29,9 +31,8 @@ - - - + + diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index ca50a64be..c7b143210 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -26,16 +26,25 @@ - - - + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all + + + + + + + + + @@ -44,20 +53,12 @@ + + - - - - - - - - - - - + \ No newline at end of file From 0e2888f4e2b5b5db9feb03a4e3709901c6f46574 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 2 Sep 2024 23:11:30 -0700 Subject: [PATCH 015/190] Additional dependencies fixes --- DotNetWorker.sln | 40 +++++++++++++++++-- ...ntAssemblyWithFunctions.NetStandard.csproj | 4 +- .../DependentAssemblyWithFunctions.csproj | 6 +-- .../DotNetWorker.OpenTelemetry.Tests.csproj | 4 +- .../DotNetWorkerTests.csproj | 4 +- .../Sdk.Analyzers.Tests.csproj | 2 + .../Sdk.Generator.Tests.csproj | 8 ++-- ...ions.Sample-IncorrectImplementation.csproj | 1 - .../Worker.Extensions.Sample.csproj | 1 - 9 files changed, 53 insertions(+), 17 deletions(-) diff --git a/DotNetWorker.sln b/DotNetWorker.sln index c778039fa..10dfb51e4 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -54,6 +54,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Analyzers.Tests", "test EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generator.Tests", "test\Sdk.Generator.Tests\Sdk.Generator.Tests.csproj", "{9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdk", "sdk", "{E785547C-7546-469F-827C-FDF999D5D7E8}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleExtensions", "SampleExtensions", "{93473E6C-2352-497F-85DA-36E01B9579F0}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Sample", "test\Worker.Extensions.Sample\Worker.Extensions.Sample.csproj", "{B2EEC775-6185-4094-B3B5-767E11EA8B36}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Sample-IncorrectImplementation", "test\Worker.Extensions.Sample-IncorrectImplementation\Worker.Extensions.Sample-IncorrectImplementation.csproj", "{AFF31023-C302-4FE9-829C-5D219DFCDFD5}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions", "test\DependentAssemblyWithFunctions\DependentAssemblyWithFunctions.csproj", "{BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{429D067C-0846-40EF-A264-AB0C5D551CB0}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -120,6 +132,22 @@ Global {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Debug|Any CPU.Build.0 = Debug|Any CPU {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Release|Any CPU.ActiveCfg = Release|Any CPU {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}.Release|Any CPU.Build.0 = Release|Any CPU + {B2EEC775-6185-4094-B3B5-767E11EA8B36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2EEC775-6185-4094-B3B5-767E11EA8B36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2EEC775-6185-4094-B3B5-767E11EA8B36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2EEC775-6185-4094-B3B5-767E11EA8B36}.Release|Any CPU.Build.0 = Release|Any CPU + {AFF31023-C302-4FE9-829C-5D219DFCDFD5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AFF31023-C302-4FE9-829C-5D219DFCDFD5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {AFF31023-C302-4FE9-829C-5D219DFCDFD5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AFF31023-C302-4FE9-829C-5D219DFCDFD5}.Release|Any CPU.Build.0 = Release|Any CPU + {BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4}.Release|Any CPU.Build.0 = Release|Any CPU + {429D067C-0846-40EF-A264-AB0C5D551CB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {429D067C-0846-40EF-A264-AB0C5D551CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU + {429D067C-0846-40EF-A264-AB0C5D551CB0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {429D067C-0846-40EF-A264-AB0C5D551CB0}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -137,9 +165,15 @@ Global {82157559-DF60-496D-817F-84B34CFF76FD} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {9AE6E00C-5E6F-4615-9C69-464E9B208E8C} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {B0A6867D-2C35-4BF1-892E-CE84795525BD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {75B18A32-D0EC-420E-9E7E-FF6846301C4D} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {C05499A2-0232-4F73-A6CA-043F0B26C485} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {75B18A32-D0EC-420E-9E7E-FF6846301C4D} = {E785547C-7546-469F-827C-FDF999D5D7E8} + {C05499A2-0232-4F73-A6CA-043F0B26C485} = {E785547C-7546-469F-827C-FDF999D5D7E8} + {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6} = {E785547C-7546-469F-827C-FDF999D5D7E8} + {E785547C-7546-469F-827C-FDF999D5D7E8} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} + {93473E6C-2352-497F-85DA-36E01B9579F0} = {E785547C-7546-469F-827C-FDF999D5D7E8} + {B2EEC775-6185-4094-B3B5-767E11EA8B36} = {93473E6C-2352-497F-85DA-36E01B9579F0} + {AFF31023-C302-4FE9-829C-5D219DFCDFD5} = {93473E6C-2352-497F-85DA-36E01B9579F0} + {BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4} = {E785547C-7546-469F-827C-FDF999D5D7E8} + {429D067C-0846-40EF-A264-AB0C5D551CB0} = {E785547C-7546-469F-827C-FDF999D5D7E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} diff --git a/test/DependentAssemblyWithFunctions.NetStandard/DependentAssemblyWithFunctions.NetStandard.csproj b/test/DependentAssemblyWithFunctions.NetStandard/DependentAssemblyWithFunctions.NetStandard.csproj index 61b7d01bd..318062ceb 100644 --- a/test/DependentAssemblyWithFunctions.NetStandard/DependentAssemblyWithFunctions.NetStandard.csproj +++ b/test/DependentAssemblyWithFunctions.NetStandard/DependentAssemblyWithFunctions.NetStandard.csproj @@ -4,7 +4,7 @@ netstandard2.0 - - + + diff --git a/test/DependentAssemblyWithFunctions/DependentAssemblyWithFunctions.csproj b/test/DependentAssemblyWithFunctions/DependentAssemblyWithFunctions.csproj index 30892ff42..b2063e4e4 100644 --- a/test/DependentAssemblyWithFunctions/DependentAssemblyWithFunctions.csproj +++ b/test/DependentAssemblyWithFunctions/DependentAssemblyWithFunctions.csproj @@ -1,14 +1,14 @@  - net7.0 + net8.0 enable enable - - + + diff --git a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj index 6d0ea830a..ed0abce00 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj +++ b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj @@ -1,4 +1,4 @@ - + net8.0 @@ -15,7 +15,7 @@ - + all diff --git a/test/DotNetWorkerTests/DotNetWorkerTests.csproj b/test/DotNetWorkerTests/DotNetWorkerTests.csproj index 967ebcfdc..58fb7c712 100644 --- a/test/DotNetWorkerTests/DotNetWorkerTests.csproj +++ b/test/DotNetWorkerTests/DotNetWorkerTests.csproj @@ -16,7 +16,7 @@ - + all @@ -24,7 +24,7 @@ - + diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index 5b0ae5c26..9b625dc1b 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -13,6 +13,8 @@ + + all diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index c7b143210..f3fc03891 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -18,15 +18,17 @@ - - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Worker.Extensions.Sample-IncorrectImplementation/Worker.Extensions.Sample-IncorrectImplementation.csproj b/test/Worker.Extensions.Sample-IncorrectImplementation/Worker.Extensions.Sample-IncorrectImplementation.csproj index 2cd2eacff..180a7b37d 100644 --- a/test/Worker.Extensions.Sample-IncorrectImplementation/Worker.Extensions.Sample-IncorrectImplementation.csproj +++ b/test/Worker.Extensions.Sample-IncorrectImplementation/Worker.Extensions.Sample-IncorrectImplementation.csproj @@ -7,7 +7,6 @@ - diff --git a/test/Worker.Extensions.Sample/Worker.Extensions.Sample.csproj b/test/Worker.Extensions.Sample/Worker.Extensions.Sample.csproj index 2cd2eacff..180a7b37d 100644 --- a/test/Worker.Extensions.Sample/Worker.Extensions.Sample.csproj +++ b/test/Worker.Extensions.Sample/Worker.Extensions.Sample.csproj @@ -7,7 +7,6 @@ - From 3cb2104f35f1c139ab15c19c0a1b18e4a5999f9a Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 2 Sep 2024 23:27:09 -0700 Subject: [PATCH 016/190] Fixes to metadata generator tests --- .../DiagnosticResultTests.cs | 2 -- .../IntegratedTriggersAndBindingsTests.cs | 2 -- .../StorageBindingTests.cs | 2 -- 3 files changed, 6 deletions(-) diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs index db66ba29c..1b8fbab6c 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs @@ -24,7 +24,6 @@ public DiagnosticResultTests() { var abstractionsExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Abstractions.dll"); var httpExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Http.dll"); - var storageExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.dll"); var blobExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs.dll"); var queueExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues.dll"); var loggerExtension = typeof(NullLogger).Assembly; @@ -37,7 +36,6 @@ public DiagnosticResultTests() { abstractionsExtension, httpExtension, - storageExtension, blobExtension, queueExtension, loggerExtension, diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs index d8e922736..89d27ca71 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs @@ -26,7 +26,6 @@ public IntegratedTriggersAndBindingsTests() // load all extensions used in tests (match extensions tested on E2E app? Or include ALL extensions?) var abstractionsExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Abstractions.dll"); var httpExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Http.dll"); - var storageExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.dll"); var timerExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Timer.dll"); var blobExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs.dll"); var queueExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues.dll"); @@ -43,7 +42,6 @@ public IntegratedTriggersAndBindingsTests() { abstractionsExtension, httpExtension, - storageExtension, timerExtension, blobExtension, queueExtension, diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs index 7cd5d4248..ae0d7272b 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs @@ -22,7 +22,6 @@ public StorageBindingTests() // load all extensions used in tests (match extensions tested on E2E app? Or include ALL extensions?) var abstractionsExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Abstractions.dll"); var httpExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Http.dll"); - var storageExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.dll"); var queueExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues.dll"); var hostingExtension = typeof(HostBuilder).Assembly; var diExtension = typeof(DefaultServiceProviderFactory).Assembly; @@ -35,7 +34,6 @@ public StorageBindingTests() abstractionsExtension, blobExtension, httpExtension, - storageExtension, queueExtension, hostingExtension, hostingAbExtension, From ff96c692cd7b23ecc4002e6081b04cc1236b33d0 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Tue, 3 Sep 2024 08:28:17 -0700 Subject: [PATCH 017/190] Updates to extension test TFMs --- .../Worker.Extensions.Rpc.Tests.csproj | 2 +- .../Worker.Extensions.Shared.Tests.csproj | 2 +- .../Worker.Extensions.SignalRService.Tests.csproj | 2 +- test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj b/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj index 136f879e4..a32cdf765 100644 --- a/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj +++ b/test/Worker.Extensions.Rpc.Tests/Worker.Extensions.Rpc.Tests.csproj @@ -1,7 +1,7 @@  - net48;net7.0 + net48;net8.0 false true true diff --git a/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj b/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj index ba37f24b5..9387c4f4c 100644 --- a/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj +++ b/test/Worker.Extensions.Shared.Tests/Worker.Extensions.Shared.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 enable enable false diff --git a/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj b/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj index 76de399d5..4e707487e 100644 --- a/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj +++ b/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj @@ -1,7 +1,7 @@ - net7.0 + net8.0 enable enable false diff --git a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj index b9bb0519c..7659b0c88 100644 --- a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj +++ b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 false Microsoft.Azure.Functions.Worker.Extensions.Tests Microsoft.Azure.Functions.Worker.Extensions.Tests From 52c54406d28f96dc52fd4872379d24c966904856 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Tue, 3 Sep 2024 08:48:34 -0700 Subject: [PATCH 018/190] Updating end-to-end run targets --- eng/ci/templates/jobs/run-integration-tests-linux.yml | 2 +- eng/ci/templates/jobs/run-integration-tests-windows.yml | 4 ++-- .../official/jobs/build-host-prelaunch-artifacts.yml | 2 +- setup-e2e-tests.ps1 | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/eng/ci/templates/jobs/run-integration-tests-linux.yml b/eng/ci/templates/jobs/run-integration-tests-linux.yml index 0c34bb056..c5f904c4a 100644 --- a/eng/ci/templates/jobs/run-integration-tests-linux.yml +++ b/eng/ci/templates/jobs/run-integration-tests-linux.yml @@ -24,7 +24,7 @@ jobs: - template: /eng/ci/templates/steps/setup-e2e-tests.yml@self parameters: - DotnetVersion: 'net7' + DotnetVersion: 'net8' UseCoreToolsBuild: $(UseCoreToolsBuildFromIntegrationTests) SkipCosmosDBEmulator: true SkipBuildOnPack: true diff --git a/eng/ci/templates/jobs/run-integration-tests-windows.yml b/eng/ci/templates/jobs/run-integration-tests-windows.yml index 65f97aeee..3a3830678 100644 --- a/eng/ci/templates/jobs/run-integration-tests-windows.yml +++ b/eng/ci/templates/jobs/run-integration-tests-windows.yml @@ -8,8 +8,8 @@ jobs: strategy: matrix: - net7: - dotnetVersion: 'net7' + net8: + dotnetVersion: 'net8' netfx: dotnetVersion: 'netfx' diff --git a/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml b/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml index 9596cc439..4982660e2 100644 --- a/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml +++ b/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml @@ -12,7 +12,7 @@ jobs: artifact: _preLaunchAppPackages variables: - dotnetVersions: 'net8.0,net7.0,net6.0' + dotnetVersions: 'net8.0,net6.0' steps: - template: /eng/ci/templates/steps/install-dotnet.yml@self diff --git a/setup-e2e-tests.ps1 b/setup-e2e-tests.ps1 index 618709d55..c781be695 100644 --- a/setup-e2e-tests.ps1 +++ b/setup-e2e-tests.ps1 @@ -4,7 +4,7 @@ param( [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String] - [ValidateSet("net7", "netfx")] + [ValidateSet("net8", "netfx")] $DotnetVersion, [Switch] From f716b5be1844ddd4d4068667ce1e6a6d6474e00b Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 5 Sep 2024 14:10:14 -0700 Subject: [PATCH 019/190] Fixing failing tests on EndpointDataSource tests --- .../AspNetCore/FunctionsEndpointDataSourceTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs b/test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs index ebda2b1b6..301d38d96 100644 --- a/test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs +++ b/test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs @@ -35,7 +35,7 @@ public void MapHttpFunction(string routePrefix) Assert.Equal("TestFunction", endpoint.DisplayName); Assert.Equal($"{routePrefix}/TestFunction", endpoint.RoutePattern.RawText); - var endpointMetadata = endpoint.Metadata.Single() as HttpMethodMetadata; + var endpointMetadata = endpoint.Metadata.OfType().Single(); Assert.Equal(new[] { "GET", "POST" }, endpointMetadata.HttpMethods); } @@ -64,7 +64,7 @@ public void MapHttpFunction_CustomRoute() Assert.Equal("TestFunction", endpoint.DisplayName); Assert.Equal($"api/customRoute/function", endpoint.RoutePattern.RawText); - var endpointMetadata = endpoint.Metadata.Single() as HttpMethodMetadata; + var endpointMetadata = endpoint.Metadata.OfType().Single(); Assert.Equal(new[] { "GET", "POST" }, endpointMetadata.HttpMethods); } @@ -93,7 +93,7 @@ public void MapHttpFunction_CustomRoute_CaseInsensitive() Assert.Equal("TestFunction", endpoint.DisplayName); Assert.Equal($"api/customRoute/function", endpoint.RoutePattern.RawText); - var endpointMetadata = endpoint.Metadata.Single() as HttpMethodMetadata; + var endpointMetadata = endpoint.Metadata.OfType().Single(); Assert.Equal(new[] { "GET", "POST" }, endpointMetadata.HttpMethods); } @@ -121,7 +121,7 @@ public void MapHttpFunction_CustomRoute_NoHttpMethodSpecified() Assert.Equal("TestFunction", endpoint.DisplayName); Assert.Equal($"api/customRoute/function", endpoint.RoutePattern.RawText); - var endpointMetadata = endpoint.Metadata.Single() as HttpMethodMetadata; + var endpointMetadata = endpoint.Metadata.OfType().Single(); Assert.Equal([], endpointMetadata.HttpMethods); } From be980ad7c07087e17ddf7a9b9b9fd2ead34479b6 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 5 Sep 2024 14:43:46 -0700 Subject: [PATCH 020/190] Replacing `#if NET5_0_OR_GREATER` with `#if NET8_0_OR_GREATER` --- src/DotNetWorker.Core/Converters/JsonPocoConverter.cs | 2 +- src/DotNetWorker.Core/Converters/MemoryConverter.cs | 2 +- .../Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs | 2 +- .../Invocation/DefaultMethodInfoLocator.cs | 4 ++-- src/DotNetWorker.Core/StartupHook.cs | 2 +- src/DotNetWorker.Core/WorkerInformation.cs | 2 +- src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs | 2 +- src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs | 4 ++-- src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs | 8 ++++---- .../NativeHostIntegration/NativeMethods.cs | 9 --------- 10 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs b/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs index ebce118b6..800c0a3d4 100644 --- a/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs +++ b/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs @@ -75,7 +75,7 @@ private async Task GetConversionResultFromDeserialization(byte { if (stream != null) { -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER await ((IAsyncDisposable)stream).DisposeAsync(); #else diff --git a/src/DotNetWorker.Core/Converters/MemoryConverter.cs b/src/DotNetWorker.Core/Converters/MemoryConverter.cs index 55685f422..28fdbedce 100644 --- a/src/DotNetWorker.Core/Converters/MemoryConverter.cs +++ b/src/DotNetWorker.Core/Converters/MemoryConverter.cs @@ -18,7 +18,7 @@ public ValueTask ConvertAsync(ConverterContext context) if (context.TargetType.IsAssignableFrom(typeof(string))) { -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER var target = Encoding.UTF8.GetString(sourceMemory.Span); #else var target = Encoding.UTF8.GetString(sourceMemory.Span.ToArray()); diff --git a/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs b/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs index 9516b0d10..ec7cb6fe7 100644 --- a/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs +++ b/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs @@ -13,7 +13,7 @@ internal static class ObjectDisposedThrowHelper /// The is . internal static void ThrowIf(bool condition, object instance) { -#if NET7_0_OR_GREATER +#if NET8_0_OR_GREATER ObjectDisposedException.ThrowIf(condition, instance); #else if (condition) diff --git a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs index a63a44f9e..0d149f1f6 100644 --- a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs +++ b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs @@ -1,6 +1,6 @@ using System; using System.Reflection; -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER using System.Runtime.Loader; #endif using System.Text.RegularExpressions; @@ -21,7 +21,7 @@ public MethodInfo GetMethod(string pathToAssembly, string entryPoint) string typeName = entryPointMatch.Groups["typename"].Value; string methodName = entryPointMatch.Groups["methodname"].Value; -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(pathToAssembly); #else Assembly assembly = Assembly.LoadFrom(pathToAssembly); diff --git a/src/DotNetWorker.Core/StartupHook.cs b/src/DotNetWorker.Core/StartupHook.cs index 18fe2fd86..575b8513f 100644 --- a/src/DotNetWorker.Core/StartupHook.cs +++ b/src/DotNetWorker.Core/StartupHook.cs @@ -32,7 +32,7 @@ public static void Initialize() RemoveSelfFromStartupHooks(); string? debuggerWaitEnabled = Environment.GetEnvironmentVariable("FUNCTIONS_ENABLE_DEBUGGER_WAIT"); string? jsonOutputEnabled = Environment.GetEnvironmentVariable("FUNCTIONS_ENABLE_JSON_OUTPUT"); -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER int processId = Environment.ProcessId; #else int processId = Process.GetCurrentProcess().Id; diff --git a/src/DotNetWorker.Core/WorkerInformation.cs b/src/DotNetWorker.Core/WorkerInformation.cs index 843e10021..35e7482b0 100644 --- a/src/DotNetWorker.Core/WorkerInformation.cs +++ b/src/DotNetWorker.Core/WorkerInformation.cs @@ -20,7 +20,7 @@ internal sealed class WorkerInformation public static WorkerInformation Instance = new(); -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER public int ProcessId => Environment.ProcessId; public string RuntimeIdentifier => RuntimeInformation.RuntimeIdentifier; diff --git a/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs b/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs index 6e4b10587..c8356da7b 100644 --- a/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs +++ b/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs @@ -54,7 +54,7 @@ public static IServiceCollection AddGrpc(this IServiceCollection services) services.TryAddSingleton(); services.TryAddSingleton(); -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER // If we are running in the native host process, use the native client // for communication (interop). Otherwise; use the gRPC client. if (AppContext.GetData("AZURE_FUNCTIONS_NATIVE_HOST") is not null) diff --git a/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs b/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs index b34fff467..aecb5f093 100644 --- a/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs +++ b/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Options; using static Microsoft.Azure.Functions.Worker.Grpc.Messages.FunctionRpc; -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER using Grpc.Net.Client; #else using GrpcCore = Grpc.Core; @@ -104,7 +104,7 @@ private async Task StartReaderAsync(IAsyncStreamReader respons private FunctionRpcClient CreateClient() { -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER GrpcChannel grpcChannel = GrpcChannel.ForAddress(_startupOptions.HostEndpoint!.AbsoluteUri, new GrpcChannelOptions() { MaxReceiveMessageSize = _startupOptions.GrpcMaxMessageLength, diff --git a/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs b/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs index 087624234..d4a7118a0 100644 --- a/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs +++ b/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs @@ -13,7 +13,7 @@ namespace Microsoft.Azure.Functions.Worker { internal class GrpcHttpRequestData : HttpRequestData, IDisposable -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER , IAsyncDisposable #endif { @@ -73,7 +73,7 @@ public override Stream Body } var stream = new MemoryStream(memory.Length); -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER stream.Write(memory.Span); #else stream.Write(memory.Span.ToArray(), 0, memory.Span.Length); @@ -127,7 +127,7 @@ public override HttpResponseData CreateResponse() return new GrpcHttpResponseData(FunctionContext, System.Net.HttpStatusCode.OK); } -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER public ValueTask DisposeAsync() { return _bodyStream?.DisposeAsync() ?? ValueTask.CompletedTask; @@ -159,7 +159,7 @@ private IReadOnlyCollection ToHttpCookies(string cookieString) List httpCookiesList = new List(separateCookies.Length); -#if NET5_0_OR_GREATER +#if NET8_0_OR_GREATER var separator = '='; #else var separator = new[] { '=' }; diff --git a/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs b/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs index ebaeea44c..7a57591d4 100644 --- a/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs +++ b/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs @@ -49,16 +49,7 @@ private static IntPtr ImportResolver(string libraryName, System.Reflection.Assem { if (libraryName == NativeWorkerDll) { -#if NET6_0 - if (OperatingSystem.IsLinux()) - { - return NativeLibraryLinux.GetMainProgramHandle(); - } -#elif NET7_0_OR_GREATER return NativeLibrary.GetMainProgramHandle(); -#else - throw new PlatformNotSupportedException("Interop communication with FunctionsNetHost is not supported in the current platform. Consider upgrading your project to .NET 7.0 or later."); -#endif } // Return 0 so that built-in resolving code will be executed. From 15c0a8063f47cc8103b847eeee045edf8ff61d65 Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Thu, 5 Sep 2024 14:57:00 -0700 Subject: [PATCH 021/190] adding FunctionsWebApplicationBuilder --- .../src/BootstrapHostBuilder.cs | 102 ++++++++++++++++++ .../src/FunctionsWebApplicationBuilder.cs | 89 +++++++++++++++ .../Worker.Extensions.Http.AspNetCore.csproj | 2 + 3 files changed, 193 insertions(+) create mode 100644 extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs create mode 100644 extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs new file mode 100644 index 000000000..dda53d64c --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs @@ -0,0 +1,102 @@ +using System; +using System.Collections.Generic; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Microsoft.Azure.Functions.Worker.Hosting +{ + internal class BootstrapHostBuilder : IHostBuilder + { + private readonly HostApplicationBuilder _builder; + + private readonly List> _configureHostActions = new(); + private readonly List> _configureAppActions = new(); + private readonly List> _configureServicesActions = new(); + + public BootstrapHostBuilder(HostApplicationBuilder builder) + { + _builder = builder; + + foreach (var descriptor in _builder.Services) + { + if (descriptor.ServiceType == typeof(HostBuilderContext)) + { + Context = (HostBuilderContext)descriptor.ImplementationInstance!; + break; + } + } + + if (Context is null) + { + throw new InvalidOperationException($"{nameof(HostBuilderContext)} must exist in the {nameof(IServiceCollection)}"); + } + } + + public IDictionary Properties => Context.Properties; + + public HostBuilderContext Context { get; } + + public IHostBuilder ConfigureAppConfiguration(Action configureDelegate) + { + _configureAppActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); + return this; + } + + public IHostBuilder ConfigureHostConfiguration(Action configureDelegate) + { + _configureHostActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); + return this; + } + + public IHostBuilder ConfigureServices(Action configureDelegate) + { + _configureServicesActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); + return this; + } + + public IHost Build() + { + // ConfigureWebHostDefaults should never call this. + throw new InvalidOperationException(); + } + + public IHostBuilder ConfigureContainer(Action configureDelegate) + { + // ConfigureWebHostDefaults should never call this. + throw new InvalidOperationException(); + } + + public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory) where TContainerBuilder : notnull + { + // ConfigureWebHostDefaults should never call this. + throw new InvalidOperationException(); + } + + public IHostBuilder UseServiceProviderFactory(Func> factory) where TContainerBuilder : notnull + { + // ConfigureWebHostDefaults should never call this. + throw new InvalidOperationException(); + } + + public void RunDefaultCallbacks() + { + foreach (var configureHostAction in _configureHostActions) + { + configureHostAction(_builder.Configuration); + } + + // ConfigureAppConfiguration cannot modify the host configuration because doing so could + // change the environment, content root and application name which is not allowed at this stage. + foreach (var configureAppAction in _configureAppActions) + { + configureAppAction(Context, _builder.Configuration); + } + + foreach (var configureServicesAction in _configureServicesActions) + { + configureServicesAction(Context, _builder.Services); + } + } + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs new file mode 100644 index 000000000..c639d0d24 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using Microsoft.AspNetCore.Hosting; +using Microsoft.Azure.Functions.Worker.Hosting; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.Hosting +{ + /// + /// Placeholder + /// + public class FunctionsWebApplicationBuilder : IHostApplicationBuilder + { + private readonly HostApplicationBuilder _hostApplicationBuilder; + + internal FunctionsWebApplicationBuilder() + { + var configuration = new ConfigurationManager(); + + _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings + { + Configuration = configuration + }); + + var bootstrapHostBuilder = new BootstrapHostBuilder(_hostApplicationBuilder); + bootstrapHostBuilder.ConfigureFunctionsWebApplication(); + + InitializeHosting(bootstrapHostBuilder); + } + + /// + public IDictionary Properties => ((IHostApplicationBuilder)_hostApplicationBuilder).Properties; + + IConfigurationManager IHostApplicationBuilder.Configuration => Configuration; + + /// + public ConfigurationManager Configuration => _hostApplicationBuilder.Configuration; + + /// + public IHostEnvironment Environment { get; private set; } + + /// + public ILoggingBuilder Logging => _hostApplicationBuilder.Logging; + + /// + public IMetricsBuilder Metrics => _hostApplicationBuilder.Metrics; + + /// + public IServiceCollection Services => _hostApplicationBuilder.Services; + + /// + /// Placeholder + /// + /// placeholder + public static FunctionsWebApplicationBuilder CreateBuilder() + { + return new FunctionsWebApplicationBuilder(); + } + + /// + /// Placeholder + /// + /// placeholder + public IHost Build() + { + return _hostApplicationBuilder.Build(); + } + + /// + public void ConfigureContainer(IServiceProviderFactory factory, Action? configure = null) where TContainerBuilder : notnull + => _hostApplicationBuilder.ConfigureContainer(factory, configure); + + private void InitializeHosting(BootstrapHostBuilder bootstrapHostBuilder) + { + bootstrapHostBuilder.RunDefaultCallbacks(); + + // Grab the WebHostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then + // grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection. + var webHostContext = (WebHostBuilderContext)bootstrapHostBuilder.Properties[typeof(WebHostBuilderContext)]; + Environment = webHostContext.HostingEnvironment; + + //Host = new ConfigureHostBuilder(bootstrapHostBuilder.Context, Configuration, Services); + //WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services); + } + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index b6d00e5ad..a3c930949 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -24,6 +24,8 @@ + + From a7b106277b99bdafefc9b4b30193765ffc747580 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 5 Sep 2024 15:02:52 -0700 Subject: [PATCH 022/190] Fixing path separator character to work with both linux and windows.Build DotnetWorker.Extensions.sln as well for tests --- .../templates/jobs/run-integration-tests-linux.yml | 5 +++-- .../jobs/run-integration-tests-windows.yml | 4 +++- eng/ci/templates/jobs/run-unit-tests.yml | 14 +++++++------- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/eng/ci/templates/jobs/run-integration-tests-linux.yml b/eng/ci/templates/jobs/run-integration-tests-linux.yml index c5f904c4a..f2b53e85d 100644 --- a/eng/ci/templates/jobs/run-integration-tests-linux.yml +++ b/eng/ci/templates/jobs/run-integration-tests-linux.yml @@ -20,7 +20,9 @@ jobs: inputs: command: build arguments: '-c Release' - projects: DotNetWorker.sln + projects: | + DotNetWorker.sln + DotNetWorker.Extensions.sln - template: /eng/ci/templates/steps/setup-e2e-tests.yml@self parameters: @@ -36,4 +38,3 @@ jobs: arguments: '--no-build -c Release --filter "FullyQualifiedName~HttpTrigger"' # only run http tests to avoid emulators on Linux projects: | test/**/*Tests.csproj - !test/**/Worker.Extensions.Rpc.Tests.csproj diff --git a/eng/ci/templates/jobs/run-integration-tests-windows.yml b/eng/ci/templates/jobs/run-integration-tests-windows.yml index 3a3830678..9da281200 100644 --- a/eng/ci/templates/jobs/run-integration-tests-windows.yml +++ b/eng/ci/templates/jobs/run-integration-tests-windows.yml @@ -30,7 +30,9 @@ jobs: inputs: command: build arguments: '-c Release' - projects: DotNetWorker.sln + projects: | + DotNetWorker.sln + DotNetWorker.Extensions.sln - template: /eng/ci/templates/steps/setup-e2e-tests.yml@self parameters: diff --git a/eng/ci/templates/jobs/run-unit-tests.yml b/eng/ci/templates/jobs/run-unit-tests.yml index 241359e64..b50cc4ce9 100644 --- a/eng/ci/templates/jobs/run-unit-tests.yml +++ b/eng/ci/templates/jobs/run-unit-tests.yml @@ -30,7 +30,7 @@ jobs: command: test arguments: -v n projects: | - **\DotNetWorkerTests.csproj + **/DotNetWorkerTests.csproj - task: DotNetCoreCLI@2 displayName: OpenTelemetry Tests @@ -38,7 +38,7 @@ jobs: command: test arguments: -v n projects: | - **\DotNetWorker.Opentelemetry.Tests.csproj + **/DotNetWorker.Opentelemetry.Tests.csproj - task: DotNetCoreCLI@2 displayName: Sdk Tests @@ -56,8 +56,8 @@ jobs: command: test arguments: -v n projects: | - **\Worker.Extensions.Http.AspNetCore.Tests.csproj - **\Worker.Extensions.Rpc.Tests.csproj - **\Worker.Extensions.Shared.Tests.csproj - **\Worker.Extensions.SignalRService.Tests.csproj - **\Worker.Extensions.Tests.csproj + **/Worker.Extensions.Http.AspNetCore.Tests.csproj + **/Worker.Extensions.Rpc.Tests.csproj + **/Worker.Extensions.Shared.Tests.csproj + **/Worker.Extensions.SignalRService.Tests.csproj + **/Worker.Extensions.Tests.csproj From 2413f0f7e79774bed38a24bcc41e5b2e59c14ee8 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Fri, 6 Sep 2024 16:10:37 -0700 Subject: [PATCH 023/190] Fixing gRPC project references --- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 39057f159..e128861ae 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -28,6 +28,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + @@ -55,7 +56,6 @@ - From 472c38b0c655f9760c9c09efe442836e4f99ee57 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Fri, 6 Sep 2024 16:10:53 -0700 Subject: [PATCH 024/190] Adding basic support for dotnet run --- .../Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index b61ae0c13..40f57986f 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -80,6 +80,15 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and + + + + func + host start $(RunArguments) + $(OutDir) + + + Date: Fri, 6 Sep 2024 16:49:00 -0700 Subject: [PATCH 025/190] Ensuring Extensions.Abstractions references are consistent across extesnsion projects --- .../src/Worker.Extensions.Storage.Blobs.csproj | 5 ++++- .../src/Worker.Extensions.Tables.csproj | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index fb21f5b80..6f4760c10 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -14,12 +14,15 @@ + + + + - diff --git a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj index f3d5596b0..54b872ea3 100644 --- a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj +++ b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj @@ -12,13 +12,16 @@ + + + + - From cebd9ab08b0967be4aafc43dc83de17d0db240b3 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 9 Sep 2024 10:19:07 -0700 Subject: [PATCH 026/190] Adding and fixing SDK E2E tests --- DotNetWorker.sln | 7 +++++++ .../DotNetWorker.OpenTelemetry.Tests.csproj | 2 +- test/DotNetWorkerTests/DotNetWorkerTests.csproj | 2 +- .../SdkTests.csproj | 2 +- .../Sdk.Analyzers.Tests.csproj | 2 +- .../Sdk.Generator.Tests.csproj | 2 +- test/SdkE2ETests/SdkE2ETests.csproj | 16 ++++++++++------ 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/DotNetWorker.sln b/DotNetWorker.sln index 10dfb51e4..d2b6206ec 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -66,6 +66,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFuncti EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{429D067C-0846-40EF-A264-AB0C5D551CB0}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SdkE2ETests", "test\SdkE2ETests\SdkE2ETests.csproj", "{750993F6-4E3B-411B-9471-74CEA4F9C23A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -148,6 +150,10 @@ Global {429D067C-0846-40EF-A264-AB0C5D551CB0}.Debug|Any CPU.Build.0 = Debug|Any CPU {429D067C-0846-40EF-A264-AB0C5D551CB0}.Release|Any CPU.ActiveCfg = Release|Any CPU {429D067C-0846-40EF-A264-AB0C5D551CB0}.Release|Any CPU.Build.0 = Release|Any CPU + {750993F6-4E3B-411B-9471-74CEA4F9C23A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {750993F6-4E3B-411B-9471-74CEA4F9C23A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {750993F6-4E3B-411B-9471-74CEA4F9C23A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {750993F6-4E3B-411B-9471-74CEA4F9C23A}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -174,6 +180,7 @@ Global {AFF31023-C302-4FE9-829C-5D219DFCDFD5} = {93473E6C-2352-497F-85DA-36E01B9579F0} {BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4} = {E785547C-7546-469F-827C-FDF999D5D7E8} {429D067C-0846-40EF-A264-AB0C5D551CB0} = {E785547C-7546-469F-827C-FDF999D5D7E8} + {750993F6-4E3B-411B-9471-74CEA4F9C23A} = {E785547C-7546-469F-827C-FDF999D5D7E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} diff --git a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj index ed0abce00..23a7cd5d8 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj +++ b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj @@ -14,7 +14,7 @@ - + diff --git a/test/DotNetWorkerTests/DotNetWorkerTests.csproj b/test/DotNetWorkerTests/DotNetWorkerTests.csproj index 58fb7c712..d7f87d381 100644 --- a/test/DotNetWorkerTests/DotNetWorkerTests.csproj +++ b/test/DotNetWorkerTests/DotNetWorkerTests.csproj @@ -15,7 +15,7 @@ - + diff --git a/test/FunctionMetadataGeneratorTests/SdkTests.csproj b/test/FunctionMetadataGeneratorTests/SdkTests.csproj index ba10764c8..6b2913f56 100644 --- a/test/FunctionMetadataGeneratorTests/SdkTests.csproj +++ b/test/FunctionMetadataGeneratorTests/SdkTests.csproj @@ -13,7 +13,7 @@ - + diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index 9b625dc1b..6077851f7 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -9,7 +9,7 @@ - + diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index f3fc03891..ce416eaac 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -26,7 +26,7 @@ - + diff --git a/test/SdkE2ETests/SdkE2ETests.csproj b/test/SdkE2ETests/SdkE2ETests.csproj index 511948b36..48beac730 100644 --- a/test/SdkE2ETests/SdkE2ETests.csproj +++ b/test/SdkE2ETests/SdkE2ETests.csproj @@ -1,7 +1,7 @@  - net7.0 + net8.0 Microsoft.Azure.Functions.SdkE2ETests Microsoft.Azure.Functions.SdkE2ETests true @@ -17,16 +17,20 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive + + + + Always From 3d2472c0664039e951a5693d1da141046d809bee Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 9 Sep 2024 17:33:37 -0700 Subject: [PATCH 027/190] Adding ASP.NET Core Analyzers project to extensions solution --- DotNetWorker.Extensions.sln | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/DotNetWorker.Extensions.sln b/DotNetWorker.Extensions.sln index dfc97f665..940dc4111 100644 --- a/DotNetWorker.Extensions.sln +++ b/DotNetWorker.Extensions.sln @@ -82,10 +82,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Http.AspN EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Shared.Tests", "test\Worker.Extensions.Shared.Tests\Worker.Extensions.Shared.Tests.csproj", "{B6342174-5436-4846-B43C-39D8E34AE5CF}" 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}") = "Worker.Extensions.Timer.Tests", "test\extensions\Worker.Extensions.Timer.Tests\Worker.Extensions.Timer.Tests.csproj", "{6947034E-C97F-4F78-940F-B6A398E23C9C}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.Extensions.Http.AspNetCore.Analyzers", "extensions\Worker.Extensions.Http.AspNetCore.Analyzers\src\Worker.Extensions.Http.AspNetCore.Analyzers.csproj", "{914B3E60-DE19-4827-956F-22080C817820}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -200,14 +200,14 @@ Global {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 {B6342174-5436-4846-B43C-39D8E34AE5CF}.Release|Any CPU.Build.0 = Release|Any CPU - {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Release|Any CPU.ActiveCfg = Release|Any CPU - {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B}.Release|Any CPU.Build.0 = Release|Any CPU {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6947034E-C97F-4F78-940F-B6A398E23C9C}.Debug|Any CPU.Build.0 = Debug|Any CPU {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.ActiveCfg = Release|Any CPU {6947034E-C97F-4F78-940F-B6A398E23C9C}.Release|Any CPU.Build.0 = Release|Any CPU + {914B3E60-DE19-4827-956F-22080C817820}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {914B3E60-DE19-4827-956F-22080C817820}.Debug|Any CPU.Build.0 = Debug|Any CPU + {914B3E60-DE19-4827-956F-22080C817820}.Release|Any CPU.ActiveCfg = Release|Any CPU + {914B3E60-DE19-4827-956F-22080C817820}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -243,8 +243,8 @@ Global {17BDCE12-6964-4B87-B2AC-68CE270A3E9A} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {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} {6947034E-C97F-4F78-940F-B6A398E23C9C} = {AA4D318D-101B-49E7-A4EC-B34165AEDB33} + {914B3E60-DE19-4827-956F-22080C817820} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} From 7ab7799fe58c30dcef443eaf6090afb9fc69eb59 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Tue, 10 Sep 2024 09:52:58 -0700 Subject: [PATCH 028/190] Updating ASP.NET Core extension version --- .../src/Worker.Extensions.Http.AspNetCore.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index a3c930949..9ccf445e2 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -6,7 +6,8 @@ ASP.NET Core extensions for .NET isolated functions - 1.3.3 + 2.0.0 + -preview1 net6.0 From 8b33b41d0ec7ad9dee435f7760e9c193bfd842b5 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Tue, 10 Sep 2024 11:40:10 -0700 Subject: [PATCH 029/190] Switching default extension builds to Windows --- .../Worker.Extensions.Abstractions/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Abstractions/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.CosmosDB/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.CosmosDB/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.EventGrid/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.EventGrid/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.EventHubs/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.EventHubs/ci/public-build.yml | 4 ++-- .../Worker.Extensions.Http.AspNetCore/ci/official-build.yml | 4 ++-- .../Worker.Extensions.Http.AspNetCore/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Http/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Http/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Kafka/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Kafka/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.RabbitMQ/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Rpc/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Rpc/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.SendGrid/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.SendGrid/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.ServiceBus/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.ServiceBus/ci/public-build.yml | 4 ++-- .../Worker.Extensions.SignalRService/ci/official-build.yml | 4 ++-- .../Worker.Extensions.SignalRService/ci/public-build.yml | 4 ++-- .../Worker.Extensions.Storage.Blobs/ci/official-build.yml | 4 ++-- .../Worker.Extensions.Storage.Blobs/ci/public-build.yml | 4 ++-- .../Worker.Extensions.Storage.Queues/ci/official-build.yml | 4 ++-- .../Worker.Extensions.Storage.Queues/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Storage/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Storage/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Tables/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Tables/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Timer/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Timer/ci/public-build.yml | 4 ++-- extensions/Worker.Extensions.Warmup/ci/official-build.yml | 4 ++-- extensions/Worker.Extensions.Warmup/ci/public-build.yml | 4 ++-- 36 files changed, 72 insertions(+), 72 deletions(-) diff --git a/extensions/Worker.Extensions.Abstractions/ci/official-build.yml b/extensions/Worker.Extensions.Abstractions/ci/official-build.yml index f0187b3b0..4b87a0f57 100644 --- a/extensions/Worker.Extensions.Abstractions/ci/official-build.yml +++ b/extensions/Worker.Extensions.Abstractions/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Abstractions/ci/public-build.yml b/extensions/Worker.Extensions.Abstractions/ci/public-build.yml index 4795d120a..1034d2b13 100644 --- a/extensions/Worker.Extensions.Abstractions/ci/public-build.yml +++ b/extensions/Worker.Extensions.Abstractions/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.CosmosDB/ci/official-build.yml b/extensions/Worker.Extensions.CosmosDB/ci/official-build.yml index abbd4ab68..86938faf6 100644 --- a/extensions/Worker.Extensions.CosmosDB/ci/official-build.yml +++ b/extensions/Worker.Extensions.CosmosDB/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.CosmosDB/ci/public-build.yml b/extensions/Worker.Extensions.CosmosDB/ci/public-build.yml index 70c836505..3e44bd491 100644 --- a/extensions/Worker.Extensions.CosmosDB/ci/public-build.yml +++ b/extensions/Worker.Extensions.CosmosDB/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.EventGrid/ci/official-build.yml b/extensions/Worker.Extensions.EventGrid/ci/official-build.yml index 507328f57..613efd388 100644 --- a/extensions/Worker.Extensions.EventGrid/ci/official-build.yml +++ b/extensions/Worker.Extensions.EventGrid/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.EventGrid/ci/public-build.yml b/extensions/Worker.Extensions.EventGrid/ci/public-build.yml index d95e3f1e2..ebb41e23c 100644 --- a/extensions/Worker.Extensions.EventGrid/ci/public-build.yml +++ b/extensions/Worker.Extensions.EventGrid/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.EventHubs/ci/official-build.yml b/extensions/Worker.Extensions.EventHubs/ci/official-build.yml index 27e2f92a4..8c9ac6cc5 100644 --- a/extensions/Worker.Extensions.EventHubs/ci/official-build.yml +++ b/extensions/Worker.Extensions.EventHubs/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.EventHubs/ci/public-build.yml b/extensions/Worker.Extensions.EventHubs/ci/public-build.yml index ef68d1e36..5908bdc6d 100644 --- a/extensions/Worker.Extensions.EventHubs/ci/public-build.yml +++ b/extensions/Worker.Extensions.EventHubs/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Http.AspNetCore/ci/official-build.yml b/extensions/Worker.Extensions.Http.AspNetCore/ci/official-build.yml index 170ccb457..38abcaf38 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/ci/official-build.yml +++ b/extensions/Worker.Extensions.Http.AspNetCore/ci/official-build.yml @@ -36,8 +36,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Http.AspNetCore/ci/public-build.yml b/extensions/Worker.Extensions.Http.AspNetCore/ci/public-build.yml index 6e712e2aa..81e472b94 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/ci/public-build.yml +++ b/extensions/Worker.Extensions.Http.AspNetCore/ci/public-build.yml @@ -44,8 +44,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Http/ci/official-build.yml b/extensions/Worker.Extensions.Http/ci/official-build.yml index c6b93d56f..8abadd548 100644 --- a/extensions/Worker.Extensions.Http/ci/official-build.yml +++ b/extensions/Worker.Extensions.Http/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Http/ci/public-build.yml b/extensions/Worker.Extensions.Http/ci/public-build.yml index 58336e9f9..011ddfeae 100644 --- a/extensions/Worker.Extensions.Http/ci/public-build.yml +++ b/extensions/Worker.Extensions.Http/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Kafka/ci/official-build.yml b/extensions/Worker.Extensions.Kafka/ci/official-build.yml index 899670150..71f758bfa 100644 --- a/extensions/Worker.Extensions.Kafka/ci/official-build.yml +++ b/extensions/Worker.Extensions.Kafka/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Kafka/ci/public-build.yml b/extensions/Worker.Extensions.Kafka/ci/public-build.yml index 3ddb3878c..b6395af8f 100644 --- a/extensions/Worker.Extensions.Kafka/ci/public-build.yml +++ b/extensions/Worker.Extensions.Kafka/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.RabbitMQ/ci/official-build.yml b/extensions/Worker.Extensions.RabbitMQ/ci/official-build.yml index 11d517d22..4566a21bb 100644 --- a/extensions/Worker.Extensions.RabbitMQ/ci/official-build.yml +++ b/extensions/Worker.Extensions.RabbitMQ/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml b/extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml index 7232c3074..c3700a646 100644 --- a/extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml +++ b/extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Rpc/ci/official-build.yml b/extensions/Worker.Extensions.Rpc/ci/official-build.yml index 4dbb8820d..49e4ff463 100644 --- a/extensions/Worker.Extensions.Rpc/ci/official-build.yml +++ b/extensions/Worker.Extensions.Rpc/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Rpc/ci/public-build.yml b/extensions/Worker.Extensions.Rpc/ci/public-build.yml index 84d671352..229b3ed68 100644 --- a/extensions/Worker.Extensions.Rpc/ci/public-build.yml +++ b/extensions/Worker.Extensions.Rpc/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.SendGrid/ci/official-build.yml b/extensions/Worker.Extensions.SendGrid/ci/official-build.yml index aa8a963e5..6b2e0b4fc 100644 --- a/extensions/Worker.Extensions.SendGrid/ci/official-build.yml +++ b/extensions/Worker.Extensions.SendGrid/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.SendGrid/ci/public-build.yml b/extensions/Worker.Extensions.SendGrid/ci/public-build.yml index b47181cdb..05afcc87e 100644 --- a/extensions/Worker.Extensions.SendGrid/ci/public-build.yml +++ b/extensions/Worker.Extensions.SendGrid/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.ServiceBus/ci/official-build.yml b/extensions/Worker.Extensions.ServiceBus/ci/official-build.yml index 36e723bd5..f1f10b0cf 100644 --- a/extensions/Worker.Extensions.ServiceBus/ci/official-build.yml +++ b/extensions/Worker.Extensions.ServiceBus/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.ServiceBus/ci/public-build.yml b/extensions/Worker.Extensions.ServiceBus/ci/public-build.yml index 3da6a0ad4..0d4ae77fc 100644 --- a/extensions/Worker.Extensions.ServiceBus/ci/public-build.yml +++ b/extensions/Worker.Extensions.ServiceBus/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.SignalRService/ci/official-build.yml b/extensions/Worker.Extensions.SignalRService/ci/official-build.yml index a98a3131b..7d1a4c541 100644 --- a/extensions/Worker.Extensions.SignalRService/ci/official-build.yml +++ b/extensions/Worker.Extensions.SignalRService/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.SignalRService/ci/public-build.yml b/extensions/Worker.Extensions.SignalRService/ci/public-build.yml index 50784ea6d..fc9421c0c 100644 --- a/extensions/Worker.Extensions.SignalRService/ci/public-build.yml +++ b/extensions/Worker.Extensions.SignalRService/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Storage.Blobs/ci/official-build.yml b/extensions/Worker.Extensions.Storage.Blobs/ci/official-build.yml index 4ba8b334a..6749a6201 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/ci/official-build.yml +++ b/extensions/Worker.Extensions.Storage.Blobs/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Storage.Blobs/ci/public-build.yml b/extensions/Worker.Extensions.Storage.Blobs/ci/public-build.yml index 5332122d4..bde591fa1 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/ci/public-build.yml +++ b/extensions/Worker.Extensions.Storage.Blobs/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Storage.Queues/ci/official-build.yml b/extensions/Worker.Extensions.Storage.Queues/ci/official-build.yml index 8f577d770..419b7c05e 100644 --- a/extensions/Worker.Extensions.Storage.Queues/ci/official-build.yml +++ b/extensions/Worker.Extensions.Storage.Queues/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Storage.Queues/ci/public-build.yml b/extensions/Worker.Extensions.Storage.Queues/ci/public-build.yml index 9d1b5adac..93dc5ba44 100644 --- a/extensions/Worker.Extensions.Storage.Queues/ci/public-build.yml +++ b/extensions/Worker.Extensions.Storage.Queues/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Storage/ci/official-build.yml b/extensions/Worker.Extensions.Storage/ci/official-build.yml index 2d9debd6f..0f51f6a3c 100644 --- a/extensions/Worker.Extensions.Storage/ci/official-build.yml +++ b/extensions/Worker.Extensions.Storage/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Storage/ci/public-build.yml b/extensions/Worker.Extensions.Storage/ci/public-build.yml index ca4c1c76b..81a8a1319 100644 --- a/extensions/Worker.Extensions.Storage/ci/public-build.yml +++ b/extensions/Worker.Extensions.Storage/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Tables/ci/official-build.yml b/extensions/Worker.Extensions.Tables/ci/official-build.yml index 1de26f1db..e43778db2 100644 --- a/extensions/Worker.Extensions.Tables/ci/official-build.yml +++ b/extensions/Worker.Extensions.Tables/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Tables/ci/public-build.yml b/extensions/Worker.Extensions.Tables/ci/public-build.yml index 624f5998a..1a4fcb639 100644 --- a/extensions/Worker.Extensions.Tables/ci/public-build.yml +++ b/extensions/Worker.Extensions.Tables/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Timer/ci/official-build.yml b/extensions/Worker.Extensions.Timer/ci/official-build.yml index 92a81603a..381bea58e 100644 --- a/extensions/Worker.Extensions.Timer/ci/official-build.yml +++ b/extensions/Worker.Extensions.Timer/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Timer/ci/public-build.yml b/extensions/Worker.Extensions.Timer/ci/public-build.yml index b4176c73b..8dc3e6529 100644 --- a/extensions/Worker.Extensions.Timer/ci/public-build.yml +++ b/extensions/Worker.Extensions.Timer/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public diff --git a/extensions/Worker.Extensions.Warmup/ci/official-build.yml b/extensions/Worker.Extensions.Warmup/ci/official-build.yml index 1dbb3aae3..bc14ce0f2 100644 --- a/extensions/Worker.Extensions.Warmup/ci/official-build.yml +++ b/extensions/Worker.Extensions.Warmup/ci/official-build.yml @@ -35,8 +35,8 @@ extends: parameters: pool: name: 1es-pool-azfunc - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc diff --git a/extensions/Worker.Extensions.Warmup/ci/public-build.yml b/extensions/Worker.Extensions.Warmup/ci/public-build.yml index 8d0db8be9..3db00dffd 100644 --- a/extensions/Worker.Extensions.Warmup/ci/public-build.yml +++ b/extensions/Worker.Extensions.Warmup/ci/public-build.yml @@ -42,8 +42,8 @@ extends: parameters: pool: name: 1es-pool-azfunc-public - image: 1es-ubuntu-22.04 - os: linux + image: 1es-windows-2022 + os: windows sdl: sourceAnalysisPool: name: 1es-pool-azfunc-public From 6be4e5905f469790ee66ff7ce4fc7a718280f70c Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 12 Sep 2024 11:43:01 -0700 Subject: [PATCH 030/190] Removed fallback command line argument reading code for grpc worker startup options. (#2693) * Removing the fallback command line argument reading code for grpc worker startup options. * Add release notes. --- release_notes.md | 11 +++++------ .../GrpcServiceCollectionExtensions.cs | 17 +++++------------ 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/release_notes.md b/release_notes.md index 0260c95a6..1591de98e 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,18 +4,17 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) 1.23.0 +### Microsoft.Azure.Functions.Worker (metapackage) -- Updating `Microsoft.Azure.Functions.Worker.Core` to 1.19.0 -- Updating `Microsoft.Azure.Functions.Worker.Grpc` to 1.17.0 -- Updating `Azure.Core` to 1.41.0 +- -### Microsoft.Azure.Functions.Worker.Core 1.19.0 +### Microsoft.Azure.Functions.Worker.Core - Updating `Azure.Core` to 1.41.0 - Updated service registrations for bootstrapping methods to ensure idempotency. -### Microsoft.Azure.Functions.Worker.Grpc 1.17.0 +### Microsoft.Azure.Functions.Worker.Grpc +- Removed fallback command line argument reading code for grpc worker startup options. (#1908) - Updating `Azure.Core` to 1.41.0 - Updated service registrations for bootstrapping methods to ensure idempotency. \ No newline at end of file diff --git a/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs b/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs index c8356da7b..7c8c0ff54 100644 --- a/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs +++ b/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs @@ -77,22 +77,15 @@ public static IServiceCollection AddGrpc(this IServiceCollection services) private static Uri GetFunctionsHostGrpcUri(IConfiguration configuration) { - Uri? grpcUri; var functionsUri = configuration["Functions:Worker:HostEndpoint"]; - if (functionsUri is not null) + if (string.IsNullOrEmpty(functionsUri)) { - if (!Uri.TryCreate(functionsUri, UriKind.Absolute, out grpcUri)) - { - throw new InvalidOperationException($"The gRPC channel URI '{functionsUri}' could not be parsed."); - } + throw new InvalidOperationException("Configuration is missing the 'HostEndpoint' information. Please ensure an entry with the key 'Functions:Worker:HostEndpoint' is present in your configuration."); } - else + + if (!Uri.TryCreate(functionsUri, UriKind.Absolute, out var grpcUri)) { - var uriString = $"http://{configuration["HOST"]}:{configuration["PORT"]}"; - if (!Uri.TryCreate(uriString, UriKind.Absolute, out grpcUri)) - { - throw new InvalidOperationException($"The gRPC channel URI '{uriString}' could not be parsed."); - } + throw new InvalidOperationException($"The gRPC channel URI '{functionsUri}' could not be parsed."); } return grpcUri; From 62a44c65d76b590848d7d74b6480c5cdf349c555 Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Thu, 12 Sep 2024 21:42:15 -0700 Subject: [PATCH 031/190] Adding default settings to support SDK container builds (#2671) --- release_notes.md | 4 +++ ...Azure.Functions.Worker.Sdk.Publish.targets | 26 +++++++++++++++++ test/SdkE2ETests/ProcessWrapper.cs | 24 ++++++++++++++++ test/SdkE2ETests/PublishTests.cs | 28 +++++++++++++++++++ test/SdkE2ETests/SdkE2ETests.csproj | 4 +++ .../SdkE2ETests_default.runsettings | 6 ++++ .../SdkE2ETests_dockertests.runsettings | 6 ++++ test/SdkE2ETests/TestUtility.cs | 7 +++++ 8 files changed, 105 insertions(+) create mode 100644 test/SdkE2ETests/SdkE2ETests_default.runsettings create mode 100644 test/SdkE2ETests/SdkE2ETests_dockertests.runsettings diff --git a/release_notes.md b/release_notes.md index 1591de98e..b2aa73930 100644 --- a/release_notes.md +++ b/release_notes.md @@ -16,5 +16,9 @@ ### Microsoft.Azure.Functions.Worker.Grpc - Removed fallback command line argument reading code for grpc worker startup options. (#1908) + +### Microsoft.Azure.Functions.Worker.Sdk 2.0.0-preview2 + +- Adding support for SDK container builds with Functions base images - Updating `Azure.Core` to 1.41.0 - Updated service registrations for bootstrapping methods to ensure idempotency. \ No newline at end of file diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.targets index 2e128f9fe..2a72f6f01 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.targets @@ -21,4 +21,30 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and + + + <_FunctionsRuntimeMajorVersion>$(_AzureFunctionsVersionStandardized.TrimStart('vV')) + mcr.microsoft.com/azure-functions/dotnet-isolated:$(_FunctionsRuntimeMajorVersion)-dotnet-isolated$(TargetFrameworkVersion.TrimStart('vV')) + /home/site/wwwroot + + linux-x64 + + + + + + + + + + \ No newline at end of file diff --git a/test/SdkE2ETests/ProcessWrapper.cs b/test/SdkE2ETests/ProcessWrapper.cs index 53c4fb7dc..a298b1d91 100644 --- a/test/SdkE2ETests/ProcessWrapper.cs +++ b/test/SdkE2ETests/ProcessWrapper.cs @@ -3,6 +3,7 @@ using System; using System.Diagnostics; +using System.Text; using System.Threading; using System.Threading.Tasks; using Xunit.Abstractions; @@ -11,8 +12,22 @@ namespace Microsoft.Azure.Functions.SdkE2ETests { public class ProcessWrapper { + public async Task RunProcess(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null) { + return await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper); + } + + public async Task> RunProcessForOutput(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null) + { + StringBuilder processOutputStringBuilder = new StringBuilder(); + var exitCode = await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper, processOutputStringBuilder); + return new Tuple(exitCode, processOutputStringBuilder.ToString()); + } + + private async Task RunProcessInternal(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null, StringBuilder processOutputBuilder = null) + { + SemaphoreSlim processExitSemaphore = new SemaphoreSlim(0, 1); ProcessStartInfo startInfo = new ProcessStartInfo @@ -39,6 +54,10 @@ public class ProcessWrapper if (o.Data != null) { testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] Error: {o.Data}"); + if (processOutputBuilder != null) + { + processOutputBuilder.AppendLine(o.Data); + } } }; @@ -47,6 +66,10 @@ public class ProcessWrapper if (o.Data != null) { testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] {o.Data}"); + if (processOutputBuilder != null) + { + processOutputBuilder.AppendLine(o.Data); + } } }; @@ -65,4 +88,5 @@ public class ProcessWrapper return testProcess?.ExitCode; } } + } diff --git a/test/SdkE2ETests/PublishTests.cs b/test/SdkE2ETests/PublishTests.cs index cee2b00a9..5a7a76923 100644 --- a/test/SdkE2ETests/PublishTests.cs +++ b/test/SdkE2ETests/PublishTests.cs @@ -34,6 +34,34 @@ public async Task Publish_Rid() await RunPublishTest(outputDir, "-r win-x86"); } + [Fact] + // This test requires the Docker daemon to be installed and running + // It is excluded through the SdkE2ETests_default.runsettings file from normal tests + // To run the test, use `dotnet test -s SdkE2ETests_dockertests.runsettings` + [Trait("Requirement", "Docker")] + public async Task Publish_Container() + { + string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Container)); + var repository = nameof(SdkE2ETests).ToLower(); + var imageTag = nameof(Publish_Container); + + // setup test environment state in case there is leftover data from previous runs + await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper); + + // perform the publish + await RunPublishTest(outputDir, $"--no-restore /t:PublishContainer --property:ContainerRepository={repository} --property:ContainerImageTag={imageTag}"); + + // validate the image base + Tuple inspectResults = await new ProcessWrapper().RunProcessForOutput("docker", $"inspect {repository}:{imageTag} --format \"{{{{ index .Config.Labels \\\"org.opencontainers.image.base.name\\\"}}}}\"", outputDir, _testOutputHelper); + var inspectExitCode = inspectResults.Item1; + var inspectOutput = inspectResults.Item2; + Assert.True(inspectExitCode.HasValue && inspectExitCode.Value == 0); + Assert.Matches("mcr\\.microsoft\\.com/azure-functions/dotnet-isolated:(\\d)+-dotnet-isolated(\\d+\\.\\d+)", inspectOutput); + + // clean up + await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper); + } + private async Task RunPublishTest(string outputDir, string additionalParams = null) { // Name of the csproj diff --git a/test/SdkE2ETests/SdkE2ETests.csproj b/test/SdkE2ETests/SdkE2ETests.csproj index 48beac730..1deb3084a 100644 --- a/test/SdkE2ETests/SdkE2ETests.csproj +++ b/test/SdkE2ETests/SdkE2ETests.csproj @@ -8,6 +8,10 @@ ..\..\key.snk + + $(MSBuildProjectDirectory)\SdkE2ETests_default.runsettings + + diff --git a/test/SdkE2ETests/SdkE2ETests_default.runsettings b/test/SdkE2ETests/SdkE2ETests_default.runsettings new file mode 100644 index 000000000..723105e33 --- /dev/null +++ b/test/SdkE2ETests/SdkE2ETests_default.runsettings @@ -0,0 +1,6 @@ + + + + (Requirement != Docker) + + \ No newline at end of file diff --git a/test/SdkE2ETests/SdkE2ETests_dockertests.runsettings b/test/SdkE2ETests/SdkE2ETests_dockertests.runsettings new file mode 100644 index 000000000..7d33ac51e --- /dev/null +++ b/test/SdkE2ETests/SdkE2ETests_dockertests.runsettings @@ -0,0 +1,6 @@ + + + + (Requirement = Docker) + + \ No newline at end of file diff --git a/test/SdkE2ETests/TestUtility.cs b/test/SdkE2ETests/TestUtility.cs index b636691fd..c92e01c62 100644 --- a/test/SdkE2ETests/TestUtility.cs +++ b/test/SdkE2ETests/TestUtility.cs @@ -135,5 +135,12 @@ private static string InitializeOutputDir(string testName) return outputDir; } + + public static async Task RemoveDockerTestImage(string repository, string imageTag, ITestOutputHelper outputHelper) + { + outputHelper.WriteLine($"Removing image {repository}:{imageTag} from local registry"); + int? rmiExitCode = await new ProcessWrapper().RunProcess("docker", $"rmi -f {repository}:{imageTag}", TestOutputDir, outputHelper); + Assert.True(rmiExitCode.HasValue && rmiExitCode.Value == 0); // daemon may still error if the image doesn't exist, but it will still return 0 + } } } From aec394f008996b54bac86c858b1a3fc315f96df1 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Fri, 13 Sep 2024 10:26:10 -0700 Subject: [PATCH 032/190] Set IncludeEmptyEntriesInMessagePayload capability to true by default (#2701) * Set IncludeEmptyEntriesInMessagePayload to true by default * Update release notes --- release_notes.md | 29 ++++++++++++++----- .../Hosting/WorkerCapabilities.cs | 20 +++++++++++++ .../Hosting/WorkerOptions.cs | 11 +++---- src/DotNetWorker.Grpc/GrpcWorker.cs | 12 ++++---- test/DotNetWorkerTests/GrpcWorkerTests.cs | 3 +- 5 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 src/DotNetWorker.Core/Hosting/WorkerCapabilities.cs diff --git a/release_notes.md b/release_notes.md index b2aa73930..2381aff7a 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,16 +4,31 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) - -- - -### Microsoft.Azure.Functions.Worker.Core - +### Microsoft.Azure.Functions.Worker (metapackage) 2.0.0 + +- Updating `Microsoft.Azure.Functions.Worker.Core` to 2.0.0 +- Updating `Microsoft.Azure.Functions.Worker.Grpc` to 2.0.0 + +### Microsoft.Azure.Functions.Worker.Core 2.0.0 + +- Capability `IncludeEmptyEntriesInMessagePayload` is now enabled by default (#2701) + - This means that empty entries will be included in the function trigger message payload by default. + - To disable this capability and return to the old behaviour, set `IncludeEmptyEntriesInMessagePayload` to `false` in the worker options. + + ```csharp + var host = new HostBuilder() + .ConfigureFunctionsWorkerDefaults(builder => + { + }, options => + { + options.IncludeEmptyEntriesInMessagePayload = false; + }) + .Build(); + ``` - Updating `Azure.Core` to 1.41.0 - Updated service registrations for bootstrapping methods to ensure idempotency. -### Microsoft.Azure.Functions.Worker.Grpc +### Microsoft.Azure.Functions.Worker.Grpc 2.0.0 - Removed fallback command line argument reading code for grpc worker startup options. (#1908) diff --git a/src/DotNetWorker.Core/Hosting/WorkerCapabilities.cs b/src/DotNetWorker.Core/Hosting/WorkerCapabilities.cs new file mode 100644 index 000000000..d5b291191 --- /dev/null +++ b/src/DotNetWorker.Core/Hosting/WorkerCapabilities.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker +{ + internal static class WorkerCapabilities + { + internal const string EnableUserCodeException = "EnableUserCodeException"; + internal const string HandlesInvocationCancelMessage = "HandlesInvocationCancelMessage"; + internal const string HandlesWorkerTerminateMessage = "HandlesWorkerTerminateMessage"; + internal const string HandlesWorkerWarmupMessage = "HandlesWorkerWarmupMessage"; + internal const string IncludeEmptyEntriesInMessagePayload = "IncludeEmptyEntriesInMessagePayload"; + internal const string RawHttpBodyBytes = "RawHttpBodyBytes"; + internal const string RpcHttpBodyOnly = "RpcHttpBodyOnly"; + internal const string RpcHttpTriggerMetadataRemoved = "RpcHttpTriggerMetadataRemoved"; + internal const string TypedDataCollection = "TypedDataCollection"; + internal const string UseNullableValueDictionaryForHttp = "UseNullableValueDictionaryForHttp"; + internal const string WorkerStatus = "WorkerStatus"; + } +} diff --git a/src/DotNetWorker.Core/Hosting/WorkerOptions.cs b/src/DotNetWorker.Core/Hosting/WorkerOptions.cs index acd500c8b..f1e98f8b1 100644 --- a/src/DotNetWorker.Core/Hosting/WorkerOptions.cs +++ b/src/DotNetWorker.Core/Hosting/WorkerOptions.cs @@ -10,7 +10,7 @@ namespace Microsoft.Azure.Functions.Worker { /// /// An options class for configuring the worker. - /// + /// public class WorkerOptions { /// @@ -30,13 +30,14 @@ public class WorkerOptions public IDictionary Capabilities { get; } = new Dictionary() { // Enable these by default, although they are not strictly required and can be removed - { "HandlesWorkerTerminateMessage", bool.TrueString }, - { "HandlesInvocationCancelMessage", bool.TrueString } + { WorkerCapabilities.HandlesWorkerTerminateMessage, bool.TrueString }, + { WorkerCapabilities.HandlesInvocationCancelMessage, bool.TrueString }, + { WorkerCapabilities.IncludeEmptyEntriesInMessagePayload, bool.TrueString } }; /// /// Gets or sets the flag for opting in to unwrapping user-code-thrown - /// exceptions when they are surfaced to the Host. + /// exceptions when they are surfaced to the Host. /// public bool EnableUserCodeException { @@ -49,7 +50,7 @@ public bool EnableUserCodeException /// For example, if a set of entries were sent to a messaging service such as Service Bus or Event Hub and your function /// app has a Service bus trigger or Event hub trigger, only the non-empty entries from the payload will be sent to the /// function code as trigger data when this setting value is . When it is , - /// All entries will be sent to the function code as it is. Default value for this setting is . + /// all entries will be sent to the function code as it is. Default value for this setting is . /// public bool IncludeEmptyEntriesInMessagePayload { diff --git a/src/DotNetWorker.Grpc/GrpcWorker.cs b/src/DotNetWorker.Grpc/GrpcWorker.cs index fac6d9f51..3435b6e20 100644 --- a/src/DotNetWorker.Grpc/GrpcWorker.cs +++ b/src/DotNetWorker.Grpc/GrpcWorker.cs @@ -320,12 +320,12 @@ private static IDictionary GetWorkerCapabilities(WorkerOptions w } // Add required capabilities; these cannot be modified and will override anything from WorkerOptions - capabilities["RpcHttpBodyOnly"] = bool.TrueString; - capabilities["RawHttpBodyBytes"] = bool.TrueString; - capabilities["RpcHttpTriggerMetadataRemoved"] = bool.TrueString; - capabilities["UseNullableValueDictionaryForHttp"] = bool.TrueString; - capabilities["TypedDataCollection"] = bool.TrueString; - capabilities["WorkerStatus"] = bool.TrueString; + capabilities[WorkerCapabilities.RpcHttpBodyOnly] = bool.TrueString; + capabilities[WorkerCapabilities.RawHttpBodyBytes] = bool.TrueString; + capabilities[WorkerCapabilities.RpcHttpTriggerMetadataRemoved] = bool.TrueString; + capabilities[WorkerCapabilities.UseNullableValueDictionaryForHttp] = bool.TrueString; + capabilities[WorkerCapabilities.TypedDataCollection] = bool.TrueString; + capabilities[WorkerCapabilities.WorkerStatus] = bool.TrueString; return capabilities; } diff --git a/test/DotNetWorkerTests/GrpcWorkerTests.cs b/test/DotNetWorkerTests/GrpcWorkerTests.cs index a19a4a8fe..ee2cd4734 100644 --- a/test/DotNetWorkerTests/GrpcWorkerTests.cs +++ b/test/DotNetWorkerTests/GrpcWorkerTests.cs @@ -234,6 +234,7 @@ void AssertKeyAndValue(KeyValuePair kvp, string expectedKey, str Assert.Collection(response.Capabilities.OrderBy(p => p.Key), c => AssertKeyAndValue(c, "HandlesInvocationCancelMessage", bool.TrueString), + c => AssertKeyAndValue(c, "IncludeEmptyEntriesInMessagePayload", bool.TrueString), c => AssertKeyAndValue(c, "RawHttpBodyBytes", bool.TrueString), c => AssertKeyAndValue(c, "RpcHttpBodyOnly", bool.TrueString), c => AssertKeyAndValue(c, "RpcHttpTriggerMetadataRemoved", bool.TrueString), @@ -324,7 +325,7 @@ void ProcessMessage(IMessageProcessor processor, string functionId = null) }); releaseFunctionEvent.Wait(5000); - + Assert.True(releaseFunctionEvent.IsSet, "Release function was never called. " + "This indicates the blocking function prevented execution flow."); From 917582cee604e6b6e9d8e78840c84b0cd6c5bdda Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Mon, 16 Sep 2024 10:06:58 -0700 Subject: [PATCH 033/190] Set ValidateScopes to true when in dev environment (#2705) --- release_notes.md | 2 ++ src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/release_notes.md b/release_notes.md index 2381aff7a..db892123e 100644 --- a/release_notes.md +++ b/release_notes.md @@ -11,6 +11,8 @@ ### Microsoft.Azure.Functions.Worker.Core 2.0.0 +- `ValidateScopes` is enabled for developement environments by default. (#2705) + - The default is the value of `IsDevelopment(IHostingEnvironment)`. - Capability `IncludeEmptyEntriesInMessagePayload` is now enabled by default (#2701) - This means that empty entries will be included in the function trigger message payload by default. - To disable this capability and return to the old behaviour, set `IncludeEmptyEntriesInMessagePayload` to `false` in the worker options. diff --git a/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs b/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs index 9c45ae7df..7df8f5339 100644 --- a/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs +++ b/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs @@ -171,6 +171,10 @@ public static IHostBuilder ConfigureFunctionsWorkerDefaults(this IHostBuilder bu // Add default middleware appBuilder.UseDefaultWorkerMiddleware(); + }) + .UseDefaultServiceProvider((context, options) => + { + options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); }); // Invoke any extension methods auto generated by functions worker sdk. From 5f237161a251b7cd47ae5102d1eb73925096e4ec Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Tue, 17 Sep 2024 15:04:01 -0700 Subject: [PATCH 034/190] Rename 'ILoggerExtensions' to 'FunctionsLoggerExtensions' (#2716) --- release_notes.md | 1 + .../{ILoggerExtensions.cs => FunctionsLoggerExtensions.cs} | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename src/DotNetWorker.Core/Logging/{ILoggerExtensions.cs => FunctionsLoggerExtensions.cs} (94%) diff --git a/release_notes.md b/release_notes.md index db892123e..2cf75c527 100644 --- a/release_notes.md +++ b/release_notes.md @@ -27,6 +27,7 @@ }) .Build(); ``` +- Rename `ILoggerExtensions` to `FunctionsLoggerExtensions` to avoid naming conflict issues (#2716) - Updating `Azure.Core` to 1.41.0 - Updated service registrations for bootstrapping methods to ensure idempotency. diff --git a/src/DotNetWorker.Core/Logging/ILoggerExtensions.cs b/src/DotNetWorker.Core/Logging/FunctionsLoggerExtensions.cs similarity index 94% rename from src/DotNetWorker.Core/Logging/ILoggerExtensions.cs rename to src/DotNetWorker.Core/Logging/FunctionsLoggerExtensions.cs index 0aaa9fb85..7dabf5ca4 100644 --- a/src/DotNetWorker.Core/Logging/ILoggerExtensions.cs +++ b/src/DotNetWorker.Core/Logging/FunctionsLoggerExtensions.cs @@ -10,7 +10,7 @@ namespace Microsoft.Extensions.Logging /// /// Extensions for . /// - public static class ILoggerExtensions + public static class FunctionsLoggerExtensions { /// /// Logs a metric value. Log will be at an information level. From 2c06eafccc537a84c7576fbbdd44410b284244d0 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Tue, 17 Sep 2024 15:59:28 -0700 Subject: [PATCH 035/190] Set EnableUserCodeException capability to true by default (#2702) --- release_notes.md | 26 +++++++++++-------- .../Hosting/WorkerOptions.cs | 10 ++++--- test/DotNetWorkerTests/GrpcWorkerTests.cs | 4 ++- .../Handlers/InvocationHandlerTests.cs | 24 ++++++++++------- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/release_notes.md b/release_notes.md index 2cf75c527..96bef8d74 100644 --- a/release_notes.md +++ b/release_notes.md @@ -16,21 +16,25 @@ - Capability `IncludeEmptyEntriesInMessagePayload` is now enabled by default (#2701) - This means that empty entries will be included in the function trigger message payload by default. - To disable this capability and return to the old behaviour, set `IncludeEmptyEntriesInMessagePayload` to `false` in the worker options. - - ```csharp - var host = new HostBuilder() - .ConfigureFunctionsWorkerDefaults(builder => - { - }, options => - { - options.IncludeEmptyEntriesInMessagePayload = false; - }) - .Build(); - ``` +- Capability `EnableUserCodeException` is now enabled by default (#2702) + - This means that exceptions thrown by user code will be surfaced to the Host as their original exception type, instead of being wrapped in an RpcException. + - To disable this capability and return to the old behaviour, set `EnableUserCodeException` to `false` in the worker options. + - The `EnableUserCodeException` property in WorkerOptions has been marked as obsolete and may be removed in a future release. - Rename `ILoggerExtensions` to `FunctionsLoggerExtensions` to avoid naming conflict issues (#2716) - Updating `Azure.Core` to 1.41.0 - Updated service registrations for bootstrapping methods to ensure idempotency. +##### Setting worker options example + +```csharp +var host = new HostBuilder() +.ConfigureFunctionsWorkerDefaults(options => +{ + options.EnableUserCodeException = false; + options.IncludeEmptyEntriesInMessagePayload = false; +}) +``` + ### Microsoft.Azure.Functions.Worker.Grpc 2.0.0 - Removed fallback command line argument reading code for grpc worker startup options. (#1908) diff --git a/src/DotNetWorker.Core/Hosting/WorkerOptions.cs b/src/DotNetWorker.Core/Hosting/WorkerOptions.cs index f1e98f8b1..c71b6dc1e 100644 --- a/src/DotNetWorker.Core/Hosting/WorkerOptions.cs +++ b/src/DotNetWorker.Core/Hosting/WorkerOptions.cs @@ -1,6 +1,7 @@ // 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.Text.Json; using Azure.Core.Serialization; @@ -32,13 +33,16 @@ public class WorkerOptions // Enable these by default, although they are not strictly required and can be removed { WorkerCapabilities.HandlesWorkerTerminateMessage, bool.TrueString }, { WorkerCapabilities.HandlesInvocationCancelMessage, bool.TrueString }, - { WorkerCapabilities.IncludeEmptyEntriesInMessagePayload, bool.TrueString } + { WorkerCapabilities.IncludeEmptyEntriesInMessagePayload, bool.TrueString }, + { WorkerCapabilities.EnableUserCodeException, bool.TrueString } }; /// - /// Gets or sets the flag for opting in to unwrapping user-code-thrown - /// exceptions when they are surfaced to the Host. + /// Gets or sets a value indicating whether exceptions thrown by user code should be unwrapped + /// and surfaced to the Host as their original exception type, instead of being wrapped in an RpcException. + /// The default value is . /// + [Obsolete("This is now the default behavior. This property may be unavailable in future releases.", false)] public bool EnableUserCodeException { get => GetBoolCapability(nameof(EnableUserCodeException)); diff --git a/test/DotNetWorkerTests/GrpcWorkerTests.cs b/test/DotNetWorkerTests/GrpcWorkerTests.cs index ee2cd4734..aa393842f 100644 --- a/test/DotNetWorkerTests/GrpcWorkerTests.cs +++ b/test/DotNetWorkerTests/GrpcWorkerTests.cs @@ -9,7 +9,6 @@ using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; -using Azure.Core.Serialization; using Microsoft.Azure.Functions.Tests; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; @@ -178,6 +177,8 @@ public void InitRequest_ReturnsExpectedMetadata() [Theory] [InlineData("IncludeEmptyEntriesInMessagePayload", true, "IncludeEmptyEntriesInMessagePayload", true, "True")] [InlineData("IncludeEmptyEntriesInMessagePayload", false, "IncludeEmptyEntriesInMessagePayload", false)] + [InlineData("EnableUserCodeException", true, "EnableUserCodeException", true, "True")] + [InlineData("EnableUserCodeException", false, "EnableUserCodeException", false)] public void InitRequest_ReturnsExpectedCapabilities_BasedOnWorkerOptions( string booleanPropertyName, bool booleanPropertyValue, @@ -233,6 +234,7 @@ void AssertKeyAndValue(KeyValuePair kvp, string expectedKey, str } Assert.Collection(response.Capabilities.OrderBy(p => p.Key), + c => AssertKeyAndValue(c, "EnableUserCodeException", bool.TrueString), c => AssertKeyAndValue(c, "HandlesInvocationCancelMessage", bool.TrueString), c => AssertKeyAndValue(c, "IncludeEmptyEntriesInMessagePayload", bool.TrueString), c => AssertKeyAndValue(c, "RawHttpBodyBytes", bool.TrueString), diff --git a/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs b/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs index 95363894d..061706acb 100644 --- a/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs +++ b/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs @@ -77,14 +77,15 @@ public async Task InvokeAsync_ThrowsTaskCanceledException_ReturnsCancelled() { _mockApplication .Setup(m => m.InvokeFunctionAsync(It.IsAny())) - .Throws(new AggregateException(new Exception[] { new TaskCanceledException() })); + .Throws(new AggregateException(new TaskCanceledException())); var request = TestUtility.CreateInvocationRequest("abc"); var invocationHandler = CreateInvocationHandler(); var response = await invocationHandler.InvokeAsync(request); Assert.Equal(StatusResult.Types.Status.Cancelled, response.Result.Status); - Assert.Contains("TaskCanceledException", response.Result.Exception.Message); + Assert.Equal("System.AggregateException", response.Result.Exception.Type); + Assert.Contains("A task was canceled", response.Result.Exception.Message); } [Fact] @@ -129,15 +130,16 @@ public async Task Cancel_InvocationCompleted_ReturnsFalse() } /// - /// Test unwrapping user code exception functionality. + /// Test unwrapping user code exception functionality. + /// EnableUserCodeException capability is true by default. /// [Fact] public async Task InvokeAsync_UserCodeThrowsException_OptionEnabled() { var exceptionMessage = "user code exception"; + var mockOptions = new OptionsWrapper(new() { - EnableUserCodeException = true, Serializer = new JsonObjectSerializer() }); @@ -156,23 +158,24 @@ public async Task InvokeAsync_UserCodeThrowsException_OptionEnabled() } /// - /// Test keeping user code exception wrapped as RpcException. + /// Test keeping user code exception wrapped as RpcException. /// [Fact] public async Task InvokeAsync_UserCodeThrowsException_OptionDisabled() { var exceptionMessage = "user code exception"; - var mockOptions = new WorkerOptions() + var mockOptions = new OptionsWrapper(new() { + Serializer = new JsonObjectSerializer(), EnableUserCodeException = false - }; + }); _mockApplication .Setup(m => m.InvokeFunctionAsync(It.IsAny())) .Throws(new Exception(exceptionMessage)); var request = TestUtility.CreateInvocationRequest("abc"); - var invocationHandler = CreateInvocationHandler(); + var invocationHandler = CreateInvocationHandler(workerOptions: mockOptions); var response = await invocationHandler.InvokeAsync(request); Assert.Equal(StatusResult.Types.Status.Failure, response.Result.Status); @@ -239,8 +242,9 @@ public async Task Invoke_CreateContextThrows_ReturnsFailure() var response = await invocationHandler.InvokeAsync(request); Assert.Equal(StatusResult.Types.Status.Failure, response.Result.Status); - Assert.Contains("InvalidOperationException: whoops", response.Result.Exception.Message); - Assert.Contains("CreateContext", response.Result.Exception.Message); + Assert.Equal("System.InvalidOperationException", response.Result.Exception.Type); + Assert.Contains("whoops", response.Result.Exception.Message); + Assert.Contains("CreateContext", response.Result.Exception.StackTrace); } [Fact] From c60530be9261606871ae41499efb7e683ca568a2 Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Wed, 25 Sep 2024 15:11:12 -0700 Subject: [PATCH 036/190] Updating release notes for worker sdk (#2736) --- sdk/release_notes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 7b7753438..bc50f23d4 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,11 +4,12 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk +### Microsoft.Azure.Functions.Worker.Sdk 2.0.0-preview2 - Changed exception handling in function invocation path to ensure fatal exceptions bubble up. - Updated `Microsoft.Azure.Functions.Worker.Sdk.Generators` reference to 1.3.4. - Setting _ToolingSuffix for TargetFrameworkVersion v9.0 +- Adding support for SDK container builds with Functions base images ### Microsoft.Azure.Functions.Worker.Sdk.Generators From fccdc86598453c7824e7888668cab9ce88a6d49a Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Wed, 25 Sep 2024 15:37:17 -0700 Subject: [PATCH 037/190] Correct sdk version to preview2 (#2738) --- sdk/Sdk/Sdk.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 71c20f050..74d7ce451 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -2,7 +2,7 @@ 2 - -preview1 + -preview2 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. From 4bfaee1e5c99e5b9234f79060ec506b5cd44523b Mon Sep 17 00:00:00 2001 From: Rohit Ranjan <90008725+RohitRanjanMS@users.noreply.github.com> Date: Wed, 9 Oct 2024 13:29:07 -0700 Subject: [PATCH 038/190] Remove HttpStatusCode=OK from WriteAsJsonAsync (#2720) * WriteAsJsonAsync HttpStatusCode Fix --- sdk/release_notes.md | 1 + .../Http/HttpResponseDataExtensions.cs | 97 ++----------------- .../Http/HttpResponseDataExtensionsTests.cs | 12 +-- 3 files changed, 16 insertions(+), 94 deletions(-) diff --git a/sdk/release_notes.md b/sdk/release_notes.md index bc50f23d4..bf0c80498 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -10,6 +10,7 @@ - Updated `Microsoft.Azure.Functions.Worker.Sdk.Generators` reference to 1.3.4. - Setting _ToolingSuffix for TargetFrameworkVersion v9.0 - Adding support for SDK container builds with Functions base images +- Removed the default value for HttpStatusCode in WriteAsJsonAsync (#2720) ### Microsoft.Azure.Functions.Worker.Sdk.Generators diff --git a/src/DotNetWorker.Core/Http/HttpResponseDataExtensions.cs b/src/DotNetWorker.Core/Http/HttpResponseDataExtensions.cs index e0f587559..e2689ecde 100644 --- a/src/DotNetWorker.Core/Http/HttpResponseDataExtensions.cs +++ b/src/DotNetWorker.Core/Http/HttpResponseDataExtensions.cs @@ -81,7 +81,7 @@ public static Task WriteStringAsync(this HttpResponseData response, string value /// /// Asynchronously writes the specified value as JSON to the response body using the default configured for this worker. - /// The response content-type will be set to application/json; charset=utf-8 and the status code set to 200. + /// The response content-type will be set to application/json; charset=utf-8. /// /// The type of object to write. /// The response to write JSON to. @@ -90,28 +90,12 @@ public static Task WriteStringAsync(this HttpResponseData response, string value /// A that represents the asynchronous operation. public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, CancellationToken cancellationToken = default) { - return WriteAsJsonAsync(response, instance, "application/json; charset=utf-8", HttpStatusCode.OK, cancellationToken); + return WriteAsJsonAsync(response, instance, "application/json; charset=utf-8", cancellationToken); } /// /// Asynchronously writes the specified value as JSON to the response body using the default configured for this worker. - /// The response content-type will be set to application/json; charset=utf-8 and the status code set to the provided . - /// - /// The type of object to write. - /// The response to write JSON to. - /// The instance to serialize and write as JSON. - /// The status code to set on the response. - /// A used to cancel the operation. - /// A that represents the asynchronous operation. - public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, HttpStatusCode statusCode, - CancellationToken cancellationToken = default) - { - return WriteAsJsonAsync(response, instance, "application/json; charset=utf-8", statusCode, cancellationToken); - } - - /// - /// Asynchronously writes the specified value as JSON to the response body using the default configured for this worker. - /// The response content-type will be set to the provided and the status code set to 200. + /// The response content-type will be set to the provided . /// /// The type of object to write. /// The response to write JSON to. @@ -128,37 +112,12 @@ public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T in ObjectSerializer serializer = GetObjectSerializer(response); - return WriteAsJsonAsync(response, instance, serializer, contentType, HttpStatusCode.OK, cancellationToken); - } - - /// - /// Asynchronously writes the specified value as JSON to the response body using the default configured for this worker. - /// The response content-type will be set to the provided and the status code set to the provided . - /// - /// The type of object to write. - /// The response to write JSON to. - /// The instance to serialize and write as JSON. - /// The content-type to set on the response. - /// The status code to set on the response. - /// A used to cancel the operation. - /// A that represents the asynchronous operation. - public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, string contentType, HttpStatusCode statusCode, - CancellationToken cancellationToken = default) - { - if (response is null) - { - throw new ArgumentNullException(nameof(response)); - } - - ObjectSerializer serializer = GetObjectSerializer(response); - - return WriteAsJsonAsync(response, instance, serializer, contentType, statusCode, cancellationToken); + return WriteAsJsonAsync(response, instance, serializer, contentType, cancellationToken); } - /// /// Asynchronously writes the specified value as JSON to the response body using the provided . - /// The response content-type will be set to application/json; charset=utf-8 and the status code set to 200. + /// The response content-type will be set to application/json; charset=utf-8. /// /// The type of object to write. /// The response to write JSON to. @@ -168,29 +127,12 @@ public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T in /// A that represents the asynchronous operation. public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, ObjectSerializer serializer, CancellationToken cancellationToken = default) { - return WriteAsJsonAsync(response, instance, serializer, "application/json; charset=utf-8", HttpStatusCode.OK, cancellationToken); + return WriteAsJsonAsync(response, instance, serializer, "application/json; charset=utf-8", cancellationToken); } - - /// - /// Asynchronously writes the specified value as JSON to the response body using the provided . - /// The response content-type will be set to application/json; charset=utf-8 and the status code set to the provided . - /// - /// The type of object to write. - /// The response to write JSON to. - /// The instance to serialize and write as JSON. - /// The serializer used to serialize the instance. - /// The status code to set on the response. - /// A used to cancel the operation. - /// A that represents the asynchronous operation. - public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, ObjectSerializer serializer, HttpStatusCode statusCode, - CancellationToken cancellationToken = default) - { - return WriteAsJsonAsync(response, instance, serializer, "application/json; charset=utf-8", statusCode, cancellationToken); - } - + /// /// Asynchronously writes the specified value as JSON to the response body using the provided . - /// The response content-type will be set to the provided and the status code set to 200. + /// The response content-type will be set to the provided . /// /// The type of object to write. /// The response to write JSON to. @@ -199,26 +141,7 @@ public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T in /// The content-type to set on the response. /// A used to cancel the operation. /// A that represents the asynchronous operation. - public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, - ObjectSerializer serializer, string contentType, - CancellationToken cancellationToken = default) - { - return WriteAsJsonAsync(response, instance, serializer, contentType, HttpStatusCode.OK, cancellationToken); - } - - /// - /// Asynchronously writes the specified value as JSON to the response body using the provided . - /// The response content-type will be set to the provided and the status code set to the provided . - /// - /// The type of object to write. - /// The response to write JSON to. - /// The instance to serialize and write as JSON. - /// The serializer used to serialize the instance. - /// The content-type to set on the response. - /// The status code to set on the response. - /// A used to cancel the operation. - /// A that represents the asynchronous operation. - public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, ObjectSerializer serializer, string contentType, HttpStatusCode statusCode, CancellationToken cancellationToken = default) + public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T instance, ObjectSerializer serializer, string contentType, CancellationToken cancellationToken = default) { if (response is null) { @@ -236,8 +159,6 @@ public static ValueTask WriteAsJsonAsync(this HttpResponseData response, T in } response.Headers.Add("Content-Type", contentType); - response.StatusCode = statusCode; - return serializer.SerializeAsync(response.Body, instance, typeof(T), cancellationToken); } diff --git a/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs b/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs index 09b51af49..2da456062 100644 --- a/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs +++ b/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs @@ -68,7 +68,7 @@ public async Task WriteAsJsonAsync_UsesRegisteredSerializer() public async Task WriteAsJsonAsync_ContentTypeOverload_AppliesParameters() { FunctionContext context = CreateContext(new NewtonsoftJsonObjectSerializer()); - var response = CreateResponse(context); + var response = CreateResponse(context, HttpStatusCode.Accepted); var poco = new ResponsePoco { @@ -81,7 +81,7 @@ public async Task WriteAsJsonAsync_ContentTypeOverload_AppliesParameters() string result = ReadResponseBody(response); Assert.Equal("application/json", response.Headers.GetValues("content-type").FirstOrDefault()); - Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Equal(HttpStatusCode.Accepted, response.StatusCode); Assert.Equal("{\"jsonnetname\":\"Test\",\"jsonnetint\":42}", result); } @@ -89,7 +89,7 @@ public async Task WriteAsJsonAsync_ContentTypeOverload_AppliesParameters() public async Task WriteAsJsonAsync_StatusCodeOverload_AppliesParameters() { FunctionContext context = CreateContext(new NewtonsoftJsonObjectSerializer()); - var response = CreateResponse(context); + var response = CreateResponse(context, HttpStatusCode.BadRequest); var poco = new ResponsePoco { @@ -97,7 +97,7 @@ public async Task WriteAsJsonAsync_StatusCodeOverload_AppliesParameters() SomeInt = 42 }; - await HttpResponseDataExtensions.WriteAsJsonAsync(response, poco, HttpStatusCode.BadRequest); + await HttpResponseDataExtensions.WriteAsJsonAsync(response, poco); string result = ReadResponseBody(response); @@ -127,9 +127,9 @@ public async Task WriteAsJsonAsync_SerializerAndContentTypeOverload_AppliesParam Assert.Equal("{\"jsonnetname\":\"Test\",\"jsonnetint\":42}", result); } - private static TestHttpResponseData CreateResponse(FunctionContext context) + private static TestHttpResponseData CreateResponse(FunctionContext context, HttpStatusCode statusCode = HttpStatusCode.OK) { - var response = new TestHttpResponseData(context, HttpStatusCode.Accepted); + var response = new TestHttpResponseData(context, statusCode); response.Body = new MemoryStream(); response.Headers = new HttpHeadersCollection(); return response; From a4f8ff86e15bd6904c2876203b2a6ff178162eeb Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Thu, 10 Oct 2024 11:05:23 -0700 Subject: [PATCH 039/190] Adding FunctionsApplicationBuilder --- .../DotNetWorker.ApplicationInsights.csproj | 2 +- .../DotNetWorker.Core.csproj | 2 +- .../DotNetWorker.Grpc.csproj | 2 +- .../DotNetWorker.OpenTelemetry.csproj | 2 +- .../Builder/BootstrapHostBuilder.cs | 179 ++++++++++++++++++ .../Builder/FunctionsApplication.cs | 17 ++ .../Builder/FunctionsApplicationBuilder.cs | 141 ++++++++++++++ src/DotNetWorker/DotNetWorker.csproj | 2 +- .../Hosting/WorkerHostBuilderExtensions.cs | 19 +- src/DotNetWorker/Properties/AssemblyInfo.cs | 1 + 10 files changed, 356 insertions(+), 11 deletions(-) create mode 100644 src/DotNetWorker/Builder/BootstrapHostBuilder.cs create mode 100644 src/DotNetWorker/Builder/FunctionsApplication.cs create mode 100644 src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 6df5556a6..ee90cd049 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -9,7 +9,7 @@ 0 0 README.md - -preview1 + -preview2 $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 66fb674d9..be50c4527 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview1 + -preview2 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index e128861ae..58b5320cc 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview1 + -preview2 true diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index 698a5ce04..28c63fb17 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -8,7 +8,7 @@ 1 1 0 - -preview1 + -preview2 README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker/Builder/BootstrapHostBuilder.cs b/src/DotNetWorker/Builder/BootstrapHostBuilder.cs new file mode 100644 index 000000000..78b1e4357 --- /dev/null +++ b/src/DotNetWorker/Builder/BootstrapHostBuilder.cs @@ -0,0 +1,179 @@ +// 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 Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +namespace Microsoft.Azure.Functions.Worker.Builder +{ + /// + /// Adapter to allow us to use our own extensions with the + /// . Based on the BootstrapHostBuilder from the + /// AspNetCore source: https://github.com/dotnet/aspnetcore/blob/54c0cc8fa74e8196a2ce0711a20959143be7fb6f/src/DefaultBuilder/src/BootstrapHostBuilder.cs + /// + internal class BootstrapHostBuilder : IHostBuilder + { + private readonly HostApplicationBuilder _builder; + + private readonly List> _configureHostActions = new(); + private readonly List> _configureAppActions = new(); + private readonly List> _configureServicesActions = new(); + private IServiceProviderFactory? _serviceProviderFactory; + private bool _defaultsComplete = false; + + public BootstrapHostBuilder(HostApplicationBuilder builder) + { + _builder = builder ?? throw new ArgumentNullException(nameof(builder)); + + foreach (var descriptor in _builder.Services) + { + if (descriptor.ServiceType == typeof(HostBuilderContext)) + { + Context = (HostBuilderContext)descriptor.ImplementationInstance!; + break; + } + } + + if (Context is null) + { + throw new InvalidOperationException($"{nameof(HostBuilderContext)} must exist in the {nameof(IServiceCollection)}"); + } + } + + public IDictionary Properties => Context.Properties; + + public HostBuilderContext Context { get; } + + public IHostBuilder ConfigureAppConfiguration(Action configureDelegate) + { + if (configureDelegate is null) + { + throw new ArgumentNullException(nameof(configureDelegate)); + } + + if (_defaultsComplete) + { + // After defaults are run, we want to run these immediately so that they are observable by the imperative code + configureDelegate(Context, _builder.Configuration); + } + else + { + _configureAppActions.Add(configureDelegate); + } + + return this; + } + + public IHostBuilder ConfigureHostConfiguration(Action configureDelegate) + { + if (configureDelegate is null) + { + throw new ArgumentNullException(nameof(configureDelegate)); + } + + if (_defaultsComplete) + { + // After defaults are run, we want to run these immediately so that they are observable by the imperative code + configureDelegate(_builder.Configuration); + } + else + { + _configureHostActions.Add(configureDelegate); + } + + return this; + } + + public IHostBuilder ConfigureServices(Action configureDelegate) + { + if (configureDelegate is null) + { + throw new ArgumentNullException(nameof(configureDelegate)); + } + + if (_defaultsComplete) + { + // After defaults are run, we want to run these immediately so that they are observable by the imperative code + configureDelegate(Context, _builder.Services); + } + else + { + _configureServicesActions.Add(configureDelegate); + } + + return this; + } + + public IHost Build() + { + // Functions configuration will never call this. + throw new InvalidOperationException(); + } + + public IHostBuilder ConfigureContainer(Action configureDelegate) + { + // Functions configuration will never call this. + throw new InvalidOperationException(); + } + + public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory) where TContainerBuilder : notnull + { + _serviceProviderFactory = new ServiceProviderFactoryAdapter(factory); + return this; + } + + public IHostBuilder UseServiceProviderFactory(Func> factory) where TContainerBuilder : notnull + { + return UseServiceProviderFactory(factory(Context)); + } + + public void RunDefaultCallbacks() + { + foreach (var configureHostAction in _configureHostActions) + { + configureHostAction(_builder.Configuration); + } + + // ConfigureAppConfiguration cannot modify the host configuration because doing so could + // change the environment, content root and application name which is not allowed at this stage. + foreach (var configureAppAction in _configureAppActions) + { + configureAppAction(Context, _builder.Configuration); + } + + foreach (var configureServicesAction in _configureServicesActions) + { + configureServicesAction(Context, _builder.Services); + } + + _defaultsComplete = true; + } + + internal void ApplyServiceProviderFactory() + { + if (_serviceProviderFactory is null) + { + return; + } + + _builder.ConfigureContainer(_serviceProviderFactory); + } + + private sealed class ServiceProviderFactoryAdapter : IServiceProviderFactory where TContainerBuilder : notnull + { + private readonly IServiceProviderFactory _serviceProviderFactory; + + public ServiceProviderFactoryAdapter(IServiceProviderFactory serviceProviderFactory) + { + _serviceProviderFactory = serviceProviderFactory; + } + + public object CreateBuilder(IServiceCollection services) => _serviceProviderFactory.CreateBuilder(services); + + public IServiceProvider CreateServiceProvider(object containerBuilder) => _serviceProviderFactory.CreateServiceProvider((TContainerBuilder)containerBuilder); + } + } +} diff --git a/src/DotNetWorker/Builder/FunctionsApplication.cs b/src/DotNetWorker/Builder/FunctionsApplication.cs new file mode 100644 index 000000000..8741a21e7 --- /dev/null +++ b/src/DotNetWorker/Builder/FunctionsApplication.cs @@ -0,0 +1,17 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +namespace Microsoft.Azure.Functions.Worker.Builder; + +/// +/// The application used to configure an Azure Functions worker. +/// +public class FunctionsApplication +{ + /// + /// Initializes a new instance of the class with preconfigured defaults. + /// + /// The command line arguments. + /// The . + public static FunctionsApplicationBuilder CreateBuilder(string[] args) => new(args); +} diff --git a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs new file mode 100644 index 000000000..363c611f2 --- /dev/null +++ b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs @@ -0,0 +1,141 @@ +// 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 Microsoft.Azure.Functions.Worker.Middleware; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Diagnostics.Metrics; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Azure.Functions.Worker.Builder; + +/// +/// A builder for Azure Functions worker applications. +/// +public class FunctionsApplicationBuilder : IHostApplicationBuilder, IFunctionsWorkerApplicationBuilder +{ + private readonly HostApplicationBuilder _hostApplicationBuilder; + private readonly BootstrapHostBuilder _bootstrapHostBuilder; + private readonly IFunctionsWorkerApplicationBuilder _functionsWorkerApplicationBuilder; + + private bool _hasBuilt = false; + + internal const string SkipDefaultWorkerMiddlewareKey = "__SkipDefaultWorkerMiddleware"; + + internal FunctionsApplicationBuilder(string[]? args) + { + var configuration = new ConfigurationManager(); + + _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings + { + Configuration = configuration + }); + + _bootstrapHostBuilder = new BootstrapHostBuilder(_hostApplicationBuilder); + + // We'll set the default middleware up just before we build. + _bootstrapHostBuilder.Context.Properties[SkipDefaultWorkerMiddlewareKey] = true; + + _bootstrapHostBuilder + .ConfigureDefaults(args) + .ConfigureFunctionsWorkerDefaults(); + + _functionsWorkerApplicationBuilder = InitializeHosting(_bootstrapHostBuilder); + } + + /// + public IDictionary Properties => ((IHostApplicationBuilder)_hostApplicationBuilder).Properties; + + IConfigurationManager IHostApplicationBuilder.Configuration => Configuration; + + /// + /// Gets the set of key/value configuration properties. + /// + /// + /// This can be mutated by adding more configuration sources, which will update its current view. + /// + public ConfigurationManager Configuration => _hostApplicationBuilder.Configuration; + + /// + public IHostEnvironment Environment { get; private set; } + + /// + public ILoggingBuilder Logging => _hostApplicationBuilder.Logging; + + /// + public IMetricsBuilder Metrics => _hostApplicationBuilder.Metrics; + + /// + public IServiceCollection Services => _hostApplicationBuilder.Services; + + /// + /// Only available to AspNetCore extension (and maybe not even there in the future) + /// + internal IHostBuilder HostBuilder => _bootstrapHostBuilder; + + /// + /// Run the given actions to initialize the host. This can only be called once. + /// + /// An initialized . + public IHost Build() + { + if (_hasBuilt) + { + throw new InvalidOperationException("The application has already been built."); + } + + // we skipped this; make sure we add it at the end + this.UseDefaultWorkerMiddleware(); + + _hasBuilt = true; + + return _hostApplicationBuilder.Build(); + } + + /// + public void ConfigureContainer(IServiceProviderFactory factory, Action? configure = null) where TContainerBuilder : notnull + { + _hostApplicationBuilder.ConfigureContainer(factory, configure); + } + + private IFunctionsWorkerApplicationBuilder InitializeHosting(BootstrapHostBuilder bootstrapHostBuilder) + { + bootstrapHostBuilder.ApplyServiceProviderFactory(); + bootstrapHostBuilder.RunDefaultCallbacks(); + + IFunctionsWorkerApplicationBuilder functionsWorkerApplicationBuilder = null!; + + foreach (var descriptor in Services) + { + if (descriptor.ServiceType == typeof(IFunctionsWorkerApplicationBuilder)) + { + functionsWorkerApplicationBuilder = (IFunctionsWorkerApplicationBuilder)descriptor.ImplementationInstance!; + break; + } + } + + // Grab the HostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then + // grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection. + //var hostContext = (HostBuilderContext)bootstrapHostBuilder.Properties[typeof(HostBuilderContext)]; + Environment = bootstrapHostBuilder.Context.HostingEnvironment; + + //Host = new ConfigureHostBuilder(bootstrapHostBuilder.Context, Configuration, Services); + //WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services); + + return functionsWorkerApplicationBuilder; + } + + /// + public IFunctionsWorkerApplicationBuilder Use(Func middleware) + { + if (_hasBuilt) + { + throw new InvalidOperationException("The application has already been built."); + } + + return _functionsWorkerApplicationBuilder.Use(middleware); + } +} diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index 244d6fb60..ce2ce568e 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview1 + -preview2 diff --git a/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs b/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs index 7df8f5339..0454a69ef 100644 --- a/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs +++ b/src/DotNetWorker/Hosting/WorkerHostBuilderExtensions.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Text.Json; using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Builder; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -169,12 +170,18 @@ public static IHostBuilder ConfigureFunctionsWorkerDefaults(this IHostBuilder bu // Call the provided configuration prior to adding default middleware configure(context, appBuilder); - // Add default middleware - appBuilder.UseDefaultWorkerMiddleware(); - }) - .UseDefaultServiceProvider((context, options) => - { - options.ValidateScopes = context.HostingEnvironment.IsDevelopment(); + static bool ShouldSkipDefaultWorkerMiddleware(IDictionary props) + { + return props is not null && + props.TryGetValue(FunctionsApplicationBuilder.SkipDefaultWorkerMiddlewareKey, out var skipObj) && + skipObj is true; + } + + if (!ShouldSkipDefaultWorkerMiddleware(context.Properties)) + { + // Add default middleware + appBuilder.UseDefaultWorkerMiddleware(); + } }); // Invoke any extension methods auto generated by functions worker sdk. diff --git a/src/DotNetWorker/Properties/AssemblyInfo.cs b/src/DotNetWorker/Properties/AssemblyInfo.cs index 982103208..6f3b6406c 100644 --- a/src/DotNetWorker/Properties/AssemblyInfo.cs +++ b/src/DotNetWorker/Properties/AssemblyInfo.cs @@ -5,3 +5,4 @@ [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] From 76e5bb1212f683831137f0e92d12a236a6cd22b3 Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Mon, 14 Oct 2024 12:00:40 -0700 Subject: [PATCH 040/190] skipping problematic tests --- test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs b/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs index e4343e9d7..bf4a454c4 100644 --- a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs +++ b/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs @@ -50,7 +50,7 @@ public async Task ExecuteZipDeploy_InvalidZipFilePath() /// /// ZipDeploy should use PublishUrl if not null or empty, else use SiteName. /// - [Theory] + [Theory(Skip = "https://github.com/Azure/azure-functions-dotnet-worker/issues/2781")] [InlineData("https://sitename.scm.azurewebsites.net", null, false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] [InlineData("https://sitename.scm.azurewebsites.net", null, true, "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false")] [InlineData("https://sitename.scm.azurewebsites.net", "", false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] @@ -96,7 +96,7 @@ public async Task ExecuteZipDeploy_NeitherPublishUrlNorSiteNameGiven(string publ await RunZipDeployAsyncTest(publishUrl, siteName, UserAgentVersion, useBlobContainerDeploy: false, HttpStatusCode.OK, verifyStep); } - [Theory] + [Theory(Skip = "https://github.com/Azure/azure-functions-dotnet-worker/issues/2781")] [InlineData(HttpStatusCode.OK, false, true)] [InlineData(HttpStatusCode.OK, true, true)] [InlineData(HttpStatusCode.Accepted, false, true)] From ea69e61d053ffc489a558dd0ac1cd57acd75594f Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Mon, 14 Oct 2024 15:32:30 -0700 Subject: [PATCH 041/190] Adding ConfigureFunctionsWebApplication() (#2782) --- ...sApplicationBuilderAspNetCoreExtensions.cs | 23 +++++ .../src/FunctionsWebApplicationBuilder.cs | 89 ------------------- .../Worker.Extensions.Http.AspNetCore.csproj | 4 +- 3 files changed, 25 insertions(+), 91 deletions(-) create mode 100644 extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsApplicationBuilderAspNetCoreExtensions.cs delete mode 100644 extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsApplicationBuilderAspNetCoreExtensions.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsApplicationBuilderAspNetCoreExtensions.cs new file mode 100644 index 000000000..0e241a282 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsApplicationBuilderAspNetCoreExtensions.cs @@ -0,0 +1,23 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using Microsoft.Extensions.Hosting; + +namespace Microsoft.Azure.Functions.Worker.Builder; + +/// +/// ASP.NET Core extensions for . +/// +public static class FunctionsApplicationBuilderAspNetCoreExtensions +{ + /// + /// Configures the worker to use the ASP.NET Core integration, enabling advanced HTTP features. + /// + /// The to configure. + /// The for chaining. + public static FunctionsApplicationBuilder ConfigureFunctionsWebApplication(this FunctionsApplicationBuilder builder) + { + builder.HostBuilder.ConfigureFunctionsWebApplication(); + return builder; + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs deleted file mode 100644 index c639d0d24..000000000 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsWebApplicationBuilder.cs +++ /dev/null @@ -1,89 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Azure.Functions.Worker.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Diagnostics.Metrics; -using Microsoft.Extensions.Logging; - -namespace Microsoft.Extensions.Hosting -{ - /// - /// Placeholder - /// - public class FunctionsWebApplicationBuilder : IHostApplicationBuilder - { - private readonly HostApplicationBuilder _hostApplicationBuilder; - - internal FunctionsWebApplicationBuilder() - { - var configuration = new ConfigurationManager(); - - _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings - { - Configuration = configuration - }); - - var bootstrapHostBuilder = new BootstrapHostBuilder(_hostApplicationBuilder); - bootstrapHostBuilder.ConfigureFunctionsWebApplication(); - - InitializeHosting(bootstrapHostBuilder); - } - - /// - public IDictionary Properties => ((IHostApplicationBuilder)_hostApplicationBuilder).Properties; - - IConfigurationManager IHostApplicationBuilder.Configuration => Configuration; - - /// - public ConfigurationManager Configuration => _hostApplicationBuilder.Configuration; - - /// - public IHostEnvironment Environment { get; private set; } - - /// - public ILoggingBuilder Logging => _hostApplicationBuilder.Logging; - - /// - public IMetricsBuilder Metrics => _hostApplicationBuilder.Metrics; - - /// - public IServiceCollection Services => _hostApplicationBuilder.Services; - - /// - /// Placeholder - /// - /// placeholder - public static FunctionsWebApplicationBuilder CreateBuilder() - { - return new FunctionsWebApplicationBuilder(); - } - - /// - /// Placeholder - /// - /// placeholder - public IHost Build() - { - return _hostApplicationBuilder.Build(); - } - - /// - public void ConfigureContainer(IServiceProviderFactory factory, Action? configure = null) where TContainerBuilder : notnull - => _hostApplicationBuilder.ConfigureContainer(factory, configure); - - private void InitializeHosting(BootstrapHostBuilder bootstrapHostBuilder) - { - bootstrapHostBuilder.RunDefaultCallbacks(); - - // Grab the WebHostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then - // grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection. - var webHostContext = (WebHostBuilderContext)bootstrapHostBuilder.Properties[typeof(WebHostBuilderContext)]; - Environment = webHostContext.HostingEnvironment; - - //Host = new ConfigureHostBuilder(bootstrapHostBuilder.Context, Configuration, Services); - //WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services); - } - } -} diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index 9ccf445e2..b606485fd 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -7,7 +7,7 @@ 2.0.0 - -preview1 + -preview2 net6.0 @@ -24,7 +24,7 @@ - + From 1dea064bdd1faa1e584659caada79753c4d2afcc Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 15 Oct 2024 14:10:04 -0700 Subject: [PATCH 042/190] updating AspNetCore to preview2 package dep (#2784) --- .../src/Worker.Extensions.Http.AspNetCore.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index b606485fd..ca17b7642 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -24,7 +24,7 @@ - + From 231ca1137b30bcd3963ee434a2c35685eb48507c Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 21 Oct 2024 23:26:16 -0700 Subject: [PATCH 043/190] Tactical fix to address a test issue (#2798) --- .../FunctionExecutor/DependentAssemblyTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index 6a446b739..89051066d 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -138,7 +138,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=1.19.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; + var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor; From cb31f4995a6d1b2cfccebfbdf23c07325802687d Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 22 Oct 2024 07:00:42 -0700 Subject: [PATCH 044/190] updating to preview3 (#2796) --- .../DotNetWorker.ApplicationInsights.csproj | 2 +- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- .../DotNetWorker.OpenTelemetry.csproj | 2 +- src/DotNetWorker/DotNetWorker.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index ee90cd049..ed7ed4dfb 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -9,7 +9,7 @@ 0 0 README.md - -preview2 + -preview3 $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index be50c4527..c8d1c07b7 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview2 + -preview3 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 58b5320cc..d4fbfb36b 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview2 + -preview3 true diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index 28c63fb17..ff4501ebe 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -8,7 +8,7 @@ 1 1 0 - -preview2 + -preview3 README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index ce2ce568e..f23fd58f2 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview2 + -preview3 From d1dd79c66d941754ff5970710edfe4f1f848149f Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 22 Oct 2024 12:30:23 -0700 Subject: [PATCH 045/190] moving AspNetCore extension to preview3 (#2801) --- .../src/Worker.Extensions.Http.AspNetCore.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index ca17b7642..2d2ae2837 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -7,7 +7,7 @@ 2.0.0 - -preview2 + -preview3 net6.0 @@ -24,7 +24,7 @@ - + From 2e10687fa0f8961655d4ec39658c0acc61e0cd3d Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Wed, 23 Oct 2024 12:47:13 -0700 Subject: [PATCH 046/190] explicitly remove ConsoleLogger (#2806) --- .../Builder/FunctionsApplicationBuilder.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs index 363c611f2..f08c91857 100644 --- a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs +++ b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs @@ -9,6 +9,7 @@ using Microsoft.Extensions.Diagnostics.Metrics; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Console; namespace Microsoft.Azure.Functions.Worker.Builder; @@ -41,6 +42,19 @@ internal FunctionsApplicationBuilder(string[]? args) _bootstrapHostBuilder .ConfigureDefaults(args) + .ConfigureServices(services => + { + // The console logger can result in duplicate logging. + foreach (var descriptor in services) + { + if (descriptor.ServiceType == typeof(ILoggerProvider) && + descriptor.ImplementationType == typeof(ConsoleLoggerProvider)) + { + services.Remove(descriptor); + break; + } + } + }) .ConfigureFunctionsWorkerDefaults(); _functionsWorkerApplicationBuilder = InitializeHosting(_bootstrapHostBuilder); From a3c367a6e1b49da628b0f9897defe44eabfa11d9 Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Wed, 23 Oct 2024 13:19:47 -0700 Subject: [PATCH 047/190] updating to preview4 (#2807) --- .../DotNetWorker.ApplicationInsights.csproj | 2 +- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- .../DotNetWorker.OpenTelemetry.csproj | 2 +- src/DotNetWorker/DotNetWorker.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index ed7ed4dfb..0684c553d 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -9,7 +9,7 @@ 0 0 README.md - -preview3 + -preview4 $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index c8d1c07b7..3a8ec0344 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview3 + -preview4 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index d4fbfb36b..4cfd096d2 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview3 + -preview4 true diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index ff4501ebe..b9e03827c 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -8,7 +8,7 @@ 1 1 0 - -preview3 + -preview4 README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index f23fd58f2..680e79ae2 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview3 + -preview4 From 2b759340a4dca043a0b3ca5b061826d71f6e0cf7 Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Wed, 23 Oct 2024 16:47:09 -0700 Subject: [PATCH 048/190] moving aspnet to preview4 (#2808) --- .../src/Worker.Extensions.Http.AspNetCore.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index 2d2ae2837..d98f96c20 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -7,7 +7,7 @@ 2.0.0 - -preview3 + -preview4 net6.0 @@ -24,7 +24,7 @@ - + From 8710447ce20e201f0c23cccbfab97f2724c6962c Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Wed, 23 Oct 2024 16:59:05 -0700 Subject: [PATCH 049/190] Updating dependencies (#2809) --- sdk/Sdk.Generators/Sdk.Generators.csproj | 2 +- sdk/Sdk/Sdk.csproj | 2 +- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 6 +++--- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 4 ++-- src/DotNetWorker/DotNetWorker.csproj | 4 ++-- test/E2ETests/E2ETests/E2ETests.csproj | 2 +- test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj | 2 +- test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj | 2 +- test/TestUtility/TestUtility.csproj | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index 584198c46..98d57854d 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -24,7 +24,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 74d7ce451..9eb4b3956 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -33,7 +33,7 @@ - + diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 3a8ec0344..316861f7b 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -23,14 +23,14 @@ - - + + - + diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 4cfd096d2..9c3a05087 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -29,8 +29,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - + + diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index 680e79ae2..3fbec5b16 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -18,8 +18,8 @@ - - + + diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index efd107a25..b7b8eb93a 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -15,7 +15,7 @@ - + all diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index 6077851f7..0e8049d66 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -14,7 +14,7 @@ - + all diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index ce416eaac..a4f836e01 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -28,7 +28,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index 0d266474e..5df330bb9 100644 --- a/test/TestUtility/TestUtility.csproj +++ b/test/TestUtility/TestUtility.csproj @@ -13,8 +13,8 @@ - - + + From 17751a27fc0a8a5b450fca571bcc5679c883f69c Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 29 Oct 2024 12:14:04 -0700 Subject: [PATCH 050/190] prepping preview5 (#2813) --- .../DotNetWorker.ApplicationInsights.csproj | 2 +- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- .../DotNetWorker.OpenTelemetry.csproj | 2 +- src/DotNetWorker/DotNetWorker.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 0684c553d..d8f263eae 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -9,7 +9,7 @@ 0 0 README.md - -preview4 + -preview5 $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 316861f7b..a88d02c49 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview4 + -preview5 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 9c3a05087..87a0038fe 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview4 + -preview5 true diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index b9e03827c..e2cc658ec 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -8,7 +8,7 @@ 1 1 0 - -preview4 + -preview5 README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index 3fbec5b16..d5cffeeef 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -11,7 +11,7 @@ 2 0 0 - -preview4 + -preview5 From e4b755ae158d11f5044b3fb250f7a15c284b346a Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 11 Nov 2024 10:10:21 -0800 Subject: [PATCH 051/190] Fix modifying collection while enumerating (#2844) --- .../Builder/FunctionsApplicationBuilder.cs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs index f08c91857..92f823d79 100644 --- a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs +++ b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using Microsoft.Azure.Functions.Worker.Middleware; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -41,21 +42,21 @@ internal FunctionsApplicationBuilder(string[]? args) _bootstrapHostBuilder.Context.Properties[SkipDefaultWorkerMiddlewareKey] = true; _bootstrapHostBuilder - .ConfigureDefaults(args) - .ConfigureServices(services => - { - // The console logger can result in duplicate logging. - foreach (var descriptor in services) - { - if (descriptor.ServiceType == typeof(ILoggerProvider) && - descriptor.ImplementationType == typeof(ConsoleLoggerProvider)) - { - services.Remove(descriptor); - break; - } - } - }) - .ConfigureFunctionsWorkerDefaults(); + .ConfigureDefaults(args) + .ConfigureServices(services => + { + // The console logger can result in duplicate logging. + List toRemove = services + .Where(d => d.ServiceType == typeof(ILoggerProvider) + && d.ImplementationType == typeof(ConsoleLoggerProvider)) + .ToList(); + + foreach (var descriptor in toRemove) + { + services.Remove(descriptor); + } + }) + .ConfigureFunctionsWorkerDefaults(); _functionsWorkerApplicationBuilder = InitializeHosting(_bootstrapHostBuilder); } From d3af65460e67eb638ebc40b78b536c7d82682843 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 11 Nov 2024 10:10:38 -0800 Subject: [PATCH 052/190] Address FunctionsApplicationBuilder.Environment null (#2837) * Address FunctionsApplicationBuilder.Environment null * Use correct host builder for environment --- .../Builder/FunctionsApplicationBuilder.cs | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs index 92f823d79..7fab02258 100644 --- a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs +++ b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs @@ -64,18 +64,14 @@ internal FunctionsApplicationBuilder(string[]? args) /// public IDictionary Properties => ((IHostApplicationBuilder)_hostApplicationBuilder).Properties; + /// IConfigurationManager IHostApplicationBuilder.Configuration => Configuration; - /// - /// Gets the set of key/value configuration properties. - /// - /// - /// This can be mutated by adding more configuration sources, which will update its current view. - /// + /// public ConfigurationManager Configuration => _hostApplicationBuilder.Configuration; /// - public IHostEnvironment Environment { get; private set; } + public IHostEnvironment Environment => _bootstrapHostBuilder.Context.HostingEnvironment; /// public ILoggingBuilder Logging => _hostApplicationBuilder.Logging; @@ -135,7 +131,6 @@ private IFunctionsWorkerApplicationBuilder InitializeHosting(BootstrapHostBuilde // Grab the HostBuilderContext from the property bag to use in the ConfigureWebHostBuilder. Then // grab the IWebHostEnvironment from the webHostContext. This also matches the instance in the IServiceCollection. //var hostContext = (HostBuilderContext)bootstrapHostBuilder.Properties[typeof(HostBuilderContext)]; - Environment = bootstrapHostBuilder.Context.HostingEnvironment; //Host = new ConfigureHostBuilder(bootstrapHostBuilder.Context, Configuration, Services); //WebHost = new ConfigureWebHostBuilder(webHostContext, Configuration, Services); From bd2dfd8589b9299f3d39882dbd8490e33dccd008 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 11 Nov 2024 15:12:24 -0800 Subject: [PATCH 053/190] Updates after taking changes from base branch --- sdk/Sdk/FunctionMetadataJsonWriter.cs | 2 +- sdk/Sdk/Sdk.csproj | 2 +- test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs | 2 ++ test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj | 1 - test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj | 2 -- 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sdk/Sdk/FunctionMetadataJsonWriter.cs b/sdk/Sdk/FunctionMetadataJsonWriter.cs index 94e4347f8..38fcadc25 100644 --- a/sdk/Sdk/FunctionMetadataJsonWriter.cs +++ b/sdk/Sdk/FunctionMetadataJsonWriter.cs @@ -19,7 +19,7 @@ private static JsonSerializerOptions CreateSerializerOptions() return new JsonSerializerOptions { WriteIndented = true, - IgnoreNullValues = true, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull, PropertyNameCaseInsensitive = true, IgnoreReadOnlyProperties = true, DictionaryKeyPolicy = namingPolicy, diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 9eb4b3956..29703f966 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -30,7 +30,7 @@ - + diff --git a/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs b/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs index 061706acb..c7e37dec2 100644 --- a/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs +++ b/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs @@ -164,11 +164,13 @@ public async Task InvokeAsync_UserCodeThrowsException_OptionEnabled() public async Task InvokeAsync_UserCodeThrowsException_OptionDisabled() { var exceptionMessage = "user code exception"; +#pragma warning disable CS0618 // Type or member is obsolete. Test obsolete property. var mockOptions = new OptionsWrapper(new() { Serializer = new JsonObjectSerializer(), EnableUserCodeException = false }); +#pragma warning restore CS0618 // Type or member is obsolete _mockApplication .Setup(m => m.InvokeFunctionAsync(It.IsAny())) diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index 0e8049d66..0ca059f81 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -13,7 +13,6 @@ - diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index a4f836e01..2c98824fd 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -27,8 +27,6 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive From f665ee9e501ba3dde83f3d32927e87e3e54c6e7d Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 11 Nov 2024 16:32:21 -0800 Subject: [PATCH 054/190] Fixing package downgrades after rebase --- samples/AspNetIntegration/AspNetIntegration.csproj | 2 +- samples/Configuration/Configuration.csproj | 2 +- samples/FunctionApp/FunctionApp.csproj | 4 ++-- samples/Net9FunctionApp/Net9FunctionApp.csproj | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/samples/AspNetIntegration/AspNetIntegration.csproj b/samples/AspNetIntegration/AspNetIntegration.csproj index 2c27549cd..0fedae833 100644 --- a/samples/AspNetIntegration/AspNetIntegration.csproj +++ b/samples/AspNetIntegration/AspNetIntegration.csproj @@ -7,7 +7,7 @@ - + diff --git a/samples/Configuration/Configuration.csproj b/samples/Configuration/Configuration.csproj index 7e4711ef4..fd487daab 100644 --- a/samples/Configuration/Configuration.csproj +++ b/samples/Configuration/Configuration.csproj @@ -10,7 +10,7 @@ - + diff --git a/samples/FunctionApp/FunctionApp.csproj b/samples/FunctionApp/FunctionApp.csproj index 23c1a738d..e0c363aa4 100644 --- a/samples/FunctionApp/FunctionApp.csproj +++ b/samples/FunctionApp/FunctionApp.csproj @@ -9,13 +9,13 @@ - + - + diff --git a/samples/Net9FunctionApp/Net9FunctionApp.csproj b/samples/Net9FunctionApp/Net9FunctionApp.csproj index 9b6b2a4ab..9784363c2 100644 --- a/samples/Net9FunctionApp/Net9FunctionApp.csproj +++ b/samples/Net9FunctionApp/Net9FunctionApp.csproj @@ -11,8 +11,8 @@ - - + + From 483de292a5e31fa3015cc848762bdb559e665c7f Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Tue, 12 Nov 2024 11:52:32 -0800 Subject: [PATCH 055/190] Update OTel release notes (#2857) --- src/DotNetWorker.OpenTelemetry/release_notes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DotNetWorker.OpenTelemetry/release_notes.md b/src/DotNetWorker.OpenTelemetry/release_notes.md index 7caeb6d1c..dcad72ebb 100644 --- a/src/DotNetWorker.OpenTelemetry/release_notes.md +++ b/src/DotNetWorker.OpenTelemetry/release_notes.md @@ -2,4 +2,4 @@ ### Microsoft.Azure.Functions.Worker.OpenTelemetry 1.0.0 (Preview 2) -- `UseFunctionsWorkerDefaults` signature now uses `OpenTelemetryBuilder` (from `IOpenTelemetryBuilder`) (#2839) +- `UseFunctionsWorkerDefaults` signature now uses `IOpenTelemetryBuilder` (from `OpenTelemetryBuilder`) (#2839) \ No newline at end of file From 11ad01e222928557bcf7f2347e7b62eca38e57b4 Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 12 Nov 2024 11:57:08 -0800 Subject: [PATCH 056/190] Add .net9 transitive dependencies (#2852) * Add .net9 transitive dependencies * more cleanup * adding net6 as target; moving to net9.0 * fixes * updating #ifs * updating sdk * bumping azure.core * removing previews * bumping global.json --------- Co-authored-by: Jacob Viau --- global.json | 2 +- sdk/Sdk/Sdk.csproj | 3 +-- .../DotNetWorker.ApplicationInsights.csproj | 3 +-- .../Converters/JsonPocoConverter.cs | 4 +-- .../Converters/MemoryConverter.cs | 2 +- .../DotNetWorker.Core.csproj | 27 ++++++++++--------- .../ThrowHelpers/ObjectDisposedThrowHelper.cs | 2 +- .../Invocation/DefaultMethodInfoLocator.cs | 4 +-- src/DotNetWorker.Core/StartupHook.cs | 6 ++--- src/DotNetWorker.Core/WorkerInformation.cs | 2 +- .../DotNetWorker.Grpc.csproj | 14 +++------- .../GrpcServiceCollectionExtensions.cs | 8 +++--- .../GrpcWorkerClientFactory.cs | 4 +-- .../Http/GrpcHttpRequestData.cs | 10 +++---- .../NativeHostIntegration/NativeMethods.cs | 9 +++++++ .../DotNetWorker.OpenTelemetry.csproj | 2 +- src/DotNetWorker/DotNetWorker.csproj | 10 ++----- 17 files changed, 53 insertions(+), 59 deletions(-) diff --git a/global.json b/global.json index e8630fed2..ec9ccb01a 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100-preview.6.24328.19", + "version": "9.0.100", "allowPrerelease": true, "rollForward": "latestPatch" }, diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 29703f966..4563be3e4 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -1,8 +1,7 @@  - 2 - -preview2 + 2 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index d8f263eae..1ab568c0e 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -8,8 +8,7 @@ 2 0 0 - README.md - -preview5 + README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs b/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs index 800c0a3d4..65710d929 100644 --- a/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs +++ b/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs @@ -73,9 +73,9 @@ private async Task GetConversionResultFromDeserialization(byte } finally { - if (stream != null) + if (stream != null) { -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER await ((IAsyncDisposable)stream).DisposeAsync(); #else diff --git a/src/DotNetWorker.Core/Converters/MemoryConverter.cs b/src/DotNetWorker.Core/Converters/MemoryConverter.cs index 28fdbedce..6915bb322 100644 --- a/src/DotNetWorker.Core/Converters/MemoryConverter.cs +++ b/src/DotNetWorker.Core/Converters/MemoryConverter.cs @@ -18,7 +18,7 @@ public ValueTask ConvertAsync(ConverterContext context) if (context.TargetType.IsAssignableFrom(typeof(string))) { -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER var target = Encoding.UTF8.GetString(sourceMemory.Span); #else var target = Encoding.UTF8.GetString(sourceMemory.Span.ToArray()); diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index a88d02c49..1d5562418 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -2,7 +2,7 @@ Library - net8.0;net9.0;netstandard2.0 + net6.0;net8.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Core This library provides the core functionality to build an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker.Core @@ -10,8 +10,7 @@ true 2 0 - 0 - -preview5 + 0 @@ -22,17 +21,19 @@ - - - - - + - + - - - - + + + + + + + + + + diff --git a/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs b/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs index ec7cb6fe7..9516b0d10 100644 --- a/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs +++ b/src/DotNetWorker.Core/Helpers/ThrowHelpers/ObjectDisposedThrowHelper.cs @@ -13,7 +13,7 @@ internal static class ObjectDisposedThrowHelper /// The is . internal static void ThrowIf(bool condition, object instance) { -#if NET8_0_OR_GREATER +#if NET7_0_OR_GREATER ObjectDisposedException.ThrowIf(condition, instance); #else if (condition) diff --git a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs index 0d149f1f6..5ab64e6f2 100644 --- a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs +++ b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs @@ -1,6 +1,6 @@ using System; using System.Reflection; -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER using System.Runtime.Loader; #endif using System.Text.RegularExpressions; @@ -21,7 +21,7 @@ public MethodInfo GetMethod(string pathToAssembly, string entryPoint) string typeName = entryPointMatch.Groups["typename"].Value; string methodName = entryPointMatch.Groups["methodname"].Value; -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER Assembly assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(pathToAssembly); #else Assembly assembly = Assembly.LoadFrom(pathToAssembly); diff --git a/src/DotNetWorker.Core/StartupHook.cs b/src/DotNetWorker.Core/StartupHook.cs index 575b8513f..baea73d30 100644 --- a/src/DotNetWorker.Core/StartupHook.cs +++ b/src/DotNetWorker.Core/StartupHook.cs @@ -32,7 +32,7 @@ public static void Initialize() RemoveSelfFromStartupHooks(); string? debuggerWaitEnabled = Environment.GetEnvironmentVariable("FUNCTIONS_ENABLE_DEBUGGER_WAIT"); string? jsonOutputEnabled = Environment.GetEnvironmentVariable("FUNCTIONS_ENABLE_JSON_OUTPUT"); -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER int processId = Environment.ProcessId; #else int processId = Process.GetCurrentProcess().Id; @@ -57,12 +57,12 @@ static bool WaitOnDebugger(int cycle) if (string.Equals(jsonOutputEnabled, bool.TrueString, StringComparison.OrdinalIgnoreCase)) { - Console.WriteLine($"azfuncjsonlog:{{ \"name\":\"dotnet-worker-startup\", \"workerProcessId\" : { processId } }}"); + Console.WriteLine($"azfuncjsonlog:{{ \"name\":\"dotnet-worker-startup\", \"workerProcessId\" : {processId} }}"); } if (string.Equals(debuggerWaitEnabled, bool.TrueString, StringComparison.OrdinalIgnoreCase)) { - Console.WriteLine($"Azure Functions .NET Worker (PID: { processId }) initialized in debug mode. Waiting for debugger to attach..."); + Console.WriteLine($"Azure Functions .NET Worker (PID: {processId}) initialized in debug mode. Waiting for debugger to attach..."); for (int i = 0; WaitOnDebugger(i); i++) { diff --git a/src/DotNetWorker.Core/WorkerInformation.cs b/src/DotNetWorker.Core/WorkerInformation.cs index 35e7482b0..fc8b79285 100644 --- a/src/DotNetWorker.Core/WorkerInformation.cs +++ b/src/DotNetWorker.Core/WorkerInformation.cs @@ -20,7 +20,7 @@ internal sealed class WorkerInformation public static WorkerInformation Instance = new(); -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER public int ProcessId => Environment.ProcessId; public string RuntimeIdentifier => RuntimeInformation.RuntimeIdentifier; diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 87a0038fe..69bc14427 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -2,7 +2,7 @@ Library - net8.0;net9.0;netstandard2.0 + net6.0;net7.0;net8.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Grpc This library provides gRPC support for Azure Functions .NET Worker communication with the Azure Functions Host. Microsoft.Azure.Functions.Worker.Grpc @@ -10,8 +10,7 @@ true 2 0 - 0 - -preview5 + 0 true @@ -22,19 +21,12 @@ - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + - - - diff --git a/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs b/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs index 7c8c0ff54..3dc7ac839 100644 --- a/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs +++ b/src/DotNetWorker.Grpc/GrpcServiceCollectionExtensions.cs @@ -5,13 +5,13 @@ using System.Threading.Channels; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; +using Microsoft.Azure.Functions.Worker.Diagnostics; +using Microsoft.Azure.Functions.Worker.Grpc; using Microsoft.Azure.Functions.Worker.Grpc.Messages; +using Microsoft.Azure.Functions.Worker.Handlers; using Microsoft.Azure.Functions.Worker.Logging; -using Microsoft.Azure.Functions.Worker.Grpc; -using Microsoft.Azure.Functions.Worker.Diagnostics; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Azure.Functions.Worker.Handlers; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.DependencyInjection @@ -54,7 +54,7 @@ public static IServiceCollection AddGrpc(this IServiceCollection services) services.TryAddSingleton(); services.TryAddSingleton(); -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER // If we are running in the native host process, use the native client // for communication (interop). Otherwise; use the gRPC client. if (AppContext.GetData("AZURE_FUNCTIONS_NATIVE_HOST") is not null) diff --git a/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs b/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs index aecb5f093..fa1251371 100644 --- a/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs +++ b/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs @@ -10,7 +10,7 @@ using Microsoft.Extensions.Options; using static Microsoft.Azure.Functions.Worker.Grpc.Messages.FunctionRpc; -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER using Grpc.Net.Client; #else using GrpcCore = Grpc.Core; @@ -104,7 +104,7 @@ private async Task StartReaderAsync(IAsyncStreamReader respons private FunctionRpcClient CreateClient() { -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER GrpcChannel grpcChannel = GrpcChannel.ForAddress(_startupOptions.HostEndpoint!.AbsoluteUri, new GrpcChannelOptions() { MaxReceiveMessageSize = _startupOptions.GrpcMaxMessageLength, diff --git a/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs b/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs index d4a7118a0..76a0d5c82 100644 --- a/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs +++ b/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs @@ -7,13 +7,13 @@ using System.Linq; using System.Security.Claims; using System.Threading.Tasks; -using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Azure.Functions.Worker.Grpc.Messages; +using Microsoft.Azure.Functions.Worker.Http; namespace Microsoft.Azure.Functions.Worker { internal class GrpcHttpRequestData : HttpRequestData, IDisposable -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER , IAsyncDisposable #endif { @@ -73,7 +73,7 @@ public override Stream Body } var stream = new MemoryStream(memory.Length); -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER stream.Write(memory.Span); #else stream.Write(memory.Span.ToArray(), 0, memory.Span.Length); @@ -127,7 +127,7 @@ public override HttpResponseData CreateResponse() return new GrpcHttpResponseData(FunctionContext, System.Net.HttpStatusCode.OK); } -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER public ValueTask DisposeAsync() { return _bodyStream?.DisposeAsync() ?? ValueTask.CompletedTask; @@ -159,7 +159,7 @@ private IReadOnlyCollection ToHttpCookies(string cookieString) List httpCookiesList = new List(separateCookies.Length); -#if NET8_0_OR_GREATER +#if NET6_0_OR_GREATER var separator = '='; #else var separator = new[] { '=' }; diff --git a/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs b/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs index 7a57591d4..ebaeea44c 100644 --- a/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs +++ b/src/DotNetWorker.Grpc/NativeHostIntegration/NativeMethods.cs @@ -49,7 +49,16 @@ private static IntPtr ImportResolver(string libraryName, System.Reflection.Assem { if (libraryName == NativeWorkerDll) { +#if NET6_0 + if (OperatingSystem.IsLinux()) + { + return NativeLibraryLinux.GetMainProgramHandle(); + } +#elif NET7_0_OR_GREATER return NativeLibrary.GetMainProgramHandle(); +#else + throw new PlatformNotSupportedException("Interop communication with FunctionsNetHost is not supported in the current platform. Consider upgrading your project to .NET 7.0 or later."); +#endif } // Return 0 so that built-in resolving code will be executed. diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index e2cc658ec..e9d0947e4 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -8,7 +8,7 @@ 1 1 0 - -preview5 + -preview6 README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index d5cffeeef..b68c14392 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -2,7 +2,7 @@ Library - net8.0;net9.0;netstandard2.0 + net6.0;net7.0;net8.0;net9.0;netstandard2.0 Microsoft.Azure.Functions.Worker This library enables you to create an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker @@ -11,19 +11,13 @@ 2 0 0 - -preview5 - - - - - - + From 0f2a95ad760b362bcbc7ef2fa4c60409f3b8c9be Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 12 Nov 2024 12:14:24 -0800 Subject: [PATCH 057/190] minor cleanup of AspNetCore extension (#2854) --- .../src/BootstrapHostBuilder.cs | 102 ------------------ .../Worker.Extensions.Http.AspNetCore.csproj | 4 +- 2 files changed, 1 insertion(+), 105 deletions(-) delete mode 100644 extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs deleted file mode 100644 index dda53d64c..000000000 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/BootstrapHostBuilder.cs +++ /dev/null @@ -1,102 +0,0 @@ -using System; -using System.Collections.Generic; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace Microsoft.Azure.Functions.Worker.Hosting -{ - internal class BootstrapHostBuilder : IHostBuilder - { - private readonly HostApplicationBuilder _builder; - - private readonly List> _configureHostActions = new(); - private readonly List> _configureAppActions = new(); - private readonly List> _configureServicesActions = new(); - - public BootstrapHostBuilder(HostApplicationBuilder builder) - { - _builder = builder; - - foreach (var descriptor in _builder.Services) - { - if (descriptor.ServiceType == typeof(HostBuilderContext)) - { - Context = (HostBuilderContext)descriptor.ImplementationInstance!; - break; - } - } - - if (Context is null) - { - throw new InvalidOperationException($"{nameof(HostBuilderContext)} must exist in the {nameof(IServiceCollection)}"); - } - } - - public IDictionary Properties => Context.Properties; - - public HostBuilderContext Context { get; } - - public IHostBuilder ConfigureAppConfiguration(Action configureDelegate) - { - _configureAppActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); - return this; - } - - public IHostBuilder ConfigureHostConfiguration(Action configureDelegate) - { - _configureHostActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); - return this; - } - - public IHostBuilder ConfigureServices(Action configureDelegate) - { - _configureServicesActions.Add(configureDelegate ?? throw new ArgumentNullException(nameof(configureDelegate))); - return this; - } - - public IHost Build() - { - // ConfigureWebHostDefaults should never call this. - throw new InvalidOperationException(); - } - - public IHostBuilder ConfigureContainer(Action configureDelegate) - { - // ConfigureWebHostDefaults should never call this. - throw new InvalidOperationException(); - } - - public IHostBuilder UseServiceProviderFactory(IServiceProviderFactory factory) where TContainerBuilder : notnull - { - // ConfigureWebHostDefaults should never call this. - throw new InvalidOperationException(); - } - - public IHostBuilder UseServiceProviderFactory(Func> factory) where TContainerBuilder : notnull - { - // ConfigureWebHostDefaults should never call this. - throw new InvalidOperationException(); - } - - public void RunDefaultCallbacks() - { - foreach (var configureHostAction in _configureHostActions) - { - configureHostAction(_builder.Configuration); - } - - // ConfigureAppConfiguration cannot modify the host configuration because doing so could - // change the environment, content root and application name which is not allowed at this stage. - foreach (var configureAppAction in _configureAppActions) - { - configureAppAction(Context, _builder.Configuration); - } - - foreach (var configureServicesAction in _configureServicesActions) - { - configureServicesAction(Context, _builder.Services); - } - } - } -} diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index d98f96c20..d110794d6 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -8,7 +8,7 @@ 2.0.0 -preview4 - net6.0 + net6.0;net8.0 @@ -25,8 +25,6 @@ - - From 9bce403951f33042d21a6ed00c2b09e630106b0f Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 12 Nov 2024 14:07:10 -0800 Subject: [PATCH 058/190] prepping AspNetCore 2.0 (#2859) --- NuGet.Config | 3 ++- .../src/Worker.Extensions.Http.AspNetCore.csproj | 5 ++--- test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj | 3 +-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/NuGet.Config b/NuGet.Config index dd8b5f55b..b35585178 100644 --- a/NuGet.Config +++ b/NuGet.Config @@ -4,6 +4,7 @@ - + + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index d110794d6..c88dded9b 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -6,8 +6,7 @@ ASP.NET Core extensions for .NET isolated functions - 2.0.0 - -preview4 + 2.0.0 net6.0;net8.0 @@ -24,7 +23,7 @@ - + diff --git a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj index 7659b0c88..1a566f4e8 100644 --- a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj +++ b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj @@ -11,8 +11,7 @@ disable - - + From 19e7126b1ad0dda922d2f590cae87cc2bd52d0e5 Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Tue, 12 Nov 2024 15:56:18 -0800 Subject: [PATCH 059/190] net9.0 sample cleanup (#2863) --- .../Net9FunctionApp/Net9FunctionApp.csproj | 23 ++++--------------- samples/Net9FunctionApp/NuGet.Config | 7 ------ samples/Net9FunctionApp/Program.cs | 18 +++++++-------- samples/Net9FunctionApp/local.settings.json | 7 ++++++ ...er.Extensions.Http.AspNetCore.Tests.csproj | 1 - 5 files changed, 20 insertions(+), 36 deletions(-) delete mode 100644 samples/Net9FunctionApp/NuGet.Config create mode 100644 samples/Net9FunctionApp/local.settings.json diff --git a/samples/Net9FunctionApp/Net9FunctionApp.csproj b/samples/Net9FunctionApp/Net9FunctionApp.csproj index 9784363c2..7bd0775c7 100644 --- a/samples/Net9FunctionApp/Net9FunctionApp.csproj +++ b/samples/Net9FunctionApp/Net9FunctionApp.csproj @@ -3,27 +3,12 @@ net9.0 v4 Exe - enable - enable - - - - - - - - - PreserveNewest - - - PreserveNewest - Never - - - - + + + + \ No newline at end of file diff --git a/samples/Net9FunctionApp/NuGet.Config b/samples/Net9FunctionApp/NuGet.Config deleted file mode 100644 index d8f90e261..000000000 --- a/samples/Net9FunctionApp/NuGet.Config +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/samples/Net9FunctionApp/Program.cs b/samples/Net9FunctionApp/Program.cs index c2df7fbe4..e0260b707 100644 --- a/samples/Net9FunctionApp/Program.cs +++ b/samples/Net9FunctionApp/Program.cs @@ -1,14 +1,14 @@ -using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Builder; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -var host = new HostBuilder() - .ConfigureFunctionsWebApplication() - .ConfigureServices(services => - { - services.AddApplicationInsightsTelemetryWorkerService(); - services.ConfigureFunctionsApplicationInsights(); - }) - .Build(); +var builder = FunctionsApplication.CreateBuilder(args); +builder.ConfigureFunctionsWebApplication(); + +builder.Services.AddApplicationInsightsTelemetryWorkerService(); +builder.Services.ConfigureFunctionsApplicationInsights(); + +var host = builder.Build(); host.Run(); diff --git a/samples/Net9FunctionApp/local.settings.json b/samples/Net9FunctionApp/local.settings.json new file mode 100644 index 000000000..401ae0c34 --- /dev/null +++ b/samples/Net9FunctionApp/local.settings.json @@ -0,0 +1,7 @@ +{ + "IsEncrypted": false, + "Values": { + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", + "AzureWebJobsStorage": "UseDevelopmentStorage=true" + } +} \ No newline at end of file diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj index 99ed1e4db..d8e416a7c 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj @@ -30,7 +30,6 @@ - From 325fce079cb303e98ec34a1e7aa950e289540a8d Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Tue, 12 Nov 2024 17:27:14 -0800 Subject: [PATCH 060/190] Address warnings in 2.x (#2861) * Address warnings in 2.x * Use indexer to map headers --- .../AspNetMiddleware/FunctionsHttpContextExtensions.cs | 2 +- .../AspNetMiddleware/WorkerRequestServicesMiddleware.cs | 2 +- .../src/HttpDataModel/AspNetCoreHttpHeadersCollection.cs | 2 +- .../src/Infrastructure/ExtensionTrace.cs | 4 +++- sdk/Sdk.Analyzers/Sdk.Analyzers.csproj | 1 + sdk/Sdk.Generators/Constants.cs | 7 +++++++ .../FunctionExecutor/FunctionExecutorGenerator.Emitter.cs | 8 ++++---- sdk/Sdk.Generators/Sdk.Generators.csproj | 5 +++++ src/DotNetWorker.Core/Logging/ISystemLogWriter.cs | 2 +- src/DotNetWorker.Core/Logging/IUserLogWriter.cs | 2 +- src/DotNetWorker.Core/Logging/NullLogWriter.cs | 4 ++-- src/DotNetWorker.Core/Logging/WorkerLogger.cs | 5 +++-- src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs | 6 +++--- src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs | 4 +++- src/DotNetWorker.Grpc/RpcExtensions.cs | 2 +- .../Worker.Extensions.Tests.csproj | 2 +- 16 files changed, 38 insertions(+), 20 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsHttpContextExtensions.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsHttpContextExtensions.cs index a1b0bd2a2..aa8c8a835 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsHttpContextExtensions.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsHttpContextExtensions.cs @@ -14,7 +14,7 @@ internal static Task InvokeFunctionAsync(this HttpContext context) { var coordinator = context.RequestServices.GetRequiredService(); context.Request.Headers.TryGetValue(Constants.CorrelationHeader, out StringValues invocationId); - return coordinator.RunFunctionInvocationAsync(invocationId); + return coordinator.RunFunctionInvocationAsync(invocationId!); // will fail later if null. } } } diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/WorkerRequestServicesMiddleware.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/WorkerRequestServicesMiddleware.cs index 8fa0e583d..36073af78 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/WorkerRequestServicesMiddleware.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/WorkerRequestServicesMiddleware.cs @@ -25,7 +25,7 @@ public async Task Invoke(HttpContext context) throw new InvalidOperationException($"Expected correlation id header ('{Constants.CorrelationHeader}') not present"); } - FunctionContext functionContext = await _coordinator.SetHttpContextAsync(invocationId, context); + FunctionContext functionContext = await _coordinator.SetHttpContextAsync(invocationId!, context); // Explicitly set the RequestServices to prevent a new scope from being created internally. // This also prevents the scope from being disposed when the request is complete. We want this to diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreHttpHeadersCollection.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreHttpHeadersCollection.cs index 20e859fe1..6378ce415 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreHttpHeadersCollection.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreHttpHeadersCollection.cs @@ -57,7 +57,7 @@ private Task ProcessResponseStarting() _originalResponseHeaders.Clear(); foreach (var item in ((HeadersEnumerable)this)) { - _originalResponseHeaders.Add(item.Key, item.Value); + _originalResponseHeaders[item.Key] = item.Value; } return Task.CompletedTask; diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Infrastructure/ExtensionTrace.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/Infrastructure/ExtensionTrace.cs index 545cce031..89724adfa 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Infrastructure/ExtensionTrace.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Infrastructure/ExtensionTrace.cs @@ -15,7 +15,9 @@ public ExtensionTrace(ILoggerFactory loggerFactory) _defaultLogger = loggerFactory.CreateLogger("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore"); } - public IDisposable BeginScope(TState state) => _defaultLogger.BeginScope(state); + public IDisposable? BeginScope(TState state) + where TState : notnull + => _defaultLogger.BeginScope(state); public bool IsEnabled(LogLevel logLevel) => _defaultLogger.IsEnabled(logLevel); diff --git a/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj b/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj index 4e1e142d6..aaef6653a 100644 --- a/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj +++ b/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj @@ -14,6 +14,7 @@ disable Azure Functions Worker, analyzers $(TargetsForTfmSpecificContentInPackage);_AddAnalyzersToOutput + true diff --git a/sdk/Sdk.Generators/Constants.cs b/sdk/Sdk.Generators/Constants.cs index 7799f557e..d3a5ceb29 100644 --- a/sdk/Sdk.Generators/Constants.cs +++ b/sdk/Sdk.Generators/Constants.cs @@ -1,10 +1,17 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System; + namespace Microsoft.Azure.Functions.Worker.Sdk.Generators { internal static class Constants { +#pragma warning disable RS1035 // Do not use APIs banned for analyzers + // Suppressing warning based on https://github.com/dotnet/roslyn-analyzers/issues/6467 + internal static readonly string NewLine = Environment.NewLine; +#pragma warning restore RS1035 // Do not use APIs banned for analyzers + internal static class ExecutionModel { internal const string Isolated = "isolated"; diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs index 40aeee233..18844cc6b 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs @@ -36,7 +36,7 @@ namespace {{FunctionsUtil.GetNamespaceForGeneratedCode(context)}} [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor { - private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator;{{(defaultExecutorNeeded ? $"{Environment.NewLine} private Lazy _defaultExecutor;" : string.Empty)}} + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator;{{(defaultExecutorNeeded ? $"{Constants.NewLine} private Lazy _defaultExecutor;" : string.Empty)}} {{GetTypesDictionary(functions)}} public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) { @@ -47,7 +47,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { {{GetMethodBody(functions, defaultExecutorNeeded)}} - }{{(defaultExecutorNeeded ? $"{Environment.NewLine}{EmitCreateDefaultExecutorMethod(context)}" : string.Empty)}} + }{{(defaultExecutorNeeded ? $"{Constants.NewLine}{EmitCreateDefaultExecutorMethod(context)}" : string.Empty)}} } /// @@ -105,7 +105,7 @@ private static string GetTypesDictionary(IEnumerable functio return $$""" private readonly Dictionary types = new Dictionary() { - {{string.Join($",{Environment.NewLine} ", typesDict.Select(c => $$""" { "{{c.Key}}", Type.GetType("{{c.Key}}, {{c.Value}}") }"""))}} + {{string.Join($",{Constants.NewLine} ", typesDict.Select(c => $$""" { "{{c.Key}}", Type.GetType("{{c.Key}}, {{c.Value}}") }"""))}} }; """; @@ -147,7 +147,7 @@ private static string GetMethodBody(IEnumerable functions, b var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; - {(anyDefaultExecutor ? $" _defaultExecutor = new Lazy(() => CreateDefaultExecutorInstance(context));{Environment.NewLine}" : string.Empty)} + {(anyDefaultExecutor ? $" _defaultExecutor = new Lazy(() => CreateDefaultExecutorInstance(context));{Constants.NewLine}" : string.Empty)} """); foreach (ExecutableFunction function in functions) diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index 98d57854d..93af6de7a 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -12,6 +12,7 @@ 3 4 true + true @@ -35,4 +36,8 @@ + + + + diff --git a/src/DotNetWorker.Core/Logging/ISystemLogWriter.cs b/src/DotNetWorker.Core/Logging/ISystemLogWriter.cs index 0f7b3eba4..4f6b6f16a 100644 --- a/src/DotNetWorker.Core/Logging/ISystemLogWriter.cs +++ b/src/DotNetWorker.Core/Logging/ISystemLogWriter.cs @@ -22,6 +22,6 @@ internal interface ISystemLogWriter /// The entry to be written. Can be also an object. /// The exception related to this entry. /// Function to create a message of the state and exception. - void WriteSystemLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter); + void WriteSystemLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter); } } diff --git a/src/DotNetWorker.Core/Logging/IUserLogWriter.cs b/src/DotNetWorker.Core/Logging/IUserLogWriter.cs index 79d0d0ef5..594fb626f 100644 --- a/src/DotNetWorker.Core/Logging/IUserLogWriter.cs +++ b/src/DotNetWorker.Core/Logging/IUserLogWriter.cs @@ -22,6 +22,6 @@ internal interface IUserLogWriter /// The entry to be written. Can be also an object. /// The exception related to this entry. /// Function to create a message of the state and exception. - void WriteUserLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter); + void WriteUserLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter); } } diff --git a/src/DotNetWorker.Core/Logging/NullLogWriter.cs b/src/DotNetWorker.Core/Logging/NullLogWriter.cs index bb08e2bb6..43b633cd6 100644 --- a/src/DotNetWorker.Core/Logging/NullLogWriter.cs +++ b/src/DotNetWorker.Core/Logging/NullLogWriter.cs @@ -22,12 +22,12 @@ private NullLogWriter() public static NullLogWriter Instance = new NullLogWriter(); /// - public void WriteSystemLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void WriteSystemLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { } /// - public void WriteUserLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void WriteUserLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { } diff --git a/src/DotNetWorker.Core/Logging/WorkerLogger.cs b/src/DotNetWorker.Core/Logging/WorkerLogger.cs index 324e58a86..7a9c1a22d 100644 --- a/src/DotNetWorker.Core/Logging/WorkerLogger.cs +++ b/src/DotNetWorker.Core/Logging/WorkerLogger.cs @@ -22,7 +22,8 @@ public WorkerLogger(string category, ISystemLogWriter systemLogWriter, IUserLogW _scopeProvider = scopeProvider; } - public IDisposable BeginScope(TState state) + public IDisposable? BeginScope(TState state) + where TState : notnull { // The built-in DI wire-up guarantees that scope provider will be set. return _scopeProvider.Push(state); @@ -33,7 +34,7 @@ public bool IsEnabled(LogLevel logLevel) return logLevel != LogLevel.None; } - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { if (WorkerMessage.IsSystemLog) { diff --git a/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs b/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs index 9178a9af2..f04cd3a5d 100644 --- a/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs +++ b/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs @@ -28,7 +28,7 @@ public GrpcFunctionsHostLogWriter(GrpcHostChannel channel, IOptions(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void WriteUserLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { Log(RpcLogCategory.User, scopeProvider, categoryName, logLevel, eventId, state, exception, formatter); } @@ -54,12 +54,12 @@ public void WriteUserMetric(IExternalScopeProvider scopeProvider, IDictionary(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void WriteSystemLog(IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { Log(RpcLogCategory.System, scopeProvider, categoryName, logLevel, eventId, state, exception, formatter); } - public void Log(RpcLogCategory category, IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + public void Log(RpcLogCategory category, IExternalScopeProvider scopeProvider, string categoryName, LogLevel logLevel, EventId eventId, TState state, Exception? exception, Func formatter) { var response = new StreamingMessage(); var rpcLog = new RpcLog diff --git a/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs b/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs index 8ddfaea64..225be24da 100644 --- a/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs +++ b/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs @@ -116,9 +116,11 @@ public async Task InvokeAsync(InvocationRequest request) } catch (Exception ex) when (!ex.IsFatal()) { +#pragma warning disable CS0618 // Type or member is obsolete response.Result.Exception = _workerOptions.EnableUserCodeException ? ex.ToUserRpcException() : ex.ToRpcException(); - response.Result.Status = StatusResult.Types.Status.Failure; +#pragma warning restore CS0618 // Type or member is obsolete + response.Result.Status = StatusResult.Types.Status.Failure; if (ex.InnerException is TaskCanceledException or OperationCanceledException) { response.Result.Status = StatusResult.Types.Status.Cancelled; diff --git a/src/DotNetWorker.Grpc/RpcExtensions.cs b/src/DotNetWorker.Grpc/RpcExtensions.cs index 5df5377be..1d0f14cde 100644 --- a/src/DotNetWorker.Grpc/RpcExtensions.cs +++ b/src/DotNetWorker.Grpc/RpcExtensions.cs @@ -122,7 +122,7 @@ internal static FunctionDefinition ToFunctionDefinition(this FunctionLoadRequest /// Returns an RpcException for system exception scenarios. /// /// An RpcException - internal static RpcException? ToRpcException(this Exception exception) + internal static RpcException? ToRpcException(this Exception? exception) { if (exception is null) { diff --git a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj index 1a566f4e8..b63593eb5 100644 --- a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj +++ b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj @@ -11,7 +11,7 @@ disable - + From 64a19d7025bc1448facaf7feb05c3ba0eb3fd4c3 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 13 Nov 2024 15:52:34 -0800 Subject: [PATCH 061/190] Update sample extension packages (#2850) --- samples/Extensions/Extensions.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/samples/Extensions/Extensions.csproj b/samples/Extensions/Extensions.csproj index 656ad9280..e93c958ef 100644 --- a/samples/Extensions/Extensions.csproj +++ b/samples/Extensions/Extensions.csproj @@ -12,7 +12,7 @@ - + From e601cb3aaaaa7f21d267df02345394610e19e095 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Wed, 13 Nov 2024 16:13:00 -0800 Subject: [PATCH 062/190] Reset release notes (#2867) --- .../release_notes.md | 3 +- release_notes.md | 41 +++---------------- sdk/release_notes.md | 8 +--- .../release_notes.md | 5 ++- 4 files changed, 13 insertions(+), 44 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index f73515feb..97bb2a3ba 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -6,7 +6,8 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore -- Addressing fix for AspNetCoreResponseCookies cookie defaults (#2811) +- ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers +- diff --git a/release_notes.md b/release_notes.md index 96bef8d74..37057e890 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,43 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) 2.0.0 +### Microsoft.Azure.Functions.Worker (metapackage) -- Updating `Microsoft.Azure.Functions.Worker.Core` to 2.0.0 -- Updating `Microsoft.Azure.Functions.Worker.Grpc` to 2.0.0 +- -### Microsoft.Azure.Functions.Worker.Core 2.0.0 +### Microsoft.Azure.Functions.Worker.Core -- `ValidateScopes` is enabled for developement environments by default. (#2705) - - The default is the value of `IsDevelopment(IHostingEnvironment)`. -- Capability `IncludeEmptyEntriesInMessagePayload` is now enabled by default (#2701) - - This means that empty entries will be included in the function trigger message payload by default. - - To disable this capability and return to the old behaviour, set `IncludeEmptyEntriesInMessagePayload` to `false` in the worker options. -- Capability `EnableUserCodeException` is now enabled by default (#2702) - - This means that exceptions thrown by user code will be surfaced to the Host as their original exception type, instead of being wrapped in an RpcException. - - To disable this capability and return to the old behaviour, set `EnableUserCodeException` to `false` in the worker options. - - The `EnableUserCodeException` property in WorkerOptions has been marked as obsolete and may be removed in a future release. -- Rename `ILoggerExtensions` to `FunctionsLoggerExtensions` to avoid naming conflict issues (#2716) -- Updating `Azure.Core` to 1.41.0 -- Updated service registrations for bootstrapping methods to ensure idempotency. +- -##### Setting worker options example +### Microsoft.Azure.Functions.Worker.Grpc -```csharp -var host = new HostBuilder() -.ConfigureFunctionsWorkerDefaults(options => -{ - options.EnableUserCodeException = false; - options.IncludeEmptyEntriesInMessagePayload = false; -}) -``` - -### Microsoft.Azure.Functions.Worker.Grpc 2.0.0 - -- Removed fallback command line argument reading code for grpc worker startup options. (#1908) - -### Microsoft.Azure.Functions.Worker.Sdk 2.0.0-preview2 - -- Adding support for SDK container builds with Functions base images -- Updating `Azure.Core` to 1.41.0 -- Updated service registrations for bootstrapping methods to ensure idempotency. \ No newline at end of file +- diff --git a/sdk/release_notes.md b/sdk/release_notes.md index bf0c80498..216f4dfcd 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,13 +4,9 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 2.0.0-preview2 +### Microsoft.Azure.Functions.Worker.Sdk -- Changed exception handling in function invocation path to ensure fatal exceptions bubble up. -- Updated `Microsoft.Azure.Functions.Worker.Sdk.Generators` reference to 1.3.4. -- Setting _ToolingSuffix for TargetFrameworkVersion v9.0 -- Adding support for SDK container builds with Functions base images -- Removed the default value for HttpStatusCode in WriteAsJsonAsync (#2720) +- ### Microsoft.Azure.Functions.Worker.Sdk.Generators diff --git a/src/DotNetWorker.ApplicationInsights/release_notes.md b/src/DotNetWorker.ApplicationInsights/release_notes.md index a24d892c6..addb34ce4 100644 --- a/src/DotNetWorker.ApplicationInsights/release_notes.md +++ b/src/DotNetWorker.ApplicationInsights/release_notes.md @@ -1,4 +1,5 @@ ## What's Changed -### Microsoft.Azure.Functions.Worker.ApplicationInsights 1.4.0 -- Updating `Azure.Identity` to 1.12.0 +### Microsoft.Azure.Functions.Worker.ApplicationInsights + +- From 28829c4cd5008d8e35a368e573bbdd82f93da6a6 Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Wed, 13 Nov 2024 17:40:30 -0800 Subject: [PATCH 063/190] Bringing back .NET 7 sample temporarily --- .../Net7Worker/EventHubCancellationToken.cs | 65 +++++++++++++++++++ samples/Net7Worker/README.md | 22 +++++++ 2 files changed, 87 insertions(+) create mode 100644 samples/Net7Worker/EventHubCancellationToken.cs create mode 100644 samples/Net7Worker/README.md diff --git a/samples/Net7Worker/EventHubCancellationToken.cs b/samples/Net7Worker/EventHubCancellationToken.cs new file mode 100644 index 000000000..fda0c3003 --- /dev/null +++ b/samples/Net7Worker/EventHubCancellationToken.cs @@ -0,0 +1,65 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace Net7Worker +{ + public class EventHubCancellationToken + { + private readonly ILogger _logger; + + public EventHubCancellationToken(ILoggerFactory loggerFactory) + { + _logger = loggerFactory.CreateLogger(); + } + + // Sample showing how to handle a cancellation token being received + // In this example, the function invocation status will be "Cancelled" + // + [Function(nameof(ThrowOnCancellation))] + public async Task ThrowOnCancellation( + [EventHubTrigger("sample-workitem-1", Connection = "EventHubConnection")] string[] messages, + FunctionContext context, + CancellationToken cancellationToken) + { + _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(ThrowOnCancellation)); + + foreach (var message in messages) + { + cancellationToken.ThrowIfCancellationRequested(); + await Task.Delay(6000); // task delay to simulate message processing + _logger.LogInformation("Message '{msg}' was processed.", message); + } + } + // + + // Sample showing how to take precautionary/clean up actions if a cancellation token is received + // In this example, the function invocation status will be "Successful" + // + [Function(nameof(HandleCancellationCleanup))] + public async Task HandleCancellationCleanup( + [EventHubTrigger("sample-workitem-2", Connection = "EventHubConnection")] string[] messages, + FunctionContext context, + CancellationToken cancellationToken) + { + _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(HandleCancellationCleanup)); + + foreach (var message in messages) + { + if (cancellationToken.IsCancellationRequested) + { + _logger.LogInformation("A cancellation token was received, taking precautionary actions."); + // Take precautions like noting how far along you are with processing the batch + _logger.LogInformation("Precautionary activities complete."); + break; + } + + await Task.Delay(6000); // task delay to simulate message processing + _logger.LogInformation("Message '{msg}' was processed.", message); + } + } + // + } +} diff --git a/samples/Net7Worker/README.md b/samples/Net7Worker/README.md new file mode 100644 index 000000000..2bd6429de --- /dev/null +++ b/samples/Net7Worker/README.md @@ -0,0 +1,22 @@ +# Former sample for .NET 7 Worker + +This sample has been removed, as support for .NET 7 ended on May 14, 2024. The `EventHubCancellationToken.cs` file is being temporarily preserved. + +### EventHubCancellationToken.cs + +Demonstrates how to use the Cancellation Token parameter binding in the context of an +EventHub trigger sample where we are processing multiple messages. + +- `ThrowOnCancellation` + - shows how to throw when a cancellation token is received + - the status of the function will be "Cancelled" +- `HandleCancellationCleanup` + - shows how to take precautionary/clean up actions if a cancellation token is received + - the status of the function will be "Successful" + +Cancellation tokens are signalled by the platform, the use cases supported today are: + +1. Sudden host shutdown or host restart +2. Function timeout (where function execution has exceeded the timeout limit) + 1. You can try this out by setting function timeout to 5 seconds in + the host.json file: `"functionTimeout": "00:00:05"` From ffb8a46dbebe3d98c643651a594411ebcec23bbf Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Thu, 14 Nov 2024 12:29:41 -0800 Subject: [PATCH 064/190] fixing linux zip tests (#2869) --- test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs b/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs index bf4a454c4..1dbd5afa0 100644 --- a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs +++ b/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs @@ -15,7 +15,7 @@ namespace Microsoft.Azure.Functions.SdkTests public class ZipDeployTaskTests { private static string _testZippedPublishContentsPath; - private const string TestAssemblyToTestZipPath = @"Resources\TestPublishContents.zip"; + private const string TestAssemblyToTestZipPath = @"Resources/TestPublishContents.zip"; private const string UserAgentName = "functions-core-tools"; private const string UserAgentVersion = "1.0"; @@ -50,7 +50,7 @@ public async Task ExecuteZipDeploy_InvalidZipFilePath() /// /// ZipDeploy should use PublishUrl if not null or empty, else use SiteName. /// - [Theory(Skip = "https://github.com/Azure/azure-functions-dotnet-worker/issues/2781")] + [Theory] [InlineData("https://sitename.scm.azurewebsites.net", null, false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] [InlineData("https://sitename.scm.azurewebsites.net", null, true, "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false")] [InlineData("https://sitename.scm.azurewebsites.net", "", false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] @@ -96,7 +96,7 @@ public async Task ExecuteZipDeploy_NeitherPublishUrlNorSiteNameGiven(string publ await RunZipDeployAsyncTest(publishUrl, siteName, UserAgentVersion, useBlobContainerDeploy: false, HttpStatusCode.OK, verifyStep); } - [Theory(Skip = "https://github.com/Azure/azure-functions-dotnet-worker/issues/2781")] + [Theory] [InlineData(HttpStatusCode.OK, false, true)] [InlineData(HttpStatusCode.OK, true, true)] [InlineData(HttpStatusCode.Accepted, false, true)] From c4113d1c5936ab3235d7a73ec5a88596977c8335 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Tue, 19 Nov 2024 15:46:16 -0800 Subject: [PATCH 065/190] Update E2E tests to use Microsoft.Azure.Cosmos (#2872) --- .../E2ETests/Cosmos/CosmosDBEndToEndTests.cs | 9 +- test/E2ETests/E2ETests/E2ETests.csproj | 2 +- .../E2ETests/Helpers/CosmosDBHelpers.cs | 121 ++++++++---------- 3 files changed, 59 insertions(+), 73 deletions(-) diff --git a/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs b/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs index 5e1593f3c..84167b864 100644 --- a/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs @@ -32,7 +32,14 @@ public async Task CosmosDBTriggerAndOutput_Succeeds() await CosmosDBHelpers.CreateDocument(expectedDocId, expectedDocId); //Read - var documentId = await CosmosDBHelpers.ReadDocument(expectedDocId); + string documentId = string.Empty; + await TestUtility.RetryAsync(async () => + { + documentId = await CosmosDBHelpers.ReadDocument(expectedDocId); + return documentId is not null; + }); + + //Assert Assert.Equal(expectedDocId, documentId); } finally diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index b7b8eb93a..e803d3ebc 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -11,7 +11,7 @@ - + diff --git a/test/E2ETests/E2ETests/Helpers/CosmosDBHelpers.cs b/test/E2ETests/E2ETests/Helpers/CosmosDBHelpers.cs index f146c3396..fc8e70fcb 100644 --- a/test/E2ETests/E2ETests/Helpers/CosmosDBHelpers.cs +++ b/test/E2ETests/E2ETests/Helpers/CosmosDBHelpers.cs @@ -4,77 +4,65 @@ using System; using System.Net.Http; using System.Threading.Tasks; -using Microsoft.Azure.Documents; -using Microsoft.Azure.Documents.Client; +using Microsoft.Azure.Cosmos; using Microsoft.Extensions.Logging; namespace Microsoft.Azure.Functions.Tests.E2ETests { public static class CosmosDBHelpers { - private static readonly DocumentClient _docDbClient; - private static readonly Uri inputCollectionsUri = UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.InputCollectionName); - private static readonly Uri outputCollectionsUri = UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.OutputCollectionName); - private static readonly Uri leasesCollectionsUri = UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.LeaseCollectionName); + private static readonly CosmosClient _cosmosClient; + private static readonly Container _inputContainer; + private static readonly Container _outputContainer; + private static readonly Container _leaseContainer; static CosmosDBHelpers() { - var builder = new System.Data.Common.DbConnectionStringBuilder - { - ConnectionString = Constants.CosmosDB.CosmosDBConnectionStringSetting - }; - var serviceUri = new Uri(builder["AccountEndpoint"].ToString()); - _docDbClient = new DocumentClient(serviceUri, builder["AccountKey"].ToString()); + _cosmosClient = new CosmosClient(Constants.CosmosDB.CosmosDBConnectionStringSetting); + + var database = _cosmosClient.GetDatabase(Constants.CosmosDB.DbName); + _inputContainer = database.GetContainer(Constants.CosmosDB.InputCollectionName); + _outputContainer = database.GetContainer(Constants.CosmosDB.OutputCollectionName); + _leaseContainer = database.GetContainer(Constants.CosmosDB.LeaseCollectionName); } // keep public async static Task CreateDocument(string docId, string docText = "test") { - Document documentToTest = new Document() { Id = docId }; - documentToTest.SetPropertyValue("Text", docText); - - _ = await _docDbClient.CreateDocumentAsync(UriFactory.CreateDocumentCollectionUri(Constants.CosmosDB.DbName, Constants.CosmosDB.InputCollectionName), documentToTest); + var documentToTest = new { id = docId, Text = docText }; + await _inputContainer.CreateItemAsync(documentToTest, new PartitionKey(docId)); } // keep public async static Task ReadDocument(string docId) { - var docUri = UriFactory.CreateDocumentUri(Constants.CosmosDB.DbName, Constants.CosmosDB.OutputCollectionName, docId); - Document retrievedDocument = null; - await TestUtility.RetryAsync(async () => + try + { + var response = await _outputContainer.ReadItemAsync(docId, new PartitionKey(docId)); + return response.Resource?.id; + } + catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) { - try - { - retrievedDocument = await _docDbClient.ReadDocumentAsync(docUri, new RequestOptions { PartitionKey = new PartitionKey(docId) }); - return true; - } - catch (DocumentClientException ex) when (ex.Error.Code == "NotFound") - { - return false; - } - }, pollingInterval: 500); - - return retrievedDocument?.Id; + return null; + } } // keep public async static Task DeleteTestDocuments(string docId) { - var inputDocUri = UriFactory.CreateDocumentUri(Constants.CosmosDB.DbName, Constants.CosmosDB.InputCollectionName, docId); - await DeleteDocument(inputDocUri, docId); - var outputDocUri = UriFactory.CreateDocumentUri(Constants.CosmosDB.DbName, Constants.CosmosDB.OutputCollectionName, docId); - await DeleteDocument(outputDocUri, docId); + await DeleteDocument(_inputContainer, docId); + await DeleteDocument(_outputContainer, docId); } - private async static Task DeleteDocument(Uri docUri, string docId) + private async static Task DeleteDocument(Container container, string docId) { try { - await _docDbClient.DeleteDocumentAsync(docUri, new RequestOptions { PartitionKey = new PartitionKey(docId) }); + await container.DeleteItemAsync(docId, new PartitionKey(docId)); } - catch (Exception) + catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) { - //ignore + // Ignore if the document is already deleted } } @@ -82,75 +70,66 @@ private async static Task CanConnectAsync(ILogger logger) { try { - await new HttpClient().GetAsync(_docDbClient.ServiceEndpoint); + var response = await _cosmosClient.ReadAccountAsync(); + return response != null; } catch { - // typically "the target machine actively refused it" if the emulator isn't running. - logger.LogError($"Could not connect to CosmosDB endpoint: '{_docDbClient.ServiceEndpoint}'. Are you using the emulator?"); + logger.LogError($"Could not connect to CosmosDB. Check the emulator or connection string."); return false; } - - return true; } - // keep public async static Task TryCreateDocumentCollectionsAsync(ILogger logger) { if (!await CanConnectAsync(logger)) { - // This can hang if the service is unavailable. Just return and let tests fail. - // The Cosmos tests may be filtered out anyway without an emulator running. return false; } - Database db = await _docDbClient.CreateDatabaseIfNotExistsAsync(new Database { Id = Constants.CosmosDB.DbName }); - Uri dbUri = UriFactory.CreateDatabaseUri(db.Id); + var databaseResponse = await _cosmosClient.CreateDatabaseIfNotExistsAsync(Constants.CosmosDB.DbName); + var database = databaseResponse.Database; await Task.WhenAll( - CreateCollection(dbUri, Constants.CosmosDB.InputCollectionName), - CreateCollection(dbUri, Constants.CosmosDB.OutputCollectionName), - CreateCollection(dbUri, Constants.CosmosDB.LeaseCollectionName)); + CreateCollection(database, Constants.CosmosDB.InputCollectionName), + CreateCollection(database, Constants.CosmosDB.OutputCollectionName), + CreateCollection(database, Constants.CosmosDB.LeaseCollectionName)); return true; } public async static Task DeleteDocumentCollections() { + var database = _cosmosClient.GetDatabase(Constants.CosmosDB.DbName); await Task.WhenAll( - DeleteCollection(inputCollectionsUri), - DeleteCollection(outputCollectionsUri), - DeleteCollection(leasesCollectionsUri)); + DeleteCollection(database, Constants.CosmosDB.InputCollectionName), + DeleteCollection(database, Constants.CosmosDB.OutputCollectionName), + DeleteCollection(database, Constants.CosmosDB.LeaseCollectionName)); } - private async static Task DeleteCollection(Uri collectionUri) + private async static Task DeleteCollection(Database database, string collectionName) { try { - await _docDbClient.DeleteDocumentCollectionAsync(collectionUri); + var container = database.GetContainer(collectionName); + await container.DeleteContainerAsync(); } - catch (Exception) + catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) { - //Ignore + // Ignore if the container is already deleted } } - private async static Task CreateCollection(Uri dbUri, string collectioName) + private async static Task CreateCollection(Database database, string collectionName) { - var pkd = new PartitionKeyDefinition(); - pkd.Paths.Add("/id"); - DocumentCollection collection = new DocumentCollection() + var containerProperties = new ContainerProperties { - Id = collectioName, - PartitionKey = pkd + Id = collectionName, + PartitionKeyPath = "/id" }; - await _docDbClient.CreateDocumentCollectionIfNotExistsAsync(dbUri, collection, - new RequestOptions() - { - PartitionKey = new PartitionKey("/id"), - OfferThroughput = 400 - }); + + await database.CreateContainerIfNotExistsAsync(containerProperties, throughput: 400); } } } From 6338dc2e08d04a78956dd48dd6738888ab215bde Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 5 Dec 2024 11:34:33 -0800 Subject: [PATCH 066/190] Use GeneratedCode attribute for generated classes (#2887) * Use GeneratedCode attribute for generated classes * update release_notes.md * Fix unit test * Fix formatting on generated xmldoc --- sdk/Sdk.Generators/Constants.cs | 5 ++ .../ExtensionStartupRunnerGenerator.cs | 2 +- .../FunctionExecutorGenerator.Emitter.cs | 5 +- ...nctionMetadataProviderGenerator.Emitter.cs | 7 ++- sdk/release_notes.md | 4 +- .../ExtensionStartupRunnerGeneratorTests.cs | 8 +-- .../FunctionExecutor/DependentAssemblyTest.cs | 2 +- .../FunctionExecutorGeneratorTests.cs | 19 +++--- .../AmbiguousNamespaceTests.cs | 7 ++- .../AutoConfigureStartupTypeTests.cs | 45 +++++++------- .../DependentAssemblyTest.NetFx.cs | 7 ++- .../DependentAssemblyTest.cs | 14 +++-- .../EventHubsBindingsTests.cs | 38 +++++++----- .../HttpTriggerTests.cs | 30 +++++----- .../IntegratedTriggersAndBindingsTests.cs | 58 +++++++++++-------- .../KafkaTests.cs | 7 ++- .../NestedTypesTest.cs | 14 +++-- .../RetryOptionsTests.cs | 14 +++-- .../ServiceBustTests.cs | 7 ++- .../SignalRTest.cs | 8 +-- .../StorageBindingTests.cs | 21 ++++--- 21 files changed, 185 insertions(+), 137 deletions(-) diff --git a/sdk/Sdk.Generators/Constants.cs b/sdk/Sdk.Generators/Constants.cs index d3a5ceb29..96cd5258a 100644 --- a/sdk/Sdk.Generators/Constants.cs +++ b/sdk/Sdk.Generators/Constants.cs @@ -12,6 +12,11 @@ internal static class Constants internal static readonly string NewLine = Environment.NewLine; #pragma warning restore RS1035 // Do not use APIs banned for analyzers + internal static readonly string GeneratedCodeAttribute = + $"[global::System.CodeDom.Compiler.GeneratedCodeAttribute(" + + $"\"{typeof(Constants).Assembly.GetName().Name}\", " + + $"\"{typeof(Constants).Assembly.GetName().Version}\")]"; + internal static class ExecutionModel { internal const string Isolated = "isolated"; diff --git a/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs b/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs index 644faf69c..6cd9dee59 100644 --- a/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs +++ b/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs @@ -102,7 +102,7 @@ internal string GenerateExtensionStartupRunner(GeneratorExecutionContext context namespace {{namespaceValue}} { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} internal class WorkerExtensionStartupCodeExecutor : global::Microsoft.Azure.Functions.Worker.Core.WorkerExtensionStartup { /// diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs index 18844cc6b..022d5b676 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs @@ -1,7 +1,6 @@ // 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.Linq; using System.Text; @@ -33,7 +32,7 @@ internal static string Emit(GeneratorExecutionContext context, IEnumerable _defaultExecutor;" : string.Empty)}} @@ -53,6 +52,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class FunctionExecutorHostBuilderExtensions { /// @@ -121,6 +121,7 @@ private static string GetAutoConfigureStartupClass(bool includeAutoRegistrationC /// Auto startup class to register the custom implementation generated for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {{Constants.GeneratedCodeAttribute}} public class FunctionExecutorAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// diff --git a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs index 0fa52199e..fdbc7e283 100644 --- a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System.CodeDom.Compiler; using System.Collections.Generic; using System.Text; using System.Text.Json; @@ -38,10 +39,10 @@ public static string Emit(GeneratorExecutionContext context, IReadOnlyList - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -56,6 +57,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -85,6 +87,7 @@ private static string GetAutoConfigureStartupClass(bool includeAutoRegistrationC /// Auto startup class to register the custom implementation generated for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {{Constants.GeneratedCodeAttribute}} public class FunctionMetadataProviderAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 216f4dfcd..72faae9bd 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -8,6 +8,6 @@ - -### Microsoft.Azure.Functions.Worker.Sdk.Generators +### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.5 -- +- Update all generated classes to use `GeneratedCodeAttribute`. (#2887) diff --git a/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs b/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs index 1cdab3995..80a53be91 100644 --- a/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs @@ -36,7 +36,7 @@ public async Task StartupExecutorCodeGetsGenerated(LanguageVersion languageVersi }; string expectedGeneratedFileName = $"WorkerExtensionStartupCodeExecutor.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using Microsoft.Azure.Functions.Worker; @@ -47,7 +47,7 @@ public async Task StartupExecutorCodeGetsGenerated(LanguageVersion languageVersi namespace TestProject { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} internal class WorkerExtensionStartupCodeExecutor : global::Microsoft.Azure.Functions.Worker.Core.WorkerExtensionStartup { /// @@ -120,7 +120,7 @@ public async Task DiagnosticErrorsAreReportedWhenStartupTypeIsInvalid(LanguageVe // Our generator will create code for the good implementation // and report 2 diagnostic errors for the bad implementation. string expectedGeneratedFileName = $"WorkerExtensionStartupCodeExecutor.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using Microsoft.Azure.Functions.Worker; @@ -131,7 +131,7 @@ public async Task DiagnosticErrorsAreReportedWhenStartupTypeIsInvalid(LanguageVe namespace MyCompany.MyProject.MyApp { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} internal class WorkerExtensionStartupCodeExecutor : global::Microsoft.Azure.Functions.Worker.Core.WorkerExtensionStartup { /// diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index 89051066d..bee14cd22 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -70,7 +70,7 @@ public HttpResponseData Foo([HttpTrigger(AuthorizationLevel.User, "get")] HttpRe namespace TestProject { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor { private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs index a94d51fa4..de4f0bb58 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs @@ -116,7 +116,7 @@ public void Run2([QueueTrigger(""myqueue-items"")] string message) namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {Constants.GeneratedCodeAttribute} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; @@ -238,7 +238,7 @@ public HttpResponseData Run2([HttpTrigger(AuthorizationLevel.User, ""get"")] Htt namespace MyCompany.MyProject.MyApp {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {Constants.GeneratedCodeAttribute} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; @@ -387,7 +387,7 @@ public static Task RunAsync1([EventHubTrigger(""items"", Connection = ""Con"")] namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {Constants.GeneratedCodeAttribute} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; @@ -519,7 +519,7 @@ public HttpResponseData Run1([HttpTrigger(AuthorizationLevel.User, ""get"")] Htt namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {Constants.GeneratedCodeAttribute} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; @@ -613,7 +613,7 @@ public static HttpResponseData FooStatic([HttpTrigger(AuthorizationLevel.User, " namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {Constants.GeneratedCodeAttribute} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; @@ -706,7 +706,7 @@ public static HttpResponseData HELLO([HttpTrigger(AuthorizationLevel.User, ""get namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {Constants.GeneratedCodeAttribute} internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; @@ -756,11 +756,12 @@ private static string GetExpectedExtensionMethodCode(bool includeAutoStartupType { if (includeAutoStartupType) { - return """ + return $$""" /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class FunctionExecutorHostBuilderExtensions { /// @@ -778,6 +779,7 @@ public static IHostBuilder ConfigureGeneratedFunctionExecutor(this IHostBuilder /// Auto startup class to register the custom implementation generated for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {{Constants.GeneratedCodeAttribute}} public class FunctionExecutorAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// @@ -792,11 +794,12 @@ public void Configure(IHostBuilder hostBuilder) """; } - return """ + return $$""" /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class FunctionExecutorHostBuilderExtensions { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs index 207ae5e06..80574dda7 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs @@ -70,7 +70,7 @@ public static HttpResponseData Run(HttpRequestData req) """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -85,10 +85,10 @@ public static HttpResponseData Run(HttpRequestData req) namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -116,6 +116,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs index 3ca59c1bf..6da55894a 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs @@ -74,7 +74,8 @@ public static void HttpTrigger([HttpTrigger(AuthorizationLevel.Admin, "get", "po """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = @$"// + string expectedOutput = $$""" +// using System; using System.Collections.Generic; using System.Collections.Immutable; @@ -86,38 +87,39 @@ public static void HttpTrigger([HttpTrigger(AuthorizationLevel.Admin, "get", "po using Microsoft.Extensions.Hosting; namespace TestProject -{{ +{ /// - /// Custom implementation that returns function metadata definitions for the current worker.""/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider - {{ + { /// public Task> GetFunctionMetadataAsync(string directory) - {{ + { var metadataList = new List(); var Function0RawBindings = new List(); - Function0RawBindings.Add(@""{{""""name"""":""""req"""",""""type"""":""""httpTrigger"""",""""direction"""":""""In"""",""""authLevel"""":""""Admin"""",""""methods"""":[""""get"""",""""post""""],""""route"""":""""/api2""""}}""); - Function0RawBindings.Add(@""{{""""name"""":""""$return"""",""""type"""":""""http"""",""""direction"""":""""Out""""}}""); + Function0RawBindings.Add(@"{""name"":""req"",""type"":""httpTrigger"",""direction"":""In"",""authLevel"":""Admin"",""methods"":[""get"",""post""],""route"":""/api2""}"); + Function0RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); var Function0 = new DefaultFunctionMetadata - {{ - Language = ""dotnet-isolated"", - Name = ""HttpTrigger"", - EntryPoint = ""FunctionApp.HttpTriggerSimple.HttpTrigger"", + { + Language = "dotnet-isolated", + Name = "HttpTrigger", + EntryPoint = "FunctionApp.HttpTriggerSimple.HttpTrigger", RawBindings = Function0RawBindings, - ScriptFile = ""TestProject.dll"" - }}; + ScriptFile = "TestProject.dll" + }; metadataList.Add(Function0); return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); - }} - }} + } + } -{GetExpectedExtensionMethodCode(includeAutoStartupType: includeAutoStartupType)} -}}"; +{{GetExpectedExtensionMethodCode(includeAutoStartupType: includeAutoStartupType)}} +} +"""; var buildPropertiesDict = new Dictionary() { { Constants.BuildProperties.AutoRegisterGeneratedMetadataProvider, includeAutoStartupType.ToString()} @@ -136,10 +138,11 @@ private static string GetExpectedExtensionMethodCode(bool includeAutoStartupType { if (includeAutoStartupType) { - return """ + return $$""" /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -159,6 +162,7 @@ public static IHostBuilder ConfigureGeneratedFunctionMetadataProvider(this IHost /// Auto startup class to register the custom implementation generated for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {{Constants.GeneratedCodeAttribute}} public class FunctionMetadataProviderAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// @@ -173,10 +177,11 @@ public void Configure(IHostBuilder hostBuilder) """; } - return """ + return $$""" /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs index 007b680b7..032ea59ba 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs @@ -70,7 +70,7 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -85,10 +85,10 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -142,6 +142,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs index 1890d6dd0..05a77aaf1 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs @@ -62,7 +62,7 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -77,10 +77,10 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -173,6 +173,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -216,7 +217,7 @@ public static void Main() """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -231,10 +232,10 @@ public static void Main() namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -314,6 +315,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs index bab3c2c84..b6f6da1af 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs @@ -98,10 +98,10 @@ public class EventHubsInput namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -132,6 +132,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -232,10 +233,10 @@ IEnumerator IEnumerable.GetEnumerator() namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -266,6 +267,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -324,7 +326,7 @@ public static void EnumerableBinaryInputFunction([EventHubTrigger("test", Con """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -339,10 +341,10 @@ public static void EnumerableBinaryInputFunction([EventHubTrigger("test", Con namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -369,6 +371,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -479,7 +482,7 @@ public class EnumerableStringNestedGenericTestClass : EnumerableStringTestCl """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -494,10 +497,10 @@ public class EnumerableStringNestedGenericTestClass : EnumerableStringTestCl namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -560,6 +563,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -644,7 +648,7 @@ public class EnumerableBinaryNestedTestClass : EnumerableBinaryTestClass """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -659,10 +663,10 @@ public class EnumerableBinaryNestedTestClass : EnumerableBinaryTestClass namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -701,6 +705,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -772,7 +777,7 @@ public class Poco """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -787,10 +792,10 @@ public class Poco namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -829,6 +834,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs index ac0270b37..d75ecf87d 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs @@ -67,7 +67,7 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -82,10 +82,10 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -113,6 +113,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -169,7 +170,7 @@ public static void HttpTrigger([HttpTrigger(AuthorizationLevel.Admin, "get", "po string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -184,10 +185,10 @@ public static void HttpTrigger([HttpTrigger(AuthorizationLevel.Admin, "get", "po namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -215,6 +216,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -276,7 +278,7 @@ public class JustHttpResponse string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -291,10 +293,10 @@ public class JustHttpResponse namespace MyCompany.MyProject.MyApp { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -322,6 +324,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -390,7 +393,7 @@ public Task FunctionWithTaskReturnType([HttpTrigger("get")] HttpRequestData req) """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """" + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -405,10 +408,10 @@ public Task FunctionWithTaskReturnType([HttpTrigger("get")] HttpRequestData req) namespace MyCompany.MyProject.MyApp { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -449,6 +452,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -465,7 +469,7 @@ public static IHostBuilder ConfigureGeneratedFunctionMetadataProvider(this IHost } } } - """"; + """; // override the namespace value for generated types using msbuild property. var buildPropertiesDict = new Dictionary() { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs index 89d27ca71..6d6bb9e88 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs @@ -103,7 +103,7 @@ public class MyOutputTypeNoHttpProp string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -118,10 +118,10 @@ public class MyOutputTypeNoHttpProp namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -163,6 +163,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -243,7 +244,7 @@ public class MyOutputType2 string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -258,10 +259,10 @@ public class MyOutputType2 namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -304,6 +305,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -380,7 +382,7 @@ public class Book """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -395,10 +397,10 @@ public class Book namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -428,6 +430,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -491,7 +494,7 @@ public FakeAttribute(string name) """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -506,10 +509,10 @@ public FakeAttribute(string name) namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -537,6 +540,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -587,7 +591,7 @@ public Task RunTimer([TimerTrigger("0 0 0 * * *", RunOnStartup = false)] object """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -602,10 +606,10 @@ public Task RunTimer([TimerTrigger("0 0 0 * * *", RunOnStartup = false)] object namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -632,6 +636,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -682,7 +687,7 @@ public Task Http([HttpTrigger(AuthorizationLevel.Admin, "get", """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -697,10 +702,10 @@ public Task Http([HttpTrigger(AuthorizationLevel.Admin, "get", namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -728,6 +733,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -787,7 +793,7 @@ public async Task RunAsync2([HttpTrigger(AuthorizationLevel.An """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -802,10 +808,10 @@ public async Task RunAsync2([HttpTrigger(AuthorizationLevel.An namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -859,6 +865,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -920,7 +927,7 @@ public sealed class HttpTriggers """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """" + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -935,10 +942,10 @@ public sealed class HttpTriggers namespace MyCompany.MyProject.MyApp { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -992,6 +999,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -1008,7 +1016,7 @@ public static IHostBuilder ConfigureGeneratedFunctionMetadataProvider(this IHost } } } - """"; + """; // override the namespace value for generated types using msbuild property. var buildPropertiesDict = new Dictionary() { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs index 48e0c3819..42bf7ac90 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs @@ -70,7 +70,7 @@ public static string Run([KafkaTrigger("LocalBroker", "stringTopicTenPartitions" """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -85,10 +85,10 @@ public static string Run([KafkaTrigger("LocalBroker", "stringTopicTenPartitions" namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -121,6 +121,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs index a37b6afb7..a84d7ff41 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs @@ -73,7 +73,7 @@ public static HttpResponseData Run(HttpRequestData req) """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -88,10 +88,10 @@ public static HttpResponseData Run(HttpRequestData req) namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -119,6 +119,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -177,7 +178,7 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.User, "get")] """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -192,10 +193,10 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.User, "get")] namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -223,6 +224,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs index 0046b717b..0e9ef0689 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs @@ -74,7 +74,7 @@ public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo, string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -89,10 +89,10 @@ public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo, namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -124,6 +124,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -180,7 +181,7 @@ public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo, """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -195,10 +196,10 @@ public static void Run([TimerTrigger("0 */5 * * * *")] TimerInfo timerInfo, namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -231,6 +232,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs index c4f7d3c61..40f4077f1 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs @@ -77,7 +77,7 @@ public static void Run([ServiceBusTrigger("queue", Connection = "ServiceBusConne string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -92,10 +92,10 @@ public static void Run([ServiceBusTrigger("queue", Connection = "ServiceBusConne namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -122,6 +122,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs index e11cb3d83..317d28504 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs @@ -1,7 +1,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Sdk.Generators; @@ -66,7 +65,7 @@ public string Negotiate([HttpTrigger(AuthorizationLevel.Function)] HttpRequestDa """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -81,10 +80,10 @@ public string Negotiate([HttpTrigger(AuthorizationLevel.Function)] HttpRequestDa namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -113,6 +112,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs index ae0d7272b..1bbf0c88c 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs @@ -74,7 +74,7 @@ public string QueueTriggerAndOutputFunction([QueueTrigger("test-input-dotnet-iso """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -89,10 +89,10 @@ public string QueueTriggerAndOutputFunction([QueueTrigger("test-input-dotnet-iso namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -120,6 +120,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -196,7 +197,7 @@ public object BlobsToQueue( """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -211,10 +212,10 @@ public object BlobsToQueue( namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -268,6 +269,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// @@ -327,7 +329,7 @@ public string Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] Http """; string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; - string expectedOutput = """ + string expectedOutput = $$""" // using System; using System.Collections.Generic; @@ -342,10 +344,10 @@ public string Run([HttpTrigger(AuthorizationLevel.Function, "get", "post")] Http namespace TestProject { /// - /// Custom implementation that returns function metadata definitions for the current worker."/> + /// Custom implementation that returns function metadata definitions for the current worker. /// [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + {{Constants.GeneratedCodeAttribute}} public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider { /// @@ -373,6 +375,7 @@ public Task> GetFunctionMetadataAsync(string d /// /// Extension methods to enable registration of the custom implementation generated for the current worker. /// + {{Constants.GeneratedCodeAttribute}} public static class WorkerHostBuilderFunctionMetadataProviderExtension { /// From 2af977c3ba5135f4c1b1e247c3b83f447641c888 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 9 Dec 2024 09:07:11 -0800 Subject: [PATCH 067/190] Fix 'AZURE_FUNCTIONS_' not respected in app builder (#2878) * Fix 'AZURE_FUNCTIONS_' not respected in app builder * update release_notes.md * Fix namespace issue --- release_notes.md | 2 +- .../Builder/FunctionsApplicationBuilder.cs | 1 + .../FunctionsApplicationBuilderTests.cs | 44 +++++++++++++++++++ .../DefaultFunctionMetadataTests.cs | 4 +- 4 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 test/DotNetWorkerTests/Builder/FunctionsApplicationBuilderTests.cs diff --git a/release_notes.md b/release_notes.md index 37057e890..173ffd02f 100644 --- a/release_notes.md +++ b/release_notes.md @@ -6,7 +6,7 @@ ### Microsoft.Azure.Functions.Worker (metapackage) -- +- `AZURE_FUNCTIONS_` environment variables are now loaded correctly when using `FunctionsApplicationBuilder`. (#2878) ### Microsoft.Azure.Functions.Worker.Core diff --git a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs index 7fab02258..4fd77bda6 100644 --- a/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs +++ b/src/DotNetWorker/Builder/FunctionsApplicationBuilder.cs @@ -30,6 +30,7 @@ public class FunctionsApplicationBuilder : IHostApplicationBuilder, IFunctionsWo internal FunctionsApplicationBuilder(string[]? args) { var configuration = new ConfigurationManager(); + configuration.AddEnvironmentVariables("AZURE_FUNCTIONS_"); _hostApplicationBuilder = new HostApplicationBuilder(new HostApplicationBuilderSettings { diff --git a/test/DotNetWorkerTests/Builder/FunctionsApplicationBuilderTests.cs b/test/DotNetWorkerTests/Builder/FunctionsApplicationBuilderTests.cs new file mode 100644 index 000000000..20b4781b0 --- /dev/null +++ b/test/DotNetWorkerTests/Builder/FunctionsApplicationBuilderTests.cs @@ -0,0 +1,44 @@ +// 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 Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Xunit; +using FuncApp = Microsoft.Azure.Functions.Worker.Builder.FunctionsApplication; + +namespace Microsoft.Azure.Functions.Worker.Tests.Builder +{ + public class FunctionsApplicationBuilderTests + { + [Theory] + [InlineData(null)] + [InlineData("Development")] + [InlineData("Staging")] + [InlineData("Production")] + [InlineData("Other")] + public void CreateBuilder_AzureFunctionsEnvironment_IsSet(string value) + { + // Explicitly set to null to ensure this is not impacted by any existing value. + Environment.SetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT", null); + Environment.SetEnvironmentVariable("ENVIRONMENT", null); + Environment.SetEnvironmentVariable("DOTNET_ENVIRONMENT", null); + Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", null); + if (!string.IsNullOrEmpty(value)) + { + Environment.SetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT", value); + } + + var builder = FuncApp.CreateBuilder([]); + Assert.Equal(value, builder.Configuration["ENVIRONMENT"]); + Assert.Equal(value ?? "Production", builder.Environment.EnvironmentName); + + IHost host = builder.Build(); + IConfiguration config = host.Services.GetService(); + IHostEnvironment env = host.Services.GetService(); + Assert.Equal(value, config["ENVIRONMENT"]); + Assert.Equal(value ?? "Production", env.EnvironmentName); + } + } +} diff --git a/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataTests.cs b/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataTests.cs index 13875a70b..4e00f6be7 100644 --- a/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataTests.cs +++ b/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataTests.cs @@ -1,11 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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 Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; using Xunit; -namespace DotNetWorkerTests.FunctionMetadata +namespace Microsoft.Azure.Functions.Worker.Tests.FunctionMetadata { public class DefaultFunctionMetadataTests { From e75979f2fcdbd2d52106caeb0a26152169bb8d70 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 28 Nov 2024 19:16:31 -0800 Subject: [PATCH 068/190] Minor code cleanup --- src/DotNetWorker.Core/Context/FunctionInvocation.cs | 2 +- .../Definition/GrpcFunctionDefinition.cs | 8 ++++---- .../FunctionMetadata/FunctionMetadataRpcExtensions.cs | 10 ++++++---- src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs | 4 ++-- src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs | 4 ++-- src/DotNetWorker.Grpc/Http/GrpcHttpResponseData.cs | 2 +- src/DotNetWorker.Grpc/RpcExtensions.cs | 2 +- 7 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/DotNetWorker.Core/Context/FunctionInvocation.cs b/src/DotNetWorker.Core/Context/FunctionInvocation.cs index 0fdd1091b..306b0c2d8 100644 --- a/src/DotNetWorker.Core/Context/FunctionInvocation.cs +++ b/src/DotNetWorker.Core/Context/FunctionInvocation.cs @@ -4,7 +4,7 @@ namespace Microsoft.Azure.Functions.Worker { /// - /// A representation of the a single function invocation. + /// A representation of a single function invocation. /// public abstract class FunctionInvocation { diff --git a/src/DotNetWorker.Grpc/Definition/GrpcFunctionDefinition.cs b/src/DotNetWorker.Grpc/Definition/GrpcFunctionDefinition.cs index efc55efa4..d5a9fd630 100644 --- a/src/DotNetWorker.Grpc/Definition/GrpcFunctionDefinition.cs +++ b/src/DotNetWorker.Grpc/Definition/GrpcFunctionDefinition.cs @@ -14,7 +14,7 @@ namespace Microsoft.Azure.Functions.Worker.Definition { - internal class GrpcFunctionDefinition : FunctionDefinition + internal sealed class GrpcFunctionDefinition : FunctionDefinition { private const string FunctionsWorkerDirectoryKey = "FUNCTIONS_WORKER_DIRECTORY"; private const string FunctionsApplicationDirectoryKey = "FUNCTIONS_APPLICATION_DIRECTORY"; @@ -42,9 +42,9 @@ public GrpcFunctionDefinition(FunctionLoadRequest loadRequest, IMethodInfoLocato string scriptFile = Path.Combine(scriptRoot, loadRequest.Metadata.ScriptFile); PathToAssembly = Path.GetFullPath(scriptFile); - var grpcBindingsGroup = loadRequest.Metadata.Bindings.GroupBy(kv => kv.Value.Direction); - var grpcInputBindings = grpcBindingsGroup.Where(kv => kv.Key == BindingInfo.Types.Direction.In).FirstOrDefault(); - var grpcOutputBindings = grpcBindingsGroup.Where(kv => kv.Key != BindingInfo.Types.Direction.In).FirstOrDefault(); + var grpcBindingsGroup = loadRequest.Metadata.Bindings.GroupBy(kv => kv.Value.Direction).ToArray(); + var grpcInputBindings = grpcBindingsGroup.FirstOrDefault(kv => kv.Key == BindingInfo.Types.Direction.In); + var grpcOutputBindings = grpcBindingsGroup.FirstOrDefault(kv => kv.Key != BindingInfo.Types.Direction.In); var infoToMetadataLambda = new Func, BindingMetadata>(kv => new GrpcBindingMetadata(kv.Key, kv.Value)); InputBindings = grpcInputBindings?.ToImmutableDictionary(kv => kv.Key, infoToMetadataLambda) diff --git a/src/DotNetWorker.Grpc/FunctionMetadata/FunctionMetadataRpcExtensions.cs b/src/DotNetWorker.Grpc/FunctionMetadata/FunctionMetadataRpcExtensions.cs index e9bbf81f0..24c1ab446 100644 --- a/src/DotNetWorker.Grpc/FunctionMetadata/FunctionMetadataRpcExtensions.cs +++ b/src/DotNetWorker.Grpc/FunctionMetadata/FunctionMetadataRpcExtensions.cs @@ -30,8 +30,10 @@ internal static MapField GetBindingInfoList(this IFunctionM { var binding = JsonSerializer.Deserialize(bindingJson); BindingInfo bindingInfo = CreateBindingInfo(binding); - binding.TryGetProperty("name", out JsonElement jsonName); - bindings.Add(jsonName.ToString()!, bindingInfo); + if (binding.TryGetProperty("name", out JsonElement jsonName)) + { + bindings.Add(jsonName.ToString(), bindingInfo); + } } return bindings; @@ -44,7 +46,7 @@ internal static BindingInfo CreateBindingInfo(JsonElement binding) if (!hasDirection || !hasType - || !Enum.TryParse(jsonDirection.ToString()!, out BindingInfo.Types.Direction direction)) + || !Enum.TryParse(jsonDirection.ToString(), out BindingInfo.Types.Direction direction)) { throw new FormatException("Bindings must declare a direction and type."); } @@ -59,7 +61,7 @@ internal static BindingInfo CreateBindingInfo(JsonElement binding) if (hasDataType) { - if (!Enum.TryParse(jsonDataType.ToString()!, out BindingInfo.Types.DataType dataType)) + if (!Enum.TryParse(jsonDataType.ToString(), out BindingInfo.Types.DataType dataType)) { throw new FormatException("Invalid DataType for a binding."); } diff --git a/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs b/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs index fa1251371..2f8b11a7f 100644 --- a/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs +++ b/src/DotNetWorker.Grpc/GrpcWorkerClientFactory.cs @@ -26,7 +26,7 @@ internal class GrpcWorkerClientFactory : IWorkerClientFactory public GrpcWorkerClientFactory(GrpcHostChannel outputChannel, IOptions startupOptions) { _outputChannel = outputChannel ?? throw new ArgumentNullException(nameof(outputChannel)); - _startupOptions = startupOptions?.Value ?? throw new ArgumentNullException(nameof(startupOptions), "gRPC Services are not correctly registered."); + _startupOptions = startupOptions.Value ?? throw new ArgumentNullException(nameof(startupOptions), "gRPC Services are not correctly registered."); } public IWorkerClient CreateClient(IMessageProcessor messageProcessor) @@ -38,8 +38,8 @@ private class GrpcWorkerClient : IWorkerClient private readonly GrpcWorkerStartupOptions _startupOptions; private readonly ChannelReader _outputReader; private readonly ChannelWriter _outputWriter; + private readonly IMessageProcessor? _processor; private bool _running; - private IMessageProcessor? _processor; public GrpcWorkerClient(GrpcHostChannel outputChannel, GrpcWorkerStartupOptions startupOptions, IMessageProcessor processor) { diff --git a/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs b/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs index 225be24da..89588f250 100644 --- a/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs +++ b/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs @@ -40,7 +40,7 @@ public InvocationHandler( _invocationFeaturesFactory = invocationFeaturesFactory ?? throw new ArgumentNullException(nameof(invocationFeaturesFactory)); _outputBindingsInfoProvider = outputBindingsInfoProvider ?? throw new ArgumentNullException(nameof(outputBindingsInfoProvider)); _inputConversionFeatureProvider = inputConversionFeatureProvider ?? throw new ArgumentNullException(nameof(inputConversionFeatureProvider)); - _workerOptions = workerOptions?.Value ?? throw new ArgumentNullException(nameof(workerOptions)); + _workerOptions = workerOptions.Value ?? throw new ArgumentNullException(nameof(workerOptions)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _inflightInvocations = new ConcurrentDictionary(); @@ -108,7 +108,7 @@ public async Task InvokeAsync(InvocationRequest request) if (functionBindings.InvocationResult is not null) { - TypedData? returnVal = await functionBindings.InvocationResult.ToRpcAsync(serializer); + TypedData returnVal = await functionBindings.InvocationResult.ToRpcAsync(serializer); response.ReturnValue = returnVal; } diff --git a/src/DotNetWorker.Grpc/Http/GrpcHttpResponseData.cs b/src/DotNetWorker.Grpc/Http/GrpcHttpResponseData.cs index c220f39d9..c69ee7bce 100644 --- a/src/DotNetWorker.Grpc/Http/GrpcHttpResponseData.cs +++ b/src/DotNetWorker.Grpc/Http/GrpcHttpResponseData.cs @@ -12,7 +12,7 @@ namespace Microsoft.Azure.Functions.Worker { - internal class GrpcHttpResponseData : HttpResponseData + internal sealed class GrpcHttpResponseData : HttpResponseData { private readonly RpcHttp _rpcHttp = new RpcHttp(); diff --git a/src/DotNetWorker.Grpc/RpcExtensions.cs b/src/DotNetWorker.Grpc/RpcExtensions.cs index 1d0f14cde..b50775abf 100644 --- a/src/DotNetWorker.Grpc/RpcExtensions.cs +++ b/src/DotNetWorker.Grpc/RpcExtensions.cs @@ -66,7 +66,7 @@ internal static TypedData ToRpcDefault(this object value, ObjectSerializer seria TypedData typedData = new TypedData(); try { - typedData.Json = serializer.Serialize(value)?.ToString(); + typedData.Json = serializer.Serialize(value).ToString(); } catch { From 795b59fc5f88374673d31a49d3a8ebe3f5655672 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 28 Nov 2024 19:18:22 -0800 Subject: [PATCH 069/190] Pef optimizations and cleanup in GrpcHttpRequestData --- .../DotNetWorker.Core.csproj | 1 + .../Http/GrpcHttpRequestData.cs | 35 +++++++------------ 2 files changed, 14 insertions(+), 22 deletions(-) diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 1d5562418..5844b5512 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -26,6 +26,7 @@ + diff --git a/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs b/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs index 76a0d5c82..9bc7c2e1e 100644 --- a/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs +++ b/src/DotNetWorker.Grpc/Http/GrpcHttpRequestData.cs @@ -12,7 +12,7 @@ namespace Microsoft.Azure.Functions.Worker { - internal class GrpcHttpRequestData : HttpRequestData, IDisposable + internal sealed class GrpcHttpRequestData : HttpRequestData, IDisposable #if NET6_0_OR_GREATER , IAsyncDisposable #endif @@ -31,16 +31,15 @@ public GrpcHttpRequestData(RpcHttp httpData, FunctionContext functionContext) _httpData = httpData ?? throw new ArgumentNullException(nameof(httpData)); _cookies = new Lazy>(() => { - if (Headers is null) - { - return Array.Empty(); - } - - var cookieString = Headers.FirstOrDefault(item => item.Key.Equals("Cookie", StringComparison.OrdinalIgnoreCase)).Value; + var cookieString = Headers + .FirstOrDefault(item => item.Key.Equals("Cookie", StringComparison.OrdinalIgnoreCase)) + .Value + ?.ToArray(); - if (cookieString != null && cookieString.Any() && !string.IsNullOrWhiteSpace(cookieString.First())) + if (cookieString is [var cookie, ..] + && !string.IsNullOrWhiteSpace(cookie)) { - return ToHttpCookies(cookieString.First()); + return ToHttpCookies(cookie); } return Array.Empty(); @@ -134,23 +133,15 @@ public ValueTask DisposeAsync() } #endif - protected virtual void Dispose(bool disposing) + public void Dispose() { - if (!_disposed) + if (_disposed) { - if (disposing) - { - _bodyStream?.Dispose(); - } - - _disposed = true; + return; } - } - public void Dispose() - { - Dispose(disposing: true); - GC.SuppressFinalize(this); + _bodyStream?.Dispose(); + _disposed = true; } private IReadOnlyCollection ToHttpCookies(string cookieString) From ec4ef88725800aeebb02632d9cc378da8010500c Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 28 Nov 2024 19:21:31 -0800 Subject: [PATCH 070/190] Improve worker runtime information parsing regex code --- src/DotNetWorker.Grpc/GrpcWorker.cs | 23 ++++++++++++++++++----- test/DotNetWorkerTests/GrpcWorkerTests.cs | 13 +++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/src/DotNetWorker.Grpc/GrpcWorker.cs b/src/DotNetWorker.Grpc/GrpcWorker.cs index 3435b6e20..581cfce78 100644 --- a/src/DotNetWorker.Grpc/GrpcWorker.cs +++ b/src/DotNetWorker.Grpc/GrpcWorker.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; @@ -23,7 +24,7 @@ namespace Microsoft.Azure.Functions.Worker { - internal class GrpcWorker : IWorker, IMessageProcessor + internal partial class GrpcWorker : IWorker, IMessageProcessor { private readonly IFunctionsApplication _application; private readonly IMethodInfoLocator _methodInfoLocator; @@ -46,7 +47,7 @@ public GrpcWorker(IFunctionsApplication application, _workerClientFactory = workerClientFactory ?? throw new ArgumentNullException(nameof(workerClientFactory)); _application = application ?? throw new ArgumentNullException(nameof(application)); _methodInfoLocator = methodInfoLocator ?? throw new ArgumentNullException(nameof(methodInfoLocator)); - _workerOptions = workerOptions?.Value ?? throw new ArgumentNullException(nameof(workerOptions)); + _workerOptions = workerOptions.Value ?? throw new ArgumentNullException(nameof(workerOptions)); _functionMetadataProvider = functionMetadataProvider ?? throw new ArgumentNullException(nameof(functionMetadataProvider)); _invocationHandler = invocationHandler; @@ -293,13 +294,25 @@ internal static FunctionEnvironmentReloadResponse EnvironmentReloadRequestHandle return envReloadResponse; } - private static WorkerMetadata GetWorkerMetadata() +#if NET7_0_OR_GREATER + [GeneratedRegex(@"^(\D*)+(?!\S)")] + private static partial Regex FrameworkDescriptionRegex(); +#else + private static readonly Regex FrameworkDescriptionRegexBacking = new Regex(@"^(\D*)+(?!\S)"); + private static Regex FrameworkDescriptionRegex() => FrameworkDescriptionRegexBacking; +#endif + + + internal static WorkerMetadata GetWorkerMetadata(string? frameworkDescription = null) { - var frameworkDescriptionRegex = new Regex(@"^(\D*)+(?!\S)"); + frameworkDescription ??= RuntimeInformation.FrameworkDescription; + + var match = FrameworkDescriptionRegex().Match(frameworkDescription); + frameworkDescription = match.Success ? match.Value : frameworkDescription; var workerMetadata = new WorkerMetadata { - RuntimeName = frameworkDescriptionRegex.Match(RuntimeInformation.FrameworkDescription).Value ?? RuntimeInformation.FrameworkDescription, + RuntimeName = frameworkDescription, RuntimeVersion = Environment.Version.ToString(), WorkerVersion = WorkerInformation.Instance.WorkerVersion, WorkerBitness = RuntimeInformation.ProcessArchitecture.ToString() diff --git a/test/DotNetWorkerTests/GrpcWorkerTests.cs b/test/DotNetWorkerTests/GrpcWorkerTests.cs index aa393842f..f3e10b56f 100644 --- a/test/DotNetWorkerTests/GrpcWorkerTests.cs +++ b/test/DotNetWorkerTests/GrpcWorkerTests.cs @@ -79,6 +79,19 @@ public void LoadFunction_ReturnsSuccess() Assert.Equal(StatusResult.Types.Status.Success, response.Result.Status); } + [Theory] + [InlineData(".NET Core 3.1.1", ".NET Core")] + [InlineData(".NET 8.0.0", ".NET")] + [InlineData(".NET Framework 4.8.4250.0", ".NET Framework")] + [InlineData(".NET Native", ".NET Native")] + [InlineData(".NET Native 1.0.0", ".NET Native")] + [InlineData("Mono 5.18.1.0", "Mono")] + public void GetWorkerMetadata_ParsesFrameworkDescription(string frameworkDescription, string expectedFramework) + { + var workerMetadata = GrpcWorker.GetWorkerMetadata(frameworkDescription); + Assert.Equal(expectedFramework, workerMetadata.RuntimeName); + } + [Fact] public void LoadFunction_WithProxyMetadata_ReturnsSuccess() { From c33fd5c7c2d591ea66735fb8ddacd49eb0608ff9 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 28 Nov 2024 19:29:12 -0800 Subject: [PATCH 071/190] Improvements to DefaultMethodInfoLocator Regex logic. --- .../Invocation/DefaultMethodInfoLocator.cs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs index 5ab64e6f2..1440028c1 100644 --- a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs +++ b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs @@ -7,10 +7,17 @@ namespace Microsoft.Azure.Functions.Worker.Invocation { - internal class DefaultMethodInfoLocator : IMethodInfoLocator + internal partial class DefaultMethodInfoLocator : IMethodInfoLocator { - private static readonly Regex _entryPointRegex = new Regex("^(?.*)\\.(?\\S*)$"); + private const string EntryPointRegexPattern = "^(?.*)\\.(?\\S*)$"; +#if NET7_0_OR_GREATER + private static readonly Regex _entryPointRegex = EntryPointRegex(); + [GeneratedRegex(EntryPointRegexPattern)] + private static partial Regex EntryPointRegex(); +#else + private static readonly Regex _entryPointRegex = new(EntryPointRegexPattern); +#endif public MethodInfo GetMethod(string pathToAssembly, string entryPoint) { var entryPointMatch = _entryPointRegex.Match(entryPoint); @@ -38,5 +45,7 @@ public MethodInfo GetMethod(string pathToAssembly, string entryPoint) return methodInfo; } + + } } From e44672f28ba3c54991583fcb3ea6270d5b73a5ff Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 2 Dec 2024 11:18:22 -0800 Subject: [PATCH 072/190] Application Insights perf optimizations and minor cleanup. --- .../TelemetryConfigurationSetup.cs | 11 +++--- .../Initializers/TokenCredentialOptions.cs | 36 +++++++++---------- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/src/DotNetWorker.ApplicationInsights/Initializers/TelemetryConfigurationSetup.cs b/src/DotNetWorker.ApplicationInsights/Initializers/TelemetryConfigurationSetup.cs index d3b2855bf..0d4535ea7 100644 --- a/src/DotNetWorker.ApplicationInsights/Initializers/TelemetryConfigurationSetup.cs +++ b/src/DotNetWorker.ApplicationInsights/Initializers/TelemetryConfigurationSetup.cs @@ -26,18 +26,17 @@ public void Configure(TelemetryConfiguration telemetryConfiguration) private string? GetAuthenticationString() { - if (_configuration is not null && _configuration[AppInsightsAuthenticationString] is string value && value is not "") + if (_configuration is not null && _configuration[AppInsightsAuthenticationString] is { } value and not "") { return value; } - else if (Environment.GetEnvironmentVariable(AppInsightsAuthenticationString) is string envValue && envValue is not "") + + if (Environment.GetEnvironmentVariable(AppInsightsAuthenticationString) is { } envValue and not "") { return envValue; } - else - { - return null; - } + + return null; } } } diff --git a/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs b/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs index 0cf7f89de..7b8ea1089 100644 --- a/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs +++ b/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs @@ -13,7 +13,7 @@ internal class TokenCredentialOptions private const string AuthClientIdKey = "ClientId"; /// - /// The client ID of an user-assigned identity. + /// The client ID of a user-assigned identity. /// /// /// This must be specified if you're using user-assigned managed identity. @@ -42,64 +42,64 @@ public static TokenCredentialOptions ParseAuthenticationString(string applicatio var tokenCredentialOptions = new TokenCredentialOptions(); bool isValidConfiguration = false; + foreach ((int, int) split in Tokenize(applicationInsightsAuthenticationString)) { (int start, int length) = split; - // Trim whitespace from start - while (length > 0 && char.IsWhiteSpace(applicationInsightsAuthenticationString[start])) - { - start++; - length--; - } + var authenticationStringToken = applicationInsightsAuthenticationString + .AsSpan(start, length) + .Trim(); // Ignore (allow) empty tokens. - if (length == 0) + if (authenticationStringToken.IsEmpty) { continue; } // Find key-value separator. - int indexOfEquals = applicationInsightsAuthenticationString.IndexOf('=', start, length); + int indexOfEquals = authenticationStringToken.IndexOf('='); if (indexOfEquals < 0) { continue; } // Extract key - int keyLength = indexOfEquals - start; - string key = applicationInsightsAuthenticationString.Substring(start, keyLength).TrimEnd(); - if (key.Length == 0) + var key = authenticationStringToken[..indexOfEquals].TrimEnd(); + if (key.IsEmpty) { // Key is blank continue; } - if (key.Equals(AuthAuthorizationKey, StringComparison.OrdinalIgnoreCase)) + // check if the span matches the string "df": + if (key.CompareTo( AuthAuthorizationKey.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0) { - if (!applicationInsightsAuthenticationString.Substring(indexOfEquals + 1, length - keyLength - 1).Trim().Equals(AuthToken, StringComparison.OrdinalIgnoreCase)) + if (authenticationStringToken[(indexOfEquals + 1)..].CompareTo(AuthToken.AsSpan(), StringComparison.OrdinalIgnoreCase) != 0) { throw new InvalidCredentialException("Credential supplied is not valid for the authorization mechanism being used in ApplicationInsights."); } isValidConfiguration = true; continue; } - if (key.Equals(AuthClientIdKey, StringComparison.OrdinalIgnoreCase)) + + if (key.CompareTo(AuthClientIdKey.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0) { - string clientId = applicationInsightsAuthenticationString.Substring(indexOfEquals + 1, length - keyLength - 1).Trim(); - if (!Guid.TryParse(clientId, out Guid clientIdGuid)) + var clientId = authenticationStringToken[(indexOfEquals + 1)..].Trim().ToString(); + if (!Guid.TryParse(clientId, out Guid _)) { throw new FormatException($"The Application Insights AuthenticationString {AuthClientIdKey} is not a valid GUID."); } tokenCredentialOptions.ClientId = clientId; - continue; } } + // Throw if the Authorization key is not present in the authentication string if (!isValidConfiguration) { throw new InvalidCredentialException("Authorization key is missing in the authentication string for ApplicationInsights."); } + return tokenCredentialOptions; } From 0347853165a4deaaf3c82e48d8a202a0890ff9aa Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 2 Dec 2024 11:19:24 -0800 Subject: [PATCH 073/190] Cleanup PR with: - Perf optimizations - Comment updates/cleanup - Minor bug fixes - Style changes/fixes --- ...dataProviderGenerator.CardinalityParser.cs | 2 +- .../FunctionMethodSyntaxReceiver.cs | 8 +- sdk/Sdk/ExtensionsMetadataEnhancer.cs | 3 +- .../Http/HttpResponseMessageForStatusCode.cs | 5 +- .../Tasks/ZipDeploy/ZipDeploymentStatus.cs | 2 +- .../Initializers/TokenCredentialOptions.cs | 2 +- .../Context/BindingContext.cs | 2 +- .../Features/DefaultInputConversionFeature.cs | 9 +- .../FunctionContextHttpRequestExtensions.cs | 2 +- .../Converter/DefaultConverterContext.cs | 2 +- .../Http/HttpRequestDataExtensions.cs | 274 +++++++++--------- .../Http/IHttpRequestDataFeature.cs | 2 +- .../Invocation/DefaultMethodInfoLocator.cs | 2 - src/DotNetWorker.Core/ModelBindingData.cs | 8 +- .../Handlers/InvocationHandler.cs | 2 +- .../TestFunctionInvocation.cs | 2 +- .../DefaultModelBindingFeatureTests.cs | 2 +- test/DotNetWorkerTests/Helpers/TestLoggerT.cs | 6 +- .../TestFunctionInvocation.cs | 2 +- .../FunctionMetadataGeneratorTests.cs | 2 +- 20 files changed, 169 insertions(+), 170 deletions(-) diff --git a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.CardinalityParser.cs b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.CardinalityParser.cs index a86a856ba..094ee8f60 100644 --- a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.CardinalityParser.cs +++ b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.CardinalityParser.cs @@ -176,7 +176,7 @@ private DataType ResolveIEnumerableOfT(IParameterSymbol parameterSymbol, out boo break; } - genericInterfaceSymbol = currSymbol.Interfaces.Where(i => i.IsOrDerivedFrom(_knownTypes.IEnumerableGeneric)).FirstOrDefault(); + genericInterfaceSymbol = currSymbol.Interfaces.FirstOrDefault(i => i.IsOrDerivedFrom(_knownTypes.IEnumerableGeneric)); if (genericInterfaceSymbol != null) { finalSymbol = genericInterfaceSymbol; diff --git a/sdk/Sdk.Generators/FunctionMethodSyntaxReceiver.cs b/sdk/Sdk.Generators/FunctionMethodSyntaxReceiver.cs index f5487bf2b..880927beb 100644 --- a/sdk/Sdk.Generators/FunctionMethodSyntaxReceiver.cs +++ b/sdk/Sdk.Generators/FunctionMethodSyntaxReceiver.cs @@ -21,12 +21,10 @@ internal class FunctionMethodSyntaxReceiver : ISyntaxReceiver /// public void OnVisitSyntaxNode(SyntaxNode syntaxNode) { - if (syntaxNode is MethodDeclarationSyntax methodSyntax) + if (syntaxNode is MethodDeclarationSyntax {AttributeLists.Count: > 0} methodSyntax) { - if (methodSyntax.AttributeLists.Count > 0) // collect all methods with attributes - we will verify they are functions when we have access to symbols to get the full name - { - CandidateMethods.Add(methodSyntax); - } + // collect all methods with attributes - we will verify they are functions when we have access to symbols to get the full name + CandidateMethods.Add(methodSyntax); } } } diff --git a/sdk/Sdk/ExtensionsMetadataEnhancer.cs b/sdk/Sdk/ExtensionsMetadataEnhancer.cs index 9259dbc70..9f24b84f7 100644 --- a/sdk/Sdk/ExtensionsMetadataEnhancer.cs +++ b/sdk/Sdk/ExtensionsMetadataEnhancer.cs @@ -17,7 +17,6 @@ public static void AddHintPath(IEnumerable extensions) { string? assemblyName = GetAssemblyNameOrNull(extension.TypeName); - // TODO: Worth checking if assembly if also present in there? if (string.IsNullOrEmpty(extension.HintPath) && !string.IsNullOrEmpty(assemblyName)) { extension.HintPath = $@"{ExtensionsBinaryDirectoryPath}/{assemblyName}.dll"; @@ -34,7 +33,7 @@ public static void AddHintPath(IEnumerable extensions) var match = Regex.Match(typeName, AssemblyNameFromQualifiedNameRegex); - if (match.Success && match.Groups.Count == 2) + if (match is {Success: true, Groups.Count: 2}) { return match.Groups[1].Value; } diff --git a/sdk/Sdk/Tasks/ZipDeploy/Http/HttpResponseMessageForStatusCode.cs b/sdk/Sdk/Tasks/ZipDeploy/Http/HttpResponseMessageForStatusCode.cs index d96299877..499023ed2 100644 --- a/sdk/Sdk/Tasks/ZipDeploy/Http/HttpResponseMessageForStatusCode.cs +++ b/sdk/Sdk/Tasks/ZipDeploy/Http/HttpResponseMessageForStatusCode.cs @@ -1,7 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.IO; using System.Net; using System.Threading.Tasks; @@ -28,7 +29,7 @@ public Task GetResponseBodyAsync() public IEnumerable GetHeader(string name) { - return new string[0]; + return Array.Empty(); } } } diff --git a/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs b/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs index b96138457..b95f3713a 100644 --- a/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs +++ b/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs @@ -75,7 +75,7 @@ public async Task PollDeploymentStatusAsync(string deploymentUrl, return DeployStatus.Unknown; } - await Task.Delay(TimeSpan.FromSeconds(StatusRefreshDelaySeconds)); + await Task.Delay(TimeSpan.FromSeconds(StatusRefreshDelaySeconds), tokenSource.Token); } return deployStatus; diff --git a/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs b/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs index 7b8ea1089..2e26c9116 100644 --- a/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs +++ b/src/DotNetWorker.ApplicationInsights/Initializers/TokenCredentialOptions.cs @@ -73,7 +73,7 @@ public static TokenCredentialOptions ParseAuthenticationString(string applicatio } // check if the span matches the string "df": - if (key.CompareTo( AuthAuthorizationKey.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0) + if (key.CompareTo(AuthAuthorizationKey.AsSpan(), StringComparison.OrdinalIgnoreCase) == 0) { if (authenticationStringToken[(indexOfEquals + 1)..].CompareTo(AuthToken.AsSpan(), StringComparison.OrdinalIgnoreCase) != 0) { diff --git a/src/DotNetWorker.Core/Context/BindingContext.cs b/src/DotNetWorker.Core/Context/BindingContext.cs index 106ce50bf..d5ad26c55 100644 --- a/src/DotNetWorker.Core/Context/BindingContext.cs +++ b/src/DotNetWorker.Core/Context/BindingContext.cs @@ -12,7 +12,7 @@ public abstract class BindingContext { /// /// Gets the binding data information for the current context. - /// This contains all of the trigger defined metadata. + /// This contains all the trigger defined metadata. /// public abstract IReadOnlyDictionary BindingData { get; } } diff --git a/src/DotNetWorker.Core/Context/Features/DefaultInputConversionFeature.cs b/src/DotNetWorker.Core/Context/Features/DefaultInputConversionFeature.cs index 267d6804e..0ef6d375f 100644 --- a/src/DotNetWorker.Core/Context/Features/DefaultInputConversionFeature.cs +++ b/src/DotNetWorker.Core/Context/Features/DefaultInputConversionFeature.cs @@ -18,9 +18,12 @@ internal sealed class DefaultInputConversionFeature : IInputConversionFeature private readonly IInputConverterProvider _inputConverterProvider; private static readonly Type _inputConverterAttributeType = typeof(InputConverterAttribute); - // Users may create a POCO and specify a special converter implementation - // to be used using "InputConverter" attribute. We cache that mapping here. - // Key is assembly qualified name of POCO and Value is assembly qualified name of converter implementation. + + /// + /// Users may create a POCO and specify a special converter implementation + /// using the . We cache that mapping here. + /// Key is assembly qualified name of POCO and Value is assembly qualified name of converter implementation. + /// private static readonly ConcurrentDictionary _typeToConverterCache = new(); public DefaultInputConversionFeature(IInputConverterProvider inputConverterProvider) diff --git a/src/DotNetWorker.Core/Context/FunctionContextHttpRequestExtensions.cs b/src/DotNetWorker.Core/Context/FunctionContextHttpRequestExtensions.cs index 522580559..db8759751 100644 --- a/src/DotNetWorker.Core/Context/FunctionContextHttpRequestExtensions.cs +++ b/src/DotNetWorker.Core/Context/FunctionContextHttpRequestExtensions.cs @@ -16,7 +16,7 @@ public static class FunctionContextHttpRequestExtensions private const string HttpBindingType = "http"; /// - /// Gets the instance if the invocation is for an http trigger. + /// Gets the instance if the invocation is for an HTTP trigger. /// /// The FunctionContext instance. /// HttpRequestData instance if the invocation is http, else null diff --git a/src/DotNetWorker.Core/Converters/Converter/DefaultConverterContext.cs b/src/DotNetWorker.Core/Converters/Converter/DefaultConverterContext.cs index 5c66a74ec..d4c2ab5ce 100644 --- a/src/DotNetWorker.Core/Converters/Converter/DefaultConverterContext.cs +++ b/src/DotNetWorker.Core/Converters/Converter/DefaultConverterContext.cs @@ -13,8 +13,8 @@ internal sealed class DefaultConverterContext : ConverterContext { public DefaultConverterContext(Type targetType, object? source, FunctionContext context, IReadOnlyDictionary properties) { - TargetType = targetType ?? throw new ArgumentNullException(nameof(context)); Source = source; + TargetType = targetType ?? throw new ArgumentNullException(nameof(targetType)); FunctionContext = context ?? throw new ArgumentNullException(nameof(context)); Properties = properties ?? throw new ArgumentNullException(nameof(properties)); } diff --git a/src/DotNetWorker.Core/Http/HttpRequestDataExtensions.cs b/src/DotNetWorker.Core/Http/HttpRequestDataExtensions.cs index f8b50c469..760c6e31d 100644 --- a/src/DotNetWorker.Core/Http/HttpRequestDataExtensions.cs +++ b/src/DotNetWorker.Core/Http/HttpRequestDataExtensions.cs @@ -1,140 +1,140 @@ -// 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.IO; -using System.Net; -using System.Text; -using System.Threading; -using System.Threading.Tasks; -using Azure.Core.Serialization; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Microsoft.Azure.Functions.Worker.Http -{ - /// - /// Provides extension methods to work with an instance. - /// - public static class HttpRequestDataExtensions - { - /// - /// Reads the body payload as a string. - /// - /// The request from which to read. - /// The encoding to use when reading the string. Defaults to UTF-8 - /// A that represents the asynchronous read operation. - public static async Task ReadAsStringAsync(this HttpRequestData request, Encoding? encoding = null) - { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - - if (request.Body is null) - { - return null; - } - - using (var reader = new StreamReader(request.Body, bufferSize: 1024, detectEncodingFromByteOrderMarks: true, encoding: encoding ?? Encoding.UTF8, leaveOpen: true)) - { - return await reader.ReadToEndAsync(); - } - } - - /// - /// Reads the body payload as a string. - /// - /// The request from which to read. - /// The encoding to use when reading the string. Defaults to UTF-8 - /// A that represents request body. - public static string? ReadAsString(this HttpRequestData request, Encoding? encoding = null) - { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - - if (request.Body is null) - { - return null; - } - - using (var reader = new StreamReader(request.Body, bufferSize: 1024, detectEncodingFromByteOrderMarks: true, encoding: encoding ?? Encoding.UTF8, leaveOpen: true)) - { - return reader.ReadToEnd(); - } - } - - /// - /// Reads the request using the default configured for this worker. - /// - /// The target type of the JSON value. - /// The request to be read. - /// A token that may be used to cancel the read operation. - /// A representing the asynchronous operation. - public static ValueTask ReadFromJsonAsync(this HttpRequestData request, CancellationToken cancellationToken = default) - { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - - ObjectSerializer serializer = request.FunctionContext.InstanceServices.GetService>()?.Value?.Serializer - ?? throw new InvalidOperationException("A serializer is not configured for the worker."); - - return ReadFromJsonAsync(request, serializer, cancellationToken); - } - - /// - /// Reads the request using the provided . - /// - /// The target type of the JSON value. - /// The request to be read. - /// The to use for the deserialization. - /// A token that may be used to cancel the read operation. - /// A representing the asynchronous operation. - public static ValueTask ReadFromJsonAsync(this HttpRequestData request, ObjectSerializer serializer, CancellationToken cancellationToken = default) - { - if (request is null) - { - throw new ArgumentNullException(nameof(request)); - } - - if (serializer is null) - { - throw new ArgumentNullException(nameof(serializer)); - } - - ValueTask result = serializer.DeserializeAsync(request.Body, typeof(T), cancellationToken); - - static T? TryCast(object? value) - { - return value != null - ? (T)value - : default; - } - - if (result.IsCompletedSuccessfully) - { - return new ValueTask(TryCast(result.Result)); - } - - return new ValueTask(result.AsTask().ContinueWith(t => TryCast(t.Result))); +// 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.IO; +using System.Net; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Azure.Core.Serialization; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace Microsoft.Azure.Functions.Worker.Http +{ + /// + /// Provides extension methods to work with an instance. + /// + public static class HttpRequestDataExtensions + { + /// + /// Reads the body payload as a string. + /// + /// The request from which to read. + /// The encoding to use when reading the string. Defaults to UTF-8 + /// A that represents the asynchronous read operation. + public static async Task ReadAsStringAsync(this HttpRequestData request, Encoding? encoding = null) + { + if (request is null) + { + throw new ArgumentNullException(nameof(request)); + } + + if (request.Body is null) + { + return null; + } + + using (var reader = new StreamReader(request.Body, bufferSize: 1024, detectEncodingFromByteOrderMarks: true, encoding: encoding ?? Encoding.UTF8, leaveOpen: true)) + { + return await reader.ReadToEndAsync(); + } } - /// - /// Creates a response for the the provided . - /// - /// The for this response. - /// The response status code. - /// The response data. - public static HttpResponseData CreateResponse(this HttpRequestData request, HttpStatusCode statusCode) - { - var response = request.CreateResponse(); - response.StatusCode = statusCode; - - return response; - } - } + /// + /// Reads the body payload as a string. + /// + /// The request from which to read. + /// The encoding to use when reading the string. Defaults to UTF-8 + /// A that represents request body. + public static string? ReadAsString(this HttpRequestData request, Encoding? encoding = null) + { + if (request is null) + { + throw new ArgumentNullException(nameof(request)); + } + + if (request.Body is null) + { + return null; + } + + using (var reader = new StreamReader(request.Body, bufferSize: 1024, detectEncodingFromByteOrderMarks: true, encoding: encoding ?? Encoding.UTF8, leaveOpen: true)) + { + return reader.ReadToEnd(); + } + } + + /// + /// Reads the request using the default configured for this worker. + /// + /// The target type of the JSON value. + /// The request to be read. + /// A token that may be used to cancel the read operation. + /// A representing the asynchronous operation. + public static ValueTask ReadFromJsonAsync(this HttpRequestData request, CancellationToken cancellationToken = default) + { + if (request is null) + { + throw new ArgumentNullException(nameof(request)); + } + + ObjectSerializer serializer = request.FunctionContext.InstanceServices.GetService>()?.Value?.Serializer + ?? throw new InvalidOperationException("A serializer is not configured for the worker."); + + return ReadFromJsonAsync(request, serializer, cancellationToken); + } + + /// + /// Reads the request using the provided . + /// + /// The target type of the JSON value. + /// The request to be read. + /// The to use for the deserialization. + /// A token that may be used to cancel the read operation. + /// A representing the asynchronous operation. + public static ValueTask ReadFromJsonAsync(this HttpRequestData request, ObjectSerializer serializer, CancellationToken cancellationToken = default) + { + if (request is null) + { + throw new ArgumentNullException(nameof(request)); + } + + if (serializer is null) + { + throw new ArgumentNullException(nameof(serializer)); + } + + ValueTask result = serializer.DeserializeAsync(request.Body, typeof(T), cancellationToken); + + static T? TryCast(object? value) + { + return value != null + ? (T)value + : default; + } + + if (result.IsCompletedSuccessfully) + { + return new ValueTask(TryCast(result.Result)); + } + + return new ValueTask(result.AsTask().ContinueWith(t => TryCast(t.Result), cancellationToken)); + } + + /// + /// Creates a response for the provided . + /// + /// The for this response. + /// The response status code. + /// The response data. + public static HttpResponseData CreateResponse(this HttpRequestData request, HttpStatusCode statusCode) + { + var response = request.CreateResponse(); + response.StatusCode = statusCode; + + return response; + } + } } diff --git a/src/DotNetWorker.Core/Http/IHttpRequestDataFeature.cs b/src/DotNetWorker.Core/Http/IHttpRequestDataFeature.cs index ab8e96a59..7742a2ade 100644 --- a/src/DotNetWorker.Core/Http/IHttpRequestDataFeature.cs +++ b/src/DotNetWorker.Core/Http/IHttpRequestDataFeature.cs @@ -11,7 +11,7 @@ namespace Microsoft.Azure.Functions.Worker.Http public interface IHttpRequestDataFeature { /// - /// Gets the instance if the FunctionContext contains an invocation for an http trigger. + /// Gets the instance if the FunctionContext contains an invocation for an HTTP trigger. /// /// The FunctionContext instance. /// HttpRequestData instance if the invocation is http, else null diff --git a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs index 1440028c1..8c9202d7c 100644 --- a/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs +++ b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs @@ -45,7 +45,5 @@ public MethodInfo GetMethod(string pathToAssembly, string entryPoint) return methodInfo; } - - } } diff --git a/src/DotNetWorker.Core/ModelBindingData.cs b/src/DotNetWorker.Core/ModelBindingData.cs index 8e4580f77..06b9122e3 100644 --- a/src/DotNetWorker.Core/ModelBindingData.cs +++ b/src/DotNetWorker.Core/ModelBindingData.cs @@ -6,17 +6,17 @@ namespace Microsoft.Azure.Functions.Worker.Core { /// - /// A representation of a Microsoft.Azure.WebJobs.ParameterBindingData + /// A representation of a Microsoft.Azure.WebJobs.ParameterBindingData. /// public abstract class ModelBindingData { /// - /// Gets the version of the binding data content + /// Gets the version of the binding data content. /// public abstract string Version { get; } /// - /// Gets the extension source of the binding data i.e CosmosDB, AzureStorageBlobs + /// Gets the extension source of the binding data (e.g., CosmosDB, AzureStorageBlobs). /// public abstract string Source { get; } @@ -26,7 +26,7 @@ public abstract class ModelBindingData public abstract BinaryData Content { get; } /// - /// Gets the content type of the binding data content i.e. "application/json" + /// Gets the content type of the binding data content (e.g., "application/json"). /// public abstract string ContentType { get; } } diff --git a/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs b/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs index 89588f250..07a5300ce 100644 --- a/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs +++ b/src/DotNetWorker.Grpc/Handlers/InvocationHandler.cs @@ -26,7 +26,7 @@ internal class InvocationHandler : IInvocationHandler private readonly WorkerOptions _workerOptions; private readonly ILogger _logger; - private ConcurrentDictionary _inflightInvocations; + private readonly ConcurrentDictionary _inflightInvocations; public InvocationHandler( IFunctionsApplication application, diff --git a/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs b/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs index b8b1afd9e..e8307dab5 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs +++ b/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs @@ -21,7 +21,7 @@ public TestFunctionInvocation(string id = null, string functionId = null) FunctionId = functionId; } - // create/dispose activity to pull off it's Id + // create/dispose activity to pull off its ID. using Activity activity = new Activity(string.Empty).Start(); TraceContext = new DefaultTraceContext(activity.Id, Guid.NewGuid().ToString()); } diff --git a/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs b/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs index 241394d16..adc9f0c17 100644 --- a/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs +++ b/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs @@ -179,7 +179,7 @@ public async Task BindFunctionInputAsync_Populates_Parameter_For_Nullable_Or_Ref Assert.NotNull(httpReqData); // The input binding data does not have values for "bar","fooId" and "bazDate" - // but since the are nullable or reference types, they should be populated with null. + // but since they are nullable or reference types, they should be populated with null. var bar = parameterValuesArray[1]; Assert.Null(bar); var fooId = parameterValuesArray[2]; diff --git a/test/DotNetWorkerTests/Helpers/TestLoggerT.cs b/test/DotNetWorkerTests/Helpers/TestLoggerT.cs index 2529a8c70..a2527cc9d 100644 --- a/test/DotNetWorkerTests/Helpers/TestLoggerT.cs +++ b/test/DotNetWorkerTests/Helpers/TestLoggerT.cs @@ -16,10 +16,10 @@ private TestLogger(string category) public static TestLogger Create() { // We want to use the logic for category naming which is internal to LoggerFactory. - // So we'll create a TestLogger via the LoggerFactory and grab it's category. + // So we'll create a TestLogger via the LoggerFactory and grab its category. TestLoggerProvider testLoggerProvider = new TestLoggerProvider(); - LoggerFactory _testLoggerFactory = new LoggerFactory(new[] { testLoggerProvider }); - _testLoggerFactory.CreateLogger(); + LoggerFactory testLoggerFactory = new LoggerFactory([testLoggerProvider]); + testLoggerFactory.CreateLogger(); TestLogger testLogger = testLoggerProvider.CreatedLoggers.Single(); return new TestLogger(testLogger.Category); } diff --git a/test/DotNetWorkerTests/TestFunctionInvocation.cs b/test/DotNetWorkerTests/TestFunctionInvocation.cs index 16a7565d0..2004d5e61 100644 --- a/test/DotNetWorkerTests/TestFunctionInvocation.cs +++ b/test/DotNetWorkerTests/TestFunctionInvocation.cs @@ -20,7 +20,7 @@ public TestFunctionInvocation(string id = null, string functionId = null) FunctionId = functionId; } - // create/dispose activity to pull off it's Id + // create/dispose activity to pull off its ID. using Activity activity = new Activity(string.Empty).Start(); TraceContext = new DefaultTraceContext(activity.Id, Guid.NewGuid().ToString()); } diff --git a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs index 335e37022..ee2bd985a 100644 --- a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs @@ -979,7 +979,7 @@ public void CardinalityManyFunctions(string functionName, string entryPoint, boo var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; - SdkFunctionMetadata metadata = functions.Where(a => string.Equals(a.Name, functionName, StringComparison.Ordinal)).Single(); + SdkFunctionMetadata metadata = functions.Single(a => string.Equals(a.Name, functionName, StringComparison.Ordinal)); ValidateFunction(metadata, functionName, GetEntryPoint(nameof(CardinalityMany), entryPoint), b => ValidateTrigger(b, cardinalityMany)); From 8ea4ffc6f9e0d7d9319734faa5486cd64db30e42 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 12 Dec 2024 10:54:40 -0800 Subject: [PATCH 074/190] Fixing the incorrect path for prelaunch app location. (#2897) --- .../templates/official/jobs/build-host-prelaunch-artifacts.yml | 2 +- .../Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml b/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml index 4982660e2..a8f745b52 100644 --- a/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml +++ b/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml @@ -25,5 +25,5 @@ jobs: publishWebProjects: false zipAfterPublish: false modifyOutputPath: false - arguments: -c Release -o $(Build.ArtifactStagingDirectory)/_preLaunchAppPackages/${{ version }} -f ${{ version }} -p:UseAppHost=false + arguments: -c Release -o $(Build.ArtifactStagingDirectory)/_preLaunchAppPackages/${{ replace(version, 'net', '') }} -f ${{ version }} -p:UseAppHost=false projects: host/src/PrelaunchApp/App.csproj diff --git a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec index 481a61ada..9207d8f38 100644 --- a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec +++ b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec @@ -4,7 +4,7 @@ Microsoft.Azure.Functions.DotNetIsolatedNativeHost Microsoft Azure Functions dotnet-isolated native host dotnet-isolated azure-functions azure - 1.0.11 + 1.0.12 Microsoft Microsoft https://github.com/Azure/azure-functions-dotnet-worker From d3b2423f815cc9213afae3e780598c5aa0822b67 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Mon, 16 Dec 2024 14:49:33 -0800 Subject: [PATCH 075/190] Adding net9 prelaunch app. (#2898) --- .../templates/official/jobs/build-host-prelaunch-artifacts.yml | 2 +- host/src/PrelaunchApp/App.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml b/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml index a8f745b52..ca62400d1 100644 --- a/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml +++ b/eng/ci/templates/official/jobs/build-host-prelaunch-artifacts.yml @@ -12,7 +12,7 @@ jobs: artifact: _preLaunchAppPackages variables: - dotnetVersions: 'net8.0,net6.0' + dotnetVersions: 'net9.0,net8.0,net6.0' steps: - template: /eng/ci/templates/steps/install-dotnet.yml@self diff --git a/host/src/PrelaunchApp/App.csproj b/host/src/PrelaunchApp/App.csproj index 1a4cf4c71..796f94048 100644 --- a/host/src/PrelaunchApp/App.csproj +++ b/host/src/PrelaunchApp/App.csproj @@ -1,7 +1,7 @@ Exe - net6.0;net7.0;net8.0 + net6.0;net7.0;net8.0;net9.0 False None From 05b42078372ce5ded90149669f7eb910edebd777 Mon Sep 17 00:00:00 2001 From: Aishwarya Bhandari <37918412+aishwaryabh@users.noreply.github.com> Date: Tue, 17 Dec 2024 13:54:26 -0800 Subject: [PATCH 076/190] ServiceBusSessionMessageActions not working with IsBatched=true for ServiceBusReceivedMessage (#2889) * initial changes * removing extra method * remove unneccessary using statement * trying to fix reference to testFunctionContext * changing type to public * changing order of using statements and removing dependency on protobuf * seeing if tests pass * reverting testFUnctionContext back to normal * remove failing test * updated comment * updating comment * addressing comments * addressing feedback for creating method for parseSessionIdFromBindingData * returning string * removing unused variable * cast converter * addressing comments regarding const --- .../src/Constants.cs | 12 +- ...erviceBusSessionMessageActionsConverter.cs | 48 +++++-- .../ServiceBusMessageActionsTests.cs | 2 +- ...> ServiceBusSessionMessageActionsTests.cs} | 0 .../ServiceBusSessionMessageConverterTests.cs | 121 ++++++++++++++++++ 5 files changed, 168 insertions(+), 15 deletions(-) rename test/Worker.Extensions.Tests/ServiceBus/{ServiceBusSessionMessageActions.cs => ServiceBusSessionMessageActionsTests.cs} (100%) create mode 100644 test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs diff --git a/extensions/Worker.Extensions.ServiceBus/src/Constants.cs b/extensions/Worker.Extensions.ServiceBus/src/Constants.cs index 8c63d4124..97e7198ef 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Constants.cs +++ b/extensions/Worker.Extensions.ServiceBus/src/Constants.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. namespace Microsoft.Azure.Functions.Worker.Extensions.ServiceBus @@ -8,5 +8,13 @@ internal static class Constants internal const string BinaryContentType = "application/octet-stream"; internal const string BindingSource = "AzureServiceBusReceivedMessage"; + + internal const string SessionId = "SessionId"; + + internal const string SessionIdArray = "SessionIdArray"; + + internal const string SessionActions = "SessionActions"; + + internal const string SessionLockedUntil = "SessionLockedUntil"; } -} \ No newline at end of file +} diff --git a/extensions/Worker.Extensions.ServiceBus/src/ServiceBusSessionMessageActionsConverter.cs b/extensions/Worker.Extensions.ServiceBus/src/ServiceBusSessionMessageActionsConverter.cs index 1a37c3c47..9df288b67 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/ServiceBusSessionMessageActionsConverter.cs +++ b/extensions/Worker.Extensions.ServiceBus/src/ServiceBusSessionMessageActionsConverter.cs @@ -2,11 +2,13 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System; +using System.Collections.Generic; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Converters; using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; +using Microsoft.Azure.Functions.Worker.Extensions.ServiceBus; using Microsoft.Azure.ServiceBus.Grpc; -using System.Text.Json; namespace Microsoft.Azure.Functions.Worker { @@ -15,7 +17,6 @@ namespace Microsoft.Azure.Functions.Worker /// [SupportsDeferredBinding] [SupportedTargetType(typeof(ServiceBusSessionMessageActions))] - [SupportedTargetType(typeof(ServiceBusSessionMessageActions[]))] internal class ServiceBusSessionMessageActionsConverter : IInputConverter { private readonly Settlement.SettlementClient _settlement; @@ -29,27 +30,23 @@ public ValueTask ConvertAsync(ConverterContext context) { try { - var foundSessionId = context.FunctionContext.BindingContext.BindingData.TryGetValue("SessionId", out object? sessionId); - if (!foundSessionId) - { - throw new InvalidOperationException($"Expecting SessionId within binding data and value was not present. Sessions must be enabled when binding to {nameof(ServiceBusSessionMessageActions)}."); - } + var sessionId = ParseSessionIdFromBindingData(context); // Get the sessionLockedUntil property from the SessionActions binding data - var foundSessionActions = context.FunctionContext.BindingContext.BindingData.TryGetValue("SessionActions", out object? sessionActions); + var foundSessionActions = context.FunctionContext.BindingContext.BindingData.TryGetValue(Constants.SessionActions, out object? sessionActions); if (!foundSessionActions) { - throw new InvalidOperationException("Expecting SessionActions within binding data and value was not present."); + throw new InvalidOperationException($"Expecting {Constants.SessionActions} within binding data and value was not present."); } JsonDocument jsonDocument = JsonDocument.Parse(sessionActions!.ToString()); - var foundSessionLockedUntil = jsonDocument.RootElement.TryGetProperty("SessionLockedUntil", out JsonElement sessionLockedUntil); + var foundSessionLockedUntil = jsonDocument.RootElement.TryGetProperty(Constants.SessionLockedUntil, out JsonElement sessionLockedUntil); if (!foundSessionLockedUntil) { - throw new InvalidOperationException("Expecting SessionLockedUntil within binding data of session actions and value was not present."); + throw new InvalidOperationException($"Expecting {Constants.SessionLockedUntil} within binding data of session actions and value was not present."); } - var sessionActionResult = new ServiceBusSessionMessageActions(_settlement, sessionId!.ToString(), sessionLockedUntil.GetDateTimeOffset()); + var sessionActionResult = new ServiceBusSessionMessageActions(_settlement, sessionId, sessionLockedUntil.GetDateTimeOffset()); var result = ConversionResult.Success(sessionActionResult); return new ValueTask(result); } @@ -58,5 +55,32 @@ public ValueTask ConvertAsync(ConverterContext context) return new ValueTask(ConversionResult.Failed(exception)); } } + + private string ParseSessionIdFromBindingData(ConverterContext context) + { + // Try to resolve sessionId directly + var bindingData = context.FunctionContext.BindingContext.BindingData; + bindingData.TryGetValue(Constants.SessionId, out object? sessionId); + + // If sessionId is not found and sessionIdRepeatedFieldArray has a value (isBatched = true), we can just parse the first sessionId from the array, as all the values are guaranteed to be the same. + // This is because there can be multiple messages but each message would belong to the same session. + // Note if web jobs extensions ever adds support for multiple sessions in a single batch, this logic will need to be updated. + if (sessionId is null && bindingData.TryGetValue(Constants.SessionIdArray, out object? sessionIdArray)) + { + var sessionIdRepeatedArray = sessionIdArray as IList; + if (sessionIdRepeatedArray is not null && sessionIdRepeatedArray.Count > 0) + { + sessionId = sessionIdRepeatedArray[0]; // Use the first sessionId in the array + } + } + + if (sessionId is null) + { + throw new InvalidOperationException( + $"Expecting {Constants.SessionId} or {Constants.SessionIdArray} within binding data and value was not present. Sessions must be enabled when binding to {nameof(ServiceBusSessionMessageActions)}."); + } + + return (string)sessionId; + } } } diff --git a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusMessageActionsTests.cs b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusMessageActionsTests.cs index 0edf5612e..49ffdc131 100644 --- a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusMessageActionsTests.cs +++ b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusMessageActionsTests.cs @@ -103,7 +103,7 @@ public async Task PassingNullMessageThrows() await Assert.ThrowsAsync(async () => await messageActions.RenewMessageLockAsync(null)); } - private class MockSettlementClient : Settlement.SettlementClient + internal class MockSettlementClient : Settlement.SettlementClient { private readonly string _lockToken; private readonly ByteString _propertiesToModify; diff --git a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActions.cs b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActionsTests.cs similarity index 100% rename from test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActions.cs rename to test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActionsTests.cs diff --git a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs new file mode 100644 index 000000000..0b069be80 --- /dev/null +++ b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs @@ -0,0 +1,121 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using Microsoft.Azure.Functions.Worker.Converters; +using static Microsoft.Azure.Functions.Worker.Extensions.Tests.ServiceBusMessageActionsTests; +using Microsoft.Azure.Functions.Worker.Tests.Converters; +using System; +using System.Collections.Generic; +using System.Text.Json; +using System.Threading.Tasks; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Tests +{ + public class ServiceBusSessionMessageConverterTests + { + internal sealed class TestBindingContext : BindingContext + { + public TestBindingContext(IReadOnlyDictionary input) + { + BindingData = input; + } + + public override IReadOnlyDictionary BindingData { get; } + } + + internal sealed class TestFunctionContext : FunctionContext + { + public TestFunctionContext(BindingContext bindingContext) + { + BindingContext = bindingContext; + } + + public override BindingContext BindingContext { get; } + + public override string InvocationId => throw new NotImplementedException(); + + public override string FunctionId => throw new NotImplementedException(); + + public override TraceContext TraceContext => throw new NotImplementedException(); + + public override RetryContext RetryContext => throw new NotImplementedException(); + + public override IServiceProvider InstanceServices { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public override FunctionDefinition FunctionDefinition => throw new NotImplementedException(); + + public override IDictionary Items { get => throw new NotImplementedException(); set => throw new NotImplementedException(); } + + public override IInvocationFeatures Features => throw new NotImplementedException(); + } + + [Fact] + public async Task ConvertAsync_ReturnsSuccess() + { + var data = "{\"SessionLockedUntil\":\"2024-12-05T21:10:36.1193094+00:00\"}"; + + var bindingDataDictionary = new Dictionary + { + { "SessionId", "test" }, + { "SessionActions", JsonSerializer.Serialize(new + { + SessionLockedUntil = "2024-12-05T21:10:36.1193094+00:00" + }) + } + }; + var context = new TestConverterContext(typeof(ServiceBusSessionMessageActions), data, new TestFunctionContext(new TestBindingContext(bindingDataDictionary))); + var converter = new ServiceBusSessionMessageActionsConverter(new MockSettlementClient("test")); + var result = await converter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, result.Status); + var output = result.Value as ServiceBusSessionMessageActions; + Assert.NotNull(output); + } + + [Fact] + public async Task ConvertAsync_Batch_ForReceivedMessage_ReturnsSuccess() + { + var data = "{\"SessionLockedUntil\":\"2024-12-05T21:10:36.1193094+00:00\"}"; + + IList repeatedField = new List { "test" }; + + var bindingDataDictionary = new Dictionary + { + { "SessionIdArray", repeatedField }, + { "SessionActions", JsonSerializer.Serialize(new + { + SessionLockedUntil = "2024-12-05T21:10:36.1193094+00:00" + }) + } + }; + var context = new TestConverterContext(typeof(ServiceBusSessionMessageActions), data, new TestFunctionContext(new TestBindingContext(bindingDataDictionary))); + var converter = new ServiceBusSessionMessageActionsConverter(new MockSettlementClient("test")); + var result = await converter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, result.Status); + var output = result.Value as ServiceBusSessionMessageActions; + Assert.NotNull(output); + } + + [Fact] + public async Task ConvertAsync_ReturnsFailure_NoSessionId() + { + var data = "{\"SessionLockedUntil\":\"2024-12-05T21:10:36.1193094+00:00\"}"; + + var bindingDataDictionary = new Dictionary + { + { "SessionActions", JsonSerializer.Serialize(new + { + SessionLockedUntil = "2024-12-05T21:10:36.1193094+00:00" + }) + } + }; + var context = new TestConverterContext(typeof(ServiceBusSessionMessageActions), data, new TestFunctionContext(new TestBindingContext(bindingDataDictionary))); + var converter = new ServiceBusSessionMessageActionsConverter(new MockSettlementClient("test")); + var result = await converter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Failed, result.Status); + } + } +} From 119843320cb0899ad9f96870dbb0ae264ecb2d7d Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Wed, 18 Dec 2024 14:32:04 -0800 Subject: [PATCH 077/190] Update EventGrid extension (#2906) --- extensions/Worker.Extensions.EventGrid/release_notes.md | 4 ++-- .../src/Worker.Extensions.EventGrid.csproj | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index 5adb0df77..ab2c2bb8a 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.4.2 +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.4.3 -- Updated `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.4.2 +- Updated `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.4.3 diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index 635fdf976..1636fe77b 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -6,7 +6,7 @@ Azure Event Grid extensions for .NET isolated functions - 3.4.2 + 3.4.3 false @@ -17,14 +17,14 @@ - + - + \ No newline at end of file From 2bbc2b98d18ebf16ce129d41dafb1ffada1ea2ec Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Mon, 30 Dec 2024 12:05:36 -0800 Subject: [PATCH 078/190] Reset release notes (#2907) --- extensions/Worker.Extensions.EventGrid/release_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index ab2c2bb8a..9e82bcaf3 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.4.3 +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid -- Updated `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.4.3 +- From 095fd097724bb6609675c07a2ad3b63416514b21 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Wed, 8 Jan 2025 11:44:48 -0800 Subject: [PATCH 079/190] Update FromBody converter to utilize DeserializeAsync (#2901) --- .../Worker.Extensions.Http/release_notes.md | 2 +- .../src/DefaultFromBodyConversionFeature.cs | 52 ++++++------------- 2 files changed, 17 insertions(+), 37 deletions(-) diff --git a/extensions/Worker.Extensions.Http/release_notes.md b/extensions/Worker.Extensions.Http/release_notes.md index 8f2985eb5..f1bef606f 100644 --- a/extensions/Worker.Extensions.Http/release_notes.md +++ b/extensions/Worker.Extensions.Http/release_notes.md @@ -6,4 +6,4 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http -- +- The 'FromBody' converter now utilizes `DeserializeAsync` for deserializing JSON content from the request body, enhancing support for asynchronous deserialization. (#2901) diff --git a/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs b/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs index c98d1950a..767832406 100644 --- a/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs +++ b/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System; +using System.IO; using System.Linq; using System.Net.Http.Headers; using System.Threading; @@ -46,44 +47,23 @@ internal class DefaultFromBodyConversionFeature : IFromBodyConversionFeature return ConvertBodyAsync(requestData, context, targetType); } - private static ValueTask ConvertBodyAsync(HttpRequestData requestData, FunctionContext context, Type targetType) + private static async ValueTask ConvertBodyAsync(HttpRequestData requestData, FunctionContext context, Type targetType) => targetType switch { - object? result; - - if (targetType == typeof(string)) - { - result = requestData.ReadAsString(); - } - else if (targetType == typeof(byte[])) - { - result = ReadBytes(requestData, context.CancellationToken); - } - else if (targetType == typeof(Memory)) - { - Memory bytes = ReadBytes(requestData, context.CancellationToken); - result = bytes; - } - else if (HasJsonContentType(requestData)) - { - ObjectSerializer serializer = requestData.FunctionContext.InstanceServices.GetService>()?.Value?.Serializer - ?? throw new InvalidOperationException("A serializer is not configured for the worker."); - - result = serializer.Deserialize(requestData.Body, targetType, context.CancellationToken); - } - else - { - throw new InvalidOperationException($"The type '{targetType}' is not supported by the '{nameof(DefaultFromBodyConversionFeature)}'."); - } - - return new ValueTask(result); - } - - private static byte[] ReadBytes(HttpRequestData requestData, CancellationToken cancellationToken) + _ when targetType == typeof(string) => await requestData.ReadAsStringAsync(), + _ when targetType == typeof(byte[]) => await ReadBytesAsync(requestData), + _ when targetType == typeof(Memory) => new Memory(await ReadBytesAsync(requestData)), + _ when HasJsonContentType(requestData) => + await (requestData.FunctionContext.InstanceServices.GetService>()?.Value?.Serializer + ?? throw new InvalidOperationException("A serializer is not configured for the worker.")) + .DeserializeAsync(requestData.Body, targetType, context.CancellationToken), + _ => throw new InvalidOperationException($"The type '{targetType}' is not supported by the '{nameof(DefaultFromBodyConversionFeature)}'.") + }; + + private static async Task ReadBytesAsync(HttpRequestData requestData) { - var bytes = new byte[requestData.Body.Length]; - requestData.Body.Read(bytes, 0, bytes.Length); - - return bytes; + using var memoryStream = new MemoryStream(); + await requestData.Body.CopyToAsync(memoryStream); + return memoryStream.ToArray(); } private static bool HasJsonContentType(HttpRequestData request) From bf563c49c2f2ab20f6c2d5a56ae9915e87f2d2c6 Mon Sep 17 00:00:00 2001 From: James May Date: Tue, 12 Nov 2024 14:10:52 +1100 Subject: [PATCH 080/190] host.json: Ignore comments and trailing commas see https://github.com/Azure/azure-functions-host/issues/9583 --- .../src/AspNetMiddleware/FunctionsEndpointDataSource.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs index 4590f6336..51285d1f2 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs @@ -22,7 +22,9 @@ internal class FunctionsEndpointDataSource : EndpointDataSource private static readonly JsonSerializerOptions _jsonSerializerOptions = new() { - PropertyNameCaseInsensitive = true + AllowTrailingCommas = true, + PropertyNameCaseInsensitive = true, + ReadCommentHandling = JsonCommentHandling.Skip, }; From 8fbe8b350168e0e48afa854565c3c66d03326df5 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 23 Jan 2025 09:17:53 -0800 Subject: [PATCH 081/190] Update ContextReference & DefaultFromBodyConversionFeature to remove invocation cancellation token usage (#2894) --- .../jobs/run-integration-tests-windows.yml | 15 +++- .../release_notes.md | 2 +- .../src/Coordinator/ContextReference.cs | 34 +------- .../src/Coordinator/DefaultHttpCoordinator.cs | 4 +- .../Worker.Extensions.Http/release_notes.md | 1 + .../src/DefaultFromBodyConversionFeature.cs | 2 +- setup-e2e-tests.ps1 | 2 +- .../E2EApps/E2EApp/local.settings.json | 2 +- .../CancellationHttpFunctions.cs | 78 ++++++++++++++++++ .../E2EAspNetCoreApp/E2EAspNetCoreApp.csproj | 32 ++++++++ .../E2EApps/E2EAspNetCoreApp/NuGet.Config | 7 ++ .../E2EApps/E2EAspNetCoreApp/Program.cs | 9 +++ .../Properties/launchSettings.json | 9 +++ .../E2EApps/E2EAspNetCoreApp/host.json | 12 +++ .../E2EAspNetCoreApp/local.settings.json | 7 ++ .../AspNetCore/CancellationEndToEndTests.cs | 68 ++++++++++++++++ test/E2ETests/E2ETests/Constants.cs | 6 ++ .../E2ETests/Fixtures/FixtureHelpers.cs | 6 +- .../E2ETests/Fixtures/FunctionAppFixture.cs | 48 +++++++---- .../IgnoreOnNetFxTestRunTheory.cs | 22 ++++++ test/E2ETests/E2ETests/Helpers/HttpHelpers.cs | 9 ++- tools/devpack.ps1 | 79 +++++++++++-------- 22 files changed, 357 insertions(+), 97 deletions(-) create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/CancellationHttpFunctions.cs create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/NuGet.Config create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/Program.cs create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/Properties/launchSettings.json create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/host.json create mode 100644 test/E2ETests/E2EApps/E2EAspNetCoreApp/local.settings.json create mode 100644 test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs create mode 100644 test/E2ETests/E2ETests/Helpers/FactAttributes/IgnoreOnNetFxTestRunTheory.cs diff --git a/eng/ci/templates/jobs/run-integration-tests-windows.yml b/eng/ci/templates/jobs/run-integration-tests-windows.yml index 9da281200..5fa5edb43 100644 --- a/eng/ci/templates/jobs/run-integration-tests-windows.yml +++ b/eng/ci/templates/jobs/run-integration-tests-windows.yml @@ -44,7 +44,20 @@ jobs: displayName: 'Run E2E Tests' inputs: command: test - arguments: -v n --no-build -c Release + arguments: -v n --no-build -c Release --filter "FullyQualifiedName!~Microsoft.Azure.Functions.Worker.E2ETests.AspNetCore" # skip AspNetCore tests projects: | **\E2ETests.csproj **\SdkE2ETests.csproj + env: + DOTNET_VERSION: $(dotnetVersion) + + - task: DotNetCoreCLI@2 + displayName: 'Run E2E AspNetCore Tests' + condition: ne(variables['dotnetVersion'], 'netfx') # Skip if dotnetVersion is netfx + inputs: + command: test + arguments: -v n --no-build -c Release --filter "FullyQualifiedName~Microsoft.Azure.Functions.Worker.E2ETests.AspNetCore" # only AspNetCore tests + projects: | + **\E2ETests.csproj + env: + DOTNET_VERSION: $(dotnetVersion) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index 97bb2a3ba..f56e86df4 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -6,7 +6,7 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore -- +- Update `ContextReference` to no longer use a given invocation's cancellation token (#2894) ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/ContextReference.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/ContextReference.cs index ddaac3487..9dcd8b026 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/ContextReference.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/ContextReference.cs @@ -8,7 +8,7 @@ namespace Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore { - internal class ContextReference : IDisposable + internal class ContextReference { private readonly TaskCompletionSource _functionStartTask = new(); private readonly TaskCompletionSource _functionCompletionTask = new(); @@ -16,9 +16,6 @@ internal class ContextReference : IDisposable private TaskCompletionSource _httpContextValueSource = new(); private TaskCompletionSource _functionContextValueSource = new(); - private CancellationToken _token; - private CancellationTokenRegistration _tokenRegistration; - public ContextReference(string invocationId) { InvocationId = invocationId; @@ -32,18 +29,6 @@ public ContextReference(string invocationId) public TaskCompletionSource FunctionContextValueSource { get => _functionContextValueSource; set => _functionContextValueSource = value; } - internal void SetCancellationToken(CancellationToken token) - { - _token = token; - _tokenRegistration = _token.Register(() => - { - _functionStartTask.TrySetCanceled(); - _functionCompletionTask.TrySetCanceled(); - _functionContextValueSource.TrySetCanceled(); - _httpContextValueSource.TrySetCanceled(); - }); - } - internal Task InvokeFunctionAsync() { _functionStartTask.SetResult(true); @@ -59,27 +44,12 @@ internal void CompleteFunction() if (_httpContextValueSource.Task.IsCompleted) { - if (_httpContextValueSource.Task.IsCanceled || _token.IsCancellationRequested) - { - _functionCompletionTask.TrySetCanceled(); - } - else - { - _functionCompletionTask.TrySetResult(true); - } + _functionCompletionTask.TrySetResult(true); } else { // we should never reach here b/c the class that calls this needs httpContextValueSource to complete to reach this method } } - - public void Dispose() - { - if (_tokenRegistration != default) - { - _tokenRegistration.Dispose(); - } - } } } diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs index cbe542cdf..9f9a5d69b 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -44,7 +44,6 @@ public async Task SetHttpContextAsync(string invocationId, Http public async Task SetFunctionContextAsync(string invocationId, FunctionContext context) { var contextRef = _contextReferenceList.GetOrAdd(invocationId, static id => new ContextReference(id)); - contextRef.SetCancellationToken(context.CancellationToken); contextRef.FunctionContextValueSource.SetResult(context); _logger.FunctionContextSet(invocationId); @@ -85,7 +84,6 @@ public void CompleteFunctionInvocation(string invocationId) if (_contextReferenceList.TryRemove(invocationId, out var contextRef)) { contextRef.CompleteFunction(); - contextRef.Dispose(); } else { diff --git a/extensions/Worker.Extensions.Http/release_notes.md b/extensions/Worker.Extensions.Http/release_notes.md index f1bef606f..e1fc96c72 100644 --- a/extensions/Worker.Extensions.Http/release_notes.md +++ b/extensions/Worker.Extensions.Http/release_notes.md @@ -7,3 +7,4 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http - The 'FromBody' converter now utilizes `DeserializeAsync` for deserializing JSON content from the request body, enhancing support for asynchronous deserialization. (#2901) +- Update `DefaultFromBodyConversionFeature` to no longer use a given invocation's cancellation token (#2894) diff --git a/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs b/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs index 767832406..fbe9c95ba 100644 --- a/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs +++ b/extensions/Worker.Extensions.Http/src/DefaultFromBodyConversionFeature.cs @@ -55,7 +55,7 @@ internal class DefaultFromBodyConversionFeature : IFromBodyConversionFeature _ when HasJsonContentType(requestData) => await (requestData.FunctionContext.InstanceServices.GetService>()?.Value?.Serializer ?? throw new InvalidOperationException("A serializer is not configured for the worker.")) - .DeserializeAsync(requestData.Body, targetType, context.CancellationToken), + .DeserializeAsync(requestData.Body, targetType, CancellationToken.None), _ => throw new InvalidOperationException($"The type '{targetType}' is not supported by the '{nameof(DefaultFromBodyConversionFeature)}'.") }; diff --git a/setup-e2e-tests.ps1 b/setup-e2e-tests.ps1 index c781be695..62f2d9925 100644 --- a/setup-e2e-tests.ps1 +++ b/setup-e2e-tests.ps1 @@ -113,7 +113,7 @@ if ($SkipBuildOnPack -eq $true) $AdditionalPackArgs += "--no-build" } -.\tools\devpack.ps1 -E2E -AdditionalPackArgs $AdditionalPackArgs +.\tools\devpack.ps1 -DotnetVersion $DotnetVersion -E2E -AdditionalPackArgs $AdditionalPackArgs if ($SkipStorageEmulator -And $SkipCosmosDBEmulator) { diff --git a/test/E2ETests/E2EApps/E2EApp/local.settings.json b/test/E2ETests/E2EApps/E2EApp/local.settings.json index 3b70ea809..c7812bf34 100644 --- a/test/E2ETests/E2EApps/E2EApp/local.settings.json +++ b/test/E2ETests/E2EApps/E2EApp/local.settings.json @@ -1,5 +1,5 @@ { - "IsEncrypted": false, + "IsEncrypted": false, "Values": { "AzureWebJobsStorage": "UseDevelopmentStorage=true", "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated", diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/CancellationHttpFunctions.cs b/test/E2ETests/E2EApps/E2EAspNetCoreApp/CancellationHttpFunctions.cs new file mode 100644 index 000000000..bf96dd01d --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/CancellationHttpFunctions.cs @@ -0,0 +1,78 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using System; + +namespace Microsoft.Azure.Functions.Worker.E2EApp +{ + public class CancellationHttpFunctions(ILogger logger) + { + private readonly ILogger _logger = logger; + + [Function(nameof(HttpWithCancellationTokenNotUsed))] + public async Task HttpWithCancellationTokenNotUsed( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req) + { + _logger.LogInformation("HttpWithCancellationTokenNotUsed processed a request."); + + await SimulateWork(CancellationToken.None); + + return new OkObjectResult("Processing completed successfully."); + } + + [Function(nameof(HttpWithCancellationTokenIgnored))] + public async Task HttpWithCancellationTokenIgnored( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequest req, + CancellationToken cancellationToken) + { + _logger.LogInformation("HttpWithCancellationTokenIgnored processed a request."); + + await SimulateWork(cancellationToken); + + return new OkObjectResult("Processing completed successfully."); + } + + [Function(nameof(HttpWithCancellationTokenHandled))] + public async Task HttpWithCancellationTokenHandled( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, + CancellationToken cancellationToken) + { + _logger.LogInformation("HttpWithCancellationTokenHandled processed a request."); + + try + { + await SimulateWork(cancellationToken); + + return new OkObjectResult("Processing completed successfully."); + } + catch (OperationCanceledException) + { + _logger.LogWarning("Request was cancelled."); + + // Take precautions like noting how far along you are with processing the batch + await Task.Delay(1000); + + return new ObjectResult(new { statusCode = StatusCodes.Status499ClientClosedRequest, message = "Request was cancelled." }); + } + } + + private async Task SimulateWork(CancellationToken cancellationToken) + { + _logger.LogInformation("Starting work..."); + + for (int i = 0; i < 5; i++) + { + // Simulate work + await Task.Delay(1000, cancellationToken); + _logger.LogWarning($"Work iteration {i + 1} completed."); + } + + _logger.LogInformation("Work completed."); + } + } +} diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj b/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj new file mode 100644 index 000000000..50a93a04f --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj @@ -0,0 +1,32 @@ + + + net8.0 + v4 + Exe + enable + enable + Microsoft.Azure.Functions.Worker.E2EAspNetCoreApp + Microsoft.Azure.Functions.Worker.E2EAspNetCoreApp + + + + + + + + + + PreserveNewest + + + PreserveNewest + Never + + + + + + + + + \ No newline at end of file diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/NuGet.Config b/test/E2ETests/E2EApps/E2EAspNetCoreApp/NuGet.Config new file mode 100644 index 000000000..2a9de739f --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/NuGet.Config @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/Program.cs b/test/E2ETests/E2EApps/E2EAspNetCoreApp/Program.cs new file mode 100644 index 000000000..e8cfbc5ba --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/Program.cs @@ -0,0 +1,9 @@ +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.DependencyInjection; + +var host = new HostBuilder() + .ConfigureFunctionsWebApplication() + .Build(); + +host.Run(); diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/Properties/launchSettings.json b/test/E2ETests/E2EApps/E2EAspNetCoreApp/Properties/launchSettings.json new file mode 100644 index 000000000..0c6540c91 --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "dni_net8_cancellation": { + "commandName": "Project", + "commandLineArgs": "--port 7097", + "launchBrowser": false + } + } +} \ No newline at end of file diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/host.json b/test/E2ETests/E2EApps/E2EAspNetCoreApp/host.json new file mode 100644 index 000000000..ee5cf5f83 --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/host.json @@ -0,0 +1,12 @@ +{ + "version": "2.0", + "logging": { + "applicationInsights": { + "samplingSettings": { + "isEnabled": true, + "excludedTypes": "Request" + }, + "enableLiveMetricsFilters": true + } + } +} \ No newline at end of file diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/local.settings.json b/test/E2ETests/E2EApps/E2EAspNetCoreApp/local.settings.json new file mode 100644 index 000000000..aa72b19ab --- /dev/null +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/local.settings.json @@ -0,0 +1,7 @@ +{ + "IsEncrypted": false, + "Values": { + "AzureWebJobsStorage": "UseDevelopmentStorage=true", + "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated" + } +} \ No newline at end of file diff --git a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs new file mode 100644 index 000000000..2a372f16b --- /dev/null +++ b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs @@ -0,0 +1,68 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Tests; +using Microsoft.Azure.Functions.Tests.E2ETests; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Azure.Functions.Worker.E2ETests.AspNetCore +{ + public class CancellationEndToEndTests : IClassFixture + { + private readonly TestFixture _fixture; + + public CancellationEndToEndTests(TestFixture fixture, ITestOutputHelper testOutputHelper) + { + _fixture = fixture; + _fixture.TestLogs.UseTestLogger(testOutputHelper); + } + + [IgnoreOnNetFxTestRunTheory] + [InlineData("HttpWithCancellationTokenNotUsed", "Work completed.", "Succeeded")] + [InlineData("HttpWithCancellationTokenIgnored", "TaskCanceledException: A task was canceled", "Failed")] + [InlineData("HttpWithCancellationTokenHandled", "Request was cancelled.", "Succeeded")] + public async Task HttpTriggerFunctions_WithCancellationToken_BehaveAsExpected(string functionName, string expectedMessage, string invocationResult) + { + using var cts = new CancellationTokenSource(); + var task = HttpHelpers.InvokeHttpTrigger(functionName, cancellationToken: cts.Token); + + // Make sure the function invocation started before we cancel + IEnumerable invocationStartLog = null; + await TestUtility.RetryAsync(() => + { + invocationStartLog = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains($"Executing 'Functions.{functionName}'")); + return Task.FromResult(invocationStartLog.Count() >= 1); + }); + + // The task should be cancelled before it completes, mimicing a client closing the connection. + // This should lead to the worker getting an InvocationCancel request from the functions host + cts.Cancel(); + await Assert.ThrowsAsync(async () => await task); + + IEnumerable invocationEndLog = null; + await TestUtility.RetryAsync(() => + { + invocationEndLog = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains($"Executed 'Functions.{functionName}'")); + return Task.FromResult(invocationEndLog.Count() >= 1); + }); + + Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains(expectedMessage, StringComparison.OrdinalIgnoreCase)); + + // TODO: 2/3 of the test invocations will fail until the host with the ForwarderProxy fix is released - uncomment this line when the fix is released + // Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains($"'Functions.{functionName}' ({invocationResult}", StringComparison.OrdinalIgnoreCase)); + } + + public class TestFixture : FunctionAppFixture + { + public TestFixture(IMessageSink messageSink) : base(messageSink, Constants.TestAppNames.E2EAspNetCoreApp) + { + } + } + } +} diff --git a/test/E2ETests/E2ETests/Constants.cs b/test/E2ETests/E2ETests/Constants.cs index 97cf15589..e8d554ab4 100644 --- a/test/E2ETests/E2ETests/Constants.cs +++ b/test/E2ETests/E2ETests/Constants.cs @@ -98,5 +98,11 @@ public static class Tables public const string TablesConnectionStringSetting = EmulatorConnectionString; public const string TableName = "TestTable"; } + + public static class TestAppNames + { + public const string E2EApp = "E2EApp"; + public const string E2EAspNetCoreApp = "E2EAspNetCoreApp"; + } } } diff --git a/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs b/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs index 68c126f99..4fdce8194 100644 --- a/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs +++ b/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs @@ -13,11 +13,11 @@ namespace Microsoft.Azure.Functions.Tests.E2ETests { public static class FixtureHelpers { - public static Process GetFuncHostProcess(bool enableAuth = false) + public static Process GetFuncHostProcess(bool enableAuth = false, string testAppName = null) { var funcProcess = new Process(); var rootDir = Path.GetFullPath(@"../../../../../.."); - var e2eAppBinPath = Path.Combine(rootDir, @"test/E2ETests/E2EApps/E2EApp/bin"); + var e2eAppBinPath = Path.Combine(rootDir, "test", "E2ETests", "E2EApps", testAppName, "bin"); string e2eHostJson = Directory.GetFiles(e2eAppBinPath, "host.json", SearchOption.AllDirectories).FirstOrDefault(); if (e2eHostJson == null) @@ -27,7 +27,7 @@ public static Process GetFuncHostProcess(bool enableAuth = false) var e2eAppPath = Path.GetDirectoryName(e2eHostJson); - var cliPath = Path.Combine(rootDir, @"Azure.Functions.Cli/func"); + var cliPath = Path.Combine(rootDir, "Azure.Functions.Cli", "func"); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { diff --git a/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs b/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs index 6674d0cad..2eedeb61f 100644 --- a/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs +++ b/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs @@ -1,6 +1,7 @@ // 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.Diagnostics; using System.IO; using System.Net.Http; @@ -19,18 +20,23 @@ public class FunctionAppFixture : IAsyncLifetime private readonly ILogger _logger; private bool _disposed; private Process _funcProcess; - private JobObjectRegistry _jobObjectRegistry; + private string _testApp = Constants.TestAppNames.E2EApp; public FunctionAppFixture(IMessageSink messageSink) { - // initialize logging + // initialize logging ILoggerFactory loggerFactory = new LoggerFactory(); TestLogs = new TestLoggerProvider(messageSink); loggerFactory.AddProvider(TestLogs); _logger = loggerFactory.CreateLogger(); } + internal FunctionAppFixture(IMessageSink messageSink, string testApp) : this(messageSink) + { + _testApp = testApp; + } + public async Task InitializeAsync() { // start host via CLI if testing locally @@ -42,7 +48,7 @@ public async Task InitializeAsync() // start functions process _logger.LogInformation($"Starting functions host for {Constants.FunctionAppCollectionName}..."); - _funcProcess = FixtureHelpers.GetFuncHostProcess(); + _funcProcess = FixtureHelpers.GetFuncHostProcess(testAppName: _testApp); string workingDir = _funcProcess.StartInfo.WorkingDirectory; _logger.LogInformation($" Working dir: '${workingDir}' Exists: '{Directory.Exists(workingDir)}'"); string fileName = _funcProcess.StartInfo.FileName; @@ -51,18 +57,29 @@ public async Task InitializeAsync() if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { // Currently only HTTP is supported in Linux CI. - _funcProcess.StartInfo.ArgumentList.Add("--functions"); - _funcProcess.StartInfo.ArgumentList.Add("HelloFromQuery"); - _funcProcess.StartInfo.ArgumentList.Add("HelloFromJsonBody"); - _funcProcess.StartInfo.ArgumentList.Add("HelloUsingPoco"); - _funcProcess.StartInfo.ArgumentList.Add("HelloWithNoResponse"); - _funcProcess.StartInfo.ArgumentList.Add("PocoFromBody"); - _funcProcess.StartInfo.ArgumentList.Add("PocoBeforeRouteParameters"); - _funcProcess.StartInfo.ArgumentList.Add("PocoAfterRouteParameters"); - _funcProcess.StartInfo.ArgumentList.Add("ExceptionFunction"); - _funcProcess.StartInfo.ArgumentList.Add("PocoWithoutBindingSource"); - _funcProcess.StartInfo.ArgumentList.Add("HelloPascal"); - _funcProcess.StartInfo.ArgumentList.Add("HelloAllCaps"); + switch (_testApp) + { + case Constants.TestAppNames.E2EApp: + _funcProcess.StartInfo.ArgumentList.Add("--functions"); + _funcProcess.StartInfo.ArgumentList.Add("HelloFromQuery"); + _funcProcess.StartInfo.ArgumentList.Add("HelloFromJsonBody"); + _funcProcess.StartInfo.ArgumentList.Add("HelloUsingPoco"); + _funcProcess.StartInfo.ArgumentList.Add("HelloWithNoResponse"); + _funcProcess.StartInfo.ArgumentList.Add("PocoFromBody"); + _funcProcess.StartInfo.ArgumentList.Add("PocoBeforeRouteParameters"); + _funcProcess.StartInfo.ArgumentList.Add("PocoAfterRouteParameters"); + _funcProcess.StartInfo.ArgumentList.Add("ExceptionFunction"); + _funcProcess.StartInfo.ArgumentList.Add("PocoWithoutBindingSource"); + _funcProcess.StartInfo.ArgumentList.Add("HelloPascal"); + _funcProcess.StartInfo.ArgumentList.Add("HelloAllCaps"); + break; + case Constants.TestAppNames.E2EAspNetCoreApp: + _funcProcess.StartInfo.ArgumentList.Add("--functions"); + _funcProcess.StartInfo.ArgumentList.Add("HttpWithCancellationTokenNotUsed"); + _funcProcess.StartInfo.ArgumentList.Add("HttpWithCancellationTokenIgnored"); + _funcProcess.StartInfo.ArgumentList.Add("HttpWithCancellationTokenHandled"); + break; + } } await CosmosDBHelpers.TryCreateDocumentCollectionsAsync(_logger); @@ -114,7 +131,6 @@ await TestUtility.RetryAsync(async () => internal TestLoggerProvider TestLogs { get; private set; } - public Task DisposeAsync() { if (!_disposed) diff --git a/test/E2ETests/E2ETests/Helpers/FactAttributes/IgnoreOnNetFxTestRunTheory.cs b/test/E2ETests/E2ETests/Helpers/FactAttributes/IgnoreOnNetFxTestRunTheory.cs new file mode 100644 index 000000000..b9e1adf48 --- /dev/null +++ b/test/E2ETests/E2ETests/Helpers/FactAttributes/IgnoreOnNetFxTestRunTheory.cs @@ -0,0 +1,22 @@ +// 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 Xunit; + +namespace Microsoft.Azure.Functions.Tests.E2ETests +{ + public sealed class IgnoreOnNetFxTestRunTheory : TheoryAttribute + { + public IgnoreOnNetFxTestRunTheory() + { + if (IsNetFxTestRun()) + { + Skip = "Ignore when test run is using netFx as AspNetCore is not supported."; + } + } + + private static bool IsNetFxTestRun() + => string.Equals(Environment.GetEnvironmentVariable("DOTNET_VERSION"), "netfx", StringComparison.OrdinalIgnoreCase); + } +} \ No newline at end of file diff --git a/test/E2ETests/E2ETests/Helpers/HttpHelpers.cs b/test/E2ETests/E2ETests/Helpers/HttpHelpers.cs index d5f788498..e44fbce98 100644 --- a/test/E2ETests/E2ETests/Helpers/HttpHelpers.cs +++ b/test/E2ETests/E2ETests/Helpers/HttpHelpers.cs @@ -5,18 +5,19 @@ using System.Net; using System.Net.Http; using System.Net.Http.Headers; +using System.Threading; using System.Threading.Tasks; namespace Microsoft.Azure.Functions.Tests.E2ETests { class HttpHelpers { - public static async Task InvokeHttpTrigger(string functionName, string queryString = "") + public static async Task InvokeHttpTrigger(string functionName, string queryString = "", CancellationToken cancellationToken = default) { // Basic http request HttpRequestMessage request = GetTestRequest(functionName, queryString); request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("text/plain")); - return await GetResponseMessage(request); + return await GetResponseMessage(request, cancellationToken); } public static async Task InvokeHttpTriggerWithBody(string functionName, string body, string mediaType) @@ -64,12 +65,12 @@ private static HttpRequestMessage GetTestRequest(string functionName, string que }; } - private static async Task GetResponseMessage(HttpRequestMessage request) + private static async Task GetResponseMessage(HttpRequestMessage request, CancellationToken cancellationToken = default) { HttpResponseMessage response = null; using (var httpClient = new HttpClient()) { - response = await httpClient.SendAsync(request); + response = await httpClient.SendAsync(request, cancellationToken); } return response; diff --git a/tools/devpack.ps1 b/tools/devpack.ps1 index 0167e24e7..c462b266c 100644 --- a/tools/devpack.ps1 +++ b/tools/devpack.ps1 @@ -1,4 +1,8 @@ param( + [Parameter(Mandatory=$false)] + [String] + [ValidateSet("net8", "netfx")] + $DotnetVersion, [Parameter(Mandatory=$false)] [Switch] $E2E, @@ -19,17 +23,22 @@ Write-Host Write-Host "Building packages with BuildNumber $buildNumber" $rootPath = Split-Path -Parent $PSScriptRoot -$project = "$rootPath/samples/FunctionApp/FunctionApp.csproj" +$projects = @("$rootPath/samples/FunctionApp/FunctionApp.csproj") $sdkProject = "$rootPath/build/DotNetWorker.Core.slnf" if($E2E -eq $true) { - $project = "$rootPath/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj" + # Only add E2EAspNetCoreApp if DotnetVersion is not netfx + if ($DotnetVersion -ne "netfx") { + $projects += "$rootPath/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj" + } + # Always add E2EApp project for E2E tests + $projects += "$rootPath/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj" } if ($SkipBuildOnPack -eq $true) { - $AdditionalPackArgs +="--no-build"; + $AdditionalPackArgs += "--no-build" } $localPack = "$rootPath/local" @@ -38,42 +47,44 @@ if (!(Test-Path $localPack)) New-Item -Path $localPack -ItemType directory | Out-Null } Write-Host -Write-Host "---Updating project with local SDK pack---" +Write-Host "---Updating projects with local SDK pack---" Write-Host "Packing Core .NET Worker projects to $localPack" -& "dotnet" "pack" $sdkProject "-p:PackageOutputPath=$localPack" "-nologo" "-p:BuildNumber=$buildNumber" $AdditionalPackArgs +& "dotnet" "pack" $sdkProject "-p:PackageOutputPath=$localPack" "-nologo" "-p:Version=2.0.1" "-p:VersionSuffix=$buildNumber" $AdditionalPackArgs Write-Host -Write-Host "Removing SDK package reference in $project" -& "dotnet" "remove" $project "package" "Microsoft.Azure.Functions.Worker.Sdk" -Write-Host +foreach ($project in $projects) { + Write-Host "Removing SDK package reference in $project" + & "dotnet" "remove" $project "package" "Microsoft.Azure.Functions.Worker.Sdk" + Write-Host -Write-Host "Removing Worker package reference in $project" -& "dotnet" "remove" $project "package" "Microsoft.Azure.Functions.Worker" -Write-Host + Write-Host "Removing Worker package reference in $project" + & "dotnet" "remove" $project "package" "Microsoft.Azure.Functions.Worker" + Write-Host -Write-Host "Finding latest local Worker package in $localPack" -$package = Find-Package Microsoft.Azure.Functions.Worker -Source $localPack -$version = $package.Version -Write-Host "Found $version" -Write-Host + Write-Host "Finding latest local Worker package in $localPack" + $package = Find-Package Microsoft.Azure.Functions.Worker -Source $localPack + $version = $package.Version + Write-Host "Found $version" + Write-Host -Write-Host "Adding Worker package version $version to $project" -& "dotnet" "add" $project "package" "Microsoft.Azure.Functions.Worker" "-v" $version "-s" $localPack "-n" -Write-Host + Write-Host "Adding Worker package version $version to $project" + & "dotnet" "add" $project "package" "Microsoft.Azure.Functions.Worker" "-v" $version "-s" $localPack "-n" + Write-Host -Write-Host "Finding latest local SDK package in $localPack" -$package = Find-Package "Microsoft.Azure.Functions.Worker.Sdk" -Source $localPack -$version = $package.Version -Write-Host "Found $version" -Write-Host -Write-Host "Adding SDK package version $version to $project" -& "dotnet" "add" $project "package" "Microsoft.Azure.Functions.Worker.Sdk" "-v" $version "-s" $localPack "-n" -Write-Host -$configFile = Split-Path "$project" -$configFile += "/NuGet.Config" -Write-Host "Config file name" $configFile -& "dotnet" "nuget" "add" "source" $localPack "--name" "local" "--configfile" "$configFile" -Write-Host "Building $project" + Write-Host "Finding latest local SDK package in $localPack" + $package = Find-Package "Microsoft.Azure.Functions.Worker.Sdk" -Source $localPack + $version = $package.Version + Write-Host "Found $version" + Write-Host + Write-Host "Adding SDK package version $version to $project" + & "dotnet" "add" $project "package" "Microsoft.Azure.Functions.Worker.Sdk" "-v" $version "-s" $localPack "-n" + Write-Host + $configFile = Split-Path "$project" + $configFile += "/NuGet.Config" + Write-Host "Config file name" $configFile + & "dotnet" "nuget" "add" "source" $localPack "--name" "local" "--configfile" "$configFile" + Write-Host "Building $project" -& "dotnet" "build" $project "-nologo" "-p:TestBuild=true" -Write-Host "------" + & "dotnet" "build" $project "-nologo" "-p:TestBuild=true" + Write-Host "------" +} From 47c63550a15553907040e84d56dd5440d587a203 Mon Sep 17 00:00:00 2001 From: Aishwarya Bhandari <37918412+aishwaryabh@users.noreply.github.com> Date: Fri, 24 Jan 2025 10:27:27 -0800 Subject: [PATCH 082/190] Updating service bus patch version (#2930) * updating service bus minor version * Update extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj Co-authored-by: Jacob Viau --------- Co-authored-by: Jacob Viau --- .../src/Worker.Extensions.ServiceBus.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj index 17878a447..d112f2334 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj +++ b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj @@ -6,7 +6,7 @@ Azure Service Bus extensions for .NET isolated functions - 5.22.0 + 5.22.1 false From d4dab47276d8116c2586fc205c5afbd25f986463 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Mon, 27 Jan 2025 12:32:31 -0800 Subject: [PATCH 083/190] Patch Http.AspNetCore extension package (#2936) * Patch http aspnetcore ext package * Update release note version --- extensions/Worker.Extensions.Http.AspNetCore/release_notes.md | 2 +- .../src/Worker.Extensions.Http.AspNetCore.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index f56e86df4..f0dc50065 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -4,7 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 2.0.1 - Update `ContextReference` to no longer use a given invocation's cancellation token (#2894) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index c88dded9b..ac2e612b0 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -6,7 +6,7 @@ ASP.NET Core extensions for .NET isolated functions - 2.0.0 + 2.0.1 net6.0;net8.0 From 97a0783dd6c610145142f6d29f2c16755f8f5856 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Tue, 28 Jan 2025 12:47:34 -0800 Subject: [PATCH 084/190] Bump http extension for release (#2940) --- extensions/Worker.Extensions.Http/release_notes.md | 2 +- .../Worker.Extensions.Http/src/Worker.Extensions.Http.csproj | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.Http/release_notes.md b/extensions/Worker.Extensions.Http/release_notes.md index e1fc96c72..5debe8123 100644 --- a/extensions/Worker.Extensions.Http/release_notes.md +++ b/extensions/Worker.Extensions.Http/release_notes.md @@ -4,7 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Http +### Microsoft.Azure.Functions.Worker.Extensions.Http 3.3.0 - The 'FromBody' converter now utilizes `DeserializeAsync` for deserializing JSON content from the request body, enhancing support for asynchronous deserialization. (#2901) - Update `DefaultFromBodyConversionFeature` to no longer use a given invocation's cancellation token (#2894) diff --git a/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj b/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj index 28f75e8be..25f4cdb2c 100644 --- a/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj +++ b/extensions/Worker.Extensions.Http/src/Worker.Extensions.Http.csproj @@ -6,7 +6,7 @@ HTTP extensions for .NET isolated functions - 3.2.0 + 3.3.0 From 19acb76f74e75ca1efb84a512ef32dc525db7690 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Wed, 29 Jan 2025 16:33:37 -0800 Subject: [PATCH 085/190] Clear release notes for worker extensions (#2939) * Clear release notes for extensions * http --- extensions/Worker.Extensions.CosmosDB/release_notes.md | 5 ++--- extensions/Worker.Extensions.EventHubs/release_notes.md | 4 ++-- .../Worker.Extensions.Http.AspNetCore/release_notes.md | 4 ++-- extensions/Worker.Extensions.Http/release_notes.md | 3 +-- extensions/Worker.Extensions.Rpc/release_notes.md | 4 ++-- extensions/Worker.Extensions.ServiceBus/release_notes.md | 5 ++--- .../Worker.Extensions.SignalRService/release_notes.md | 4 ++-- extensions/Worker.Extensions.Storage/release_notes.md | 8 ++++---- extensions/Worker.Extensions.Tables/release_notes.md | 4 ++-- 9 files changed, 19 insertions(+), 22 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index 41b9b3e1f..1f7c96d5a 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.11.0 +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB -- Updated `Microsoft.Azure.WebJobs.Extensions.CosmosDB` reference to 4.8.0 -- Updated `Microsoft.Extensions.Azure` dependency to 1.7.5 +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.EventHubs/release_notes.md b/extensions/Worker.Extensions.EventHubs/release_notes.md index 3d9324175..3d6e918a8 100644 --- a/extensions/Worker.Extensions.EventHubs/release_notes.md +++ b/extensions/Worker.Extensions.EventHubs/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.3.6 +### Microsoft.Azure.Functions.Worker.Extensions.EventHubs -- Updated `Microsoft.Extensions.Azure` reference to 1.7.5 +- diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index f0dc50065..97bb2a3ba 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -4,9 +4,9 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 2.0.1 +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore -- Update `ContextReference` to no longer use a given invocation's cancellation token (#2894) +- ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers diff --git a/extensions/Worker.Extensions.Http/release_notes.md b/extensions/Worker.Extensions.Http/release_notes.md index 5debe8123..634fa5eb2 100644 --- a/extensions/Worker.Extensions.Http/release_notes.md +++ b/extensions/Worker.Extensions.Http/release_notes.md @@ -6,5 +6,4 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http 3.3.0 -- The 'FromBody' converter now utilizes `DeserializeAsync` for deserializing JSON content from the request body, enhancing support for asynchronous deserialization. (#2901) -- Update `DefaultFromBodyConversionFeature` to no longer use a given invocation's cancellation token (#2894) +- diff --git a/extensions/Worker.Extensions.Rpc/release_notes.md b/extensions/Worker.Extensions.Rpc/release_notes.md index 45f46f3e9..3fe81032f 100644 --- a/extensions/Worker.Extensions.Rpc/release_notes.md +++ b/extensions/Worker.Extensions.Rpc/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Rpc 1.0.1 +### Microsoft.Azure.Functions.Worker.Extensions.Rpc -- Set max message send and receive length on gRPC `CallInvoker`. +- diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index 5b169b47d..c92b7d33c 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.22.0 +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus -- Updated `Azure.Identity` reference to 1.12.0 -- Updated `Microsoft.Extensions.Azure` to 1.7.5 \ No newline at end of file +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.SignalRService/release_notes.md b/extensions/Worker.Extensions.SignalRService/release_notes.md index 1f4444583..1b3fe21c2 100644 --- a/extensions/Worker.Extensions.SignalRService/release_notes.md +++ b/extensions/Worker.Extensions.SignalRService/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.SignalRService 1.15.0 +### Microsoft.Azure.Functions.Worker.Extensions.SignalRService -- Fix SignalR trigger return value not working issue. +- diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index e15e98a87..4ab632232 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,14 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.6.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage -- Updated `Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs` to 6.6.0 +- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.6.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs -- Updated `Microsoft.Extensions.Azure` dependency to 1.7.4 +- ### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues diff --git a/extensions/Worker.Extensions.Tables/release_notes.md b/extensions/Worker.Extensions.Tables/release_notes.md index 8350d5fc4..79200facf 100644 --- a/extensions/Worker.Extensions.Tables/release_notes.md +++ b/extensions/Worker.Extensions.Tables/release_notes.md @@ -4,7 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.4.2 +### Microsoft.Azure.Functions.Worker.Extensions.Tables -- Updated `Microsoft.Extensions.Azure` dependency to 1.7.5 +- From cc39fcf1d1aeb126d92bcc4aaeb8c2269d8c3139 Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Thu, 30 Jan 2025 12:29:44 -0600 Subject: [PATCH 086/190] CosmosDb webjobs extension update (#2944) --- extensions/Worker.Extensions.CosmosDB/release_notes.md | 4 ++-- .../src/Worker.Extensions.CosmosDB.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index 1f7c96d5a..f9b91fced 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.12.0 -- \ No newline at end of file +- Updated `Microsoft.Azure.WebJobs.Extensions.CosmosDB` reference to 4.9.0 diff --git a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj index 782383eba..b5cb4b712 100644 --- a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj +++ b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj @@ -6,7 +6,7 @@ Azure Cosmos DB extensions for .NET isolated functions - 4.11.0 + 4.12.0 false @@ -31,7 +31,7 @@ - + \ No newline at end of file From 9314bae3a5151ddd42a6af47816da3f5d2d2b30f Mon Sep 17 00:00:00 2001 From: Florian Lenz <33814851+florianlenz96@users.noreply.github.com> Date: Thu, 30 Jan 2025 22:33:10 +0100 Subject: [PATCH 087/190] Return null if cosmos db input can't find item (#2942) * Fix cosmos db 404 exception fix * Update release_notes.md * Update release_notes.md * Update release_notes.md * Update test/Worker.Extensions.Tests/Cosmos/CosmosDBConverterTests.cs Co-authored-by: Lilian Kasem * Update release_notes.md * add e2e tests * Update release_notes.md --------- Co-authored-by: Florian Lenz <33814851+FlonairLenz@users.noreply.github.com> Co-authored-by: Lilian Kasem --- .../release_notes.md | 1 + .../src/CosmosDBConverter.cs | 4 ++ .../E2EApps/E2EApp/Cosmos/CosmosFunction.cs | 5 +++ .../E2ETests/Cosmos/CosmosDBEndToEndTests.cs | 22 +++++++++++ .../Cosmos/CosmosDBConverterTests.cs | 37 +++++++++++++++++-- 5 files changed, 66 insertions(+), 3 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index f9b91fced..06e3c8aae 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -7,3 +7,4 @@ ### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.12.0 - Updated `Microsoft.Azure.WebJobs.Extensions.CosmosDB` reference to 4.9.0 +- Return a successful result with a null value when a Cosmos document cannot be found (#2942/#2545) diff --git a/extensions/Worker.Extensions.CosmosDB/src/CosmosDBConverter.cs b/extensions/Worker.Extensions.CosmosDB/src/CosmosDBConverter.cs index aeeb881d0..cc7274201 100644 --- a/extensions/Worker.Extensions.CosmosDB/src/CosmosDBConverter.cs +++ b/extensions/Worker.Extensions.CosmosDB/src/CosmosDBConverter.cs @@ -58,6 +58,10 @@ private async ValueTask ConvertFromBindingDataAsync(ConverterC return ConversionResult.Success(result); } + catch (CosmosException ex) when (ex.StatusCode == System.Net.HttpStatusCode.NotFound) + { + return ConversionResult.Success(null); + } catch (Exception ex) { return ConversionResult.Failed(ex); diff --git a/test/E2ETests/E2EApps/E2EApp/Cosmos/CosmosFunction.cs b/test/E2ETests/E2EApps/E2EApp/Cosmos/CosmosFunction.cs index 50038ed60..980a5f097 100644 --- a/test/E2ETests/E2EApps/E2EApp/Cosmos/CosmosFunction.cs +++ b/test/E2ETests/E2EApps/E2EApp/Cosmos/CosmosFunction.cs @@ -127,6 +127,11 @@ public async Task DocByIdFromRouteData( Id = "{id}", PartitionKey = "{partitionKey}")] MyDocument doc) { + if (doc == null) + { + return req.CreateResponse(HttpStatusCode.NotFound); + } + var response = req.CreateResponse(HttpStatusCode.OK); await response.WriteStringAsync(doc.Text); return response; diff --git a/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs b/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs index 84167b864..55e3e9482 100644 --- a/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs +++ b/test/E2ETests/E2ETests/Cosmos/CosmosDBEndToEndTests.cs @@ -105,6 +105,28 @@ public async Task CosmosInput_DocByIdFromRouteData_Succeeds() } } + [Fact] + public async Task CosmosInput_DocByIdFromRouteDataNotFound_Succeeds() + { + string expectedDocId = Guid.NewGuid().ToString(); + string functionPath = $"docsbyroute/{expectedDocId}/{expectedDocId}"; + try + { + //Trigger + HttpResponseMessage response = await HttpHelpers.InvokeHttpTrigger(functionPath); + + //Verify + HttpStatusCode expectedStatusCode = HttpStatusCode.NotFound; + + Assert.Equal(expectedStatusCode, response.StatusCode); + } + finally + { + //Clean up + await CosmosDBHelpers.DeleteTestDocuments(expectedDocId); + } + } + [Fact] public async Task CosmosInput_DocByIdFromRouteDataUsingSqlQuery_Succeeds() { diff --git a/test/Worker.Extensions.Tests/Cosmos/CosmosDBConverterTests.cs b/test/Worker.Extensions.Tests/Cosmos/CosmosDBConverterTests.cs index 42e11050b..593ad8ef9 100644 --- a/test/Worker.Extensions.Tests/Cosmos/CosmosDBConverterTests.cs +++ b/test/Worker.Extensions.Tests/Cosmos/CosmosDBConverterTests.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; @@ -359,14 +360,18 @@ public async Task ConvertAsync_CosmosContainerIsNull_ThrowsException_ReturnsFail Assert.Equal($"Unable to create Cosmos container client for 'myContainer'.", conversionResult.Error.Message); } - [Fact] - public async Task ConvertAsync_POCO_IdProvided_StatusNot200_ThrowsException_ReturnsFailure() + [Theory] + [InlineData(HttpStatusCode.Conflict)] + [InlineData(HttpStatusCode.Forbidden)] + [InlineData(HttpStatusCode.InternalServerError)] + [InlineData(HttpStatusCode.BadRequest)] + public async Task ConvertAsync_POCO_IdProvided_NotSuccessStatus_ThrowsException_ReturnsFailure(HttpStatusCode httpStatusCode) { object grpcModelBindingData = GrpcTestHelper.GetTestGrpcModelBindingData(GetTestBinaryData(id: "1", partitionKey: "1"), "CosmosDB"); var context = new TestConverterContext(typeof(ToDoItem), grpcModelBindingData); var mockResponse = new Mock(); - var cosmosException = new CosmosException("test failure", System.Net.HttpStatusCode.NotFound, 0, "test", 0); + var cosmosException = new CosmosException("test failure", httpStatusCode, 0, "test", 0); mockResponse.Setup(x => x.EnsureSuccessStatusCode()).Throws(cosmosException); var mockContainer = new Mock(); @@ -384,6 +389,32 @@ public async Task ConvertAsync_POCO_IdProvided_StatusNot200_ThrowsException_Retu Assert.Equal("test failure", conversionResult.Error.Message); } + [Fact] + public async Task ConvertAsync_POCO_IdProvided_Status404_ReturnsSuccess() + { + object grpcModelBindingData = GrpcTestHelper.GetTestGrpcModelBindingData(GetTestBinaryData(id: "1", partitionKey: "1"), "CosmosDB"); + var context = new TestConverterContext(typeof(ToDoItem), grpcModelBindingData); + + var mockResponse = new Mock(); + mockResponse.Setup(x => x.IsSuccessStatusCode).Returns(false); + var cosmosException = new CosmosException("test failure", HttpStatusCode.NotFound, 0, "test", 0); + mockResponse.Setup(x => x.EnsureSuccessStatusCode()).Throws(cosmosException); + + var mockContainer = new Mock(); + mockContainer + .Setup(m => m.ReadItemStreamAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(mockResponse.Object); + + _mockCosmosClient + .Setup(m => m.GetContainer(It.IsAny(), It.IsAny())) + .Returns(mockContainer.Object); + + var conversionResult = await _cosmosDBConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + Assert.Null(conversionResult.Value); + } + private BinaryData GetTestBinaryData(string db = "testDb", string container = "testContainer", string connection = "cosmosConnection", string id = "", string partitionKey = "", string query = "", string location = "", string queryParams = "{}") { string jsonData = $@"{{ From 89ac21b75723b70179cb454d130b2df70573ed31 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 30 Jan 2025 15:37:17 -0800 Subject: [PATCH 088/190] Reset cosmos notes (#2945) --- extensions/Worker.Extensions.CosmosDB/release_notes.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index 06e3c8aae..921fdcf34 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.12.0 +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB -- Updated `Microsoft.Azure.WebJobs.Extensions.CosmosDB` reference to 4.9.0 -- Return a successful result with a null value when a Cosmos document cannot be found (#2942/#2545) +- From 9c6ae7a88da33c78c008dd0afe199c7d3d850988 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Mon, 3 Feb 2025 10:49:42 -0800 Subject: [PATCH 089/190] Update EventGrid & SendGrid extension dependencies and prepare for release (#2947) --- extensions/Worker.Extensions.EventGrid/release_notes.md | 5 +++-- .../src/Worker.Extensions.EventGrid.csproj | 6 +++--- extensions/Worker.Extensions.SendGrid/release_notes.md | 4 ++-- .../src/Worker.Extensions.SendGrid.csproj | 4 ++-- .../E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj | 1 + tools/devpack.ps1 | 6 ++++-- 6 files changed, 15 insertions(+), 11 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index 9e82bcaf3..ac6291af0 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 4.5.0 -- +- Update dependency "Azure.Messaging.EventGrid" to v4.29.0 +- Update dependency "Microsoft.Azure.Functions.Worker.Core" to v1.20.0 diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index 1636fe77b..97b7900a7 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -6,7 +6,7 @@ Azure Event Grid extensions for .NET isolated functions - 3.4.3 + 3.5.0 false @@ -19,8 +19,8 @@ - - + + diff --git a/extensions/Worker.Extensions.SendGrid/release_notes.md b/extensions/Worker.Extensions.SendGrid/release_notes.md index 791f66a3d..bbdb339a6 100644 --- a/extensions/Worker.Extensions.SendGrid/release_notes.md +++ b/extensions/Worker.Extensions.SendGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.SendGrid +### Microsoft.Azure.Functions.Worker.Extensions.SendGrid 3.1.0 -- +- Update dependency "Microsoft.Azure.WebJobs.Extensions.SendGrid" to v3.1.0 diff --git a/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj b/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj index 44e1f3221..3f324fcf9 100644 --- a/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj +++ b/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj @@ -6,7 +6,7 @@ Azure SendGrid extension for .NET isolated functions - 3.0.3 + 3.1.0 false @@ -19,7 +19,7 @@ - + diff --git a/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj b/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj index 50a93a04f..5c2fd1e8c 100644 --- a/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj +++ b/test/E2ETests/E2EApps/E2EAspNetCoreApp/E2EAspNetCoreApp.csproj @@ -26,6 +26,7 @@ + diff --git a/tools/devpack.ps1 b/tools/devpack.ps1 index c462b266c..166b040b9 100644 --- a/tools/devpack.ps1 +++ b/tools/devpack.ps1 @@ -17,7 +17,9 @@ # Packs the SDK locally, and (by default) updates the Sample to use this package, then builds. # Specify --E2E to instead target the E2E test app. -$buildNumber = "local" + [System.DateTime]::Now.ToString("yyyyMMddHHmm") +# Use metadata to provide a version that is always head of the latest stable package +# E.g: Nuget packages will be named 2.0.0 with the version metedata set to 2.0.0+202501311440-local +$buildNumber = "+" + [System.DateTime]::Now.ToString("yyyyMMddHHmm") Write-Host Write-Host "Building packages with BuildNumber $buildNumber" @@ -49,7 +51,7 @@ if (!(Test-Path $localPack)) Write-Host Write-Host "---Updating projects with local SDK pack---" Write-Host "Packing Core .NET Worker projects to $localPack" -& "dotnet" "pack" $sdkProject "-p:PackageOutputPath=$localPack" "-nologo" "-p:Version=2.0.1" "-p:VersionSuffix=$buildNumber" $AdditionalPackArgs +& "dotnet" "pack" $sdkProject "-p:PackageOutputPath=$localPack" "-nologo" "-p:VersionSuffix=$buildNumber" $AdditionalPackArgs Write-Host foreach ($project in $projects) { From f112461c6bdd61c76e05130ceaf1a8b970ad17e0 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Mon, 3 Feb 2025 11:14:04 -0800 Subject: [PATCH 090/190] Fix ContinuousIntegrationBuild property (#2946) --- build/Common.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/Common.props b/build/Common.props index df8a00e68..7f4ac28e4 100644 --- a/build/Common.props +++ b/build/Common.props @@ -20,7 +20,7 @@ $(MSBuildThisFileDirectory)/../key.snk embedded true - true" + true true false From 99824a1750c69623cfe4746c14e3cf89629fe27f Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Mon, 3 Feb 2025 11:35:24 -0800 Subject: [PATCH 091/190] Bump Storage extension versions for release (#2948) --- .../src/Worker.Extensions.Storage.Blobs.csproj | 2 +- .../src/Worker.Extensions.Storage.Queues.csproj | 2 +- .../src/Worker.Extensions.Storage.csproj | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index 6f4760c10..00df03913 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -6,7 +6,7 @@ Azure Blob Storage extensions for .NET isolated functions - 6.6.0 + 6.6.1 false diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj index 380fb81ce..d1096396e 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj +++ b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj @@ -6,7 +6,7 @@ Azure Queue Storage extensions for .NET isolated functions - 5.5.0 + 5.5.1 false diff --git a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj index 022d03b6e..7098d2e9a 100644 --- a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj +++ b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj @@ -6,7 +6,7 @@ Azure Storage extensions for .NET isolated functions - 6.6.0 + 6.6.1 false From 06bfbf2413699b6b59101ebf0f9977dd3a33e0bb Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Mon, 3 Feb 2025 14:59:20 -0800 Subject: [PATCH 092/190] Update extension validation template (#2949) --- eng/build/extensionValidationProjectTemplate.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eng/build/extensionValidationProjectTemplate.txt b/eng/build/extensionValidationProjectTemplate.txt index c6e2d69dc..db66e460d 100644 --- a/eng/build/extensionValidationProjectTemplate.txt +++ b/eng/build/extensionValidationProjectTemplate.txt @@ -2,6 +2,8 @@ net8.0 Library + false + false From 5366211c497e10e7c1534010069f79a9d06106ca Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 5 Feb 2025 14:48:51 -0800 Subject: [PATCH 093/190] Add support for externally supplied worker extensions project (#2763) * Refactor SDK to consume output path from WorkerExtensions.csproj * Allow for extension project to be externally supplied * Fix JSON deserialization * Update unit test for order * Fix PublishTests * Fix InnerBuildTests * Suppress OutDir and OutputPath from inner build * Remove directory recreation on generate csproj * Update unit tests * Ensure directories created * Add more csproj generator tests * Update unit tests * Update assertion failure message for investigation * Update datetime assertions in tests * Add short delays for timestamp consistency * update SDK release_notes.md --- .reporoot | 1 + samples/FunctionApp/FunctionApp.csproj | 2 +- sdk/Sdk/ExtensionsCsprojGenerator.cs | 26 +-- sdk/Sdk/ExtensionsMetadata.cs | 4 +- sdk/Sdk/ExtensionsMetadataEnhancer.cs | 60 ++++++ ...crosoft.Azure.Functions.Worker.Sdk.targets | 201 ++++++++++-------- sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs | 12 +- sdk/Sdk/Tasks/GenerateFunctionMetadata.cs | 13 +- sdk/release_notes.md | 5 +- .../ExtensionsCsProjGeneratorTests.cs | 168 +++++++++++++-- .../ExtensionsMetadataEnhancerTests.cs | 19 ++ test/SdkE2ETests/InnerBuildTests.cs | 12 +- test/SdkE2ETests/PublishTests.cs | 8 +- test/TestUtility/TestUtility.cs | 19 ++ 14 files changed, 408 insertions(+), 142 deletions(-) create mode 100644 .reporoot diff --git a/.reporoot b/.reporoot new file mode 100644 index 000000000..96003cbd2 --- /dev/null +++ b/.reporoot @@ -0,0 +1 @@ +File to mark repo root. Do not edit. \ No newline at end of file diff --git a/samples/FunctionApp/FunctionApp.csproj b/samples/FunctionApp/FunctionApp.csproj index e0c363aa4..0683410bf 100644 --- a/samples/FunctionApp/FunctionApp.csproj +++ b/samples/FunctionApp/FunctionApp.csproj @@ -9,7 +9,7 @@ - + diff --git a/sdk/Sdk/ExtensionsCsprojGenerator.cs b/sdk/Sdk/ExtensionsCsprojGenerator.cs index b8ba95584..4b5b0a3de 100644 --- a/sdk/Sdk/ExtensionsCsprojGenerator.cs +++ b/sdk/Sdk/ExtensionsCsprojGenerator.cs @@ -10,8 +10,6 @@ namespace Microsoft.Azure.Functions.Worker.Sdk { internal class ExtensionsCsprojGenerator { - internal const string ExtensionsProjectName = "WorkerExtensions.csproj"; - private readonly IDictionary _extensions; private readonly string _outputPath; private readonly string _targetFrameworkIdentifier; @@ -29,32 +27,20 @@ public ExtensionsCsprojGenerator(IDictionary extensions, string public void Generate() { - var extensionsCsprojFilePath = Path.Combine(_outputPath, ExtensionsProjectName); - string csproj = GetCsProjContent(); - if (File.Exists(extensionsCsprojFilePath)) + if (File.Exists(_outputPath)) { - string existing = File.ReadAllText(extensionsCsprojFilePath); + string existing = File.ReadAllText(_outputPath); if (string.Equals(csproj, existing, StringComparison.Ordinal)) { // If contents are the same, only touch the file to update timestamp. - File.SetLastWriteTimeUtc(extensionsCsprojFilePath, DateTime.UtcNow); + File.SetLastWriteTimeUtc(_outputPath, DateTime.UtcNow); return; } } - RecreateDirectory(_outputPath); - File.WriteAllText(extensionsCsprojFilePath, csproj); - } - - private void RecreateDirectory(string directoryPath) - { - if (Directory.Exists(directoryPath)) - { - Directory.Delete(directoryPath, recursive: true); - } - - Directory.CreateDirectory(directoryPath); + Directory.CreateDirectory(Path.GetDirectoryName(_outputPath)); + File.WriteAllText(_outputPath, csproj); } internal string GetCsProjContent() @@ -70,7 +56,7 @@ internal string GetCsProjContent() } } - string netSdkVersion = _azureFunctionsVersion.StartsWith(Constants.AzureFunctionsVersion3, StringComparison.OrdinalIgnoreCase) ? "3.1.2" : "4.3.0"; + string netSdkVersion = _azureFunctionsVersion.StartsWith(Constants.AzureFunctionsVersion3, StringComparison.OrdinalIgnoreCase) ? "3.1.2" : "4.6.0"; return $@" diff --git a/sdk/Sdk/ExtensionsMetadata.cs b/sdk/Sdk/ExtensionsMetadata.cs index f7ed7912f..2fcd1ae18 100644 --- a/sdk/Sdk/ExtensionsMetadata.cs +++ b/sdk/Sdk/ExtensionsMetadata.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Generic; @@ -9,6 +9,6 @@ namespace Microsoft.Azure.Functions.Worker.Sdk public class ExtensionsMetadata { [JsonPropertyName("extensions")] - public IEnumerable? Extensions { get; set; } + public List Extensions { get; set; } = new List(); } } diff --git a/sdk/Sdk/ExtensionsMetadataEnhancer.cs b/sdk/Sdk/ExtensionsMetadataEnhancer.cs index 9f24b84f7..bbb2671aa 100644 --- a/sdk/Sdk/ExtensionsMetadataEnhancer.cs +++ b/sdk/Sdk/ExtensionsMetadataEnhancer.cs @@ -2,7 +2,11 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; using System.Text.RegularExpressions; +using Mono.Cecil; namespace Microsoft.Azure.Functions.Worker.Sdk { @@ -24,6 +28,34 @@ public static void AddHintPath(IEnumerable extensions) } } + public static IEnumerable GetWebJobsExtensions(string fileName) + { + // NOTE: this is an incomplete approach to getting extensions and is intended only for our usages. + // Running this with arbitrary assemblies (especially user supplied) can lead to exceptions. + AssemblyDefinition assembly = AssemblyDefinition.ReadAssembly(fileName); + IEnumerable attributes = assembly.Modules.SelectMany(p => p.GetCustomAttributes()) + .Where(a => a.AttributeType.FullName == "Microsoft.Azure.WebJobs.Hosting.WebJobsStartupAttribute"); + + foreach (CustomAttribute attribute in attributes) + { + CustomAttributeArgument typeProperty = attribute.ConstructorArguments.ElementAtOrDefault(0); + CustomAttributeArgument nameProperty = attribute.ConstructorArguments.ElementAtOrDefault(1); + + TypeDefinition typeDef = (TypeDefinition)typeProperty.Value; + string assemblyQualifiedName = Assembly.CreateQualifiedName( + typeDef.Module.Assembly.FullName, GetReflectionFullName(typeDef)); + + string name = GetName((string)nameProperty.Value, typeDef); + + yield return new ExtensionReference + { + Name = name, + TypeName = assemblyQualifiedName, + HintPath = $@"{ExtensionsBinaryDirectoryPath}/{Path.GetFileName(fileName)}", + }; + } + } + private static string? GetAssemblyNameOrNull(string? typeName) { if (typeName == null) @@ -40,5 +72,33 @@ public static void AddHintPath(IEnumerable extensions) return null; } + + // Copying the WebJobsStartup constructor logic from: + // https://github.com/Azure/azure-webjobs-sdk/blob/e5417775bcb8c8d3d53698932ca8e4e265eac66d/src/Microsoft.Azure.WebJobs.Host/Hosting/WebJobsStartupAttribute.cs#L33-L47. + private static string GetName(string name, TypeDefinition startupTypeDef) + { + if (string.IsNullOrEmpty(name)) + { + // for a startup class named 'CustomConfigWebJobsStartup' or 'CustomConfigStartup', + // default to a name 'CustomConfig' + name = startupTypeDef.Name; + int idx = name.IndexOf("WebJobsStartup"); + if (idx < 0) + { + idx = name.IndexOf("Startup"); + } + if (idx > 0) + { + name = name.Substring(0, idx); + } + } + + return name; + } + + private static string GetReflectionFullName(TypeReference typeRef) + { + return typeRef.FullName.Replace("/", "+"); + } } } diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 40f57986f..5b057d1b6 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -10,11 +10,33 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and --> + + + <_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 + $(MSBuildExtensionsPath)\Microsoft\VisualStudio\Managed.Functions\ + + + + + true + <_FunctionsExtensionsDirectory>.azurefunctions + <_FunctionsExtensionsJsonName>extensions.json + <_FunctionsWorkerConfigInputFile>$([MSBuild]::NormalizePath($(MSBuildThisFileDirectory)\..\tools\worker.config.json)) + <_FunctionsMetadataLoaderExtensionFile>$([MSBuild]::NormalizePath($(MSBuildThisFileDirectory)\..\tools\netstandard2.0\Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll)) + <_FunctionsExtensionCommonProps>ImportDirectoryBuildProps=false;ImportDirectoryBuildTargets=false;ImportDirectoryPackagesProps=false + <_FunctionsExtensionRemoveProps>TargetFramework;RuntimeIdentifier;SelfContained;PublishSingleFile;PublishReadyToRun;UseCurrentRuntimeIdentifier;WebPublishMethod;PublishProfile;DeployOnBuild;PublishDir;OutDir;OutputPath; + + + - <_ToolingSuffix> <_DefaultAzureFunctionsVersion>v4 <_AzureFunctionsVersionNotSet Condition="'$(AzureFunctionsVersion)' == ''">true $(_DefaultAzureFunctionsVersion) + true + <_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 @@ -22,19 +44,6 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v9.0'">net9-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 @@ -44,13 +53,13 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and true true - <_FunctionsGenerateExtensionProject Condition="'$(DesignTimeBuild)' != 'true'">true + <_FunctionsBuildEnabled Condition="'$(DesignTimeBuild)' != 'true'">true $(RootNamespace.Replace("-", "_")) <_FunctionsVersion Include="v3" InSupport="false" /> - <_FunctionsVersion Include="$(_DefaultAzureFunctionsVersion)" InSupport="true" /> + <_FunctionsVersion Include="v4" InSupport="true" /> @@ -61,23 +70,42 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and + + + $([System.IO.Path]::GetDirectoryName($(ExtensionsCsProj))) + $(IntermediateOutputPath)WorkerExtensions + $([System.IO.Path]::GetFullPath($(ExtensionsCsProjDirectory))) + $([System.IO.Path]::Combine($(ExtensionsCsProjDirectory), WorkerExtensions.csproj)) + + + + <_FunctionsMetadataPath>$(IntermediateOutputPath)functions.metadata + <_FunctionsWorkerConfigPath>$(IntermediateOutputPath)worker.config.json + + + - + <_AzureFunctionsVersionStandardized>$(AzureFunctionsVersion.ToLowerInvariant().Split('-')[0]) - true <_SelectedFunctionVersion Include="@(_FunctionsVersion)" Condition="'%(_FunctionsVersion.Identity)' == '$(_AzureFunctionsVersionStandardized)'" /> + + + + + + - - + + @@ -90,68 +118,72 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and + + + + DependsOnTargets="_WorkerExtensionsRestore;_WorkerExtensionsBuild" /> - - + + + + - - + + - <_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) + <_WorkerExtensionTarget>Build + <_WorkerExtensionTarget Condition="'$(FunctionsGenerateExtensionProject)' == 'false'">GetTargetPath + <_WorkerExtensionProperties Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">Configuration=Release;$(_FunctionsExtensionCommonProps) + + + + + + + + <_FunctionsExtensionsOutputPath>$([System.IO.Path]::GetDirectoryName($(_WorkerExtensionsAssembly))) + <_FunctionsIntermediateExtensionJsonPath>$(_FunctionsExtensionsOutputPath)/bin/$(_FunctionsExtensionsJsonName) <_FunctionsIntermediateExtensionUpdatedJsonPath>$(IntermediateOutputPath)$(_FunctionsExtensionsJsonName) - - - - - - - - + + + DependsOnTargets="_FunctionsGenerateCommon;_FunctionsGenerateWorkerConfig" /> + + + <_TargetExtensionsCsProj Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">$(ExtensionsCsProj) + + - - - - - @@ -171,27 +203,12 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and Overwrite="true" /> - - - - - - - - - - - + + OutputPath="$(_FunctionsIntermediateExtensionUpdatedJsonPath)" + AdditionalExtensions="$(_FunctionsMetadataLoaderExtensionFile)" /> - <_ExtensionBinaries Include="$(ExtensionsCsProjDirectory)\buildout\bin\**" - Exclude="$(ExtensionsCsProjDirectory)\buildout\bin\runtimes\**;$(_FunctionsIntermediateExtensionJsonPath)" - CopyToOutputDirectory="PreserveNewest" - CopyToPublishDirectory="PreserveNewest" /> - <_ExtensionRuntimeBinaries Include="$(ExtensionsCsProjDirectory)\buildout\runtimes\**" - CopyToOutputDirectory="PreserveNewest" - CopyToPublishDirectory="PreserveNewest" /> + <_ExtensionBinaries Include="$(_FunctionsExtensionsOutputPath)\bin\**" + Exclude="$(_FunctionsExtensionsOutputPath)\bin\runtimes\**;$(_FunctionsIntermediateExtensionJsonPath)" /> + <_ExtensionRuntimeBinaries Include="$(_FunctionsExtensionsOutputPath)\runtimes\**" /> - + - + - <_NoneWithTargetPath Include="@(_ExtensionFilesWithTargetPath)" TargetPath="$(_FunctionsExtensionsDirectory)/%(_ExtensionFilesWithTargetPath.TargetPath)" /> + <_FunctionsAdditionalFile Include="$(_FunctionsMetadataPath);$(_FunctionsWorkerConfigPath);$(_FunctionsIntermediateExtensionUpdatedJsonPath)" /> + <_FunctionsAdditionalFile Include="$(_FunctionsMetadataLoaderExtensionFile)" SubPath="$(_FunctionsExtensionsDirectory)/" /> + <_NoneWithTargetPath Include="@(_FunctionsAdditionalFile)" + TargetPath="%(_FunctionsAdditionalFile.SubPath)%(Filename)%(Extension)" + CopyToOutputDirectory="PreserveNewest" + CopyToPublishDirectory="PreserveNewest"/> + <_NoneWithTargetPath Include="@(_ExtensionFilesWithTargetPath)" + TargetPath="$(_FunctionsExtensionsDirectory)/%(_ExtensionFilesWithTargetPath.TargetPath)" + CopyToOutputDirectory="PreserveNewest" + CopyToPublishDirectory="PreserveNewest"/> - <_WorkerExtFilesToClean Include="$(ExtensionsCsProjDirectory)\**" Condition="'$(ExtensionsCsProjDirectory)' != ''" /> - <_WorkerExtFilesToClean Include="$(TargetDir)$(_FunctionsExtensionsDirectory)\**" /> + <_WorkerExtFilesToClean Include="$(ExtensionsCsProjDirectory)/**" Condition="'$(ExtensionsCsProjDirectory)' != '' AND '$(FunctionsGenerateExtensionProject)' == 'true'" /> + <_WorkerExtFilesToClean Include="$(TargetDir)$(_FunctionsExtensionsDirectory)/**" /> <_WorkerExtFilesToClean Include="$(_FunctionsMetadataPath)" /> <_WorkerExtFilesToClean Include="$(_FunctionsWorkerConfigPath)" /> <_WorkerExtFilesToClean Include="$(TargetDir)worker.config.json" /> @@ -239,10 +261,19 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + + + + + + + + + true + - \ No newline at end of file + diff --git a/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs b/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs index c76bb4871..4d0460761 100644 --- a/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs +++ b/sdk/Sdk/Tasks/EnhanceExtensionsMetadata.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System.Collections.Generic; using System.IO; using System.Linq; using System.Text.Json; @@ -24,12 +25,19 @@ public class EnhanceExtensionsMetadata : Task [Required] public string? OutputPath { get; set; } + public ITaskItem[]? AdditionalExtensions { get; set; } + public override bool Execute() { string json = File.ReadAllText(ExtensionsJsonPath); - var extensionsMetadata = JsonSerializer.Deserialize(json); - ExtensionsMetadataEnhancer.AddHintPath(extensionsMetadata?.Extensions ?? Enumerable.Empty()); + var extensionsMetadata = JsonSerializer.Deserialize(json) ?? new ExtensionsMetadata(); + ExtensionsMetadataEnhancer.AddHintPath(extensionsMetadata.Extensions); + + foreach (ITaskItem item in AdditionalExtensions ?? Enumerable.Empty()) + { + extensionsMetadata.Extensions.AddRange(ExtensionsMetadataEnhancer.GetWebJobsExtensions(item.ItemSpec)); + } string newJson = JsonSerializer.Serialize(extensionsMetadata, _serializerOptions); File.WriteAllText(OutputPath, newJson); diff --git a/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs b/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs index e8e42cee2..e54aa995a 100644 --- a/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs +++ b/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs @@ -24,7 +24,6 @@ public class GenerateFunctionMetadata : Task [Required] public string? OutputPath { get; set; } - [Required] public string? ExtensionsCsProjFilePath { get; set; } [Required] @@ -45,12 +44,16 @@ public override bool Execute() { var functionGenerator = new FunctionMetadataGenerator(MSBuildLogger); - var functions = functionGenerator.GenerateFunctionMetadata(AssemblyPath!, ReferencePaths ?? Enumerable.Empty()); + IEnumerable functions = functionGenerator.GenerateFunctionMetadata(AssemblyPath!, ReferencePaths ?? Enumerable.Empty()); + IDictionary extensions = functionGenerator.Extensions; - var extensions = functionGenerator.Extensions; - var extensionsCsProjGenerator = new ExtensionsCsprojGenerator(extensions, ExtensionsCsProjFilePath!, AzureFunctionsVersion!, TargetFrameworkIdentifier!, TargetFrameworkVersion!); + if (!string.IsNullOrEmpty(ExtensionsCsProjFilePath)) + { + // Null/empty ExtensionsCsProjFilePath means the extension project is externally provided. + var extensionsCsProjGenerator = new ExtensionsCsprojGenerator(extensions, ExtensionsCsProjFilePath!, AzureFunctionsVersion!, TargetFrameworkIdentifier!, TargetFrameworkVersion!); + extensionsCsProjGenerator.Generate(); + } - extensionsCsProjGenerator.Generate(); WriteMetadataWithRetry(functions); } catch (FunctionsMetadataGenerationException) diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 72faae9bd..579c67796 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -6,7 +6,10 @@ ### Microsoft.Azure.Functions.Worker.Sdk -- +- Addresses issue with `dotnet build --no-incremental` failing build (PR #2763, Issue #2601) +- Addresses issue with setting `OutDir` msbuild property failing build (PR #2763, Issue #2125) +- Adds support for externally supplied worker extensions project. (PR #2763, Issues #1252, #1888) + - This mode is opt-in only. Using it eliminates the inner-build. This is useful for scenarios where performing a restore inside of build was problematic. ### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.5 diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs index 6576e99d7..e5326296b 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs @@ -4,25 +4,42 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; +using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Sdk; using Xunit; namespace Microsoft.Azure.Functions.SdkTests { - public class ExtensionsCsProjGeneratorTests + public sealed class ExtensionsCsProjGeneratorTests : IDisposable { + private HashSet _directoriesToCleanup = new(); + public enum FuncVersion { V3, V4, } + public void Dispose() + { + foreach (string directory in _directoriesToCleanup) + { + if (Directory.Exists(directory)) + { + Directory.Delete(directory, true); + } + } + + _directoriesToCleanup.Clear(); + } + [Theory] [InlineData(FuncVersion.V3)] [InlineData(FuncVersion.V4)] public void GetCsProjContent_Succeeds(FuncVersion version) { - var generator = GetGenerator(version); + var generator = GetGenerator(version, "TestExtension.csproj"); string actual = generator.GetCsProjContent().Replace("\r\n", "\n"); string expected = ExpectedCsproj(version).Replace("\r\n", "\n"); Assert.Equal(expected, actual); @@ -31,40 +48,159 @@ public void GetCsProjContent_Succeeds(FuncVersion version) [Theory] [InlineData(FuncVersion.V3)] [InlineData(FuncVersion.V4)] - public void GetCsProjContent_IncrementalSupport(FuncVersion version) + public void Generate_IncrementalSupport(FuncVersion version) { - DateTime RunGenerate(string subPath, out string contents) + DateTime RunGenerate(string project, out string contents) { - var generator = GetGenerator(version, subPath); + _directoriesToCleanup.Add(Path.GetDirectoryName(project)); + var generator = GetGenerator(version, project); generator.Generate(); - string path = Path.Combine(subPath, ExtensionsCsprojGenerator.ExtensionsProjectName); - contents = File.ReadAllText(path); - var csproj = new FileInfo(Path.Combine(subPath, ExtensionsCsprojGenerator.ExtensionsProjectName)); + contents = File.ReadAllText(project); + var csproj = new FileInfo(project); return csproj.LastWriteTimeUtc; } - string subPath = Guid.NewGuid().ToString(); - DateTime firstRun = RunGenerate(subPath, out string first); - DateTime secondRun = RunGenerate(subPath, out string second); + string project = Path.Combine(Guid.NewGuid().ToString(), "TestExtension.csproj"); + DateTime firstRun = RunGenerate(project, out string first); + DateTime secondRun = RunGenerate(project, out string second); Assert.NotEqual(firstRun, secondRun); Assert.Equal(first, second); } - static ExtensionsCsprojGenerator GetGenerator(FuncVersion version, string subPath = "") + [Fact] + public async Task Generate_Updates() { - IDictionary extensions = new Dictionary + DateTime RunGenerate(string project, IDictionary extensions, out string contents) + { + _directoriesToCleanup.Add(Path.GetDirectoryName(project)); + var generator = GetGenerator(FuncVersion.V4, project, extensions); + generator.Generate(); + + contents = File.ReadAllText(project); + var csproj = new FileInfo(project); + return csproj.LastWriteTimeUtc; + } + + Dictionary extensions = new() { { "Microsoft.Azure.WebJobs.Extensions.Storage", "4.0.3" }, { "Microsoft.Azure.WebJobs.Extensions.Http", "3.0.0" }, { "Microsoft.Azure.WebJobs.Extensions", "2.0.0" }, }; + string project = Path.Combine(Guid.NewGuid().ToString(), "TestExtension.csproj"); + DateTime firstRun = RunGenerate(project, extensions, out string first); + + await Task.Delay(10); // to ensure timestamps progress. + extensions.Remove(extensions.Keys.First()); + DateTime secondRun = RunGenerate(project, extensions, out string second); + + Assert.NotEqual(firstRun.Ticks, secondRun.Ticks); + Assert.NotEqual(first, second); + } + + [Fact] + public async Task Generate_Subdirectory_CreatesAll() + { + DateTime RunGenerate(string project, out string contents) + { + _directoriesToCleanup.Add(Path.GetDirectoryName(project)); + var generator = GetGenerator(FuncVersion.V4, project); + generator.Generate(); + + contents = File.ReadAllText(project); + var csproj = new FileInfo(project); + return csproj.LastWriteTimeUtc; + } + + DateTime earliest = DateTime.UtcNow; + + await Task.Delay(10); + string project = Path.Combine(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), "TestExtension.csproj"); + DateTime time = RunGenerate(project, out string contents); + + Assert.True(time.Ticks >= earliest.Ticks, $"expected last write time {time.Ticks} to be greater than {earliest.Ticks}."); + Assert.NotNull(contents); + } + + [Fact] + public async Task Generate_Subdirectory_CreatesPartial() + { + DateTime RunGenerate(string project, out string contents) + { + _directoriesToCleanup.Add(Path.GetDirectoryName(project)); + var generator = GetGenerator(FuncVersion.V4, project); + generator.Generate(); + + contents = File.ReadAllText(project); + var csproj = new FileInfo(project); + return csproj.LastWriteTimeUtc; + } + + DateTime earliest = DateTime.UtcNow; + string parent = Guid.NewGuid().ToString(); + Directory.CreateDirectory(parent); + _directoriesToCleanup.Add(parent); + + await Task.Delay(10); + string project = Path.Combine(parent, Guid.NewGuid().ToString(), "TestExtension.csproj"); + DateTime time = RunGenerate(project, out string contents); + + Assert.True(time.Ticks >= earliest.Ticks, $"expected last write time {time.Ticks} to be greater than {earliest.Ticks}."); + Assert.NotNull(contents); + } + + [Fact] + public async Task Generate_ExistingDirectory_DoesNotOverwrite() + { + DateTime RunGenerate(string project, out string contents) + { + _directoriesToCleanup.Add(Path.GetDirectoryName(project)); + var generator = GetGenerator(FuncVersion.V4, project); + generator.Generate(); + + contents = File.ReadAllText(project); + var csproj = new FileInfo(project); + return csproj.LastWriteTimeUtc; + } + + string parent = Guid.NewGuid().ToString(); + Directory.CreateDirectory(parent); + _directoriesToCleanup.Add(parent); + + string existing = Path.Combine(parent, "existing.txt"); + File.WriteAllText(existing, ""); + DateTime expectedWriteTime = new FileInfo(existing).LastWriteTimeUtc; + + await Task.Delay(10); + string project = Path.Combine(parent, "TestExtension.csproj"); + DateTime time = RunGenerate(project, out string contents); + + Assert.True(time.Ticks >= expectedWriteTime.Ticks, $"expected last write time {time.Ticks} to be greater than {expectedWriteTime.Ticks}."); + Assert.NotNull(contents); + Assert.Equal(expectedWriteTime, new FileInfo(existing).LastWriteTimeUtc); + } + + static ExtensionsCsprojGenerator GetGenerator(FuncVersion version, string outputPath) + { + Dictionary extensions = new() + { + { "Microsoft.Azure.WebJobs.Extensions.Storage", "4.0.3" }, + { "Microsoft.Azure.WebJobs.Extensions.Http", "3.0.0" }, + { "Microsoft.Azure.WebJobs.Extensions", "2.0.0" }, + }; + + return GetGenerator(version, outputPath, extensions); + } + + static ExtensionsCsprojGenerator GetGenerator(FuncVersion version, string outputPath, IDictionary extensions) + { 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), + FuncVersion.V3 => new ExtensionsCsprojGenerator(extensions, outputPath, "v3", Constants.NetCoreApp, Constants.NetCoreVersion31), + FuncVersion.V4 => new ExtensionsCsprojGenerator(extensions, outputPath, "v4", Constants.NetCoreApp, Constants.NetCoreVersion6), _ => throw new ArgumentOutOfRangeException(nameof(version)), }; } @@ -119,7 +255,7 @@ private static string ExpectedCsProjV4() - + diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs b/test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs index 8b8b21402..0fcf68854 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs +++ b/test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Generic; +using System.IO; using System.Linq; using Microsoft.Azure.Functions.Worker.Sdk; using Xunit; @@ -37,6 +38,24 @@ public void AddHintPath_DoesNotAdd_WhenAlreadyPresent() ValidateAllEqual(GetBasicReferences_WithPresetHintPath(), extensionsPreset); } + [Fact] + public void GetWebJobsExtensions_FindsExtensions() + { + string assembly = Path.Combine(Tests.TestUtility.RepoRoot, "sdk", "FunctionMetadataLoaderExtension", "bin", Tests.TestUtility.Config, "netstandard2.0", "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"); + var extensions = ExtensionsMetadataEnhancer.GetWebJobsExtensions(assembly); + + ValidateAllEqual( + [ + new ExtensionReference() + { + Name = "Startup", + TypeName = "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c", + HintPath = "./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll", + } + ], + extensions); + } + private static void ValidateAllEqual(IEnumerable expected, IEnumerable actual) { Assert.Equal(expected.Count(), actual.Count()); diff --git a/test/SdkE2ETests/InnerBuildTests.cs b/test/SdkE2ETests/InnerBuildTests.cs index 1f993bd24..3d271f99b 100644 --- a/test/SdkE2ETests/InnerBuildTests.cs +++ b/test/SdkE2ETests/InnerBuildTests.cs @@ -33,11 +33,6 @@ public async Task Build_ScansReferences() JToken extensionsJsonContents = JObject.Parse(File.ReadAllText(extensionsJsonPath)); JToken expectedExtensionsJson = JObject.Parse(@"{ ""extensions"": [ - { - ""name"": ""Startup"", - ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"", - ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"" - }, { ""name"": ""AzureStorageBlobs"", ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageBlobsWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage.Blobs, Version=5.3.1.0, Culture=neutral, PublicKeyToken=92742159e12e44c8"", @@ -47,7 +42,12 @@ public async Task Build_ScansReferences() ""name"": ""AzureStorageQueues"", ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageQueuesWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage.Queues, Version=5.1.3.0, Culture=neutral, PublicKeyToken=92742159e12e44c8"", ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.Storage.Queues.dll"" - } + }, + { + ""name"": ""Startup"", + ""typeName"": ""Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"", + ""hintPath"": ""./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"" + }, ] }"); diff --git a/test/SdkE2ETests/PublishTests.cs b/test/SdkE2ETests/PublishTests.cs index 5a7a76923..10b50f39f 100644 --- a/test/SdkE2ETests/PublishTests.cs +++ b/test/SdkE2ETests/PublishTests.cs @@ -88,15 +88,15 @@ private async Task RunPublishTest(string outputDir, string additionalParams = nu { extensions = new[] { - new Extension("Startup", - "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c", - @"./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"), new Extension("AzureStorageBlobs", "Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageBlobsWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage.Blobs, Version=5.3.1.0, Culture=neutral, PublicKeyToken=92742159e12e44c8", @"./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.Storage.Blobs.dll"), new Extension("AzureStorageQueues", "Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageQueuesWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage.Queues, Version=5.3.1.0, Culture=neutral, PublicKeyToken=92742159e12e44c8", - @"./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.Storage.Queues.dll") + @"./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.Storage.Queues.dll"), + new Extension("Startup", + "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.Startup, Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader, Version=1.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c", + @"./.azurefunctions/Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"), } }); Assert.True(JToken.DeepEquals(extensionsJsonContents, expected), $"Actual: {extensionsJsonContents}{Environment.NewLine}Expected: {expected}"); diff --git a/test/TestUtility/TestUtility.cs b/test/TestUtility/TestUtility.cs index dd4eb98ba..cf5df14e3 100644 --- a/test/TestUtility/TestUtility.cs +++ b/test/TestUtility/TestUtility.cs @@ -11,6 +11,25 @@ namespace Microsoft.Azure.Functions.Tests { public static class TestUtility { +#if DEBUG + public static readonly string Config = "Debug"; +#else + public static readonly string Config = "Release"; +#endif + + public static readonly string RepoRoot = GetDirectoryOfFileAbove(".reporoot"); + + public static string GetDirectoryOfFileAbove(string fileName) + { + string current = Directory.GetCurrentDirectory(); + while (!File.Exists(Path.Combine(current, fileName))) + { + current = Directory.GetParent(current).FullName; + } + + return current; + } + public static IConfiguration GetTestConfiguration() { return new ConfigurationBuilder() From 78d152ad13074dc00928f1ab32d444e0bfa43094 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 13 Feb 2025 08:43:55 -0800 Subject: [PATCH 094/190] Use p2p reference for external ext proj entry point (#2954) * Update SDK version to 2.1.0-preview.1 * Add external csproj sample. Refactor external csproj to be p2p ref entry point * Error out if external ext proj does not exist * Suppress ManagePackageVersionsCentrally when generating ext proj * Update error & warnings * Update readme section title * Add example scenarios to external ext proj sample * Fix README mistake --- .../App/ExternalExtensionProject.App.csproj | 19 +++ .../ExternalExtensionProject/App/Program.cs | 8 ++ .../App/QueueFunction.cs | 22 ++++ .../Ext/ExternalExtensionProject.Ext.csproj | 19 +++ samples/ExternalExtensionProject/README.md | 123 ++++++++++++++++++ .../Net9FunctionApp/Net9FunctionApp.csproj | 2 +- samples/README.md | 3 + sdk/Sdk/ExtensionsCsprojGenerator.cs | 2 - sdk/Sdk/Sdk.csproj | 4 +- ...crosoft.Azure.Functions.Worker.Sdk.targets | 40 ++++-- sdk/release_notes.md | 2 +- .../ExtensionsCsProjGeneratorTests.cs | 4 - 12 files changed, 229 insertions(+), 19 deletions(-) create mode 100644 samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj create mode 100644 samples/ExternalExtensionProject/App/Program.cs create mode 100644 samples/ExternalExtensionProject/App/QueueFunction.cs create mode 100644 samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj create mode 100644 samples/ExternalExtensionProject/README.md diff --git a/samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj b/samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj new file mode 100644 index 000000000..062170bcf --- /dev/null +++ b/samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + v4 + Exe + + + + + + + + + + + + + diff --git a/samples/ExternalExtensionProject/App/Program.cs b/samples/ExternalExtensionProject/App/Program.cs new file mode 100644 index 000000000..2838127e6 --- /dev/null +++ b/samples/ExternalExtensionProject/App/Program.cs @@ -0,0 +1,8 @@ +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Builder; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; + +var builder = FunctionsApplication.CreateBuilder(args); +var host = builder.Build(); +host.Run(); diff --git a/samples/ExternalExtensionProject/App/QueueFunction.cs b/samples/ExternalExtensionProject/App/QueueFunction.cs new file mode 100644 index 000000000..091bb464c --- /dev/null +++ b/samples/ExternalExtensionProject/App/QueueFunction.cs @@ -0,0 +1,22 @@ +// 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 Azure.Storage.Queues.Models; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace ExternalExtensionProject.App; + +public class QueueFunction(ILogger logger) +{ + /// + /// This function demonstrates binding to a single . + /// + [Function(nameof(QueueMessageFunction))] + public void QueueMessageFunction([QueueTrigger("input-queue")] QueueMessage message) + { + logger.LogInformation(message.MessageText); + } +} diff --git a/samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj b/samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj new file mode 100644 index 000000000..4937feb6c --- /dev/null +++ b/samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj @@ -0,0 +1,19 @@ + + + + net6.0 + Microsoft.Azure.Functions.Worker.Extensions + true + + + + + + + + + + + + + diff --git a/samples/ExternalExtensionProject/README.md b/samples/ExternalExtensionProject/README.md new file mode 100644 index 000000000..e88709d1c --- /dev/null +++ b/samples/ExternalExtensionProject/README.md @@ -0,0 +1,123 @@ +# External Extension Project + +This sample shows how to supply the worker extension project manually. + +## What is the worker extension project? + +To support triggers and bindings in dotnet-isolated function apps, an extensions payload needs to be constructed and loaded into the host process (separate from your worker process). For example, if you use `Microsoft.Azure.Functions.Worker.Extensions.ServiceBus`, a host-side extension `Microsoft.Azure.WebJobs.Extensions.ServiceBus` also needs to be loaded into the function host. + +Collecting these extensions to be loaded is accomplished by build steps provided by `Microsoft.Azure.Functions.Worker.Sdk`. These steps will scan for WebJobs extensions indicated by Worker extensions. These extensions are added as `PackageReference`'s to a _new_ `WorkerExtensions.csproj` which is dynamically generated during build. This project is then restored, built, and outputs collected into the `.azurefunctions` folder of your function app build output. This process is often referred to as the "extension inner-build". + +## What is this scenario for? + +For most customers, this inner-build process is frictionless and requires no customization. However, for some customers this process conflicts with some external factors (no network during build, nuget feed auth issues, among others). To accommodate these conflicts SDK `2.1.0` and on supports the ability to externally supply this extension project, giving full control of the extension project to the customer. This project can now be restored and built alongside the function app. Since the csproj is controlled by the customer, any changes can be made to it. + +There is a major drawback though: ensuring the extension project builds a *valid* payload is now the customer's responsibility. Failures to build a valid payload will only be discovered at runtime. Issues may be obscure and varied, from assembly load failures, method missing exceptions, to odd behavior due to mismatching worker & webjobs extensions. Any time the set of extensions for the function app changes, this external project will need to be manually updated. As such, this scenario is only recommended if customization is **absolutely** necessary. + +## How to use external extension project feature + +### 1. Prepare the project for external extension +Add the follow item to your csproj: + +``` diff + + + + net8.0 + v4 + Exe + + ++ ++ ++ + + + +``` + +### 2. First time generation of external extension csproj + +Run a target to generate the extension project one-time: + +``` shell +dotnet build -t:GenerateExtensionProject {{path-to-function-app-csproj}} +``` + +This will generate the same csproj as the inner-build would. Absent of any external influences by your build process (ie, directory-based imports), this project _should_ produce a valid extension payload. + +> [!NOTE] +> The target `GenerateExtensionProject` can be ran whenever to regenerate the csproj. **However**, it will overwrite the contents of the csproj indicated by `ProjectReference` each time. Make sure to re-apply any customizations you have! + +> [!TIP] +> To avoid needing to re-apply customizations, this sample shows putting all custom logic into `Directory.Build.props` and `Directory.Build.targets` and leaving the csproj to always be the generated contents. + +### 3. Add the extension project to be built as part of your regular build + +If using a solution, make sure to add this new project to the solution file. Failure to do so may cause Visual Studio to skip building this project. + +## Example Scenarios + +### Scenario 1. No-network build phase + +In some cases, a CI's build phase may restrict network access. If this network restriction blocks access to nuget feeds, then the extension inner-build will fail. Using external extension project and ensuring it is part of your existing restore phase will workaround this issue. No project customization is needed by default, unless there are rules enforced by your CI (such as mandating central package versioning). The exact changes needed in those cases will be your responsibility to determine and implement. + +### Scenario 2. Authenticated nuget feeds + +The extension inner-build inherits the nuget configuration of your function app. If the configured feeds require authentication there are two routes: + +1. First, see if you can authenticate using your CI's features. For example, in Azure Devops see [NuGetAuthenticate@1](https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/nuget-authenticate-v1?view=azure-pipelines). +2. If option 1 does not work and there is no feasible way to pass in authentication context into the extension inner-build, then performing same steps as [scenario 1](#scenario-1-no-network-build-phase) may workaround the auth issue. + +### Scenario 3. Extension development testing + +This feature is useful for extension development itself, as the `PackageReference` for the WebJobs extension can be replaced with a `ProjectReference`. + +``` diff + + + +- ++ + +``` + +With the above change you can have a function app to locally test your extension without any need for nuget pack and publishing. + +### Scenario 4. Pinning a transitive dependency + +In the case where an extension brings in a transitive dependency that is not compliant with some CI scans or rules you have, you can manually pin it to an in-compliance version. + +``` diff + + + + ++ + +``` + +> [!CAUTION] +> Be very careful with this scenario, as pinning may bring in runtime breaking changes. Especially be careful about pinning across major versions. If the transitive dependency is `vN.x.x`, and you pin to `vN+y.x.x`, this may lead to runtime failures. It is recommended you validate the version you are pinning to is compatible with the originally requested version. + +## Things to be aware of + +❌ DO NOT change the `TargetFramework` of the extension project + +> [!CAUTION] +> The target framework, and all dependent assemblies of this generated project, must be compatible with the host process. Changing the TFM risks assembly load failures. + +⚠️ AVOID changing the packages of the extension project + +> [!WARNING] +> The package closure of the extension project is sensitive to changes. The host process ultimately controls the dependency graph and assembly loads. Depending on a package/assembly not supported by the host process may cause issues. E.G, trying to depend on any `Microsoft.Extensions.*/9x` from the extension project will cause issues. + +❌ DO NOT include more than 1 `ProjectReference` with `WorkerExtensions=true` + +> [!NOTE] +> The build will be intentionally failed if there are more than 1 extension projects declared. + +✔️ DO set `ReferenceOutputAssembly=false` on the `ProjectReference` with `WorkerExtensions=true` + +> [!IMPORTANT] +> Setting `ReferenceOutputAssembly=false` will exclude this extensions projects package references from being included in your function app. This is not done automatically as it needs to be present for restore phase (and the functions SDK targets are not present until _after_ restore). diff --git a/samples/Net9FunctionApp/Net9FunctionApp.csproj b/samples/Net9FunctionApp/Net9FunctionApp.csproj index 7bd0775c7..b6b7bac9e 100644 --- a/samples/Net9FunctionApp/Net9FunctionApp.csproj +++ b/samples/Net9FunctionApp/Net9FunctionApp.csproj @@ -6,7 +6,7 @@ - + diff --git a/samples/README.md b/samples/README.md index b339e6650..ff4fc1a07 100644 --- a/samples/README.md +++ b/samples/README.md @@ -6,10 +6,13 @@ This folder contains a set of samples that demonstrate various scenarios. | Sample | Description | | ------ | ------------ | +|[AspNetCore Integration](./AspNetIntegration)| Demonstrates writing `HttpTrigger`s using AspNetCore integration. | |[Configuration](./Configuration)| Demonstrates how to configure the worker using Program.cs and WorkerOptions | |[Custom Middleware](./CustomMiddleware)| Demonstrates how to create and use custom middleware | |[Entity Framework](./EntityFramework)| Demonstrates how to work with entity framework | +|[External Extension Project](./ExternalExtensionProject)| An advanced scenario. Demonstrates supplying the worker extension project manually. | |[Extensions](./Extensions)| Examples of how to work with various extensions | |[Function App](./FunctionApp)| Examples of using the HTTP Trigger; default project for debugging the worker SDK | |[.NET 7 Worker](./Net7Worker)| Demonstrates how to setup a .NET 7 Function App | +|[.NET 9 Worker](./Net9FunctionApp)| Demonstrates how to setup a .NET 9 Function App using `HostApplicationBuilder` | |[.NET Framework Worker](./NetFxWorker)| Demonstrates how to setup a .NET Framework Function App | diff --git a/sdk/Sdk/ExtensionsCsprojGenerator.cs b/sdk/Sdk/ExtensionsCsprojGenerator.cs index 4b5b0a3de..e3491eccf 100644 --- a/sdk/Sdk/ExtensionsCsprojGenerator.cs +++ b/sdk/Sdk/ExtensionsCsprojGenerator.cs @@ -62,10 +62,8 @@ internal string GetCsProjContent() {targetFramework} - Release Microsoft.Azure.Functions.Worker.Extensions true - false diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 4563be3e4..e1c1715a5 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -1,7 +1,9 @@  - 2 + 2 + 1 + -preview.1 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 5b057d1b6..478129f77 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -70,7 +70,26 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + + + <_WorkerExtensionProject Include="@(ProjectReference)" Condition="'%(ProjectReference.WorkerExtensions)' == 'true'" /> + <_WorkerExtensionProjectNonExistent Include="@(_WorkerExtensionProject)" Condition="!Exists('%(Identity)')" /> + + + + + + false + %(_WorkerExtensionProject.Identity) + + + + + + + + + $([System.IO.Path]::GetDirectoryName($(ExtensionsCsProj))) $(IntermediateOutputPath)WorkerExtensions @@ -89,23 +108,18 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and <_AzureFunctionsVersionStandardized>$(AzureFunctionsVersion.ToLowerInvariant().Split('-')[0]) + <_FunctionsExtensionRemoveProps Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">$(_FunctionsExtensionRemoveProps)ManagePackageVersionsCentrally; <_SelectedFunctionVersion Include="@(_FunctionsVersion)" Condition="'%(_FunctionsVersion.Identity)' == '$(_AzureFunctionsVersionStandardized)'" /> - - - - - - @@ -160,7 +174,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + @@ -168,7 +182,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and DependsOnTargets="_FunctionsGenerateCommon;_FunctionsGenerateWorkerConfig" /> - + <_TargetExtensionsCsProj Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">$(ExtensionsCsProj) @@ -264,13 +278,19 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + + <_ForceGenerateExtensionProject>true true + + + + + -### Microsoft.Azure.Functions.Worker.Sdk +### Microsoft.Azure.Functions.Worker.Sdk 2.1.0-preview.1 - Addresses issue with `dotnet build --no-incremental` failing build (PR #2763, Issue #2601) - Addresses issue with setting `OutDir` msbuild property failing build (PR #2763, Issue #2125) diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs index e5326296b..1aa4dc241 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs @@ -219,10 +219,8 @@ private static string ExpectedCsProjV3() netcoreapp3.1 - Release Microsoft.Azure.Functions.Worker.Extensions true - false @@ -247,10 +245,8 @@ private static string ExpectedCsProjV4() net6.0 - Release Microsoft.Azure.Functions.Worker.Extensions true - false From ee63bff74d848e4c12234a4099fbadc0152c90ec Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Fri, 14 Feb 2025 17:43:44 -0600 Subject: [PATCH 095/190] Package upgrade (#2958) --- test/E2ETests/E2ETests/E2ETests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index e803d3ebc..e1aa3c837 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -11,7 +11,7 @@ - + From 61d3c41dcc6aa3918db20fa5d8faa59e147b08d6 Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Fri, 21 Feb 2025 16:55:23 -0800 Subject: [PATCH 096/190] Removing .NET 9 issue template (#2960) --- .../ISSUE_TEMPLATE/02b-net9-question-or-issue.yml | 15 --------------- 1 file changed, 15 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml diff --git a/.github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml b/.github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml deleted file mode 100644 index 139a111be..000000000 --- a/.github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml +++ /dev/null @@ -1,15 +0,0 @@ -name: .NET 9 issue or question -description: Ask questions or raise issues related to .NET 9 -labels: [".NET 9"] -body: -- type: markdown - attributes: - value: | - Please use this template for any issues you have using .NET 9 or for any questions not answered in our [tracking thread for .NET 9 GA support](https://github.com/Azure/azure-functions-dotnet-worker/issues/2817). -- id: description - type: textarea - attributes: - label: Description - placeholder: Please provide a succinct description of the question or issue. For issue reports, please include the versions of the Azure Functions packages your projects references. - validations: - required: true \ No newline at end of file From 1aa40a940e369003b98d636a29b7aa0a367b8463 Mon Sep 17 00:00:00 2001 From: jainharsh98 Date: Wed, 12 Mar 2025 08:25:07 +0530 Subject: [PATCH 097/190] Updates for Kafka Extension 4.1.0 (#2972) * Updates for Kafka Extension 4.1.0 * Updating release_notes.md --- .../Worker.Extensions.Kafka/release_notes.md | 7 ++-- .../src/KafkaMessageKeyType.cs | 20 ++++++++++ .../src/KafkaOutputAttribute.cs | 38 +++++++++++++++++++ .../src/KafkaTriggerAttribute.cs | 38 +++++++++++++++++++ .../src/OAuthBearerMethod.cs | 2 +- .../src/Worker.Extensions.Kafka.csproj | 4 +- 6 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 extensions/Worker.Extensions.Kafka/src/KafkaMessageKeyType.cs diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index 6bf707d25..98573c02c 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,7 +4,8 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.0.0 +### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.0 -- Add OAuthBearer trigger and output Attributes to the dotnet isolated model(#2799) -- Update kafka extension version to 4.0.0(#2799) +- Add KeyAvroSchema and KeyDataType for trigger and output Attributes to the dotnet isolated model.(#2972) +- Add SslCertificatePEM, SslKeyPEM, SslCaPEM and SslCertificateandKeyPEM for trigger and output Attributes to the dotnet isolated model.(#2972) +- Update kafka extension version to 4.1.0(#2972) diff --git a/extensions/Worker.Extensions.Kafka/src/KafkaMessageKeyType.cs b/extensions/Worker.Extensions.Kafka/src/KafkaMessageKeyType.cs new file mode 100644 index 000000000..7c98a16c7 --- /dev/null +++ b/extensions/Worker.Extensions.Kafka/src/KafkaMessageKeyType.cs @@ -0,0 +1,20 @@ +// 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.Text; + +namespace Microsoft.Azure.Functions.Worker +{ + /// + /// Defines the data type used in kafka extension as enum. + /// + public enum KafkaMessageKeyType + { + Int = 0, + Long, + String, + Binary + } +} diff --git a/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs b/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs index bb640abdb..9f6af78ed 100644 --- a/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs +++ b/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs @@ -34,6 +34,20 @@ public KafkaOutputAttribute(string brokerList, string topic) /// public string AvroSchema { get; set; } + /// + /// Gets or sets the Avro schema of message key. + /// Should be used only if a generic record should be generated. + /// + public string KeyAvroSchema { get; set; } + + /// + /// Specifies the data type of the message key. + /// This data type will be used to serialize the key before sending it to the Kafka topic. + /// If KeyAvroSchema is set, this value is ignored and the key will be serialized using Avro. + /// The default type is System.String. + /// + public KafkaMessageKeyType KeyDataType { get; set; } = KafkaMessageKeyType.String; + /// /// Gets or sets the maximum transmit message size in bytes. Default: 1MB /// @@ -123,6 +137,30 @@ public KafkaOutputAttribute(string brokerList, string topic) /// public string SslKeyPassword { get; set; } + /// + /// Client certificate in PEM format. + /// ssl.certificate.pem in librdkafka + /// + public string SslCertificatePEM { get; set; } + + /// + /// Client Private Key in PEM format. + /// ssl.key.pem in librdkafka + /// + public string SslKeyPEM { get; set; } + + /// + /// CA certificate for verifying the broker's certificate in PEM format + /// ssl.ca.pem in librdkafka + /// + public string SslCaPEM { get; set; } + + /// + /// Client certificate and key in PEM format. + /// Additional Configuration for extension as KeyVault supports uploading certificate only with private key. + /// + public string SslCertificateandKeyPEM { get; set; } + /// /// Linger.MS property provides the time between batches of messages /// being sent to cluster. Larger value allows more batching results in high throughput. diff --git a/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs b/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs index 9b9a594e5..5c6cc934e 100644 --- a/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs +++ b/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs @@ -45,6 +45,19 @@ public KafkaTriggerAttribute(string brokerList, string topic) /// public string AvroSchema { get; set; } + /// + /// Gets or sets the Avro schema of message key. + /// Should be used only if a generic record should be generated. + /// + public string KeyAvroSchema { get; set; } + + /// + /// Specifies the data type of the message key that will be deserialized from the Kafka topic. + /// If KeyAvroSchema is set, this value is ignored and the key will be generated as a generic record. + /// The default type is System.String. + /// + public KafkaMessageKeyType KeyDataType { get; set; } = KafkaMessageKeyType.String; + /// /// SASL mechanism to use for authentication. /// Allowed values: Gssapi, Plain, ScramSha256, ScramSha512, OAuthBearer @@ -103,6 +116,31 @@ public KafkaTriggerAttribute(string brokerList, string topic) /// public string SslKeyPassword { get; set; } + /// + /// Client certificate in PEM format. + /// ssl.certificate.pem in librdkafka + /// + public string SslCertificatePEM { get; set; } + + /// + /// Client Private Key in PEM format. + /// ssl.key.pem in librdkafka + /// + public string SslKeyPEM { get; set; } + + /// + /// CA certificate for verifying the broker's certificate in PEM format + /// ssl.ca.pem in librdkafka + /// + public string SslCaPEM { get; set; } + + /// + /// Client certificate and key in PEM format. + /// Additional Configuration for extension as KeyVault supports uploading certificate only with private key. + /// + public string SslCertificateandKeyPEM { get; set; } + + /// /// Maximum number of unprocessed messages a worker is expected to have at an instance. /// When target-based scaling is not disabled, this is used to divide the diff --git a/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs b/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs index 47030255d..8e43b3fc0 100644 --- a/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs +++ b/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs @@ -15,4 +15,4 @@ public enum OAuthBearerMethod Default, Oidc } -} \ No newline at end of file +} diff --git a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj index e78a27be0..278b9a2e2 100644 --- a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj +++ b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj @@ -6,7 +6,7 @@ Kafka extensions for .NET isolated functions - 4.0.0 + 4.1.0 false @@ -21,7 +21,7 @@ - + \ No newline at end of file From 855f201d5ce4c5d522ebd65005c8f09b7d1f6753 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 17 Mar 2025 11:33:04 -0700 Subject: [PATCH 098/190] Update WorkerExtensions.csproj to net8 (#2973) * Update WorkerExtensions.csproj to net8 * update release notes * Remove unused constants --- sdk/Sdk/Constants.cs | 4 ++-- sdk/Sdk/ExtensionsCsprojGenerator.cs | 2 +- sdk/release_notes.md | 1 + .../ExtensionsCsProjGeneratorTests.cs | 6 +++--- 4 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sdk/Sdk/Constants.cs b/sdk/Sdk/Constants.cs index 91573e53d..4a95ad3fd 100644 --- a/sdk/Sdk/Constants.cs +++ b/sdk/Sdk/Constants.cs @@ -43,10 +43,10 @@ internal static class Constants // NetFramework internal const string NetCoreApp31 = "netcoreapp3.1"; - internal const string Net60 = "net6.0"; + internal const string Net80 = "net8.0"; internal const string NetCoreApp = ".NETCoreApp"; - internal const string NetCoreVersion6 = "v6.0"; internal const string NetCoreVersion31 = "v3.1"; + internal const string NetCoreVersion8 = "v8.0"; internal const string AzureFunctionsVersion3 = "v3"; // Binding directions diff --git a/sdk/Sdk/ExtensionsCsprojGenerator.cs b/sdk/Sdk/ExtensionsCsprojGenerator.cs index e3491eccf..52b5b133c 100644 --- a/sdk/Sdk/ExtensionsCsprojGenerator.cs +++ b/sdk/Sdk/ExtensionsCsprojGenerator.cs @@ -46,7 +46,7 @@ public void Generate() internal string GetCsProjContent() { string extensionReferences = GetExtensionReferences(); - string targetFramework = Constants.Net60; + string targetFramework = Constants.Net80; if (_targetFrameworkIdentifier.Equals(Constants.NetCoreApp, StringComparison.OrdinalIgnoreCase)) { diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 421c91c27..7e074a87c 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -10,6 +10,7 @@ - Addresses issue with setting `OutDir` msbuild property failing build (PR #2763, Issue #2125) - Adds support for externally supplied worker extensions project. (PR #2763, Issues #1252, #1888) - This mode is opt-in only. Using it eliminates the inner-build. This is useful for scenarios where performing a restore inside of build was problematic. +- Updates the generated extension csproj to be net8.0 (from net6.0) ### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.5 diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs index 1aa4dc241..c50422faa 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs @@ -200,7 +200,7 @@ static ExtensionsCsprojGenerator GetGenerator(FuncVersion version, string output return version switch { FuncVersion.V3 => new ExtensionsCsprojGenerator(extensions, outputPath, "v3", Constants.NetCoreApp, Constants.NetCoreVersion31), - FuncVersion.V4 => new ExtensionsCsprojGenerator(extensions, outputPath, "v4", Constants.NetCoreApp, Constants.NetCoreVersion6), + FuncVersion.V4 => new ExtensionsCsprojGenerator(extensions, outputPath, "v4", Constants.NetCoreApp, Constants.NetCoreVersion8), _ => throw new ArgumentOutOfRangeException(nameof(version)), }; } @@ -244,7 +244,7 @@ private static string ExpectedCsProjV4() return @" - net6.0 + net8.0 Microsoft.Azure.Functions.Worker.Extensions true @@ -259,7 +259,7 @@ private static string ExpectedCsProjV4() - + "; From f012606a0498b1276d897b722a6bbf4e597b761d Mon Sep 17 00:00:00 2001 From: yzt Date: Thu, 20 Mar 2025 01:20:38 +0800 Subject: [PATCH 099/190] Update SignalR extensions to 2.0.1 (#2998) --- .../release_notes.md | 5 +++-- .../src/Worker.Extensions.SignalRService.csproj | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/extensions/Worker.Extensions.SignalRService/release_notes.md b/extensions/Worker.Extensions.SignalRService/release_notes.md index 1b3fe21c2..926c24e55 100644 --- a/extensions/Worker.Extensions.SignalRService/release_notes.md +++ b/extensions/Worker.Extensions.SignalRService/release_notes.md @@ -4,6 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.SignalRService +### Microsoft.Azure.Functions.Worker.Extensions.SignalRService 2.0.1 -- +- Update SignalR worker extensions to 2.0.1 version. +- Update other dependencies versions. \ No newline at end of file diff --git a/extensions/Worker.Extensions.SignalRService/src/Worker.Extensions.SignalRService.csproj b/extensions/Worker.Extensions.SignalRService/src/Worker.Extensions.SignalRService.csproj index 925fdb45f..b93b76674 100644 --- a/extensions/Worker.Extensions.SignalRService/src/Worker.Extensions.SignalRService.csproj +++ b/extensions/Worker.Extensions.SignalRService/src/Worker.Extensions.SignalRService.csproj @@ -6,7 +6,7 @@ Azure SignalR Service extensions for .NET isolated functions annotations - 1.15.0 + 2.0.1 false @@ -19,15 +19,15 @@ - - - - - + + + + + - + From 7196a008f300f23bd14e567f0382524b18c3d79c Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 20 Mar 2025 08:54:24 -0700 Subject: [PATCH 100/190] Write metadata and worker.config only if content has changed (#2999) * Write metadata and worker.config only if content has changed * update release notes * Add incremental build test * Remove unused using --- sdk/Sdk/FunctionMetadataJsonWriter.cs | 24 +++++++-- ...crosoft.Azure.Functions.Worker.Sdk.targets | 3 +- sdk/release_notes.md | 1 + .../FunctionMetadataGeneratorTests.cs | 51 ++++++++++++++++--- 4 files changed, 68 insertions(+), 11 deletions(-) diff --git a/sdk/Sdk/FunctionMetadataJsonWriter.cs b/sdk/Sdk/FunctionMetadataJsonWriter.cs index 38fcadc25..b9706732d 100644 --- a/sdk/Sdk/FunctionMetadataJsonWriter.cs +++ b/sdk/Sdk/FunctionMetadataJsonWriter.cs @@ -1,6 +1,7 @@ // 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 System.Text.Json; @@ -34,9 +35,26 @@ private static JsonSerializerOptions CreateSerializerOptions() public static void WriteMetadata(IEnumerable functions, string metadataFileDirectory) { string metadataFile = Path.Combine(metadataFileDirectory, FileName); - using var fs = new FileStream(metadataFile, FileMode.Create, FileAccess.Write); - using var writer = new Utf8JsonWriter(fs, new JsonWriterOptions { Indented = true }); - JsonSerializer.Serialize(writer, functions, s_serializerOptions); + string newContent = JsonSerializer.Serialize(functions, s_serializerOptions); + if (TryReadFile(metadataFile, out string? current) && string.Equals(current, newContent, StringComparison.Ordinal)) + { + // Incremental build support. Skip writing if the content is the same. + return; + } + + File.WriteAllText(metadataFile, newContent); + } + + private static bool TryReadFile(string filePath, out string? content) + { + if (File.Exists(filePath)) + { + content = File.ReadAllText(filePath); + return true; + } + + content = null; + return false; } } } diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 478129f77..fc68c7794 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -214,7 +214,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and .Replace('$functionExe$', '$(_FunctionsExecutable)') .Replace('$functionWorker$', '$(TargetName)$(TargetExt)') .Replace('$enableWorkerIndexing$', '$(FunctionsEnableWorkerIndexing)'))" - Overwrite="true" /> + Overwrite="true" + WriteOnlyWhenDifferent="true" /> diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 7e074a87c..c0f89804d 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -10,6 +10,7 @@ - Addresses issue with setting `OutDir` msbuild property failing build (PR #2763, Issue #2125) - Adds support for externally supplied worker extensions project. (PR #2763, Issues #1252, #1888) - This mode is opt-in only. Using it eliminates the inner-build. This is useful for scenarios where performing a restore inside of build was problematic. +- Write `worker.config` and `functions.metadata` only if contents have changed. (#2999) - Updates the generated extension csproj to be net8.0 (from net6.0) ### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.5 diff --git a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs index ee2bd985a..0ea8b6888 100644 --- a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs @@ -30,7 +30,17 @@ namespace Microsoft.Azure.Functions.SdkTests { public class FunctionMetadataGeneratorTests { - private static Assembly _thisAssembly = typeof(FunctionMetadataGeneratorTests).Assembly; + private const string MetadataFileDirectory = "."; + private const string MetadataFile = $"{MetadataFileDirectory}/functions.metadata"; + private static readonly Assembly _thisAssembly = typeof(FunctionMetadataGeneratorTests).Assembly; + + public FunctionMetadataGeneratorTests() + { + if (File.Exists(MetadataFile)) + { + File.Delete(MetadataFile); + } + } [Fact] public void BasicHttpFunction() @@ -73,7 +83,34 @@ void ValidateReturn(ExpandoObject b) }); } - FunctionMetadataJsonWriter.WriteMetadata(functions, "."); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); + } + + [Fact] + public async Task Incremental_WritesOnlyIfChanged() + { + var generator = new FunctionMetadataGenerator(); + var module = ModuleDefinition.ReadModule(_thisAssembly.Location); + var typeDef = TestUtility.GetTypeDefinition(typeof(BasicHttp)); + var functions = generator.GenerateFunctionMetadata(typeDef); + + // Simulate an existing functions.metadata file with different content. + File.WriteAllText(MetadataFile, "[]"); // empty json array. + DateTime lastWrite = File.GetLastWriteTimeUtc(MetadataFile); + + await Task.Delay(100); // ensure time passes so timestamp isn't too identical. + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); + string contents = File.ReadAllText(MetadataFile); + + DateTime newWrite = File.GetLastWriteTimeUtc(MetadataFile); + Assert.NotEqual(lastWrite, newWrite); + Assert.NotEqual("[]", contents); // ensure the file was written with new content. + + // write again to test incremental. + await Task.Delay(100); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); + Assert.Equal(newWrite, File.GetLastWriteTimeUtc(MetadataFile)); + Assert.Equal(contents, File.ReadAllText(MetadataFile)); } [Fact] @@ -117,7 +154,7 @@ void ValidateReturn(ExpandoObject b) }); } - FunctionMetadataJsonWriter.WriteMetadata(functions, "."); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); } [Fact] @@ -150,7 +187,7 @@ void ValidateTrigger(ExpandoObject b) }); } - FunctionMetadataJsonWriter.WriteMetadata(functions, "."); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); } [Fact] @@ -194,7 +231,7 @@ void ValidateQueueOutput(ExpandoObject b) }); } - FunctionMetadataJsonWriter.WriteMetadata(functions, "."); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); } [Fact] @@ -1104,7 +1141,7 @@ public void FunctionWithFixedDelayRetry() Assert.Null(retry.MinimumInterval); Assert.Null(retry.MaximumInterval); - FunctionMetadataJsonWriter.WriteMetadata(functions, "."); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); } [Fact] @@ -1126,7 +1163,7 @@ public void FunctionWithExponentialBackoffRetry() Assert.Equal("00:00:04", retry.MinimumInterval); Assert.Equal("00:15:00", retry.MaximumInterval); - FunctionMetadataJsonWriter.WriteMetadata(functions, "."); + FunctionMetadataJsonWriter.WriteMetadata(functions, MetadataFileDirectory); } [Fact] From d62e5622b774b7d176c7e07ed3d384c771921bbd Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Mon, 24 Mar 2025 13:40:08 -0700 Subject: [PATCH 101/190] Update extension dependencies (#3001) * Update EventGrid and ServiceBus dependencies --- extensions/Worker.Extensions.EventGrid/release_notes.md | 1 + .../src/Worker.Extensions.EventGrid.csproj | 2 +- extensions/Worker.Extensions.ServiceBus/release_notes.md | 4 ++-- .../src/Worker.Extensions.ServiceBus.csproj | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index ac6291af0..bac3d3d47 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -8,3 +8,4 @@ - Update dependency "Azure.Messaging.EventGrid" to v4.29.0 - Update dependency "Microsoft.Azure.Functions.Worker.Core" to v1.20.0 +- Update dependency "Microsoft.Azure.WebJobs.Extensions.EventGrid" to 3.4.4 diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index 97b7900a7..d45de0ec0 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -24,7 +24,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index c92b7d33c..29f7500fa 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.22.2 -- \ No newline at end of file +- Update dependency `Microsoft.Azure.WebJobs.Extensions.ServiceBus` to 5.16.5 \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj index d112f2334..69392a826 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj +++ b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj @@ -6,7 +6,7 @@ Azure Service Bus extensions for .NET isolated functions - 5.22.1 + 5.22.2 false @@ -36,7 +36,7 @@ - + From 2600cbe5369188ea640e560ad3862e4797a970fd Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Tue, 25 Mar 2025 09:45:32 -0700 Subject: [PATCH 102/190] Reset ext release notes (#3004) --- extensions/Worker.Extensions.EventGrid/release_notes.md | 6 ++---- extensions/Worker.Extensions.ServiceBus/release_notes.md | 4 ++-- .../Worker.Extensions.SignalRService/release_notes.md | 5 ++--- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index bac3d3d47..65290e0c6 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,8 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 4.5.0 +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid -- Update dependency "Azure.Messaging.EventGrid" to v4.29.0 -- Update dependency "Microsoft.Azure.Functions.Worker.Core" to v1.20.0 -- Update dependency "Microsoft.Azure.WebJobs.Extensions.EventGrid" to 3.4.4 +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index 29f7500fa..c92b7d33c 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.22.2 +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus -- Update dependency `Microsoft.Azure.WebJobs.Extensions.ServiceBus` to 5.16.5 \ No newline at end of file +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.SignalRService/release_notes.md b/extensions/Worker.Extensions.SignalRService/release_notes.md index 926c24e55..2d0995b06 100644 --- a/extensions/Worker.Extensions.SignalRService/release_notes.md +++ b/extensions/Worker.Extensions.SignalRService/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.SignalRService 2.0.1 +### Microsoft.Azure.Functions.Worker.Extensions.SignalRService -- Update SignalR worker extensions to 2.0.1 version. -- Update other dependencies versions. \ No newline at end of file +- \ No newline at end of file From 05fe54c765f3925c4ba418fb34ab62adcd30fcf1 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Thu, 3 Apr 2025 09:24:53 -0700 Subject: [PATCH 103/190] Setting _ToolingSuffix for V10.0 TargetFrameworkVersion. (#3012) --- sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 1 + sdk/release_notes.md | 1 + 2 files changed, 2 insertions(+) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index fc68c7794..ae8b32e48 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -42,6 +42,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and <_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)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v9.0'">net9-isolated + <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v10.0'">net10-isolated <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETFramework'">netfx-isolated $(_ToolingSuffix) diff --git a/sdk/release_notes.md b/sdk/release_notes.md index c0f89804d..8aaa0dbff 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -12,6 +12,7 @@ - This mode is opt-in only. Using it eliminates the inner-build. This is useful for scenarios where performing a restore inside of build was problematic. - Write `worker.config` and `functions.metadata` only if contents have changed. (#2999) - Updates the generated extension csproj to be net8.0 (from net6.0) +- Setting _ToolingSuffix for V10.0 TargetFrameworkVersion. (#2983) ### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.5 From 684f8473753e905e0b719073888b682e5ce5bfad Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Thu, 3 Apr 2025 14:11:34 -0700 Subject: [PATCH 104/190] Reset Kafka Release Notes (#3014) --- extensions/Worker.Extensions.Kafka/release_notes.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index 98573c02c..e73c591ab 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,8 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.0 +### Microsoft.Azure.Functions.Worker.Extensions.Kafka -- Add KeyAvroSchema and KeyDataType for trigger and output Attributes to the dotnet isolated model.(#2972) -- Add SslCertificatePEM, SslKeyPEM, SslCaPEM and SslCertificateandKeyPEM for trigger and output Attributes to the dotnet isolated model.(#2972) -- Update kafka extension version to 4.1.0(#2972) +- From 86e0359ec88d87f56ea8e814acf49912badd424e Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Mon, 7 Apr 2025 10:55:55 -0700 Subject: [PATCH 105/190] Update RabbitMQ (#3019) --- extensions/Worker.Extensions.RabbitMQ/release_notes.md | 4 ++-- .../src/Worker.Extensions.RabbitMQ.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.RabbitMQ/release_notes.md b/extensions/Worker.Extensions.RabbitMQ/release_notes.md index bb1ab4914..3f80c4614 100644 --- a/extensions/Worker.Extensions.RabbitMQ/release_notes.md +++ b/extensions/Worker.Extensions.RabbitMQ/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ +### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ 2.0.4 -- +- Update `Microsoft.Azure.WebJobs.Extensions.RabbitMQ` to `2.0.4` (#3019) diff --git a/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj b/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj index 0868de5ac..1616cbba6 100644 --- a/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj +++ b/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj @@ -6,7 +6,7 @@ RabbitMQ extensions for .NET isolated functions - 2.0.3 + 2.0.4 false @@ -19,7 +19,7 @@ - + From 00454eaa9832ad78e732c7c17ed07e71ab30c3b3 Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Tue, 8 Apr 2025 11:33:16 -0700 Subject: [PATCH 106/190] Reset Release Notes (#3021) --- extensions/Worker.Extensions.RabbitMQ/release_notes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.RabbitMQ/release_notes.md b/extensions/Worker.Extensions.RabbitMQ/release_notes.md index 3f80c4614..fbb45f266 100644 --- a/extensions/Worker.Extensions.RabbitMQ/release_notes.md +++ b/extensions/Worker.Extensions.RabbitMQ/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ 2.0.4 +### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ -- Update `Microsoft.Azure.WebJobs.Extensions.RabbitMQ` to `2.0.4` (#3019) +- From 53223442fb0b471eada194a5440639675ec9f8ad Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Tue, 8 Apr 2025 13:40:59 -0700 Subject: [PATCH 107/190] Move FunctionMetadataGeneratorTests to Sdk.Generator.Tests (#3022) * Move FunctionMetadataGeneratorTests to Sdk.Generator.Tests * Fix sdk tests on unix machines * Fix compile issue * Fix build warnings * Use OperatingSystem.IsWindows() --- DotNetWorker.sln | 9 +- .../jobs/run-integration-tests-windows.yml | 6 +- eng/ci/templates/jobs/run-unit-tests.yml | 1 - global.json | 2 +- samples/FunctionApp/FunctionApp.csproj | 2 +- sdk/Sdk.Generators/Properties/AssemblyInfo.cs | 2 +- sdk/Sdk/Extensions/StringExtensions.cs | 6 +- sdk/Sdk/FunctionMetadataGenerator.cs | 2 +- sdk/Sdk/Properties/AssemblyInfo.cs | 4 +- sdk/Sdk/Tasks/ZipDeploy/ZipDeployTask.cs | 2 +- .../AspNetCore/CancellationEndToEndTests.cs | 1 + .../SdkTests.csproj | 48 --------- .../Contents/functions.metadata | 0 .../InnerBuildTests.cs | 2 +- .../ProcessWrapper.cs | 2 +- .../PublishTests.cs | 10 +- .../Sdk.E2ETests.csproj} | 6 +- .../Sdk.E2ETests_default.runsettings} | 0 .../Sdk.E2ETests_dockertests.runsettings} | 0 .../TestUtility.cs | 6 +- .../ZipDeployTests.cs | 45 ++++---- .../xunit.runner.json | 0 .../ExtensionStartupRunnerGeneratorTests.cs | 4 +- .../NotGeneratedTests.cs | 4 +- .../FunctionExecutor/DependentAssemblyTest.cs | 3 +- .../FunctionExecutorGeneratorTests.cs | 3 +- .../FunctionExecutor/NotGeneratedTests.cs | 3 +- .../CustomAttributeExtensionsTests.cs | 6 +- .../ExtensionsCsProjGeneratorTests.cs | 15 ++- .../ExtensionsMetadataEnhancerTests.cs | 7 +- .../FunctionMetadataGeneratorTests.cs | 99 +++++++++--------- .../StringExtensionsTests.cs | 4 +- .../FunctionMetadata/TypeHelpers.cs} | 12 +-- .../FunctionMetadata}/ZipDeployTaskTests.cs | 19 ++-- .../ZipDeploymentStatusTests.cs | 22 ++-- .../AmbiguousNamespaceTests.cs | 3 +- .../AutoConfigureStartupTypeTests.cs | 3 +- .../DependentAssemblyTest.NetFx.cs | 3 +- .../DependentAssemblyTest.cs | 3 +- .../DiagnosticResultTests.cs | 3 +- .../EventHubsBindingsTests.cs | 3 +- .../ExtensionsTests.cs | 2 +- .../HttpTriggerTests.cs | 3 +- .../IntegratedTriggersAndBindingsTests.cs | 3 +- .../KafkaTests.cs | 4 +- .../NestedTypesTest.cs | 3 +- .../NotGeneratedTests.cs | 3 +- .../RetryOptionsTests.cs | 3 +- .../ServiceBustTests.cs | 10 +- .../SignalRTest.cs | 3 +- .../StorageBindingTests.cs | 3 +- .../Properties/AssemblyInfo.cs | 2 +- .../Resources/TestPublishContents.zip | Bin .../Sdk.Generator.Tests.csproj | 42 +++++--- .../SymbolExtensionsTest.cs | 2 +- test/Sdk.Generator.Tests/TestHelpers.cs | 2 +- .../ServiceBusSessionMessageConverterTests.cs | 4 +- 57 files changed, 230 insertions(+), 234 deletions(-) delete mode 100644 test/FunctionMetadataGeneratorTests/SdkTests.csproj rename test/{SdkE2ETests => Sdk.E2ETests}/Contents/functions.metadata (100%) rename test/{SdkE2ETests => Sdk.E2ETests}/InnerBuildTests.cs (98%) rename test/{SdkE2ETests => Sdk.E2ETests}/ProcessWrapper.cs (98%) rename test/{SdkE2ETests => Sdk.E2ETests}/PublishTests.cs (94%) rename test/{SdkE2ETests/SdkE2ETests.csproj => Sdk.E2ETests/Sdk.E2ETests.csproj} (83%) rename test/{SdkE2ETests/SdkE2ETests_default.runsettings => Sdk.E2ETests/Sdk.E2ETests_default.runsettings} (100%) rename test/{SdkE2ETests/SdkE2ETests_dockertests.runsettings => Sdk.E2ETests/Sdk.E2ETests_dockertests.runsettings} (100%) rename test/{SdkE2ETests => Sdk.E2ETests}/TestUtility.cs (97%) rename test/{SdkE2ETests => Sdk.E2ETests}/ZipDeployTests.cs (50%) rename test/{SdkE2ETests => Sdk.E2ETests}/xunit.runner.json (100%) rename test/Sdk.Generator.Tests/{ExtensionStartup => ExtensionStartupRunner}/ExtensionStartupRunnerGeneratorTests.cs (98%) rename test/Sdk.Generator.Tests/{ExtensionStartup => ExtensionStartupRunner}/NotGeneratedTests.cs (93%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/CustomAttributeExtensionsTests.cs (98%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/ExtensionsCsProjGeneratorTests.cs (96%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/ExtensionsMetadataEnhancerTests.cs (94%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/FunctionMetadataGeneratorTests.cs (96%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/StringExtensionsTests.cs (79%) rename test/{FunctionMetadataGeneratorTests/TestUtility.cs => Sdk.Generator.Tests/FunctionMetadata/TypeHelpers.cs} (64%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/ZipDeployTaskTests.cs (92%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests/FunctionMetadata}/ZipDeploymentStatusTests.cs (93%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/AmbiguousNamespaceTests.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/AutoConfigureStartupTypeTests.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/DependentAssemblyTest.NetFx.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/DependentAssemblyTest.cs (99%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/DiagnosticResultTests.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/EventHubsBindingsTests.cs (99%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/ExtensionsTests.cs (94%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/HttpTriggerTests.cs (99%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/IntegratedTriggersAndBindingsTests.cs (99%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/KafkaTests.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/NestedTypesTest.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/NotGeneratedTests.cs (95%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/RetryOptionsTests.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/ServiceBustTests.cs (96%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/SignalRTest.cs (98%) rename test/Sdk.Generator.Tests/{FunctionMetadataProviderGeneratorTests => FunctionMetadataProvider}/StorageBindingTests.cs (99%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests}/Properties/AssemblyInfo.cs (77%) rename test/{FunctionMetadataGeneratorTests => Sdk.Generator.Tests}/Resources/TestPublishContents.zip (100%) rename test/Sdk.Generator.Tests/{SymbolExtensionsTest => }/SymbolExtensionsTest.cs (98%) diff --git a/DotNetWorker.sln b/DotNetWorker.sln index d2b6206ec..3f3663791 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -48,8 +48,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorker.OpenTelemetry. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorkerTests", "test\DotNetWorkerTests\DotNetWorkerTests.csproj", "{B0A6867D-2C35-4BF1-892E-CE84795525BD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkTests", "test\FunctionMetadataGeneratorTests\SdkTests.csproj", "{75B18A32-D0EC-420E-9E7E-FF6846301C4D}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Analyzers.Tests", "test\Sdk.Analyzers.Tests\Sdk.Analyzers.Tests.csproj", "{C05499A2-0232-4F73-A6CA-043F0B26C485}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generator.Tests", "test\Sdk.Generator.Tests\Sdk.Generator.Tests.csproj", "{9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}" @@ -66,7 +64,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFuncti EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{429D067C-0846-40EF-A264-AB0C5D551CB0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SdkE2ETests", "test\SdkE2ETests\SdkE2ETests.csproj", "{750993F6-4E3B-411B-9471-74CEA4F9C23A}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Sdk.E2ETests", "test\Sdk.E2ETests\Sdk.E2ETests.csproj", "{750993F6-4E3B-411B-9471-74CEA4F9C23A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -122,10 +120,6 @@ Global {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Debug|Any CPU.Build.0 = Debug|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.ActiveCfg = Release|Any CPU {B0A6867D-2C35-4BF1-892E-CE84795525BD}.Release|Any CPU.Build.0 = Release|Any CPU - {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {75B18A32-D0EC-420E-9E7E-FF6846301C4D}.Release|Any CPU.Build.0 = Release|Any CPU {C05499A2-0232-4F73-A6CA-043F0B26C485}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C05499A2-0232-4F73-A6CA-043F0B26C485}.Debug|Any CPU.Build.0 = Debug|Any CPU {C05499A2-0232-4F73-A6CA-043F0B26C485}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -171,7 +165,6 @@ Global {82157559-DF60-496D-817F-84B34CFF76FD} = {083592CA-7DAB-44CE-8979-44FAFA46AEC3} {9AE6E00C-5E6F-4615-9C69-464E9B208E8C} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} {B0A6867D-2C35-4BF1-892E-CE84795525BD} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} - {75B18A32-D0EC-420E-9E7E-FF6846301C4D} = {E785547C-7546-469F-827C-FDF999D5D7E8} {C05499A2-0232-4F73-A6CA-043F0B26C485} = {E785547C-7546-469F-827C-FDF999D5D7E8} {9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6} = {E785547C-7546-469F-827C-FDF999D5D7E8} {E785547C-7546-469F-827C-FDF999D5D7E8} = {FD7243E4-BF18-43F8-8744-BA1D17ACF378} diff --git a/eng/ci/templates/jobs/run-integration-tests-windows.yml b/eng/ci/templates/jobs/run-integration-tests-windows.yml index 5fa5edb43..85993c9b6 100644 --- a/eng/ci/templates/jobs/run-integration-tests-windows.yml +++ b/eng/ci/templates/jobs/run-integration-tests-windows.yml @@ -46,8 +46,8 @@ jobs: command: test arguments: -v n --no-build -c Release --filter "FullyQualifiedName!~Microsoft.Azure.Functions.Worker.E2ETests.AspNetCore" # skip AspNetCore tests projects: | - **\E2ETests.csproj - **\SdkE2ETests.csproj + **/E2ETests.csproj + **/Sdk.E2ETests.csproj env: DOTNET_VERSION: $(dotnetVersion) @@ -58,6 +58,6 @@ jobs: command: test arguments: -v n --no-build -c Release --filter "FullyQualifiedName~Microsoft.Azure.Functions.Worker.E2ETests.AspNetCore" # only AspNetCore tests projects: | - **\E2ETests.csproj + **/E2ETests.csproj env: DOTNET_VERSION: $(dotnetVersion) diff --git a/eng/ci/templates/jobs/run-unit-tests.yml b/eng/ci/templates/jobs/run-unit-tests.yml index b50cc4ce9..b7ec444bc 100644 --- a/eng/ci/templates/jobs/run-unit-tests.yml +++ b/eng/ci/templates/jobs/run-unit-tests.yml @@ -46,7 +46,6 @@ jobs: command: test arguments: -v n projects: | - **\SdkTests.csproj **\Sdk.Analyzers.Tests.csproj **\Sdk.Generator.Tests.csproj diff --git a/global.json b/global.json index ec9ccb01a..34000aad5 100644 --- a/global.json +++ b/global.json @@ -2,7 +2,7 @@ "sdk": { "version": "9.0.100", "allowPrerelease": true, - "rollForward": "latestPatch" + "rollForward": "latestFeature" }, "msbuild-sdks": { "Microsoft.Build.NoTargets": "3.7.56", diff --git a/samples/FunctionApp/FunctionApp.csproj b/samples/FunctionApp/FunctionApp.csproj index 0683410bf..1dd3c4ff7 100644 --- a/samples/FunctionApp/FunctionApp.csproj +++ b/samples/FunctionApp/FunctionApp.csproj @@ -8,7 +8,7 @@ - + diff --git a/sdk/Sdk.Generators/Properties/AssemblyInfo.cs b/sdk/Sdk.Generators/Properties/AssemblyInfo.cs index 7997f2a1d..1c68e8efb 100644 --- a/sdk/Sdk.Generators/Properties/AssemblyInfo.cs +++ b/sdk/Sdk.Generators/Properties/AssemblyInfo.cs @@ -3,4 +3,4 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.SdkGeneratorTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Sdk.Generator.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/sdk/Sdk/Extensions/StringExtensions.cs b/sdk/Sdk/Extensions/StringExtensions.cs index d91bbb429..efbd43b24 100644 --- a/sdk/Sdk/Extensions/StringExtensions.cs +++ b/sdk/Sdk/Extensions/StringExtensions.cs @@ -1,8 +1,8 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System.Linq; using System; +using System.Linq; namespace Microsoft.Azure.Functions.Worker.Sdk { @@ -11,11 +11,11 @@ internal static class StringExtensions /// /// Returns a copy of the string where the first character is in lower case. /// - public static string ToLowerFirstCharacter(this string str) + public static string? ToLowerFirstCharacter(this string? str) { if (!string.IsNullOrEmpty(str)) { - return Char.ToLowerInvariant(str.First()) + str.Substring(1); + return Char.ToLowerInvariant(str.First()) + str!.Substring(1); } else { diff --git a/sdk/Sdk/FunctionMetadataGenerator.cs b/sdk/Sdk/FunctionMetadataGenerator.cs index 38c9693ea..bad72cf7b 100644 --- a/sdk/Sdk/FunctionMetadataGenerator.cs +++ b/sdk/Sdk/FunctionMetadataGenerator.cs @@ -741,7 +741,7 @@ private static string GetBindingType(CustomAttribute attribute) // The first character of "Type" property value must be lower case for the scaling infrastructure to work correctly bindingType = bindingType.ToLowerFirstCharacter(); - return bindingType; + return bindingType!; } private static void AddHttpOutputBinding(IList bindingMetadata, string name) diff --git a/sdk/Sdk/Properties/AssemblyInfo.cs b/sdk/Sdk/Properties/AssemblyInfo.cs index 7bd7d7957..b9e27da61 100644 --- a/sdk/Sdk/Properties/AssemblyInfo.cs +++ b/sdk/Sdk/Properties/AssemblyInfo.cs @@ -3,6 +3,6 @@ using System.Runtime.CompilerServices; -[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.SdkTests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] -[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.SdkE2ETests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Sdk.Generator.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Sdk.E2ETests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/sdk/Sdk/Tasks/ZipDeploy/ZipDeployTask.cs b/sdk/Sdk/Tasks/ZipDeploy/ZipDeployTask.cs index 28df601f7..662052c79 100644 --- a/sdk/Sdk/Tasks/ZipDeploy/ZipDeployTask.cs +++ b/sdk/Sdk/Tasks/ZipDeploy/ZipDeployTask.cs @@ -63,7 +63,7 @@ internal System.Threading.Tasks.Task ZipDeployAsync(string zipToPublishPat return ZipDeployAsync(zipToPublishPath, userName, password, publishUrl, siteName, userAgentVersion, useBlobContainerDeploy: false, client, logMessages); } - internal async System.Threading.Tasks.Task ZipDeployAsync(string zipToPublishPath, string userName, string password, string? publishUrl, string siteName, string userAgentVersion, bool useBlobContainerDeploy, IHttpClient client, bool logMessages) + internal async System.Threading.Tasks.Task ZipDeployAsync(string zipToPublishPath, string userName, string password, string? publishUrl, string? siteName, string userAgentVersion, bool useBlobContainerDeploy, IHttpClient client, bool logMessages) { if (!File.Exists(zipToPublishPath) || client == null) { diff --git a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs index 2a372f16b..4bfce6034 100644 --- a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs +++ b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs @@ -55,6 +55,7 @@ await TestUtility.RetryAsync(() => Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains(expectedMessage, StringComparison.OrdinalIgnoreCase)); // TODO: 2/3 of the test invocations will fail until the host with the ForwarderProxy fix is released - uncomment this line when the fix is released + Assert.NotEqual(null, invocationResult); // just here to 'use' invocationResult to avoid a warning. // Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains($"'Functions.{functionName}' ({invocationResult}", StringComparison.OrdinalIgnoreCase)); } diff --git a/test/FunctionMetadataGeneratorTests/SdkTests.csproj b/test/FunctionMetadataGeneratorTests/SdkTests.csproj deleted file mode 100644 index 6b2913f56..000000000 --- a/test/FunctionMetadataGeneratorTests/SdkTests.csproj +++ /dev/null @@ -1,48 +0,0 @@ - - - - net8.0 - Microsoft.Azure.Functions.SdkTests - Microsoft.Azure.Functions.SdkTests - true - ..\..\key.snk - - $(NoWarn);NU1608;NU1701 - - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - - - - - - - - - - - - - - - - - - - - - Always - - - diff --git a/test/SdkE2ETests/Contents/functions.metadata b/test/Sdk.E2ETests/Contents/functions.metadata similarity index 100% rename from test/SdkE2ETests/Contents/functions.metadata rename to test/Sdk.E2ETests/Contents/functions.metadata diff --git a/test/SdkE2ETests/InnerBuildTests.cs b/test/Sdk.E2ETests/InnerBuildTests.cs similarity index 98% rename from test/SdkE2ETests/InnerBuildTests.cs rename to test/Sdk.E2ETests/InnerBuildTests.cs index 3d271f99b..e38822c14 100644 --- a/test/SdkE2ETests/InnerBuildTests.cs +++ b/test/Sdk.E2ETests/InnerBuildTests.cs @@ -7,7 +7,7 @@ using Xunit; using Xunit.Abstractions; -namespace Microsoft.Azure.Functions.SdkE2ETests +namespace Microsoft.Azure.Functions.Sdk.E2ETests { public class InnerBuildTests { diff --git a/test/SdkE2ETests/ProcessWrapper.cs b/test/Sdk.E2ETests/ProcessWrapper.cs similarity index 98% rename from test/SdkE2ETests/ProcessWrapper.cs rename to test/Sdk.E2ETests/ProcessWrapper.cs index a298b1d91..ae250e4ae 100644 --- a/test/SdkE2ETests/ProcessWrapper.cs +++ b/test/Sdk.E2ETests/ProcessWrapper.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using Xunit.Abstractions; -namespace Microsoft.Azure.Functions.SdkE2ETests +namespace Microsoft.Azure.Functions.Sdk.E2ETests { public class ProcessWrapper { diff --git a/test/SdkE2ETests/PublishTests.cs b/test/Sdk.E2ETests/PublishTests.cs similarity index 94% rename from test/SdkE2ETests/PublishTests.cs rename to test/Sdk.E2ETests/PublishTests.cs index 10b50f39f..d707922e2 100644 --- a/test/SdkE2ETests/PublishTests.cs +++ b/test/Sdk.E2ETests/PublishTests.cs @@ -9,7 +9,7 @@ using Xunit; using Xunit.Abstractions; -namespace Microsoft.Azure.Functions.SdkE2ETests +namespace Microsoft.Azure.Functions.Sdk.E2ETests { public class PublishTests { @@ -36,13 +36,13 @@ public async Task Publish_Rid() [Fact] // This test requires the Docker daemon to be installed and running - // It is excluded through the SdkE2ETests_default.runsettings file from normal tests - // To run the test, use `dotnet test -s SdkE2ETests_dockertests.runsettings` + // It is excluded through the Sdk.E2ETests_default.runsettings file from normal tests + // To run the test, use `dotnet test -s Sdk.E2ETests_dockertests.runsettings` [Trait("Requirement", "Docker")] public async Task Publish_Container() { string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Container)); - var repository = nameof(SdkE2ETests).ToLower(); + var repository = nameof(Sdk.E2ETests).ToLower(); var imageTag = nameof(Publish_Container); // setup test environment state in case there is leftover data from previous runs @@ -102,7 +102,7 @@ private async Task RunPublishTest(string outputDir, string additionalParams = nu Assert.True(JToken.DeepEquals(extensionsJsonContents, expected), $"Actual: {extensionsJsonContents}{Environment.NewLine}Expected: {expected}"); // Verify functions.metadata - TestUtility.ValidateFunctionsMetadata(functionsMetadataPath, "Microsoft.Azure.Functions.SdkE2ETests.Contents.functions.metadata"); + TestUtility.ValidateFunctionsMetadata(functionsMetadataPath, "Microsoft.Azure.Functions.Sdk.E2ETests.Contents.functions.metadata"); } private class Extension diff --git a/test/SdkE2ETests/SdkE2ETests.csproj b/test/Sdk.E2ETests/Sdk.E2ETests.csproj similarity index 83% rename from test/SdkE2ETests/SdkE2ETests.csproj rename to test/Sdk.E2ETests/Sdk.E2ETests.csproj index 1deb3084a..ef1dda5e9 100644 --- a/test/SdkE2ETests/SdkE2ETests.csproj +++ b/test/Sdk.E2ETests/Sdk.E2ETests.csproj @@ -2,14 +2,14 @@ net8.0 - Microsoft.Azure.Functions.SdkE2ETests - Microsoft.Azure.Functions.SdkE2ETests + Microsoft.Azure.Functions.Sdk.E2ETests + Microsoft.Azure.Functions.Sdk.E2ETests true ..\..\key.snk - $(MSBuildProjectDirectory)\SdkE2ETests_default.runsettings + $(MSBuildProjectDirectory)\Sdk.E2ETests_default.runsettings diff --git a/test/SdkE2ETests/SdkE2ETests_default.runsettings b/test/Sdk.E2ETests/Sdk.E2ETests_default.runsettings similarity index 100% rename from test/SdkE2ETests/SdkE2ETests_default.runsettings rename to test/Sdk.E2ETests/Sdk.E2ETests_default.runsettings diff --git a/test/SdkE2ETests/SdkE2ETests_dockertests.runsettings b/test/Sdk.E2ETests/Sdk.E2ETests_dockertests.runsettings similarity index 100% rename from test/SdkE2ETests/SdkE2ETests_dockertests.runsettings rename to test/Sdk.E2ETests/Sdk.E2ETests_dockertests.runsettings diff --git a/test/SdkE2ETests/TestUtility.cs b/test/Sdk.E2ETests/TestUtility.cs similarity index 97% rename from test/SdkE2ETests/TestUtility.cs rename to test/Sdk.E2ETests/TestUtility.cs index c92e01c62..b1217ad3f 100644 --- a/test/SdkE2ETests/TestUtility.cs +++ b/test/Sdk.E2ETests/TestUtility.cs @@ -11,7 +11,7 @@ using Xunit; using Xunit.Abstractions; -namespace Microsoft.Azure.Functions.SdkE2ETests +namespace Microsoft.Azure.Functions.Sdk.E2ETests { public static class TestUtility { @@ -27,14 +27,14 @@ public static class TestUtility // Paths and executables public static readonly string DotNetExecutable = "dotnet"; - public static readonly string PathToRepoRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, @"..\..\..\..\..\")); + public static readonly string PathToRepoRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../")); public static readonly string SrcRoot = Path.Combine(PathToRepoRoot, "src"); public static readonly string SdkSolutionRoot = Path.Combine(PathToRepoRoot, "sdk"); public static readonly string SdkProjectRoot = Path.Combine(SdkSolutionRoot, "Sdk"); public static readonly string TestRoot = Path.Combine(PathToRepoRoot, "test"); public static readonly string SamplesRoot = Path.Combine(PathToRepoRoot, "samples"); public static readonly string LocalPackages = Path.Combine(PathToRepoRoot, "local"); - public static readonly string TestOutputDir = Path.Combine(Path.GetTempPath(), "FunctionsWorkerSdkE2ETests"); + public static readonly string TestOutputDir = Path.Combine(Path.GetTempPath(), "FunctionsWorkerSdk.E2ETests"); public static readonly string TestResourcesProjectsRoot = Path.Combine(TestRoot, "Resources", "Projects"); public static readonly string NuGetOrgPackages = "https://api.nuget.org/v3/index.json"; diff --git a/test/SdkE2ETests/ZipDeployTests.cs b/test/Sdk.E2ETests/ZipDeployTests.cs similarity index 50% rename from test/SdkE2ETests/ZipDeployTests.cs rename to test/Sdk.E2ETests/ZipDeployTests.cs index d0a40c8ff..5d8c522a2 100644 --- a/test/SdkE2ETests/ZipDeployTests.cs +++ b/test/Sdk.E2ETests/ZipDeployTests.cs @@ -1,12 +1,13 @@ -using System.IO; +using System; +using System.IO; +using System.Runtime.InteropServices; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.Zip; -using Microsoft.Azure.Functions.SdkE2ETests; using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; using Xunit; using Xunit.Abstractions; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.E2ETests { public class ZipDeployTests { @@ -35,31 +36,33 @@ public async Task CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContaine string projectFileDirectory = Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj"); - await TestUtility.RestoreAndPublishProjectAsync(projectFileDirectory, directoryToZip, $"-r {rid} --self-contained {selfContained}", _testOutputHelper); + await TestUtility.RestoreAndPublishProjectAsync( + projectFileDirectory, directoryToZip, $"-r {rid} --self-contained {selfContained}", _testOutputHelper); CreateZipFileTask.CreateZipFileFromDirectory(directoryToZip, zipName); - using (var zip = new ZipFile(zipName)) + using var zip = new ZipFile(zipName); + Assert.Equal(Directory.GetFiles(directoryToZip, "*", SearchOption.AllDirectories).Length, zip.Count); + foreach (ZipEntry entry in zip) { - Assert.Equal(Directory.GetFiles(directoryToZip, "*", SearchOption.AllDirectories).Length, zip.Count); - - for (int i = 0; i < zip.Count; i++) + if (selfContained && (entry.Name == "FunctionApp" || entry.Name == "FunctionApp.exe")) + { + Assert.Equal(3, entry.HostSystem); + Assert.Equal(CreateZipFileTask.UnixExecutablePermissions, entry.ExternalFileAttributes); + } + else if (OperatingSystem.IsWindows()) { - var entry = zip[i]; - if (selfContained && - (entry.Name == "FunctionApp" || entry.Name == "FunctionApp.exe")) - { - Assert.Equal(3, entry.HostSystem); - Assert.Equal(CreateZipFileTask.UnixExecutablePermissions, entry.ExternalFileAttributes); - } - else - { - Assert.Equal(0, entry.HostSystem); - Assert.Equal(0, entry.ExternalFileAttributes); - } + // All other files are default on windows. + Assert.Equal(0, entry.HostSystem); + Assert.Equal(0, entry.ExternalFileAttributes); } + else + { + Assert.Equal(3, entry.HostSystem); - zip.Close(); + // Unix permissions will vary based on the file. Just making sure they have _some_ permissions + Assert.NotEqual(0, entry.ExternalFileAttributes); + } } } } diff --git a/test/SdkE2ETests/xunit.runner.json b/test/Sdk.E2ETests/xunit.runner.json similarity index 100% rename from test/SdkE2ETests/xunit.runner.json rename to test/Sdk.E2ETests/xunit.runner.json diff --git a/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs b/test/Sdk.Generator.Tests/ExtensionStartupRunner/ExtensionStartupRunnerGeneratorTests.cs similarity index 98% rename from test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs rename to test/Sdk.Generator.Tests/ExtensionStartupRunner/ExtensionStartupRunnerGeneratorTests.cs index 80a53be91..790695209 100644 --- a/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/ExtensionStartupRunner/ExtensionStartupRunnerGeneratorTests.cs @@ -4,13 +4,15 @@ using System; using System.Collections.Generic; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Tests.WorkerExtensionsSample; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; using Worker.Extensions.Sample_IncorrectImplementation; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests + +namespace Microsoft.Azure.Functions.Sdk.Generator.ExtensionStartupRunner.Tests { public partial class ExtensionStartupRunnerGeneratorTests { diff --git a/test/Sdk.Generator.Tests/ExtensionStartup/NotGeneratedTests.cs b/test/Sdk.Generator.Tests/ExtensionStartupRunner/NotGeneratedTests.cs similarity index 93% rename from test/Sdk.Generator.Tests/ExtensionStartup/NotGeneratedTests.cs rename to test/Sdk.Generator.Tests/ExtensionStartupRunner/NotGeneratedTests.cs index 5f1191a01..5e0935d12 100644 --- a/test/Sdk.Generator.Tests/ExtensionStartup/NotGeneratedTests.cs +++ b/test/Sdk.Generator.Tests/ExtensionStartupRunner/NotGeneratedTests.cs @@ -2,11 +2,13 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Tests.WorkerExtensionsSample; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests + +namespace Microsoft.Azure.Functions.Sdk.Generator.ExtensionStartupRunner.Tests { public partial class ExtensionStartupRunnerGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index bee14cd22..3ce6c543f 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -3,12 +3,13 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionExecutor.Tests { public partial class FunctionExecutorGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs index de4f0bb58..289e8c2c5 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Azure.Messaging.EventHubs; using Azure.Storage.Queues.Models; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; @@ -15,7 +16,7 @@ using Microsoft.Extensions.Logging; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionExecutor.Tests { public partial class FunctionExecutorGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/NotGeneratedTests.cs b/test/Sdk.Generator.Tests/FunctionExecutor/NotGeneratedTests.cs index fe8c2ea26..eb9bfd74a 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/NotGeneratedTests.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/NotGeneratedTests.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; @@ -12,7 +13,7 @@ using Microsoft.Extensions.Logging; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionExecutor.Tests { public partial class FunctionExecutorGeneratorTests { diff --git a/test/FunctionMetadataGeneratorTests/CustomAttributeExtensionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/CustomAttributeExtensionsTests.cs similarity index 98% rename from test/FunctionMetadataGeneratorTests/CustomAttributeExtensionsTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/CustomAttributeExtensionsTests.cs index df544fbbc..87c5f2de8 100644 --- a/test/FunctionMetadataGeneratorTests/CustomAttributeExtensionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/CustomAttributeExtensionsTests.cs @@ -1,14 +1,14 @@ // 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; using System.Collections.Generic; using System.Reflection; using Microsoft.Azure.Functions.Worker.Sdk; using Mono.Cecil; using Xunit; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public class CustomAttributeExtensionsTests { @@ -163,7 +163,7 @@ public void Use_JustProperties() { } - [JustProperties(Value = null)] + [JustProperties(Value = null!)] public void Use_JustProperties_Null() { } diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/ExtensionsCsProjGeneratorTests.cs similarity index 96% rename from test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/ExtensionsCsProjGeneratorTests.cs index c50422faa..e32b1d8b7 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/ExtensionsCsProjGeneratorTests.cs @@ -9,11 +9,11 @@ using Microsoft.Azure.Functions.Worker.Sdk; using Xunit; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public sealed class ExtensionsCsProjGeneratorTests : IDisposable { - private HashSet _directoriesToCleanup = new(); + private HashSet _directoriesToCleanup = new(); public enum FuncVersion { @@ -23,12 +23,17 @@ public enum FuncVersion public void Dispose() { - foreach (string directory in _directoriesToCleanup) + foreach (string? directory in _directoriesToCleanup) { - if (Directory.Exists(directory)) + if (directory is null) { - Directory.Delete(directory, true); + continue; } + + if (Directory.Exists(directory)) + { + Directory.Delete(directory, true); + } } _directoriesToCleanup.Clear(); diff --git a/test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/ExtensionsMetadataEnhancerTests.cs similarity index 94% rename from test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/ExtensionsMetadataEnhancerTests.cs index 0fcf68854..45cdb3a82 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsMetadataEnhancerTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/ExtensionsMetadataEnhancerTests.cs @@ -1,13 +1,14 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using System.Linq; +using Microsoft.Azure.Functions.Tests; using Microsoft.Azure.Functions.Worker.Sdk; using Xunit; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public class ExtensionsMetadataEnhancerTests { @@ -41,7 +42,7 @@ public void AddHintPath_DoesNotAdd_WhenAlreadyPresent() [Fact] public void GetWebJobsExtensions_FindsExtensions() { - string assembly = Path.Combine(Tests.TestUtility.RepoRoot, "sdk", "FunctionMetadataLoaderExtension", "bin", Tests.TestUtility.Config, "netstandard2.0", "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"); + string assembly = Path.Combine(TestUtility.RepoRoot, "sdk", "FunctionMetadataLoaderExtension", "bin", TestUtility.Config, "netstandard2.0", "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"); var extensions = ExtensionsMetadataEnhancer.GetWebJobsExtensions(assembly); ValidateAllEqual( diff --git a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs similarity index 96% rename from test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs index 0ea8b6888..44f4a48c8 100644 --- a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs @@ -1,6 +1,9 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +// 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; using System.Collections.Concurrent; @@ -26,7 +29,7 @@ using Mono.Cecil; using Xunit; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public class FunctionMetadataGeneratorTests { @@ -47,7 +50,7 @@ public void BasicHttpFunction() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(BasicHttp)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(BasicHttp)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -91,7 +94,7 @@ public async Task Incremental_WritesOnlyIfChanged() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(BasicHttp)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(BasicHttp)); var functions = generator.GenerateFunctionMetadata(typeDef); // Simulate an existing functions.metadata file with different content. @@ -118,7 +121,7 @@ public void BasicHttpAspNetFunction() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(BasicHttpAspNet)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(BasicHttpAspNet)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -162,7 +165,7 @@ public void BasicHttpFunctionWithNoResponse() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(BasicHttpWithNoResponse)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(BasicHttpWithNoResponse)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -195,7 +198,7 @@ public void BasicHttpFunctionWithExternalReturnType() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(ExternalType_Return)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(ExternalType_Return)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -239,7 +242,7 @@ public void StorageFunctions() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(Storage)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(Storage)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -337,7 +340,7 @@ public void BlobStorageFunctions_SDKTypeBindings() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(SDKTypeBindings_BlobStorage)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(SDKTypeBindings_BlobStorage)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -430,7 +433,7 @@ public void BlobCollectionFunctions_SDKTypeBindings() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(SDKTypeBindings_BlobCollection)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(SDKTypeBindings_BlobCollection)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -526,7 +529,7 @@ public void TableFunctions_SDKTypeBindings() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(SDKTypeBindings_Table)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(SDKTypeBindings_Table)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -595,7 +598,7 @@ public void TimerFunction() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(Timer)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(Timer)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -623,7 +626,7 @@ public void QueueStorageFunctions_SDKTypeBindings() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(SDKTypeBindings_Queue)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(SDKTypeBindings_Queue)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -674,7 +677,7 @@ public void MultiOutput_OnReturnType() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(MultiOutput_ReturnType)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(MultiOutput_ReturnType)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -740,7 +743,7 @@ public void MultiOutput_OnReturnType_WithHttp() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(MultiOutput_ReturnType_Http)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(MultiOutput_ReturnType_Http)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -800,7 +803,7 @@ public void MultiOutput_OnReturnType_WithHttp_AspNet() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(MultiOutput_ReturnType_Http_AspNet)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(MultiOutput_ReturnType_Http_AspNet)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -859,15 +862,15 @@ public void JustHttp_OnReturnTypeProperty() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(ReturnType_JustHttp)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(ReturnType_JustHttp)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; Assert.Single(functions); - var HttpAndQueue = functions.Single(p => p.Name == "JustHtt"); + var HttpAndQueue = functions.Single(p => p.Name == "JustHttp"); - ValidateFunction(HttpAndQueue, "JustHtt", GetEntryPoint(nameof(ReturnType_JustHttp), nameof(ReturnType_JustHttp.Justhtt)), + ValidateFunction(HttpAndQueue, "JustHttp", GetEntryPoint(nameof(ReturnType_JustHttp), nameof(ReturnType_JustHttp.JustHttp)), b => ValidateHttpTrigger(b), b => ValidateHttpOutput(b)); @@ -902,7 +905,7 @@ public void MultiReturn_MultiAttribute_IsValid() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(MultiOutput_ReturnType_MultiAttribute)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(MultiOutput_ReturnType_MultiAttribute)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -962,7 +965,7 @@ public void MultiOutput_OnMethod_Throws() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(MultiOutput_Method)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(MultiOutput_Method)); var exception = Assert.Throws(() => generator.GenerateFunctionMetadata(typeDef)); @@ -974,7 +977,7 @@ public void MultiOutput_OnReturnTypeProperty_Throws() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(MultiReturn_MultiBinding)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(MultiReturn_MultiBinding)); var exception = Assert.Throws(() => generator.GenerateFunctionMetadata(typeDef)); @@ -1012,7 +1015,7 @@ public void MultiOutput_OnReturnTypeProperty_Throws() public void CardinalityManyFunctions(string functionName, string entryPoint, bool cardinalityMany, string dataType) { var generator = new FunctionMetadataGenerator(); - var typeDef = TestUtility.GetTypeDefinition(typeof(CardinalityMany)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(CardinalityMany)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -1059,7 +1062,7 @@ void ValidateTrigger(ExpandoObject b, bool many) public void CardinalityMany_WithNotIterableTypeThrows() { var generator = new FunctionMetadataGenerator(); - var typeDef = TestUtility.GetTypeDefinition(typeof(EventHubNotBatched)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(EventHubNotBatched)); var exception = Assert.Throws(() => generator.GenerateFunctionMetadata(typeDef)); Assert.Contains("Function is configured to process events in batches but parameter type is not iterable", exception.Message); @@ -1083,14 +1086,14 @@ public void EnableImplicitRegistration_True() var module = ModuleDefinition.ReadModule(_thisAssembly.Location); // Inject enableImplicitRegistration = true into the constructor - var enableImplicitRegistrationParam = new CustomAttributeArgument(TestUtility.GetTypeDefinition(typeof(bool)), true); + var enableImplicitRegistrationParam = new CustomAttributeArgument(TypeHelpers.GetTypeDefinition(typeof(bool)), true); var extInfo = module.Assembly.CustomAttributes.Single(p => p.AttributeType.FullName == Constants.ExtensionsInformationType); extInfo.ConstructorArguments.Add(enableImplicitRegistrationParam); generator.GenerateFunctionMetadata(module); var extension = generator.Extensions.Single(); - Assert.Equal("SdkTests", extension.Key); + Assert.Equal("Sdk.Generator.Tests", extension.Key); Assert.Equal("1.0.0", extension.Value); } @@ -1101,7 +1104,7 @@ public void EnableImplicitRegistration_False() var module = ModuleDefinition.ReadModule(_thisAssembly.Location); // Inject enableImplicitRegistration = false into the constructor - var enableImplicitRegistrationParam = new CustomAttributeArgument(TestUtility.GetTypeDefinition(typeof(bool)), false); + var enableImplicitRegistrationParam = new CustomAttributeArgument(TypeHelpers.GetTypeDefinition(typeof(bool)), false); var extInfo = module.Assembly.CustomAttributes.Single(p => p.AttributeType.FullName == Constants.ExtensionsInformationType); extInfo.ConstructorArguments.Add(enableImplicitRegistrationParam); @@ -1114,7 +1117,7 @@ public void FunctionWithNoRetryHasNullRetryProperty() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(Storage)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(Storage)); var functions = generator.GenerateFunctionMetadata(typeDef); var queueToBlob = functions.Single(p => p.Name == "QueueToBlobFunction"); @@ -1127,13 +1130,13 @@ public void FunctionWithFixedDelayRetry() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(RetryFunctions)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(RetryFunctions)); var functions = generator.GenerateFunctionMetadata(typeDef); var funcName = "FixedDelayRetryFunction"; var fixedDelayFunction = functions.Single(p => p.Name == funcName); - var retry = fixedDelayFunction.Retry; + var retry = fixedDelayFunction.Retry!; Assert.Equal("fixedDelay", retry.Strategy); Assert.Equal(5, retry.MaxRetryCount); @@ -1149,13 +1152,13 @@ public void FunctionWithExponentialBackoffRetry() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(RetryFunctions)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(RetryFunctions)); var functions = generator.GenerateFunctionMetadata(typeDef); var funcName = "ExponentialBackoffRetryFunction"; var fixedDelayFunction = functions.Single(p => p.Name == funcName); - var retry = fixedDelayFunction.Retry; + var retry = fixedDelayFunction.Retry!; Assert.Equal("exponentialBackoff", retry.Strategy); Assert.Equal(5, retry.MaxRetryCount); @@ -1186,13 +1189,13 @@ public void ServiceBus_SDKTypeBindings() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(SDKTypeBindings_ServiceBus)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(SDKTypeBindings_ServiceBus)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; Assert.Equal(2, functions.Count()); - var extensionReference = typeof(ServiceBusExtensionStartup).Assembly.GetCustomAttribute(); + var extensionReference = typeof(ServiceBusExtensionStartup).Assembly.GetCustomAttribute()!; AssertDictionary(extensions, new Dictionary { @@ -1241,7 +1244,7 @@ public void EventHubs_SDKTypeBindings() { var generator = new FunctionMetadataGenerator(); var module = ModuleDefinition.ReadModule(_thisAssembly.Location); - var typeDef = TestUtility.GetTypeDefinition(typeof(SDKTypeBindings_EventHubs)); + var typeDef = TypeHelpers.GetTypeDefinition(typeof(SDKTypeBindings_EventHubs)); var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; @@ -1316,7 +1319,7 @@ private void ValidateFunction(SdkFunctionMetadata sdkFunctionMetadata, string na private static void AssertExpandoObject(ExpandoObject expando, IDictionary expected) { - var dict = (IDictionary)expando; + var dict = (IDictionary)expando!; AssertDictionary(dict, expected); } @@ -1622,8 +1625,8 @@ public MultiReturn QueueToBlob( private class ReturnType_JustHttp { - [Function("JustHtt")] - public JustHttp Justhtt( + [Function("JustHttp")] + public JustHttp JustHttp( [HttpTrigger("get")] string req) { throw new NotImplementedException(); @@ -1663,38 +1666,38 @@ public MultiReturn_MultiAttribute HttpAndQueue( private class MultiReturn { [BlobOutput("container1/hello.txt", Connection = "MyOtherConnection")] - public string blobOutput { get; set; } + public string? blobOutput { get; set; } [QueueOutput("queue2")] - public string queueOutput { get; set; } + public string? queueOutput { get; set; } } private class MultiReturn_Http { [QueueOutput("queue2")] - public string queueOutput { get; set; } + public string? queueOutput { get; set; } - public HttpResponseData httpResponseProp { get; set; } + public HttpResponseData? httpResponseProp { get; set; } } private class MultiReturn_Http_AspNet { [QueueOutput("queue2")] - public string queueOutput { get; set; } + public string? queueOutput { get; set; } [HttpResult] - public IActionResult httpResponseProp { get; set; } + public IActionResult? httpResponseProp { get; set; } } private class MultiReturn_MultiAttribute { [QueueOutput("queue2")] - public string queueOutput { get; set; } + public string? queueOutput { get; set; } [SuppressMessage("Microsoft.Naming", "Foo", Justification = "Bar")] [HttpResult] [CustomTest] - public IActionResult httpResponseProp { get; set; } + public IActionResult? httpResponseProp { get; set; } } private class CustomTestAttribute: Attribute @@ -1706,15 +1709,15 @@ private class MultiReturn_MultiBindingOnProp { [BlobOutput("./result")] [QueueOutput("queue2")] - public string queueOutput { get; set; } + public string? queueOutput { get; set; } [HttpResult] - public IActionResult httpResponseProp { get; set; } + public IActionResult? httpResponseProp { get; set; } } private class JustHttp { - public HttpResponseData httpResponseProp { get; set; } + public HttpResponseData? httpResponseProp { get; set; } } private class Timer diff --git a/test/FunctionMetadataGeneratorTests/StringExtensionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/StringExtensionsTests.cs similarity index 79% rename from test/FunctionMetadataGeneratorTests/StringExtensionsTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/StringExtensionsTests.cs index 36c50ca71..ebacbfd8d 100644 --- a/test/FunctionMetadataGeneratorTests/StringExtensionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/StringExtensionsTests.cs @@ -4,7 +4,7 @@ using Microsoft.Azure.Functions.Worker.Sdk; using Xunit; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public class StringExtensionsTests { @@ -14,7 +14,7 @@ public class StringExtensionsTests [InlineData("http", "http")] [InlineData("", "")] [InlineData(null, null)] - public void ToLowerFirstCharacterWorks(string input, string expectedOutput) + public void ToLowerFirstCharacterWorks(string? input, string? expectedOutput) { var actual = input.ToLowerFirstCharacter(); diff --git a/test/FunctionMetadataGeneratorTests/TestUtility.cs b/test/Sdk.Generator.Tests/FunctionMetadata/TypeHelpers.cs similarity index 64% rename from test/FunctionMetadataGeneratorTests/TestUtility.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/TypeHelpers.cs index 854ba4a08..1a61ca289 100644 --- a/test/FunctionMetadataGeneratorTests/TestUtility.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/TypeHelpers.cs @@ -6,11 +6,11 @@ using System.Linq; using Mono.Cecil; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { - public static class TestUtility + public static class TypeHelpers { - public static MethodDefinition GetMethodDefinition(Type type, string methodName) + public static MethodDefinition? GetMethodDefinition(Type type, string methodName) { return GetTypeDefinition(type).Methods.SingleOrDefault(p => p.Name == methodName); } @@ -18,14 +18,14 @@ public static MethodDefinition GetMethodDefinition(Type type, string methodName) public static TypeDefinition GetTypeDefinition(Type type) { var module = ModuleDefinition.ReadModule(type.Assembly.Location); - return module.GetType(type.FullName.Replace("+", "/")); + return module.GetType(type.FullName!.Replace("+", "/")); } public static IEnumerable GetCustomAttributes(Type type, string methodName, string parameterName) { var methodDef = GetMethodDefinition(type, methodName); - var paramDef = methodDef.Parameters.SingleOrDefault(p => p.Name == parameterName); - return paramDef.CustomAttributes; + var paramDef = methodDef!.Parameters.SingleOrDefault(p => p.Name == parameterName); + return paramDef!.CustomAttributes; } } } diff --git a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/ZipDeployTaskTests.cs similarity index 92% rename from test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/ZipDeployTaskTests.cs index 1dbd5afa0..46a058963 100644 --- a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/ZipDeployTaskTests.cs @@ -1,4 +1,7 @@ -using System; +// 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.IO; using System.Linq; using System.Net; @@ -10,11 +13,11 @@ using Moq; using Xunit; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public class ZipDeployTaskTests { - private static string _testZippedPublishContentsPath; + private static string? _testZippedPublishContentsPath; private const string TestAssemblyToTestZipPath = @"Resources/TestPublishContents.zip"; private const string UserAgentName = "functions-core-tools"; private const string UserAgentVersion = "1.0"; @@ -27,7 +30,7 @@ public static string TestZippedPublishContentsPath { string codebase = typeof(ZipDeployTaskTests).Assembly.Location; string assemblyPath = new Uri(codebase, UriKind.Absolute).LocalPath; - string baseDirectory = Path.GetDirectoryName(assemblyPath); + string baseDirectory = Path.GetDirectoryName(assemblyPath)!; _testZippedPublishContentsPath = Path.Combine(baseDirectory, TestAssemblyToTestZipPath); } @@ -61,7 +64,7 @@ public async Task ExecuteZipDeploy_InvalidZipFilePath() [InlineData(null, "sitename", true, "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false")] [InlineData("", "sitename", false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] [InlineData("", "sitename", true, "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false")] - public async Task ExecuteZipDeploy_PublishUrlOrSiteNameGiven(string publishUrl, string siteName, bool useBlobContainerDeploy, string expectedZipDeployEndpoint) + public async Task ExecuteZipDeploy_PublishUrlOrSiteNameGiven(string? publishUrl, string? siteName, bool useBlobContainerDeploy, string expectedZipDeployEndpoint) { Action, bool> verifyStep = (client, result) => { @@ -81,7 +84,7 @@ public async Task ExecuteZipDeploy_PublishUrlOrSiteNameGiven(string publishUrl, [InlineData("", "")] [InlineData("", null)] [InlineData(null, "")] - public async Task ExecuteZipDeploy_NeitherPublishUrlNorSiteNameGiven(string publishUrl, string siteName) + public async Task ExecuteZipDeploy_NeitherPublishUrlNorSiteNameGiven(string? publishUrl, string? siteName) { Action, bool> verifyStep = (client, result) => { @@ -129,7 +132,7 @@ public async Task ExecuteZipDeploy_VaryingHttpResponseStatuses( await RunZipDeployAsyncTest("https://sitename.scm.azurewebsites.net", null, UserAgentVersion, useBlobContainerDeploy, responseStatusCode, verifyStep); } - private async Task RunZipDeployAsyncTest(string publishUrl, string siteName, string userAgentVersion, bool useBlobContainerDeploy, HttpStatusCode responseStatusCode, Action, bool> verifyStep) + private async Task RunZipDeployAsyncTest(string? publishUrl, string? siteName, string userAgentVersion, bool useBlobContainerDeploy, HttpStatusCode responseStatusCode, Action, bool> verifyStep) { Mock client = new Mock(); @@ -141,7 +144,7 @@ private async Task RunZipDeployAsyncTest(string publishUrl, string siteName, str byte[] plainAuthBytes = Encoding.ASCII.GetBytes("username:password"); string base64AuthParam = Convert.ToBase64String(plainAuthBytes); - Assert.Equal(base64AuthParam, client.Object.DefaultRequestHeaders.Authorization.Parameter); + Assert.Equal(base64AuthParam, client.Object.DefaultRequestHeaders.Authorization!.Parameter); Assert.Equal("Basic", client.Object.DefaultRequestHeaders.Authorization.Scheme); return Task.FromResult(new HttpResponseMessage(responseStatusCode)); diff --git a/test/FunctionMetadataGeneratorTests/ZipDeploymentStatusTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/ZipDeploymentStatusTests.cs similarity index 93% rename from test/FunctionMetadataGeneratorTests/ZipDeploymentStatusTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadata/ZipDeploymentStatusTests.cs index 0e0e92cc1..8eb2cccff 100644 --- a/test/FunctionMetadataGeneratorTests/ZipDeploymentStatusTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/ZipDeploymentStatusTests.cs @@ -1,17 +1,22 @@ -using System; +// 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.Linq; using System.Net; using System.Net.Http; using System.Text; using System.Threading; -using System.Threading.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; using Microsoft.NET.Sdk.Functions.Http; using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; using Moq; using Newtonsoft.Json; using Xunit; +using Task = System.Threading.Tasks.Task; -namespace Microsoft.Azure.Functions.SdkTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadata.Tests { public class ZipDeploymentStatusTests { @@ -45,6 +50,8 @@ public class ZipDeploymentStatusTests } }"; + private readonly TaskLoggingHelper _log = new(Mock.Of(), "test"); + [Theory] [InlineData(HttpStatusCode.Forbidden, DeployStatus.Unknown)] [InlineData(HttpStatusCode.NotFound, DeployStatus.Unknown)] @@ -69,7 +76,8 @@ public async Task PollDeploymentStatusTest_ForErrorResponses(HttpStatusCode resp { return Task.FromResult(new HttpResponseMessage(responseStatusCode)); }); - ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", _log, false); // Act var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); @@ -89,7 +97,7 @@ public async Task PollDeploymentStatusTest_ForErrorResponses(HttpStatusCode resp [InlineData(HttpStatusCode.Accepted, "", DeployStatus.Conflict)] [InlineData(HttpStatusCode.OK, null, DeployStatus.Unknown)] [InlineData(HttpStatusCode.Accepted, null, DeployStatus.Unknown)] - public async Task PollDeploymentStatusTest_ForValidResponses(HttpStatusCode responseStatusCode, string statusMessage, DeployStatus expectedDeployStatus) + public async Task PollDeploymentStatusTest_ForValidResponses(HttpStatusCode responseStatusCode, string? statusMessage, DeployStatus expectedDeployStatus) { // Arrange string deployUrl = "https://sitename.scm.azurewebsites.net/DeploymentStatus?Id=knownId"; @@ -119,7 +127,7 @@ public async Task PollDeploymentStatusTest_ForValidResponses(HttpStatusCode resp }; return Task.FromResult(responseMessage); }); - ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", _log, false); // Act var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); @@ -154,7 +162,7 @@ public async Task PollDeploymentStatusTest_WithDeploymentSummary_Succeeds() return Task.FromResult(responseMessage); }); - ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", _log, false); // Act var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/AmbiguousNamespaceTests.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/AmbiguousNamespaceTests.cs index 80574dda7..615a8d868 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/AmbiguousNamespaceTests.cs @@ -3,13 +3,14 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/AutoConfigureStartupTypeTests.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/AutoConfigureStartupTypeTests.cs index 6da55894a..52b39a997 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/AutoConfigureStartupTypeTests.cs @@ -4,13 +4,14 @@ using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/DependentAssemblyTest.NetFx.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/DependentAssemblyTest.NetFx.cs index 032ea59ba..daaede3a4 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/DependentAssemblyTest.NetFx.cs @@ -4,13 +4,14 @@ using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/DependentAssemblyTest.cs similarity index 99% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/DependentAssemblyTest.cs index 05a77aaf1..a7a505695 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/DependentAssemblyTest.cs @@ -3,12 +3,13 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/DiagnosticResultTests.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/DiagnosticResultTests.cs index 1b8fbab6c..c7b685a71 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/DiagnosticResultTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; @@ -12,7 +13,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/EventHubsBindingsTests.cs similarity index 99% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/EventHubsBindingsTests.cs index b6f6da1af..a805e1be4 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/EventHubsBindingsTests.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Text; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; @@ -12,7 +13,7 @@ using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ExtensionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/ExtensionsTests.cs similarity index 94% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ExtensionsTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/ExtensionsTests.cs index e489bb673..8323ea49a 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ExtensionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/ExtensionsTests.cs @@ -4,7 +4,7 @@ using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/HttpTriggerTests.cs similarity index 99% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/HttpTriggerTests.cs index d75ecf87d..76aaeae35 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/HttpTriggerTests.cs @@ -4,13 +4,14 @@ using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/IntegratedTriggersAndBindingsTests.cs similarity index 99% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/IntegratedTriggersAndBindingsTests.cs index 6d6bb9e88..67f4fd91d 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/IntegratedTriggersAndBindingsTests.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; @@ -13,7 +14,7 @@ using Microsoft.Extensions.Logging.Abstractions; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/KafkaTests.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/KafkaTests.cs index 42bf7ac90..bade20b0f 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/KafkaTests.cs @@ -1,16 +1,16 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System.Collections.Generic; using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/NestedTypesTest.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/NestedTypesTest.cs index a84d7ff41..bb58b9df0 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/NestedTypesTest.cs @@ -3,13 +3,14 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NotGeneratedTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/NotGeneratedTests.cs similarity index 95% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NotGeneratedTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/NotGeneratedTests.cs index 33133b38e..1b98fc62b 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NotGeneratedTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/NotGeneratedTests.cs @@ -3,6 +3,7 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; @@ -12,7 +13,7 @@ using Microsoft.Extensions.Logging; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs index 0e9ef0689..caec922fb 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Reflection; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using System.Threading.Tasks; using Xunit; @@ -9,7 +10,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/ServiceBustTests.cs similarity index 96% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/ServiceBustTests.cs index 40f4077f1..ee22eb7cd 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/ServiceBustTests.cs @@ -1,16 +1,16 @@ -using System; -using System.Collections.Generic; -using System.Linq; +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + using System.Reflection; -using System.Text; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/SignalRTest.cs similarity index 98% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/SignalRTest.cs index 317d28504..478a5452d 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/SignalRTest.cs @@ -3,13 +3,14 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/StorageBindingTests.cs similarity index 99% rename from test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs rename to test/Sdk.Generator.Tests/FunctionMetadataProvider/StorageBindingTests.cs index 1bbf0c88c..e4e3652b3 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/StorageBindingTests.cs @@ -3,13 +3,14 @@ using System.Reflection; using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests { public partial class FunctionMetadataProviderGeneratorTests { diff --git a/test/FunctionMetadataGeneratorTests/Properties/AssemblyInfo.cs b/test/Sdk.Generator.Tests/Properties/AssemblyInfo.cs similarity index 77% rename from test/FunctionMetadataGeneratorTests/Properties/AssemblyInfo.cs rename to test/Sdk.Generator.Tests/Properties/AssemblyInfo.cs index 343971321..cc01840b4 100644 --- a/test/FunctionMetadataGeneratorTests/Properties/AssemblyInfo.cs +++ b/test/Sdk.Generator.Tests/Properties/AssemblyInfo.cs @@ -3,4 +3,4 @@ using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("SdkTests", "1.0.0")] +[assembly: ExtensionInformation("Sdk.Generator.Tests", "1.0.0")] diff --git a/test/FunctionMetadataGeneratorTests/Resources/TestPublishContents.zip b/test/Sdk.Generator.Tests/Resources/TestPublishContents.zip similarity index 100% rename from test/FunctionMetadataGeneratorTests/Resources/TestPublishContents.zip rename to test/Sdk.Generator.Tests/Resources/TestPublishContents.zip diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index 2c98824fd..f0e9e900a 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -3,8 +3,8 @@ net8.0 latest - Microsoft.Azure.Functions.SdkGeneratorTests - Microsoft.Azure.Functions.SdkGeneratorTests + Microsoft.Azure.Functions.Sdk.Generator.Tests + Microsoft.Azure.Functions.Sdk.Generator.Tests true ..\..\key.snk enable @@ -17,21 +17,6 @@ - - - - - - - - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - runtime; build; native; contentfiles; analyzers; buildtransitive all @@ -45,11 +30,29 @@ + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + @@ -59,6 +62,11 @@ + + + + + \ No newline at end of file diff --git a/test/Sdk.Generator.Tests/SymbolExtensionsTest/SymbolExtensionsTest.cs b/test/Sdk.Generator.Tests/SymbolExtensionsTest.cs similarity index 98% rename from test/Sdk.Generator.Tests/SymbolExtensionsTest/SymbolExtensionsTest.cs rename to test/Sdk.Generator.Tests/SymbolExtensionsTest.cs index 0eb389a99..9acd3a0e9 100644 --- a/test/Sdk.Generator.Tests/SymbolExtensionsTest/SymbolExtensionsTest.cs +++ b/test/Sdk.Generator.Tests/SymbolExtensionsTest.cs @@ -7,7 +7,7 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Xunit; -namespace Microsoft.Azure.Functions.SdkGeneratorTests.SymbolExtensionsTest +namespace Microsoft.Azure.Functions.Sdk.Generator.Tests { public class SymbolExtensionsTest { diff --git a/test/Sdk.Generator.Tests/TestHelpers.cs b/test/Sdk.Generator.Tests/TestHelpers.cs index 6562f3d68..9a3dabe5e 100644 --- a/test/Sdk.Generator.Tests/TestHelpers.cs +++ b/test/Sdk.Generator.Tests/TestHelpers.cs @@ -18,7 +18,7 @@ using System.Linq; using System.Runtime.Versioning; -namespace Microsoft.Azure.Functions.SdkGeneratorTests +namespace Microsoft.Azure.Functions.Sdk.Generator.Tests { static class TestHelpers { diff --git a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs index 0b069be80..c6b8c0d76 100644 --- a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs +++ b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageConverterTests.cs @@ -16,12 +16,12 @@ public class ServiceBusSessionMessageConverterTests { internal sealed class TestBindingContext : BindingContext { - public TestBindingContext(IReadOnlyDictionary input) + public TestBindingContext(IReadOnlyDictionary input) { BindingData = input; } - public override IReadOnlyDictionary BindingData { get; } + public override IReadOnlyDictionary BindingData { get; } } internal sealed class TestFunctionContext : FunctionContext From 49b7ef69019e4c86ce35aeabaeecf353e15ae7ca Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Wed, 9 Apr 2025 10:14:53 -0700 Subject: [PATCH 108/190] Better error message when Azure Functions Core Tools is missing in `dotnet run` use case. (#3020) * Enhanced error message for missing Azure Functions Core Tools in the user's environment when they try to run `dotnet run` to start function app. * Fix whitespace * Switching to msbuild Error task. * Simplif using `func --version` instead of checking installation path. * Improvements to condition check --- ...crosoft.Azure.Functions.Worker.Sdk.targets | 19 ++++++++++++++++--- sdk/release_notes.md | 1 + 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index ae8b32e48..ae6b02779 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -124,14 +124,27 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - + + func host start $(RunArguments) $(OutDir) - + + + + + + + true + + + + + + + Date: Fri, 11 Apr 2025 09:59:15 -0700 Subject: [PATCH 109/190] Add nuget release yaml pipelines (#3013) * Add test nupkg release * Fix release stage dependency * Make unofficial for testing * Skip signing to save time during tests * Skip tests for now * Comment out approvers for now * Further release tests * Re-add approvers * Comment out approvers for now * Using testing branch * artifactName -> artifact * Add initial official-release.yml * Fix pwsh step * Don't run pipeline * Fix package_name * Remove buildId parameter * Validate as release job * Fix get package version * Support releasing all worker extensions * undo invalid template changes * Add template and abstraction release yaml * fix template * Add ServiceBus release * Fix nuget version regex * Test artifact feed * Remove pipeline template * Add comment * Extract ext targetFolder by convention * target_folder_prefix -> target_folder * Use @eng=refs/tags/release * Undo official-build.yml changes * Validate -> Prepare Release --- eng/ci/official-build.yml | 1 - eng/ci/official-release.yml | 116 ++++++++++++++++++ .../jobs/run-integration-tests-windows.yml | 2 +- eng/ci/templates/jobs/run-unit-tests.yml | 8 +- .../official/jobs/build-artifacts.yml | 2 +- .../pipelines/release-extension-packages.yml | 83 +++++++++++++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ .../ci/official-release.yml | 18 +++ global.json | 2 +- 25 files changed, 530 insertions(+), 8 deletions(-) create mode 100644 eng/ci/official-release.yml create mode 100644 eng/ci/templates/pipelines/release-extension-packages.yml create mode 100644 extensions/Worker.Extensions.Abstractions/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.CosmosDB/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.EventGrid/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.EventHubs/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Http.AspNetCore/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Http/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Kafka/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.RabbitMQ/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Rpc/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.SendGrid/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.ServiceBus/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.SignalRService/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Storage.Blobs/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Storage.Queues/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Storage/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Tables/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Timer/ci/official-release.yml create mode 100644 extensions/Worker.Extensions.Warmup/ci/official-release.yml diff --git a/eng/ci/official-build.yml b/eng/ci/official-build.yml index 63776cde4..e55f81491 100644 --- a/eng/ci/official-build.yml +++ b/eng/ci/official-build.yml @@ -56,7 +56,6 @@ extends: stages: - stage: Build - jobs: - template: /eng/ci/templates/official/jobs/build-artifacts.yml@self diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml new file mode 100644 index 000000000..b9b25285e --- /dev/null +++ b/eng/ci/official-release.yml @@ -0,0 +1,116 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false +- name: packages + displayName: Packages to publish + type: string + default: core + values: + - core + - sdk + +pr: none +trigger: none + +resources: + repositories: + - repository: 1es + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + - repository: eng + type: git + name: engineering + ref: refs/tags/release + pipelines: + - pipeline: build + source: dotnet-worker.official + +variables: + artifact_name: NugetPackages + ${{ if eq(parameters.packages, 'core') }}: + target_folder: azure-functions/dotnet/worker + package_name: Microsoft.Azure.Functions.Worker + package_pattern: | + Microsoft.Azure.Functions.Worker.*.nupkg + !Microsoft.Azure.Functions.Worker.Sdk.*.nupkg + !*.symbols.nupkg + ${{ if eq(parameters.packages, 'sdk') }}: + target_folder: azure-functions/dotnet/worker-sdk + package_name: Microsoft.Azure.Functions.Worker.Sdk + package_pattern: | + Microsoft.Azure.Functions.Worker.Sdk.*.nupkg + !*.symbols.nupkg + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1es + parameters: + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + + stages: + - stage: Prepare + jobs: + - job: Prepare Release + + variables: + drop_path: $(Pipeline.Workspace)/drop + + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + targetPath: $(drop_path) + artifactName: $(artifact_name) + pipeline: build + + steps: + + # Our build does not have a custom version number set. To convey the version number to the release stage, + # we parse out the version from the .nupkg in the drop and set that as the build number. The release stage + # can then reference $(Build.BuildVersion) for the target upload folder. + - pwsh: | + $ErrorActionPreference = 'Stop' + + $name = "$(package_name)".Trim() + Write-Host "Getting version for $name" + $package = Get-ChildItem -Path $(drop_path) -Recurse -Filter "$name.?.*.nupkg" + + if ($package.Count -eq 0) { + Write-Host "##vso[task.LogIssue type=error;]Could not find package $name." + exit 1 + } + + if ($package.Count -gt 1) { + Write-Host "##vso[task.LogIssue type=error;]Too many packages matched $name." + exit 1 + } + + $version = $package.Name.Trim("$name.").Trim('.nupkg') + Write-Host "##vso[build.updatebuildnumber]$version" + Write-Host "##vso[build.addbuildtag]${{ parameters.packages }}" + Write-Host "##vso[build.addbuildtag]$version" + displayName: Get package version + + - stage: Release + dependsOn: Prepare + jobs: + - template: /ci/release-nuget-package.yml@eng + parameters: + isProduction: true + approvers: '[internal]\Azure Functions Core' + stagingFeed: public/pre-release + packages: $(package_pattern) + artifact: + name: NugetPackages + pipeline: build + ${{ if eq(parameters.publishToNugetOrg, true) }}: + partnerDrop: + serviceConnection: azure-sdk-partner-drops + targetFolder: $(target_folder)/$(Build.BuildNumber) + runPipeline: false diff --git a/eng/ci/templates/jobs/run-integration-tests-windows.yml b/eng/ci/templates/jobs/run-integration-tests-windows.yml index 85993c9b6..ea07fef37 100644 --- a/eng/ci/templates/jobs/run-integration-tests-windows.yml +++ b/eng/ci/templates/jobs/run-integration-tests-windows.yml @@ -1,5 +1,5 @@ parameters: - name: PoolName +- name: PoolName type: string jobs: diff --git a/eng/ci/templates/jobs/run-unit-tests.yml b/eng/ci/templates/jobs/run-unit-tests.yml index b7ec444bc..b96ccb0ea 100644 --- a/eng/ci/templates/jobs/run-unit-tests.yml +++ b/eng/ci/templates/jobs/run-unit-tests.yml @@ -1,5 +1,5 @@ parameters: - name: PoolName +- name: PoolName type: string jobs: @@ -38,7 +38,7 @@ jobs: command: test arguments: -v n projects: | - **/DotNetWorker.Opentelemetry.Tests.csproj + **/DotNetWorker.OpenTelemetry.Tests.csproj - task: DotNetCoreCLI@2 displayName: Sdk Tests @@ -46,8 +46,8 @@ jobs: command: test arguments: -v n projects: | - **\Sdk.Analyzers.Tests.csproj - **\Sdk.Generator.Tests.csproj + **/Sdk.Analyzers.Tests.csproj + **/Sdk.Generator.Tests.csproj - task: DotNetCoreCLI@2 displayName: Extension Tests diff --git a/eng/ci/templates/official/jobs/build-artifacts.yml b/eng/ci/templates/official/jobs/build-artifacts.yml index 887d2912d..671ed8052 100644 --- a/eng/ci/templates/official/jobs/build-artifacts.yml +++ b/eng/ci/templates/official/jobs/build-artifacts.yml @@ -17,7 +17,7 @@ jobs: os: windows variables: - ${{ if and( not(contains(variables['Build.SourceBranch'], '/release/')), not(startsWith(variables['Build.SourceBranch'], 'refs/tags')) ) }}: + ${{ if and( not(startsWith(variables['Build.SourceBranch'], 'refs/heads/release/')), not(startsWith(variables['Build.SourceBranch'], 'refs/tags')) ) }}: buildNumberTemp: $(Build.BuildNumber) buildNumber: $[variables.buildNumberTemp] diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml new file mode 100644 index 000000000..239a6d900 --- /dev/null +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -0,0 +1,83 @@ +parameters: +- name: publishToNugetOrg + type: boolean +- name: artifactName + type: string + default: NugetPackages +- name: targetFolder + type: string + default: '' + +resources: + repositories: + - repository: 1es + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + - repository: eng + type: git + name: engineering + ref: refs/tags/release + +variables: +- name: target_folder + readonly: true + ${{ if ne(parameters.targetFolder, '') }}: + value: ${{ parameters.targetFolder }} + ${{ else }}: + value: ${{ replace(replace(replace(variables['resources.pipeline.build.pipelineName'], 'extensions.', ''), '.official', ''), '.', '-') }} + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1es + parameters: + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + + stages: + - stage: Prepare + jobs: + - job: Prepare Release + + variables: + drop_path: $(Pipeline.Workspace)/drop + + templateContext: + type: releaseJob + isProduction: true + inputs: + - input: pipelineArtifact + targetPath: $(drop_path) + artifactName: ${{ parameters.artifactName }} + pipeline: build + + steps: + # For extension releases, we assume the first package (alphanumerically) in the drop is the one we want to version off of. + # This is a bit of a hack, but it works for our current setup. + # We use a regex to extract the version from the package name and set it as the build number. + - pwsh: | + $ErrorActionPreference = 'Stop' + $packages = Get-ChildItem -Path $(drop_path) -Filter *.nupkg -Recurse + $name = $packages[0].Name + Write-Host "Getting version for $name" + $version = [Regex]::Match($name, '(\d+\.\d+\.\d+(?:\.\d+)?(?:-[\w\.].*)?)(?=\.nupkg$)').Value + Write-Host "##vso[build.updatebuildnumber]$version" + displayName: Get package version + + - stage: Release + dependsOn: Prepare + jobs: + - template: /ci/release-nuget-package.yml@eng + parameters: + isProduction: true + approvers: '[internal]\Azure Functions Core' + stagingFeed: public/pre-release + artifact: + name: NugetPackages + pipeline: build + ${{ if eq(parameters.publishToNugetOrg, true) }}: + partnerDrop: + serviceConnection: azure-sdk-partner-drops + targetFolder: azure-functions/dotnet/worker-extensions/$(target_folder)/$(Build.BuildNumber) + runPipeline: false diff --git a/extensions/Worker.Extensions.Abstractions/ci/official-release.yml b/extensions/Worker.Extensions.Abstractions/ci/official-release.yml new file mode 100644 index 000000000..82814651b --- /dev/null +++ b/extensions/Worker.Extensions.Abstractions/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.abstractions.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.CosmosDB/ci/official-release.yml b/extensions/Worker.Extensions.CosmosDB/ci/official-release.yml new file mode 100644 index 000000000..543ffb0fa --- /dev/null +++ b/extensions/Worker.Extensions.CosmosDB/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.cosmos.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.EventGrid/ci/official-release.yml b/extensions/Worker.Extensions.EventGrid/ci/official-release.yml new file mode 100644 index 000000000..f8d006ca8 --- /dev/null +++ b/extensions/Worker.Extensions.EventGrid/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.eventgrid.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.EventHubs/ci/official-release.yml b/extensions/Worker.Extensions.EventHubs/ci/official-release.yml new file mode 100644 index 000000000..7ea6fd52e --- /dev/null +++ b/extensions/Worker.Extensions.EventHubs/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.eventhubs.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Http.AspNetCore/ci/official-release.yml b/extensions/Worker.Extensions.Http.AspNetCore/ci/official-release.yml new file mode 100644 index 000000000..bd711f136 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.http.aspnetcore.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Http/ci/official-release.yml b/extensions/Worker.Extensions.Http/ci/official-release.yml new file mode 100644 index 000000000..c32ffd8b1 --- /dev/null +++ b/extensions/Worker.Extensions.Http/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.http.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Kafka/ci/official-release.yml b/extensions/Worker.Extensions.Kafka/ci/official-release.yml new file mode 100644 index 000000000..a498aa2f6 --- /dev/null +++ b/extensions/Worker.Extensions.Kafka/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.kafka.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.RabbitMQ/ci/official-release.yml b/extensions/Worker.Extensions.RabbitMQ/ci/official-release.yml new file mode 100644 index 000000000..8e3d3b933 --- /dev/null +++ b/extensions/Worker.Extensions.RabbitMQ/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.rabbitmq.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Rpc/ci/official-release.yml b/extensions/Worker.Extensions.Rpc/ci/official-release.yml new file mode 100644 index 000000000..3256a7e4c --- /dev/null +++ b/extensions/Worker.Extensions.Rpc/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.rpc.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.SendGrid/ci/official-release.yml b/extensions/Worker.Extensions.SendGrid/ci/official-release.yml new file mode 100644 index 000000000..d1daea0a3 --- /dev/null +++ b/extensions/Worker.Extensions.SendGrid/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.sendgrid.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.ServiceBus/ci/official-release.yml b/extensions/Worker.Extensions.ServiceBus/ci/official-release.yml new file mode 100644 index 000000000..97a2cd768 --- /dev/null +++ b/extensions/Worker.Extensions.ServiceBus/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.servicebus.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.SignalRService/ci/official-release.yml b/extensions/Worker.Extensions.SignalRService/ci/official-release.yml new file mode 100644 index 000000000..3917aa1cf --- /dev/null +++ b/extensions/Worker.Extensions.SignalRService/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.signalr.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Storage.Blobs/ci/official-release.yml b/extensions/Worker.Extensions.Storage.Blobs/ci/official-release.yml new file mode 100644 index 000000000..0190402b8 --- /dev/null +++ b/extensions/Worker.Extensions.Storage.Blobs/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.storage.blobs.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Storage.Queues/ci/official-release.yml b/extensions/Worker.Extensions.Storage.Queues/ci/official-release.yml new file mode 100644 index 000000000..081c02a58 --- /dev/null +++ b/extensions/Worker.Extensions.Storage.Queues/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.storage.queues.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Storage/ci/official-release.yml b/extensions/Worker.Extensions.Storage/ci/official-release.yml new file mode 100644 index 000000000..00fbb0d9c --- /dev/null +++ b/extensions/Worker.Extensions.Storage/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.storage.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Tables/ci/official-release.yml b/extensions/Worker.Extensions.Tables/ci/official-release.yml new file mode 100644 index 000000000..3476bd45f --- /dev/null +++ b/extensions/Worker.Extensions.Tables/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.tables.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Timer/ci/official-release.yml b/extensions/Worker.Extensions.Timer/ci/official-release.yml new file mode 100644 index 000000000..5e9fe690f --- /dev/null +++ b/extensions/Worker.Extensions.Timer/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.timer.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/extensions/Worker.Extensions.Warmup/ci/official-release.yml b/extensions/Worker.Extensions.Warmup/ci/official-release.yml new file mode 100644 index 000000000..e7ac837f9 --- /dev/null +++ b/extensions/Worker.Extensions.Warmup/ci/official-release.yml @@ -0,0 +1,18 @@ +parameters: +- name: publishToNugetOrg + displayName: Publish to nuget.org? + type: boolean + default: false + +pr: none +trigger: none + +resources: + pipelines: + - pipeline: build + source: extensions.warmup.official + +extends: + template: /eng/ci/templates/pipelines/release-extension-packages.yml@self + parameters: + publishToNugetOrg: ${{ parameters.publishToNugetOrg }} diff --git a/global.json b/global.json index 34000aad5..c8f2593ac 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.100", + "version": "9.0.201", "allowPrerelease": true, "rollForward": "latestFeature" }, From ef73bae6cc92b69a683e53152bcb6d3749e53146 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Fri, 18 Apr 2025 08:29:44 -0700 Subject: [PATCH 110/190] Fix job names (#3033) --- eng/ci/official-release.yml | 5 ++--- eng/ci/templates/pipelines/release-extension-packages.yml | 5 ++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml index b9b25285e..3e5d4ebb9 100644 --- a/eng/ci/official-release.yml +++ b/eng/ci/official-release.yml @@ -55,14 +55,13 @@ extends: stages: - stage: Prepare jobs: - - job: Prepare Release + - job: Prepare variables: drop_path: $(Pipeline.Workspace)/drop templateContext: - type: releaseJob - isProduction: true + type: validationJob inputs: - input: pipelineArtifact targetPath: $(drop_path) diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml index 239a6d900..1ee7995f9 100644 --- a/eng/ci/templates/pipelines/release-extension-packages.yml +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -38,14 +38,13 @@ extends: stages: - stage: Prepare jobs: - - job: Prepare Release + - job: Prepare variables: drop_path: $(Pipeline.Workspace)/drop templateContext: - type: releaseJob - isProduction: true + type: validationJob inputs: - input: pipelineArtifact targetPath: $(drop_path) From 0db5c449a7135b7adc87aff8df680c5c6b840725 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Fri, 18 Apr 2025 10:22:23 -0700 Subject: [PATCH 111/190] Minor updates to the `dotnet run` Core Tools failure verbiage. --- sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index ae6b02779..021378afb 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -142,7 +142,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + From 657139791e5becf4a8104420596b3ba1831eae4a Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Fri, 18 Apr 2025 13:34:09 -0700 Subject: [PATCH 112/190] Update e2e setup script to download latest cli from GH (#3036) * Update e2e setup script to use latest cli from GH * Fix the fixture cmd for calling func start --- setup-e2e-tests.ps1 | 74 +++++++++++-------- .../E2ETests/Fixtures/FixtureHelpers.cs | 2 - 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/setup-e2e-tests.ps1 b/setup-e2e-tests.ps1 index 62f2d9925..c9cb60358 100644 --- a/setup-e2e-tests.ps1 +++ b/setup-e2e-tests.ps1 @@ -25,66 +25,76 @@ param( $FunctionsRuntimeVersion = 4 -# A function that checks exit codes and fails script if an error is found function StopOnFailedExecution { - if ($LastExitCode) - { - exit $LastExitCode + if ($LastExitCode) + { + exit $LastExitCode } } if($SkipCoreTools) { Write-Host - Write-Host "---Skipping Core Tools download---" + Write-Host "---Skipping Core Tools download---" } else { $arch = [System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture.ToString().ToLowerInvariant() + if ($IsWindows) { $os = "win" $coreToolsURL = $env:CORE_TOOLS_URL } + elseif ($IsMacOS) { + $os = "osx" + } else { - if ($IsMacOS) { - $os = "osx" - } else { - $os = "linux" - $coreToolsURL = $env:CORE_TOOLS_URL_LINUX - } + $os = "linux" + $coreToolsURL = $env:CORE_TOOLS_URL_LINUX } - if ($UseCoreToolsBuildFromIntegrationTests.IsPresent) - { + if ($UseCoreToolsBuildFromIntegrationTests -eq $true -or $UseCoreToolsBuildFromIntegrationTests.IsPresent) { Write-Host "" - Write-Host "Install the Core Tools for Integration Tests..." - $coreToolsURL = "https://functionsintegclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/Azure.Functions.Cli.$os-$arch.zip" - $versionUrl = "https://functionsintegclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/version.txt" + Write-Host "Using Core Tools from integration test feed..." + + if ([string]::IsNullOrWhiteSpace($coreToolsURL)) { + Write-Error "CORE_TOOLS_URL (or CORE_TOOLS_URL_LINUX) is not set." + exit 1 + } } - else - { - if ([string]::IsNullOrWhiteSpace($coreToolsURL)) - { - $coreToolsURL = "https://functionsclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/Azure.Functions.Cli.$os-$arch.zip" - $versionUrl = "https://functionsclibuilds.blob.core.windows.net/builds/$FunctionsRuntimeVersion/latest/version.txt" + else { + Write-Host "" + Write-Host "Using latest Core Tools release from GitHub..." + + # GitHub API call for latest release + $releaseInfo = Invoke-RestMethod -Uri "https://api.github.com/repos/Azure/azure-functions-core-tools/releases/latest" -Headers @{ "User-Agent" = "PowerShell" } + + $latestVersion = $releaseInfo.tag_name + Write-Host "`nLatest Core Tools version: $latestVersion" + + # Look for zip file matching os and arch + $pattern = "Azure\.Functions\.Cli\.$os-$arch\..*\.zip$" + $asset = $releaseInfo.assets | Where-Object { + $_.name -match $pattern } + + if (-not $asset) { + Write-Error "Could not find a Core Tools .zip for OS '$os' and arch '$arch'" + exit 1 + } + + $coreToolsURL = $asset.browser_download_url } Write-Host "" Write-Host "---Downloading the Core Tools for Functions V$FunctionsRuntimeVersion---" - Write-Host "Core Tools download url: $coreToolsURL" + Write-Host "Core Tools download URL: $coreToolsURL" $FUNC_CLI_DIRECTORY = Join-Path $PSScriptRoot 'Azure.Functions.Cli' Write-Host 'Deleting Functions Core Tools if exists...' Remove-Item -Force "$FUNC_CLI_DIRECTORY.zip" -ErrorAction Ignore Remove-Item -Recurse -Force $FUNC_CLI_DIRECTORY -ErrorAction Ignore - if ($versionUrl) - { - $version = Invoke-RestMethod -Uri $versionUrl - Write-Host "Downloading Functions Core Tools (Version: $version)..." - } - $output = "$FUNC_CLI_DIRECTORY.zip" Invoke-RestMethod -Uri $coreToolsURL -OutFile $output @@ -95,11 +105,11 @@ else { & "chmod" "a+x" "$FUNC_CLI_DIRECTORY/func" } - + Write-Host "------" } -if (Test-Path $output) +if (Test-Path $output) { Remove-Item $output -Recurse -Force -ErrorAction Ignore } @@ -121,7 +131,7 @@ if ($SkipStorageEmulator -And $SkipCosmosDBEmulator) Write-Host "---Skipping emulator startup---" Write-Host } -else +else { .\tools\start-emulators.ps1 -SkipStorageEmulator:$SkipStorageEmulator -SkipCosmosDBEmulator:$SkipCosmosDBEmulator } diff --git a/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs b/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs index 4fdce8194..3b31026b4 100644 --- a/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs +++ b/test/E2ETests/E2ETests/Fixtures/FixtureHelpers.cs @@ -45,9 +45,7 @@ public static Process GetFuncHostProcess(bool enableAuth = false, string testApp funcProcess.StartInfo.CreateNoWindow = true; funcProcess.StartInfo.WorkingDirectory = e2eAppPath; funcProcess.StartInfo.FileName = cliPath; - funcProcess.StartInfo.ArgumentList.Add("host"); funcProcess.StartInfo.ArgumentList.Add("start"); - funcProcess.StartInfo.ArgumentList.Add("--csharp"); funcProcess.StartInfo.ArgumentList.Add("--verbose"); if (enableAuth) From 847a7cd9f3ccde92a046921b028cda92fcc5989e Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Fri, 18 Apr 2025 14:06:13 -0700 Subject: [PATCH 113/190] Update storage extensions & prep for release (#3029) --- .../src/BlobStorageConverter.cs | 2 +- .../src/Worker.Extensions.Storage.Blobs.csproj | 11 +++++------ .../src/TypeConverters/QueueMessageConverter.cs | 2 +- .../src/Worker.Extensions.Storage.Queues.csproj | 8 ++++---- .../Worker.Extensions.Storage/release_notes.md | 17 +++++++++++------ .../src/Worker.Extensions.Storage.csproj | 2 +- 6 files changed, 23 insertions(+), 19 deletions(-) diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/BlobStorageConverter.cs b/extensions/Worker.Extensions.Storage.Blobs/src/BlobStorageConverter.cs index 029043908..1498f67c2 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/BlobStorageConverter.cs +++ b/extensions/Worker.Extensions.Storage.Blobs/src/BlobStorageConverter.cs @@ -93,7 +93,7 @@ private BlobBindingData GetBindingDataContent(ModelBindingData bindingData) return bindingData.ContentType switch { - Constants.JsonContentType => bindingData.Content.ToObjectFromJson(), + Constants.JsonContentType => bindingData.Content.ToObjectFromJson()!, _ => throw new InvalidContentTypeException(bindingData.ContentType, Constants.JsonContentType) }; } diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index 00df03913..b4c9ad017 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -6,7 +6,7 @@ Azure Blob Storage extensions for .NET isolated functions - 6.6.1 + 6.7.0 false @@ -19,10 +19,9 @@ - - - - + + + @@ -30,7 +29,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueMessageConverter.cs b/extensions/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueMessageConverter.cs index 02e319657..fd595c3eb 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueMessageConverter.cs +++ b/extensions/Worker.Extensions.Storage.Queues/src/TypeConverters/QueueMessageConverter.cs @@ -38,7 +38,7 @@ private QueueMessage ExtractQueueMessage(ModelBindingData modelBindingData) throw new InvalidContentTypeException(modelBindingData.ContentType, Constants.JsonContentType); } - return modelBindingData.Content.ToObjectFromJson(_jsonOptions); + return modelBindingData.Content.ToObjectFromJson(_jsonOptions)!; } } } diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj index d1096396e..6333b6c85 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj +++ b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj @@ -6,7 +6,7 @@ Azure Queue Storage extensions for .NET isolated functions - 5.5.1 + 5.5.2 false @@ -19,8 +19,8 @@ - - + + @@ -28,7 +28,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 4ab632232..71d645aa1 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,15 +4,20 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage +### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.7.0 -- +- Update `Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs` to 6.7.0 +- Update `Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues` to 5.5.2 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.7.0 -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs +- Update WebJobs package `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` to 5.3.4 +- Removed `Microsoft.Bcl.AsyncInterfaces` as direct dependency +- Update other dependencies to latest versions -- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.5.2 + +- Update WebJobs package `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` to 5.3.4 +- Update other dependencies to latest versions -- diff --git a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj index 7098d2e9a..af4803771 100644 --- a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj +++ b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj @@ -6,7 +6,7 @@ Azure Storage extensions for .NET isolated functions - 6.6.1 + 6.7.0 false From 029996c09d422ccc87963a20a24f4fa3cf4fec6d Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Fri, 18 Apr 2025 14:07:16 -0700 Subject: [PATCH 114/190] Update Tables extension (#3006) --- extensions/Worker.Extensions.Tables/release_notes.md | 5 ++--- .../src/Worker.Extensions.Tables.csproj | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.Tables/release_notes.md b/extensions/Worker.Extensions.Tables/release_notes.md index 79200facf..95e1a335b 100644 --- a/extensions/Worker.Extensions.Tables/release_notes.md +++ b/extensions/Worker.Extensions.Tables/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Tables - -- +### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.4.3 +- Update `Microsoft.Azure.WebJobs.Extensions.Tables` to `1.3.3`. \ No newline at end of file diff --git a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj index 54b872ea3..31cd9102b 100644 --- a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj +++ b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj @@ -6,7 +6,7 @@ Azure Table Storage extensions for .NET isolated functions - 1.4.2 + 1.4.3 @@ -29,7 +29,7 @@ - + \ No newline at end of file From 89563d5c7a299778f86bec744db12f5f09d3cabf Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Fri, 18 Apr 2025 14:56:16 -0700 Subject: [PATCH 115/190] Move variables section (#3037) * Move variables section * Move if statement * Remove publishToNuget usage for now * Update template * Remove runPipeline: false --- eng/ci/code-mirror.yml | 2 +- .../pipelines/release-extension-packages.yml | 19 ++++++++++--------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/eng/ci/code-mirror.yml b/eng/ci/code-mirror.yml index 279f4f289..5d9fcb4cd 100644 --- a/eng/ci/code-mirror.yml +++ b/eng/ci/code-mirror.yml @@ -13,7 +13,7 @@ resources: ref: refs/tags/release variables: - - template: ci/variables/cfs.yml@eng +- template: ci/variables/cfs.yml@eng extends: template: ci/code-mirror.yml@eng diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml index 1ee7995f9..4900252ac 100644 --- a/eng/ci/templates/pipelines/release-extension-packages.yml +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -19,14 +19,6 @@ resources: name: engineering ref: refs/tags/release -variables: -- name: target_folder - readonly: true - ${{ if ne(parameters.targetFolder, '') }}: - value: ${{ parameters.targetFolder }} - ${{ else }}: - value: ${{ replace(replace(replace(variables['resources.pipeline.build.pipelineName'], 'extensions.', ''), '.official', ''), '.', '-') }} - extends: template: v1/1ES.Official.PipelineTemplate.yml@1es parameters: @@ -36,6 +28,7 @@ extends: os: linux stages: + - stage: Prepare jobs: - job: Prepare @@ -66,6 +59,15 @@ extends: - stage: Release dependsOn: Prepare + + variables: + - name: target_folder + readonly: true + ${{ if ne(parameters.targetFolder, '') }}: + value: ${{ parameters.targetFolder }} + ${{ else }}: + value: ${{ replace(replace(replace(variables['resources.pipeline.build.pipelineName'], 'extensions.', ''), '.official', ''), '.', '-') }} + jobs: - template: /ci/release-nuget-package.yml@eng parameters: @@ -79,4 +81,3 @@ extends: partnerDrop: serviceConnection: azure-sdk-partner-drops targetFolder: azure-functions/dotnet/worker-extensions/$(target_folder)/$(Build.BuildNumber) - runPipeline: false From 574b06a0ab623d2ca4799510bdd6bf22f753e7f2 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 21 Apr 2025 09:07:34 -0700 Subject: [PATCH 116/190] Skip checkout for release pipelines (#3038) --- eng/ci/official-release.yml | 28 +++++++++++++------ .../pipelines/release-extension-packages.yml | 7 ++++- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml index 3e5d4ebb9..230f7ea6a 100644 --- a/eng/ci/official-release.yml +++ b/eng/ci/official-release.yml @@ -29,18 +29,27 @@ resources: source: dotnet-worker.official variables: - artifact_name: NugetPackages - ${{ if eq(parameters.packages, 'core') }}: - target_folder: azure-functions/dotnet/worker - package_name: Microsoft.Azure.Functions.Worker - package_pattern: | +- name: artifact_name + value: NugetPackages + +- ${{ if eq(parameters.packages, 'core') }}: + - name: target_folder + value: azure-functions/dotnet/worker + - name: package_name + value: Microsoft.Azure.Functions.Worker + - name: package_pattern + value: | Microsoft.Azure.Functions.Worker.*.nupkg !Microsoft.Azure.Functions.Worker.Sdk.*.nupkg !*.symbols.nupkg - ${{ if eq(parameters.packages, 'sdk') }}: - target_folder: azure-functions/dotnet/worker-sdk - package_name: Microsoft.Azure.Functions.Worker.Sdk - package_pattern: | + +- ${{ if eq(parameters.packages, 'sdk') }}: + - name: target_folder + value: azure-functions/dotnet/worker-sdk + - name: package_name + value: Microsoft.Azure.Functions.Worker.Sdk + - name: package_pattern + value: | Microsoft.Azure.Functions.Worker.Sdk.*.nupkg !*.symbols.nupkg @@ -69,6 +78,7 @@ extends: pipeline: build steps: + - checkout: none # Our build does not have a custom version number set. To convey the version number to the release stage, # we parse out the version from the .nupkg in the drop and set that as the build number. The release stage diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml index 4900252ac..600e51859 100644 --- a/eng/ci/templates/pipelines/release-extension-packages.yml +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -34,7 +34,9 @@ extends: - job: Prepare variables: - drop_path: $(Pipeline.Workspace)/drop + - template: ci/variables/cfs.yml@eng + - name: drop_path + value: $(Pipeline.Workspace)/drop templateContext: type: validationJob @@ -45,6 +47,8 @@ extends: pipeline: build steps: + - checkout: none + # For extension releases, we assume the first package (alphanumerically) in the drop is the one we want to version off of. # This is a bit of a hack, but it works for our current setup. # We use a regex to extract the version from the package name and set it as the build number. @@ -61,6 +65,7 @@ extends: dependsOn: Prepare variables: + - template: ci/variables/cfs.yml@eng - name: target_folder readonly: true ${{ if ne(parameters.targetFolder, '') }}: From a5b5e5fcf6541c89ecde747a51d633f35172accf Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 21 Apr 2025 10:32:10 -0700 Subject: [PATCH 117/190] Use retail artifact inputs in validationJob (#3039) --- eng/ci/official-release.yml | 12 ++++++------ .../pipelines/release-extension-packages.yml | 11 +++++------ 2 files changed, 11 insertions(+), 12 deletions(-) diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml index 230f7ea6a..3e2f5cf1e 100644 --- a/eng/ci/official-release.yml +++ b/eng/ci/official-release.yml @@ -67,19 +67,19 @@ extends: - job: Prepare variables: - drop_path: $(Pipeline.Workspace)/drop + - name: drop_path + value: $(Pipeline.Workspace)/build/$(artifact_name) templateContext: type: validationJob - inputs: - - input: pipelineArtifact - targetPath: $(drop_path) - artifactName: $(artifact_name) - pipeline: build steps: - checkout: none + # validationJob uses retail artifact inputs + - download: build + artifact: $(artifact_name) + # Our build does not have a custom version number set. To convey the version number to the release stage, # we parse out the version from the .nupkg in the drop and set that as the build number. The release stage # can then reference $(Build.BuildVersion) for the target upload folder. diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml index 600e51859..e21435e55 100644 --- a/eng/ci/templates/pipelines/release-extension-packages.yml +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -36,19 +36,18 @@ extends: variables: - template: ci/variables/cfs.yml@eng - name: drop_path - value: $(Pipeline.Workspace)/drop + value: $(Pipeline.Workspace)/build/${{ parameters.artifactName }} templateContext: type: validationJob - inputs: - - input: pipelineArtifact - targetPath: $(drop_path) - artifactName: ${{ parameters.artifactName }} - pipeline: build steps: - checkout: none + # validationJob uses retail artifact inputs + - download: build + artifact: ${{ parameters.artifactName }} + # For extension releases, we assume the first package (alphanumerically) in the drop is the one we want to version off of. # This is a bit of a hack, but it works for our current setup. # We use a regex to extract the version from the package name and set it as the build number. From 20901205a4b2e8ca7da1eaea242658e0776f1091 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 21 Apr 2025 15:47:27 -0700 Subject: [PATCH 118/190] Use variable expression (#3040) --- eng/ci/templates/pipelines/release-extension-packages.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml index e21435e55..dac5eb5dd 100644 --- a/eng/ci/templates/pipelines/release-extension-packages.yml +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -70,7 +70,7 @@ extends: ${{ if ne(parameters.targetFolder, '') }}: value: ${{ parameters.targetFolder }} ${{ else }}: - value: ${{ replace(replace(replace(variables['resources.pipeline.build.pipelineName'], 'extensions.', ''), '.official', ''), '.', '-') }} + value: $[ replace(replace(replace(variables['resources.pipeline.build.pipelineName'], 'extensions.', ''), '.official', ''), '.', '-') ] jobs: - template: /ci/release-nuget-package.yml@eng From bbf3d7296d51e0836b2a1d2359ec55e4117bcae4 Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Mon, 21 Apr 2025 18:02:59 -0500 Subject: [PATCH 119/190] Support deferred binding for poco types in Table Input binding (#3003) --- .../Worker.Extensions.Tables/release_notes.md | 4 +- .../src/TableInputAttribute.cs | 1 + .../TypeConverters/TableClientConverter.cs | 10 +- .../src/TypeConverters/TableConverterBase.cs | 52 ++- .../TypeConverters/TableEntityConverter.cs | 19 +- .../TableEntityEnumerableConverter.cs | 44 +- .../src/TypeConverters/TablePocoConverter.cs | 98 +++++ .../src/Worker.Extensions.Tables.csproj | 2 +- .../Table/TableInputBindingFunctions.cs | 46 ++- .../FunctionMetadataGeneratorTests.cs | 16 +- .../Table/TableEntityConverterTests.cs | 2 +- .../TableEntityEnumerableConverterTests.cs | 2 +- .../Table/TablePocoConverterTests.cs | 387 ++++++++++++++++++ .../Table/TableTestHelper.cs | 17 +- 14 files changed, 616 insertions(+), 84 deletions(-) create mode 100644 extensions/Worker.Extensions.Tables/src/TypeConverters/TablePocoConverter.cs create mode 100644 test/Worker.Extensions.Tests/Table/TablePocoConverterTests.cs diff --git a/extensions/Worker.Extensions.Tables/release_notes.md b/extensions/Worker.Extensions.Tables/release_notes.md index 95e1a335b..197b1a6c1 100644 --- a/extensions/Worker.Extensions.Tables/release_notes.md +++ b/extensions/Worker.Extensions.Tables/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.4.3 +### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.5.0 -- Update `Microsoft.Azure.WebJobs.Extensions.Tables` to `1.3.3`. \ No newline at end of file +- Support deferred binding for poco types in Table Input binding (#3003) \ No newline at end of file diff --git a/extensions/Worker.Extensions.Tables/src/TableInputAttribute.cs b/extensions/Worker.Extensions.Tables/src/TableInputAttribute.cs index bd873b20e..f182d83be 100644 --- a/extensions/Worker.Extensions.Tables/src/TableInputAttribute.cs +++ b/extensions/Worker.Extensions.Tables/src/TableInputAttribute.cs @@ -13,6 +13,7 @@ namespace Microsoft.Azure.Functions.Worker [InputConverter(typeof(TableClientConverter))] [InputConverter(typeof(TableEntityConverter))] [InputConverter(typeof(TableEntityEnumerableConverter))] + [InputConverter(typeof(TablePocoConverter))] [ConverterFallbackBehavior(ConverterFallbackBehavior.Default)] public class TableInputAttribute : InputBindingAttribute { diff --git a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableClientConverter.cs b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableClientConverter.cs index 86d028fd7..ac0b2d208 100644 --- a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableClientConverter.cs +++ b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableClientConverter.cs @@ -34,6 +34,11 @@ public override ValueTask ConvertAsync(ConverterContext contex return new(ConversionResult.Unhandled()); } + if (context.TargetType != typeof(TableClient)) + { + return new(ConversionResult.Unhandled()); + } + var modelBindingData = context?.Source as ModelBindingData; var tableData = GetBindingDataContent(modelBindingData); var result = ConvertModelBindingData(tableData); @@ -48,10 +53,7 @@ public override ValueTask ConvertAsync(ConverterContext contex private TableClient ConvertModelBindingData(TableData content) { - if (string.IsNullOrEmpty(content.TableName)) - { - throw new ArgumentNullException(nameof(content.TableName)); - } + ThrowIfNullOrEmpty(content.TableName, nameof(content.TableName)); return GetTableClient(content.Connection, content.TableName!); } diff --git a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableConverterBase.cs b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableConverterBase.cs index d4cd6ceed..1f621b46e 100644 --- a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableConverterBase.cs +++ b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableConverterBase.cs @@ -2,6 +2,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System; +using System.Collections.Generic; using System.Threading.Tasks; using Azure.Data.Tables; using Microsoft.Azure.Functions.Worker.Converters; @@ -30,11 +31,6 @@ protected bool CanConvert(ConverterContext context) throw new ArgumentNullException(nameof(context)); } - if (context.TargetType != typeof(T)) - { - return false; - } - if (context.Source is not ModelBindingData bindingData) { return false; @@ -71,6 +67,52 @@ protected TableClient GetTableClient(string? connection, string tableName) return tableServiceClient.GetTableClient(tableName); } + protected void ThrowIfNullOrEmpty(string? value, string nameOfValue) + { + if (string.IsNullOrEmpty(value)) + { + throw new ArgumentNullException(nameOfValue); + } + } + + protected async Task> GetEnumerableTableEntityAsync(TableData content) + { + var tableClient = GetTableClient(content.Connection, content.TableName!); + string? filter = content.Filter; + + if (!string.IsNullOrEmpty(content.PartitionKey)) + { + var partitionKeyPredicate = TableClient.CreateQueryFilter($"PartitionKey eq {content.PartitionKey}"); + filter = !string.IsNullOrEmpty(content.Filter) ? $"{partitionKeyPredicate} and {content.Filter}" : partitionKeyPredicate; + } + + int? maxPerPage = null; + if (content.Take > 0) + { + maxPerPage = content.Take; + } + + int countRemaining = content.Take; + + var entities = tableClient.QueryAsync( + filter: filter, + maxPerPage: maxPerPage).ConfigureAwait(false); + + List entityList = new(); + + await foreach (var entity in entities) + { + countRemaining--; + entityList.Add(entity); + if (countRemaining == 0) + { + break; + } + } + + return entityList; + } + protected class TableData { public string? TableName { get; set; } diff --git a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityConverter.cs b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityConverter.cs index b28d53587..cea24a6a6 100644 --- a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityConverter.cs +++ b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityConverter.cs @@ -33,6 +33,10 @@ public override async ValueTask ConvertAsync(ConverterContext { return ConversionResult.Unhandled(); } + if (context.TargetType != typeof(TableEntity)) + { + return ConversionResult.Unhandled(); + } var modelBindingData = context?.Source as ModelBindingData; var tableData = GetBindingDataContent(modelBindingData); @@ -48,20 +52,11 @@ public override async ValueTask ConvertAsync(ConverterContext private async Task ConvertModelBindingData(TableData content) { - if (string.IsNullOrEmpty(content.TableName)) - { - throw new ArgumentNullException(nameof(content.TableName)); - } + ThrowIfNullOrEmpty(content.TableName, nameof(content.TableName)); - if (string.IsNullOrEmpty(content.PartitionKey)) - { - throw new ArgumentNullException(nameof(content.PartitionKey)); - } + ThrowIfNullOrEmpty(content.PartitionKey, nameof(content.PartitionKey)); - if (string.IsNullOrEmpty(content.RowKey)) - { - throw new ArgumentNullException(nameof(content.RowKey)); - } + ThrowIfNullOrEmpty(content.RowKey, nameof(content.RowKey)); return await GetTableEntity(content); } diff --git a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityEnumerableConverter.cs b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityEnumerableConverter.cs index 762a49a72..fc975efea 100644 --- a/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityEnumerableConverter.cs +++ b/extensions/Worker.Extensions.Tables/src/TypeConverters/TableEntityEnumerableConverter.cs @@ -35,6 +35,10 @@ public override async ValueTask ConvertAsync(ConverterContext { return ConversionResult.Unhandled(); } + if (context.TargetType != typeof(IEnumerable)) + { + return ConversionResult.Unhandled(); + } var modelBindingData = context?.Source as ModelBindingData; var tableData = GetBindingDataContent(modelBindingData); @@ -60,45 +64,7 @@ private async Task> ConvertModelBindingData(TableData c throw new InvalidOperationException($"Row key {content.RowKey} cannot have a value if {content.Take} or {content.Filter} are defined"); } - return await GetEnumerableTableEntity(content); - } - - private async Task> GetEnumerableTableEntity(TableData content) - { - var tableClient = GetTableClient(content.Connection, content.TableName!); - string? filter = content.Filter; - - if (!string.IsNullOrEmpty(content.PartitionKey)) - { - var partitionKeyPredicate = TableClient.CreateQueryFilter($"PartitionKey eq {content.PartitionKey}"); - filter = !string.IsNullOrEmpty(content.Filter) ? $"{partitionKeyPredicate} and {content.Filter}" : partitionKeyPredicate; - } - - int? maxPerPage = null; - if (content.Take > 0) - { - maxPerPage = content.Take; - } - - int countRemaining = content.Take; - - var entities = tableClient.QueryAsync( - filter: filter, - maxPerPage: maxPerPage).ConfigureAwait(false); - - List entityList = new(); - - await foreach (var entity in entities) - { - countRemaining--; - entityList.Add(entity); - if (countRemaining == 0) - { - break; - } - } - - return entityList; + return await GetEnumerableTableEntityAsync(content); } } } diff --git a/extensions/Worker.Extensions.Tables/src/TypeConverters/TablePocoConverter.cs b/extensions/Worker.Extensions.Tables/src/TypeConverters/TablePocoConverter.cs new file mode 100644 index 000000000..f2084ff3f --- /dev/null +++ b/extensions/Worker.Extensions.Tables/src/TypeConverters/TablePocoConverter.cs @@ -0,0 +1,98 @@ +// 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.Threading.Tasks; +using Azure.Data.Tables; +using Microsoft.Azure.Functions.Worker.Converters; +using Microsoft.Azure.Functions.Worker.Core; +using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; +using Microsoft.Azure.Functions.Worker.Extensions.Tables.Config; +using Microsoft.Extensions.Options; +using Microsoft.Extensions.Logging; +using System.Threading; +using System.IO; +using System.Text.Json; +using System.Text; +using System.Collections.Generic; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Tables.TypeConverters +{ + /// + /// Converter to bind type parameters. + /// + [SupportsDeferredBinding] + internal sealed class TablePocoConverter : TableConverterBase + { + private readonly IOptions _workerOptions; + + public TablePocoConverter(IOptions workerOptions, IOptionsMonitor tableOptions, ILogger logger) + : base(tableOptions, logger) + { + _workerOptions = workerOptions ?? throw new ArgumentNullException(nameof(workerOptions)); + } + + public override async ValueTask ConvertAsync(ConverterContext context) + { + try + { + if (!CanConvert(context)) + { + return ConversionResult.Unhandled(); + } + + var modelBindingData = context?.Source as ModelBindingData; + var tableData = GetBindingDataContent(modelBindingData); + var result = await ConvertModelBindingDataAsync(tableData, context!.TargetType); + + if (result is null) + { + return ConversionResult.Failed(new InvalidOperationException($"Unable to convert table binding data to type '{context.TargetType.Name}'.")); + } + + return ConversionResult.Success(result); + } + catch (JsonException ex) + { + return ConversionResult.Failed(new InvalidOperationException($"Unsupported binding type: '{context.TargetType}'", ex)); + } + catch (Exception ex) + { + return ConversionResult.Failed(ex); + } + } + + private async Task ConvertModelBindingDataAsync(TableData content, Type targetType) + { + ThrowIfNullOrEmpty(content.TableName, nameof(content.TableName)); + + ThrowIfNullOrEmpty(content.PartitionKey, nameof(content.PartitionKey)); + + var tableClient = GetTableClient(content.Connection, content.TableName!); + + if (targetType.IsCollectionType()) + { + IEnumerable tableEntities = await GetEnumerableTableEntityAsync(content); + return DeserializeToTargetObject(targetType, tableEntities); + } + else + { + ThrowIfNullOrEmpty(content.RowKey, nameof(content.RowKey)); + + TableEntity tableEntity = await tableClient.GetEntityAsync(content.PartitionKey, content.RowKey); + return DeserializeToTargetObject(targetType, tableEntity); + } + } + + private object? DeserializeToTargetObject(Type targetType, object tableEntity) + { + string jsonString = JsonSerializer.Serialize(tableEntity); + byte[] byteArray = Encoding.UTF8.GetBytes(jsonString); + + var stream = new MemoryStream(byteArray); + stream.Seek(0, SeekOrigin.Begin); + + return _workerOptions?.Value?.Serializer?.Deserialize(stream, targetType, CancellationToken.None); + } + } +} diff --git a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj index 31cd9102b..ab07ea44e 100644 --- a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj +++ b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj @@ -6,7 +6,7 @@ Azure Table Storage extensions for .NET isolated functions - 1.4.3 + 1.5.0 diff --git a/test/E2ETests/E2EApps/E2EApp/Table/TableInputBindingFunctions.cs b/test/E2ETests/E2EApps/E2EApp/Table/TableInputBindingFunctions.cs index 58db63c9f..f9437c76f 100644 --- a/test/E2ETests/E2EApps/E2EApp/Table/TableInputBindingFunctions.cs +++ b/test/E2ETests/E2EApps/E2EApp/Table/TableInputBindingFunctions.cs @@ -1,9 +1,11 @@ // 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.Net; using System.Threading.Tasks; +using Azure; using Azure.Data.Tables; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; @@ -87,7 +89,7 @@ public async Task EnumerableFunction( return response; } - [Function("DoesNotSupportDeferredBinding")] + [Function("PocoFunction")] public static void TableInput( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req, [TableInput("TestTable", "MyPartition", "yo")] MyPoco poco, @@ -96,11 +98,53 @@ public static void TableInput( log.LogInformation($"PK={poco.PartitionKey}, RK={poco.RowKey}, Text={poco.Text}"); } + [Function("PocoEnumerableFunction")] + public static void TableInput( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req, + [TableInput("TestTable", "MyPartition")] IEnumerable pocoList, + ILogger log) + { + foreach (MyPoco poco in pocoList) + { + log.LogInformation($"PK={poco.PartitionKey}, Text={poco.Text}"); + } + } + + [Function("MyEntityFunction")] + public static void TableInput( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req, + [TableInput("TestTable", "MyPartition", "yo")] MyEntity poco, + ILogger log) + { + log.LogInformation($"PK={poco.PartitionKey}, RK={poco.RowKey}, Text={poco.Text}"); + } + + [Function("MyEntityEnumerableFunction")] + public static void TableInput( + [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req, + [TableInput("TestTable", "MyPartition")] IEnumerable pocoList, + ILogger log) + { + foreach (MyEntity poco in pocoList) + { + log.LogInformation($"PK={poco.PartitionKey}, Text={poco.Text}"); + } + } + public class MyPoco { public string PartitionKey { get; set; } public string RowKey { get; set; } public string Text { get; set; } } + + public class MyEntity : ITableEntity + { + public string PartitionKey { get; set; } + public string RowKey { get; set; } + public string Text { get; set; } + public DateTimeOffset? Timestamp { get; set; } + public ETag ETag { get; set; } + } } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs index 44f4a48c8..4cb92467b 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadata/FunctionMetadataGeneratorTests.cs @@ -533,7 +533,7 @@ public void TableFunctions_SDKTypeBindings() var functions = generator.GenerateFunctionMetadata(typeDef); var extensions = generator.Extensions; - Assert.Equal(5, functions.Count()); + Assert.Equal(4, functions.Count()); var tableClientFunction = functions.Single(p => p.Name == "TableClientFunction"); @@ -556,13 +556,6 @@ public void TableFunctions_SDKTypeBindings() ValidateFunction(enumerableTableEntityFunction, "EnumerableTableEntityFunction", GetEntryPoint(nameof(SDKTypeBindings_Table), nameof(SDKTypeBindings_Table.EnumerableTableEntityFunction)), b => ValidateTableInput(b)); - - var tableUnsupportedTypeFunction = functions.Single(p => p.Name == "TableUnsupportedTypeFunction"); - - ValidateFunction(tableUnsupportedTypeFunction, "TableUnsupportedTypeFunction", GetEntryPoint(nameof(SDKTypeBindings_Table), nameof(SDKTypeBindings_Table.TableUnsupportedTypeFunction)), - b => ValidateTableInputBypassDeferredBinding(b)); - - var tablePocoFunction = functions.Single(p => p.Name == "TablePocoFunction"); ValidateFunction(tablePocoFunction, "TablePocoFunction", GetEntryPoint(nameof(SDKTypeBindings_Table), nameof(SDKTypeBindings_Table.TablePocoFunction)), @@ -1473,13 +1466,6 @@ public object EnumerableTableEntityFunction( throw new NotImplementedException(); } - [Function("TableUnsupportedTypeFunction")] - public object TableUnsupportedTypeFunction( - [TableInput("tableName")] BinaryData tableInput) - { - throw new NotImplementedException(); - } - [Function("TablePocoFunction")] public object TablePocoFunction( [TableInput("tableName")] Poco tableInput) diff --git a/test/Worker.Extensions.Tests/Table/TableEntityConverterTests.cs b/test/Worker.Extensions.Tests/Table/TableEntityConverterTests.cs index 9003ec32b..081606b52 100644 --- a/test/Worker.Extensions.Tests/Table/TableEntityConverterTests.cs +++ b/test/Worker.Extensions.Tests/Table/TableEntityConverterTests.cs @@ -81,7 +81,7 @@ public async Task ConvertAsync_CollectionTableEntity_ReturnsUnhandled() [Fact] public async Task ConvertAsync_BadTableEntity_ReturnsFailed() { - object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetBadEntityBinaryData(), "AzureStorageTables"); + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetEntityWithoutRowKeyBinaryData(), "AzureStorageTables"); var context = new TestConverterContext(typeof(TableEntity), source); var mockResponse = new Mock(); var tableClient = new Mock(); diff --git a/test/Worker.Extensions.Tests/Table/TableEntityEnumerableConverterTests.cs b/test/Worker.Extensions.Tests/Table/TableEntityEnumerableConverterTests.cs index ccc969214..b7c141e73 100644 --- a/test/Worker.Extensions.Tests/Table/TableEntityEnumerableConverterTests.cs +++ b/test/Worker.Extensions.Tests/Table/TableEntityEnumerableConverterTests.cs @@ -87,7 +87,7 @@ public async Task ConvertAsync_CollectionTableEntity_ReturnsSuccess() [Fact] public async Task ConvertAsync_BadTableEntity_ReturnsFailed() { - object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetBadEntityBinaryData(), "AzureStorageTables"); + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetEntityWithoutRowKeyBinaryData(), "AzureStorageTables"); var context = new TestConverterContext(typeof(IEnumerable), source); var mockResponse = new Mock(); var tableClient = new Mock(); diff --git a/test/Worker.Extensions.Tests/Table/TablePocoConverterTests.cs b/test/Worker.Extensions.Tests/Table/TablePocoConverterTests.cs new file mode 100644 index 000000000..a290f91a2 --- /dev/null +++ b/test/Worker.Extensions.Tests/Table/TablePocoConverterTests.cs @@ -0,0 +1,387 @@ +// 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.Threading.Tasks; +using Azure; +using Azure.Core.Serialization; +using Azure.Data.Tables; +using Microsoft.Azure.Functions.Worker.Extensions.Tables.Config; +using Microsoft.Azure.Functions.Worker.Extensions.Tables; +using Microsoft.Azure.Functions.Worker.Extensions.Tables.TypeConverters; +using Microsoft.Azure.Functions.Worker.Converters; +using Microsoft.Azure.Functions.Worker.Tests.Converters; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Moq; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Tests.Table +{ + public class TablePocoConverterTests + { + private TablePocoConverter _tableConverter; + private Mock _mockTableServiceClient; + + public TablePocoConverterTests() + { + var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { }).Build(); + var logger = host.Services.GetService>(); + + var workerOptions = host.Services.GetService>(); + + _mockTableServiceClient = new Mock(); + + var mockTableOptions = new Mock(); + mockTableOptions + .Setup(m => m.CreateClient()) + .Returns(_mockTableServiceClient.Object); + + var mockTablesOptionsMonitor = new Mock>(); + mockTablesOptionsMonitor + .Setup(m => m.Get(It.IsAny())) + .Returns(mockTableOptions.Object); + + _tableConverter = new TablePocoConverter(workerOptions, mockTablesOptionsMonitor.Object, logger); + } + + [Theory] + [InlineData(typeof(MyEntity))] + [InlineData(typeof(MyTableEntity))] + public async Task ConvertAsync_SinglePocoEntity_ReturnsSuccess(Type targetType) + { + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(targetType, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + _mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var conversionResult = await _tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + Assert.Equal(targetType, conversionResult.Value.GetType()); + } + + [Theory] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IEnumerable))] + public async Task ConvertAsync_CollectionPocoEntity_ReturnsSuccess(Type targetType) + { + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetEntityWithoutRowKeyBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(targetType, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + _mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var expectedOutput = Page.FromValues(new List { new TableEntity("partitionKey", "rowKey") }, continuationToken: null, mockResponse.Object); + + tableClient + .Setup(c => c.QueryAsync(It.IsAny(), null, null, default)) + .Returns(AsyncPageable.FromPages(new List> { expectedOutput })); + + var conversionResult = await _tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + } + + [Theory] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IEnumerable))] + public async Task ConvertAsync_CollectionPocoEntity_WithRowKey_ReturnsSuccess(Type targetType) + { + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(targetType, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + _mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var expectedOutput = Page.FromValues(new List { new TableEntity("partitionKey", "rowKey") }, continuationToken: null, mockResponse.Object); + + tableClient + .Setup(c => c.QueryAsync(It.IsAny(), null, null, default)) + .Returns(AsyncPageable.FromPages(new List> { expectedOutput })); + + var conversionResult = await _tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + } + + [Fact] + public async Task ConvertAsync_ModelBindingData_Null_ReturnsUnhandled() + { + var context = new TestConverterContext(typeof(IEnumerable), null); + + var conversionResult = await _tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Unhandled, conversionResult.Status); + } + + [Fact] + public async Task ConvertAsync_SingleTableEntity_NullTargetType_ReturnsFailed() + { + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(null, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + _mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var conversionResult = await _tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Failed, conversionResult.Status); + } + + [Fact] + public async Task ConvertAsync_MyEntityNewField_NewtonSoftJsonSerializer_ReturnsSuccess() + { + var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { options.Serializer = new NewtonsoftJsonObjectSerializer(); }).Build(); + var logger = host.Services.GetService>(); + + var workerOptions = host.Services.GetService>(); + + var mockTableServiceClient = new Mock(); + + var mockTableOptions = new Mock(); + mockTableOptions + .Setup(m => m.CreateClient()) + .Returns(mockTableServiceClient.Object); + + var mockTablesOptionsMonitor = new Mock>(); + mockTablesOptionsMonitor + .Setup(m => m.Get(It.IsAny())) + .Returns(mockTableOptions.Object); + + var tableConverter = new TablePocoConverter(workerOptions, mockTablesOptionsMonitor.Object, logger); + + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityWithNewFieldBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(typeof(MyTableEntityWithField), source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var conversionResult = await tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + Assert.Equal(typeof(MyTableEntityWithField), conversionResult.Value.GetType()); + } + + [Theory] + [InlineData(typeof(MyEntity))] + [InlineData(typeof(MyTableEntity))] + public async Task ConvertAsync_NewtonSoftJsonSerializer_ReturnsSuccess(Type targetType) + { + var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { options.Serializer = new NewtonsoftJsonObjectSerializer(); }).Build(); + var logger = host.Services.GetService>(); + + var workerOptions = host.Services.GetService>(); + + var mockTableServiceClient = new Mock(); + + var mockTableOptions = new Mock(); + mockTableOptions + .Setup(m => m.CreateClient()) + .Returns(mockTableServiceClient.Object); + + var mockTablesOptionsMonitor = new Mock>(); + mockTablesOptionsMonitor + .Setup(m => m.Get(It.IsAny())) + .Returns(mockTableOptions.Object); + + var tableConverter = new TablePocoConverter(workerOptions, mockTablesOptionsMonitor.Object, logger); + + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(targetType, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var conversionResult = await tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + Assert.Equal(targetType, conversionResult.Value.GetType()); + } + + [Theory] + [InlineData(typeof(MyEntity))] + [InlineData(typeof(MyTableEntity))] + public async Task ConvertAsync_JsonSerializer_ReturnsSuccess(Type t) + { + var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { options.Serializer = new JsonObjectSerializer (); }).Build(); + var logger = host.Services.GetService>(); + + var workerOptions = host.Services.GetService>(); + + var mockTableServiceClient = new Mock(); + + var mockTableOptions = new Mock(); + mockTableOptions + .Setup(m => m.CreateClient()) + .Returns(mockTableServiceClient.Object); + + var mockTablesOptionsMonitor = new Mock>(); + mockTablesOptionsMonitor + .Setup(m => m.Get(It.IsAny())) + .Returns(mockTableOptions.Object); + + var tableConverter = new TablePocoConverter(workerOptions, mockTablesOptionsMonitor.Object, logger); + + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(t, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var conversionResult = await tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + Assert.Equal(t, conversionResult.Value.GetType()); + } + + [Theory] + [InlineData(typeof(IEnumerable))] + [InlineData(typeof(IEnumerable))] + public async Task ConvertAsync_CollectionPocoEntity_NewtonSoftSerializer_ReturnsSuccess(Type t) + { + var host = new HostBuilder().ConfigureFunctionsWorkerDefaults((WorkerOptions options) => { options.Serializer = new NewtonsoftJsonObjectSerializer(); }).Build(); + var logger = host.Services.GetService>(); + + var workerOptions = host.Services.GetService>(); + + var mockTableServiceClient = new Mock(); + + var mockTableOptions = new Mock(); + mockTableOptions + .Setup(m => m.CreateClient()) + .Returns(mockTableServiceClient.Object); + + var mockTablesOptionsMonitor = new Mock>(); + mockTablesOptionsMonitor + .Setup(m => m.Get(It.IsAny())) + .Returns(mockTableOptions.Object); + + var tableConverter = new TablePocoConverter(workerOptions, mockTablesOptionsMonitor.Object, logger); + + object source = GrpcTestHelper.GetTestGrpcModelBindingData(TableTestHelper.GetTableEntityBinaryData(), "AzureStorageTables"); + var context = new TestConverterContext(t, source); + var mockResponse = new Mock(); + var tableClient = new Mock(); + + tableClient + .Setup(c => c.GetEntityAsync(It.IsAny(), It.IsAny(), null, default)) + .ReturnsAsync(Response.FromValue(new TableEntity(It.IsAny(), It.IsAny()), mockResponse.Object)); + + mockTableServiceClient + .Setup(c => c.GetTableClient(Constants.TableName)) + .Returns(tableClient.Object); + + var expectedOutput = Page.FromValues(new List { new TableEntity("partitionKey", "rowKey") }, continuationToken: null, mockResponse.Object); + + tableClient + .Setup(c => c.QueryAsync(It.IsAny(), null, null, default)) + .Returns(AsyncPageable.FromPages(new List> { expectedOutput })); + + var conversionResult = await tableConverter.ConvertAsync(context); + + Assert.Equal(ConversionStatus.Succeeded, conversionResult.Status); + } + + class MyEntity + { + public MyEntity() { } + + public MyEntity(string pk, string rk) + { + PartitionKey = pk; + RowKey = rk; + } + + public string PartitionKey { get; set; } + public string RowKey { get; set; } + } + + class MyTableEntity : ITableEntity + { + public MyTableEntity() { } + + public MyTableEntity(string pk, string rk) + { + PartitionKey = pk; + RowKey = rk; + } + + public string PartitionKey { get; set; } + public string RowKey { get; set; } + public DateTimeOffset? Timestamp { get; set; } + public ETag ETag { get; set; } + } + + class MyTableEntityWithField : ITableEntity + { + public MyTableEntityWithField() { } + + public MyTableEntityWithField(string pk, string rk) + { + PartitionKey = pk; + RowKey = rk; + NewField = "test"; + } + + public string PartitionKey { get; set; } + public string RowKey { get; set; } + public DateTimeOffset? Timestamp { get; set; } + public ETag ETag { get; set; } + public string NewField { get; set; } + } + } +} diff --git a/test/Worker.Extensions.Tests/Table/TableTestHelper.cs b/test/Worker.Extensions.Tests/Table/TableTestHelper.cs index 623b03800..0cb3d0d77 100644 --- a/test/Worker.Extensions.Tests/Table/TableTestHelper.cs +++ b/test/Worker.Extensions.Tests/Table/TableTestHelper.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -29,7 +29,7 @@ public static BinaryData GetTableEntityBinaryData() "}"); } - public static BinaryData GetBadEntityBinaryData() + public static BinaryData GetEntityWithoutRowKeyBinaryData() { return new BinaryData("{" + "\"Connection\" : \"Connection\"," + @@ -37,5 +37,16 @@ public static BinaryData GetBadEntityBinaryData() "\"PartitionKey\" : \"PartitionKey\"" + "}"); } + + public static BinaryData GetTableEntityWithNewFieldBinaryData() + { + return new BinaryData("{" + + "\"Connection\" : \"Connection\"," + + "\"TableName\" : \"TableName\"," + + "\"PartitionKey\" : \"PartitionKey\"," + + "\"RowKey\" : \"RowKey\"," + + "\"NewField\" : \"NewField\"" + + "}"); + } } -} \ No newline at end of file +} From cfb4d9cba288df1bf1e14572ac5af46600cfd6d3 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Tue, 29 Apr 2025 08:49:03 -0700 Subject: [PATCH 120/190] Update storage release_notes.md (#3044) --- .../Worker.Extensions.Storage/release_notes.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 71d645aa1..4ab75b73f 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,20 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.7.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage -- Update `Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs` to 6.7.0 -- Update `Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues` to 5.5.2 +- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.7.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs -- Update WebJobs package `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` to 5.3.4 -- Removed `Microsoft.Bcl.AsyncInterfaces` as direct dependency -- Update other dependencies to latest versions +- +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.5.2 - -- Update WebJobs package `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` to 5.3.4 -- Update other dependencies to latest versions - +- From 7f234a579752c91aa1a68c07a391d2a2f2087cd6 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Tue, 13 May 2025 12:08:32 -0700 Subject: [PATCH 121/190] Remove external extension proj support (#3053) * Remove external extension proj support * Update release notes --- ...crosoft.Azure.Functions.Worker.Sdk.targets | 61 +++---------------- sdk/release_notes.md | 2 - 2 files changed, 10 insertions(+), 53 deletions(-) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 021378afb..d4832489e 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -21,7 +21,6 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - true <_FunctionsExtensionsDirectory>.azurefunctions <_FunctionsExtensionsJsonName>extensions.json <_FunctionsWorkerConfigInputFile>$([MSBuild]::NormalizePath($(MSBuildThisFileDirectory)\..\tools\worker.config.json)) @@ -54,7 +53,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and true true - <_FunctionsBuildEnabled Condition="'$(DesignTimeBuild)' != 'true'">true + <_FunctionsBuildEnabled>true + <_FunctionsBuildEnabled Condition="'$(DesignTimeBuild)' == 'true'">false $(RootNamespace.Replace("-", "_")) @@ -71,27 +71,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - - <_WorkerExtensionProject Include="@(ProjectReference)" Condition="'%(ProjectReference.WorkerExtensions)' == 'true'" /> - <_WorkerExtensionProjectNonExistent Include="@(_WorkerExtensionProject)" Condition="!Exists('%(Identity)')" /> - - - - + - false - %(_WorkerExtensionProject.Identity) - - - - - - - - - - $([System.IO.Path]::GetDirectoryName($(ExtensionsCsProj))) $(IntermediateOutputPath)WorkerExtensions $([System.IO.Path]::GetFullPath($(ExtensionsCsProjDirectory))) @@ -109,7 +90,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and <_AzureFunctionsVersionStandardized>$(AzureFunctionsVersion.ToLowerInvariant().Split('-')[0]) - <_FunctionsExtensionRemoveProps Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">$(_FunctionsExtensionRemoveProps)ManagePackageVersionsCentrally; + <_FunctionsExtensionRemoveProps>$(_FunctionsExtensionRemoveProps)ManagePackageVersionsCentrally; @@ -165,7 +146,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + @@ -173,8 +154,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and <_WorkerExtensionTarget>Build - <_WorkerExtensionTarget Condition="'$(FunctionsGenerateExtensionProject)' == 'false'">GetTargetPath - <_WorkerExtensionProperties Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">Configuration=Release;$(_FunctionsExtensionCommonProps) + <_WorkerExtensionProperties>Configuration=Release;$(_FunctionsExtensionCommonProps) @@ -192,20 +172,14 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + - - - <_TargetExtensionsCsProj Condition="'$(FunctionsGenerateExtensionProject)' == 'true'">$(ExtensionsCsProj) - - - <_WorkerExtFilesToClean Include="$(ExtensionsCsProjDirectory)/**" Condition="'$(ExtensionsCsProjDirectory)' != '' AND '$(FunctionsGenerateExtensionProject)' == 'true'" /> + <_WorkerExtFilesToClean Include="$(ExtensionsCsProjDirectory)/**" Condition="'$(ExtensionsCsProjDirectory)' != ''" /> <_WorkerExtFilesToClean Include="$(TargetDir)$(_FunctionsExtensionsDirectory)/**" /> <_WorkerExtFilesToClean Include="$(_FunctionsMetadataPath)" /> <_WorkerExtFilesToClean Include="$(_FunctionsWorkerConfigPath)" /> @@ -290,22 +264,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - - - - - - - - <_ForceGenerateExtensionProject>true - true - - - - - - + Date: Tue, 13 May 2025 16:44:45 -0700 Subject: [PATCH 122/190] Reenable tests and refactor tests to use shared types (#2979) --- .../Properties/AssemblyInfo.cs | 2 ++ src/DotNetWorker/Properties/AssemblyInfo.cs | 1 + .../EndToEndTests.cs | 1 + .../TestFunctionInvocation.cs | 35 ------------------- .../ApplicationInsights/EndToEndTests.cs | 1 - .../DefaultFunctionInvokerTests.cs | 1 - .../DefaultModelBindingFeatureTests.cs | 1 - .../Executors/NullInstanceFactoryTests.cs | 2 -- .../DefaultInputConversionFeatureTests.cs | 1 - .../Features/TestFunctionBindingsFeature.cs | 20 ----------- .../FunctionContextExtensionTests.cs | 1 - .../FunctionContextHttpExtensionTests.cs | 2 -- .../Http/HttpResponseDataExtensionsTests.cs | 4 --- test/E2ETests/E2ETests/E2ETests.csproj | 2 +- test/TestUtility/ExternalPoco.cs | 4 --- test/TestUtility/Properties/AssemblyInfo.cs | 7 ++++ .../TestBindingMetadata.cs | 0 .../TestFunctionBindingsFeature.cs | 2 +- .../TestFunctionContext.cs | 5 ++- .../TestFunctionDefinition.cs | 0 .../TestFunctionInvocation.cs | 0 test/TestUtility/TestUtility.csproj | 6 +++- .../FunctionsHttpProxyingMiddlewareTests.cs | 7 ++-- .../WorkerRequestServicesMiddlewareTests.cs | 4 +-- .../TestBindingMetadata.cs | 21 ----------- .../Worker.Extensions.Tests.csproj | 2 ++ 26 files changed, 25 insertions(+), 107 deletions(-) delete mode 100644 test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs delete mode 100644 test/DotNetWorkerTests/Features/TestFunctionBindingsFeature.cs create mode 100644 test/TestUtility/Properties/AssemblyInfo.cs rename test/{DotNetWorkerTests => TestUtility}/TestBindingMetadata.cs (100%) rename test/{DotNetWorker.OpenTelemetry.Tests => TestUtility}/TestFunctionBindingsFeature.cs (95%) rename test/{DotNetWorkerTests => TestUtility}/TestFunctionContext.cs (95%) rename test/{DotNetWorkerTests => TestUtility}/TestFunctionDefinition.cs (100%) rename test/{DotNetWorkerTests => TestUtility}/TestFunctionInvocation.cs (100%) delete mode 100644 test/Worker.Extensions.Tests/TestBindingMetadata.cs diff --git a/src/DotNetWorker.Core/Properties/AssemblyInfo.cs b/src/DotNetWorker.Core/Properties/AssemblyInfo.cs index 3f9259f3e..b40f3e167 100644 --- a/src/DotNetWorker.Core/Properties/AssemblyInfo.cs +++ b/src/DotNetWorker.Core/Properties/AssemblyInfo.cs @@ -7,3 +7,5 @@ [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Grpc, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Tests.TestUtility, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/src/DotNetWorker/Properties/AssemblyInfo.cs b/src/DotNetWorker/Properties/AssemblyInfo.cs index 6f3b6406c..a82f769b3 100644 --- a/src/DotNetWorker/Properties/AssemblyInfo.cs +++ b/src/DotNetWorker/Properties/AssemblyInfo.cs @@ -6,3 +6,4 @@ [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Tests.TestUtility, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs b/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs index 7ed21080c..1a60ba907 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs +++ b/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs @@ -15,6 +15,7 @@ using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Diagnostics; using Microsoft.Azure.Functions.Worker.OpenTelemetry; +using Microsoft.Azure.Functions.Worker.Tests; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs b/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs deleted file mode 100644 index e8307dab5..000000000 --- a/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionInvocation.cs +++ /dev/null @@ -1,35 +0,0 @@ -// 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.Diagnostics; -using Microsoft.Azure.Functions.Worker; - -namespace DotNetWorker.OpenTelemetry.Tests -{ - public class TestFunctionInvocation : FunctionInvocation - { - public TestFunctionInvocation(string id = null, string functionId = null) - { - if (id is not null) - { - Id = id; - } - - if (functionId is not null) - { - FunctionId = functionId; - } - - // create/dispose activity to pull off its ID. - using Activity activity = new Activity(string.Empty).Start(); - TraceContext = new DefaultTraceContext(activity.Id, Guid.NewGuid().ToString()); - } - - public override string Id { get; } = Guid.NewGuid().ToString(); - - public override string FunctionId { get; } = Guid.NewGuid().ToString(); - - public override TraceContext TraceContext { get; } - } -} diff --git a/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs b/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs index a229063f3..f4914517f 100644 --- a/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs +++ b/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs @@ -16,7 +16,6 @@ using Microsoft.Azure.Functions.Worker.ApplicationInsights.Initializers; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Diagnostics; -using Microsoft.Azure.Functions.Worker.Tests.Features; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; diff --git a/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs b/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs index cced17717..20359d7d9 100644 --- a/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs +++ b/test/DotNetWorkerTests/DefaultFunctionInvokerTests.cs @@ -12,7 +12,6 @@ using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Converters; using Microsoft.Azure.Functions.Worker.Invocation; -using Microsoft.Azure.Functions.Worker.Tests.Features; using Microsoft.Extensions.Logging.Abstractions; using Moq; using Xunit; diff --git a/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs b/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs index adc9f0c17..007fdd016 100644 --- a/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs +++ b/test/DotNetWorkerTests/DefaultModelBindingFeatureTests.cs @@ -8,7 +8,6 @@ using Azure.Core.Serialization; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.Azure.Functions.Worker.Tests.Features; using Microsoft.Extensions.DependencyInjection; using Xunit; diff --git a/test/DotNetWorkerTests/Executors/NullInstanceFactoryTests.cs b/test/DotNetWorkerTests/Executors/NullInstanceFactoryTests.cs index 7611f5951..0e1db23f4 100644 --- a/test/DotNetWorkerTests/Executors/NullInstanceFactoryTests.cs +++ b/test/DotNetWorkerTests/Executors/NullInstanceFactoryTests.cs @@ -4,8 +4,6 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using Microsoft.Azure.Functions.Worker; -using Microsoft.Extensions.DependencyInjection; using Xunit; namespace Microsoft.Azure.Functions.Worker.Tests diff --git a/test/DotNetWorkerTests/Features/DefaultInputConversionFeatureTests.cs b/test/DotNetWorkerTests/Features/DefaultInputConversionFeatureTests.cs index f71716975..646787b8e 100644 --- a/test/DotNetWorkerTests/Features/DefaultInputConversionFeatureTests.cs +++ b/test/DotNetWorkerTests/Features/DefaultInputConversionFeatureTests.cs @@ -10,7 +10,6 @@ using Azure.Core.Serialization; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Converters; -using Microsoft.Azure.Functions.Worker.Core; using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; using Xunit; diff --git a/test/DotNetWorkerTests/Features/TestFunctionBindingsFeature.cs b/test/DotNetWorkerTests/Features/TestFunctionBindingsFeature.cs deleted file mode 100644 index 9ba8218e3..000000000 --- a/test/DotNetWorkerTests/Features/TestFunctionBindingsFeature.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Collections.Generic; -using System.Collections.ObjectModel; -using Microsoft.Azure.Functions.Worker.Context.Features; -using Microsoft.Azure.Functions.Worker.OutputBindings; - -namespace Microsoft.Azure.Functions.Worker.Tests.Features -{ - internal class TestFunctionBindingsFeature : IFunctionBindingsFeature - { - public IReadOnlyDictionary TriggerMetadata { get; init; } = new ReadOnlyDictionary(new Dictionary()); - - public IReadOnlyDictionary InputData { get; init; } = new ReadOnlyDictionary(new Dictionary()); - - public IDictionary OutputBindingData { get; } = new Dictionary(); - - public OutputBindingsInfo OutputBindingsInfo { get; init; } = EmptyOutputBindingsInfo.Instance; - - public object InvocationResult { get; set; } - } -} diff --git a/test/DotNetWorkerTests/FunctionContextExtensionTests.cs b/test/DotNetWorkerTests/FunctionContextExtensionTests.cs index 501d5e3a2..0326f9d98 100644 --- a/test/DotNetWorkerTests/FunctionContextExtensionTests.cs +++ b/test/DotNetWorkerTests/FunctionContextExtensionTests.cs @@ -11,7 +11,6 @@ using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Converters; using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.Azure.Functions.Worker.Tests.Features; using Microsoft.Extensions.DependencyInjection; using Moq; using Newtonsoft.Json; diff --git a/test/DotNetWorkerTests/FunctionContextHttpExtensionTests.cs b/test/DotNetWorkerTests/FunctionContextHttpExtensionTests.cs index 2778da067..e2d7fc825 100644 --- a/test/DotNetWorkerTests/FunctionContextHttpExtensionTests.cs +++ b/test/DotNetWorkerTests/FunctionContextHttpExtensionTests.cs @@ -10,9 +10,7 @@ using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Converters; -using Microsoft.Azure.Functions.Worker.Grpc.Messages; using Microsoft.Azure.Functions.Worker.Http; -using Microsoft.Azure.Functions.Worker.Tests.Features; using Microsoft.Extensions.DependencyInjection; using Moq; using Xunit; diff --git a/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs b/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs index 2da456062..a2bc312d3 100644 --- a/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs +++ b/test/DotNetWorkerTests/Http/HttpResponseDataExtensionsTests.cs @@ -1,13 +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 System.Linq; using System.Net; -using System.Runtime.InteropServices; -using System.Text; using System.Text.Json.Serialization; using System.Threading.Tasks; using Azure.Core.Serialization; diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index e1aa3c837..9b23ae8e8 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -12,7 +12,7 @@ - + diff --git a/test/TestUtility/ExternalPoco.cs b/test/TestUtility/ExternalPoco.cs index 25331ae4b..0ca66c32c 100644 --- a/test/TestUtility/ExternalPoco.cs +++ b/test/TestUtility/ExternalPoco.cs @@ -1,10 +1,6 @@ // 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.Text; - namespace Microsoft.Azure.Functions.Tests { /// diff --git a/test/TestUtility/Properties/AssemblyInfo.cs b/test/TestUtility/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..3acc9faac --- /dev/null +++ b/test/TestUtility/Properties/AssemblyInfo.cs @@ -0,0 +1,7 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/test/DotNetWorkerTests/TestBindingMetadata.cs b/test/TestUtility/TestBindingMetadata.cs similarity index 100% rename from test/DotNetWorkerTests/TestBindingMetadata.cs rename to test/TestUtility/TestBindingMetadata.cs diff --git a/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionBindingsFeature.cs b/test/TestUtility/TestFunctionBindingsFeature.cs similarity index 95% rename from test/DotNetWorker.OpenTelemetry.Tests/TestFunctionBindingsFeature.cs rename to test/TestUtility/TestFunctionBindingsFeature.cs index f1b84c7de..659db24a8 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/TestFunctionBindingsFeature.cs +++ b/test/TestUtility/TestFunctionBindingsFeature.cs @@ -6,7 +6,7 @@ using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.OutputBindings; -namespace DotNetWorker.OpenTelemetry.Tests +namespace Microsoft.Azure.Functions.Worker.Tests { internal class TestFunctionBindingsFeature : IFunctionBindingsFeature { diff --git a/test/DotNetWorkerTests/TestFunctionContext.cs b/test/TestUtility/TestFunctionContext.cs similarity index 95% rename from test/DotNetWorkerTests/TestFunctionContext.cs rename to test/TestUtility/TestFunctionContext.cs index 731885dca..636cc6212 100644 --- a/test/DotNetWorkerTests/TestFunctionContext.cs +++ b/test/TestUtility/TestFunctionContext.cs @@ -9,12 +9,11 @@ using Azure.Core.Serialization; using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.OutputBindings; -using Microsoft.Azure.Functions.Worker.Tests.Features; using Microsoft.Extensions.DependencyInjection; namespace Microsoft.Azure.Functions.Worker.Tests { - internal class TestAsyncFunctionContext : TestFunctionContext, IAsyncDisposable + public class TestAsyncFunctionContext : TestFunctionContext, IAsyncDisposable { public TestAsyncFunctionContext() : base(new TestFunctionDefinition(), new TestFunctionInvocation(), CancellationToken.None) @@ -33,7 +32,7 @@ public ValueTask DisposeAsync() } } - internal class TestFunctionContext : FunctionContext, IDisposable + public class TestFunctionContext : FunctionContext, IDisposable { private readonly FunctionInvocation _invocation; private readonly CancellationToken _cancellationToken; diff --git a/test/DotNetWorkerTests/TestFunctionDefinition.cs b/test/TestUtility/TestFunctionDefinition.cs similarity index 100% rename from test/DotNetWorkerTests/TestFunctionDefinition.cs rename to test/TestUtility/TestFunctionDefinition.cs diff --git a/test/DotNetWorkerTests/TestFunctionInvocation.cs b/test/TestUtility/TestFunctionInvocation.cs similarity index 100% rename from test/DotNetWorkerTests/TestFunctionInvocation.cs rename to test/TestUtility/TestFunctionInvocation.cs diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index 5df330bb9..46e6caf2d 100644 --- a/test/TestUtility/TestUtility.csproj +++ b/test/TestUtility/TestUtility.csproj @@ -12,10 +12,14 @@ - + + + + + diff --git a/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs b/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs index 9c10358ed..c131629b9 100644 --- a/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs +++ b/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs @@ -16,9 +16,7 @@ using Xunit; namespace Microsoft.Azure.Functions.Worker.Tests.AspNetCore -{ - -#if false // Needs updates to shared types +{ public class FunctionsHttpProxyingMiddlewareTests { [Fact] @@ -191,7 +189,7 @@ private static (FunctionContext FunctionContext, HttpContext HttpContext, Mock(); mockCoordinator @@ -279,5 +277,4 @@ public async Task CompleteFunctionInvocation_RunsWhen_FunctionThrowsException() test.MockCoordinator.Verify(p => p.CompleteFunctionInvocation(It.IsAny()), Times.Once()); } } -#endif } diff --git a/test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs b/test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs index a23d452c1..070aed046 100644 --- a/test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs +++ b/test/Worker.Extensions.Tests/AspNetCore/WorkerRequestServicesMiddlewareTests.cs @@ -13,7 +13,6 @@ namespace Microsoft.Azure.Functions.Worker.Tests.AspNetCore { public class WorkerRequestServicesMiddlewareTests { -#if false // Needs updates to shared types [Fact] public async Task ServiceProviders_Equal() { @@ -39,7 +38,7 @@ public async Task ServiceProviders_Equal() serviceProvider: provider); var httpContext = new DefaultHttpContext(); - httpContext.Request.Headers.Add(Constants.CorrelationHeader, functionContext.InvocationId); + httpContext.Request.Headers.Append(Constants.CorrelationHeader, functionContext.InvocationId); var httpCoordinator = new Mock(); httpCoordinator @@ -53,7 +52,6 @@ public async Task ServiceProviders_Equal() private class MyService { } -#endif } } diff --git a/test/Worker.Extensions.Tests/TestBindingMetadata.cs b/test/Worker.Extensions.Tests/TestBindingMetadata.cs deleted file mode 100644 index 88b59e9b9..000000000 --- a/test/Worker.Extensions.Tests/TestBindingMetadata.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) .NET Foundation. All rights reserved. -// Licensed under the MIT License. See License.txt in the project root for license information. - -namespace Microsoft.Azure.Functions.Worker.Tests -{ - public class TestBindingMetadata : BindingMetadata - { - public TestBindingMetadata(string name, string type, BindingDirection direction) - { - Name = name; - Type = type; - Direction = direction; - } - - public override string Name { get; } - - public override string Type { get; } - - public override BindingDirection Direction { get; } - } -} diff --git a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj index b63593eb5..50eb07d1b 100644 --- a/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj +++ b/test/Worker.Extensions.Tests/Worker.Extensions.Tests.csproj @@ -30,6 +30,8 @@ + + From 788fad24df980b4d56eddb1f7a2e8c19165a61cb Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 14 May 2025 11:24:53 -0700 Subject: [PATCH 123/190] Remove external ext proj docs (#3055) * Update external ext proj docs * Delete external ext proj docs for now --- .../App/ExternalExtensionProject.App.csproj | 19 --- .../ExternalExtensionProject/App/Program.cs | 8 -- .../App/QueueFunction.cs | 22 ---- .../Ext/ExternalExtensionProject.Ext.csproj | 19 --- samples/ExternalExtensionProject/README.md | 123 ------------------ 5 files changed, 191 deletions(-) delete mode 100644 samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj delete mode 100644 samples/ExternalExtensionProject/App/Program.cs delete mode 100644 samples/ExternalExtensionProject/App/QueueFunction.cs delete mode 100644 samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj delete mode 100644 samples/ExternalExtensionProject/README.md diff --git a/samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj b/samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj deleted file mode 100644 index 062170bcf..000000000 --- a/samples/ExternalExtensionProject/App/ExternalExtensionProject.App.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net8.0 - v4 - Exe - - - - - - - - - - - - - diff --git a/samples/ExternalExtensionProject/App/Program.cs b/samples/ExternalExtensionProject/App/Program.cs deleted file mode 100644 index 2838127e6..000000000 --- a/samples/ExternalExtensionProject/App/Program.cs +++ /dev/null @@ -1,8 +0,0 @@ -using Microsoft.Azure.Functions.Worker; -using Microsoft.Azure.Functions.Worker.Builder; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -var builder = FunctionsApplication.CreateBuilder(args); -var host = builder.Build(); -host.Run(); diff --git a/samples/ExternalExtensionProject/App/QueueFunction.cs b/samples/ExternalExtensionProject/App/QueueFunction.cs deleted file mode 100644 index 091bb464c..000000000 --- a/samples/ExternalExtensionProject/App/QueueFunction.cs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 Azure.Storage.Queues.Models; -using Microsoft.Azure.Functions.Worker; -using Microsoft.Extensions.Logging; - -namespace ExternalExtensionProject.App; - -public class QueueFunction(ILogger logger) -{ - /// - /// This function demonstrates binding to a single . - /// - [Function(nameof(QueueMessageFunction))] - public void QueueMessageFunction([QueueTrigger("input-queue")] QueueMessage message) - { - logger.LogInformation(message.MessageText); - } -} diff --git a/samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj b/samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj deleted file mode 100644 index 4937feb6c..000000000 --- a/samples/ExternalExtensionProject/Ext/ExternalExtensionProject.Ext.csproj +++ /dev/null @@ -1,19 +0,0 @@ - - - - net6.0 - Microsoft.Azure.Functions.Worker.Extensions - true - - - - - - - - - - - - - diff --git a/samples/ExternalExtensionProject/README.md b/samples/ExternalExtensionProject/README.md deleted file mode 100644 index e88709d1c..000000000 --- a/samples/ExternalExtensionProject/README.md +++ /dev/null @@ -1,123 +0,0 @@ -# External Extension Project - -This sample shows how to supply the worker extension project manually. - -## What is the worker extension project? - -To support triggers and bindings in dotnet-isolated function apps, an extensions payload needs to be constructed and loaded into the host process (separate from your worker process). For example, if you use `Microsoft.Azure.Functions.Worker.Extensions.ServiceBus`, a host-side extension `Microsoft.Azure.WebJobs.Extensions.ServiceBus` also needs to be loaded into the function host. - -Collecting these extensions to be loaded is accomplished by build steps provided by `Microsoft.Azure.Functions.Worker.Sdk`. These steps will scan for WebJobs extensions indicated by Worker extensions. These extensions are added as `PackageReference`'s to a _new_ `WorkerExtensions.csproj` which is dynamically generated during build. This project is then restored, built, and outputs collected into the `.azurefunctions` folder of your function app build output. This process is often referred to as the "extension inner-build". - -## What is this scenario for? - -For most customers, this inner-build process is frictionless and requires no customization. However, for some customers this process conflicts with some external factors (no network during build, nuget feed auth issues, among others). To accommodate these conflicts SDK `2.1.0` and on supports the ability to externally supply this extension project, giving full control of the extension project to the customer. This project can now be restored and built alongside the function app. Since the csproj is controlled by the customer, any changes can be made to it. - -There is a major drawback though: ensuring the extension project builds a *valid* payload is now the customer's responsibility. Failures to build a valid payload will only be discovered at runtime. Issues may be obscure and varied, from assembly load failures, method missing exceptions, to odd behavior due to mismatching worker & webjobs extensions. Any time the set of extensions for the function app changes, this external project will need to be manually updated. As such, this scenario is only recommended if customization is **absolutely** necessary. - -## How to use external extension project feature - -### 1. Prepare the project for external extension -Add the follow item to your csproj: - -``` diff - - - - net8.0 - v4 - Exe - - -+ -+ -+ - - - -``` - -### 2. First time generation of external extension csproj - -Run a target to generate the extension project one-time: - -``` shell -dotnet build -t:GenerateExtensionProject {{path-to-function-app-csproj}} -``` - -This will generate the same csproj as the inner-build would. Absent of any external influences by your build process (ie, directory-based imports), this project _should_ produce a valid extension payload. - -> [!NOTE] -> The target `GenerateExtensionProject` can be ran whenever to regenerate the csproj. **However**, it will overwrite the contents of the csproj indicated by `ProjectReference` each time. Make sure to re-apply any customizations you have! - -> [!TIP] -> To avoid needing to re-apply customizations, this sample shows putting all custom logic into `Directory.Build.props` and `Directory.Build.targets` and leaving the csproj to always be the generated contents. - -### 3. Add the extension project to be built as part of your regular build - -If using a solution, make sure to add this new project to the solution file. Failure to do so may cause Visual Studio to skip building this project. - -## Example Scenarios - -### Scenario 1. No-network build phase - -In some cases, a CI's build phase may restrict network access. If this network restriction blocks access to nuget feeds, then the extension inner-build will fail. Using external extension project and ensuring it is part of your existing restore phase will workaround this issue. No project customization is needed by default, unless there are rules enforced by your CI (such as mandating central package versioning). The exact changes needed in those cases will be your responsibility to determine and implement. - -### Scenario 2. Authenticated nuget feeds - -The extension inner-build inherits the nuget configuration of your function app. If the configured feeds require authentication there are two routes: - -1. First, see if you can authenticate using your CI's features. For example, in Azure Devops see [NuGetAuthenticate@1](https://learn.microsoft.com/azure/devops/pipelines/tasks/reference/nuget-authenticate-v1?view=azure-pipelines). -2. If option 1 does not work and there is no feasible way to pass in authentication context into the extension inner-build, then performing same steps as [scenario 1](#scenario-1-no-network-build-phase) may workaround the auth issue. - -### Scenario 3. Extension development testing - -This feature is useful for extension development itself, as the `PackageReference` for the WebJobs extension can be replaced with a `ProjectReference`. - -``` diff - - - -- -+ - -``` - -With the above change you can have a function app to locally test your extension without any need for nuget pack and publishing. - -### Scenario 4. Pinning a transitive dependency - -In the case where an extension brings in a transitive dependency that is not compliant with some CI scans or rules you have, you can manually pin it to an in-compliance version. - -``` diff - - - - -+ - -``` - -> [!CAUTION] -> Be very careful with this scenario, as pinning may bring in runtime breaking changes. Especially be careful about pinning across major versions. If the transitive dependency is `vN.x.x`, and you pin to `vN+y.x.x`, this may lead to runtime failures. It is recommended you validate the version you are pinning to is compatible with the originally requested version. - -## Things to be aware of - -❌ DO NOT change the `TargetFramework` of the extension project - -> [!CAUTION] -> The target framework, and all dependent assemblies of this generated project, must be compatible with the host process. Changing the TFM risks assembly load failures. - -⚠️ AVOID changing the packages of the extension project - -> [!WARNING] -> The package closure of the extension project is sensitive to changes. The host process ultimately controls the dependency graph and assembly loads. Depending on a package/assembly not supported by the host process may cause issues. E.G, trying to depend on any `Microsoft.Extensions.*/9x` from the extension project will cause issues. - -❌ DO NOT include more than 1 `ProjectReference` with `WorkerExtensions=true` - -> [!NOTE] -> The build will be intentionally failed if there are more than 1 extension projects declared. - -✔️ DO set `ReferenceOutputAssembly=false` on the `ProjectReference` with `WorkerExtensions=true` - -> [!IMPORTANT] -> Setting `ReferenceOutputAssembly=false` will exclude this extensions projects package references from being included in your function app. This is not done automatically as it needs to be present for restore phase (and the functions SDK targets are not present until _after_ restore). From fccfc11b0bbad436ce019148108fed7a294c96de Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Thu, 15 May 2025 13:21:40 -0700 Subject: [PATCH 124/190] Skip serialization of http result when it is stored in an output binding (#2896) --- .../release_notes.md | 2 +- .../FunctionsHttpProxyingMiddleware.cs | 16 +++++++++++++++- .../FunctionsHttpProxyingMiddlewareTests.cs | 19 +++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index 97bb2a3ba..b837fa992 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -6,7 +6,7 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore -- +- Fix intermittent error `IFeatureCollection has been disposed` exception in multiple-output binding scenarios. (#2896) ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsMiddleware/FunctionsHttpProxyingMiddleware.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsMiddleware/FunctionsHttpProxyingMiddleware.cs index 83dbaeac0..15afd4bf7 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsMiddleware/FunctionsHttpProxyingMiddleware.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/FunctionsMiddleware/FunctionsHttpProxyingMiddleware.cs @@ -9,8 +9,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Abstractions; using Microsoft.AspNetCore.Routing; -using Microsoft.Azure.Functions.Worker.Extensions.Http.Converters; using Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Infrastructure; +using Microsoft.Azure.Functions.Worker.Extensions.Http.Converters; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Azure.Functions.Worker.Middleware; using Microsoft.Extensions.DependencyInjection; @@ -85,6 +85,9 @@ private static async Task TryHandleHttpResult(object? result, FunctionCont // processing is required. context.GetInvocationResult().Value = null; break; + case AspNetCoreHttpResponseData when !isInvocationResult: + ClearHttpOutputBinding(context); + break; case IResult iResult: await iResult.ExecuteAsync(httpContext); break; @@ -105,6 +108,17 @@ private static Task TryHandleOutputBindingsHttpResult(FunctionContext cont : TryHandleHttpResult(httpOutputBinding.Value, context, httpContext); } + private static void ClearHttpOutputBinding(FunctionContext context) + { + var httpOutputBinding = context.GetOutputBindings() + .FirstOrDefault(a => string.Equals(a.BindingType, HttpBindingType, StringComparison.OrdinalIgnoreCase)); + + if (httpOutputBinding != null) + { + httpOutputBinding.Value = null; + } + } + private static void AddHttpContextToFunctionContext(FunctionContext funcContext, HttpContext httpContext) { funcContext.Items.Add(Constants.HttpContextKey, httpContext); diff --git a/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs b/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs index c131629b9..35ed6e4f4 100644 --- a/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs +++ b/test/Worker.Extensions.Tests/AspNetCore/FunctionsHttpProxyingMiddlewareTests.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -168,6 +169,24 @@ public async Task InvocationResultNull_WhenResultIsTypeAspNetCoreHttpResponseDat test.MockCoordinator.Verify(p => p.CompleteFunctionInvocation(It.IsAny()), Times.Once()); } + [Fact] + public async Task HttpResultOutputBindingNull_WhenUsingAspNetCoreHttpResponseDataInMultiOutputBinding() + { + var test = SetupTest("httpTrigger", GetMultiOutputTypeOutputBindings()); + var mockDelegate = new Mock(); + + SetUpAspNetCoreHttpResponseDataBindingInfo(test.FunctionContext, false); + + var funcMiddleware = new FunctionsHttpProxyingMiddleware(test.MockCoordinator.Object); + await funcMiddleware.Invoke(test.FunctionContext, mockDelegate.Object); + + var httpOutputBinding = test.FunctionContext.GetOutputBindings() + .FirstOrDefault(a => string.Equals(a.BindingType, "http", StringComparison.OrdinalIgnoreCase)); + + Assert.Null(httpOutputBinding.Value); + test.MockCoordinator.Verify(p => p.CompleteFunctionInvocation(It.IsAny()), Times.Once()); + } + private static (FunctionContext FunctionContext, HttpContext HttpContext, Mock MockCoordinator) SetupTest(string triggerType, IDictionary outputBindings = null) { var inputBindings = new Dictionary() From 44ad22fbc6fbbb4cc167ae290965a23c254f9a1d Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Fri, 16 May 2025 13:07:46 -0700 Subject: [PATCH 125/190] Update HttpResultAttribute analyzer to include case where return type is Task (#3056) --- .../CodeFixForHttpResultAttributeExpected.cs | 12 +- .../HttpResultAttributeExpectedAnalyzer.cs | 10 + .../src/SymbolUtils.cs | 30 +++ ...xtensions.Http.AspNetCore.Analyzers.csproj | 2 +- .../release_notes.md | 6 +- .../Worker.Extensions.Http.AspNetCore.csproj | 2 +- .../HttpResultAttributeExpectedTests.cs | 173 ++++++++++++++++++ 7 files changed, 229 insertions(+), 6 deletions(-) create mode 100644 extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/SymbolUtils.cs diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs index df004ca11..e38e2ee5d 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs @@ -64,8 +64,18 @@ protected override async Task GetChangedDocumentAsync(CancellationToke var typeNode = root.FindNode(this._diagnostic.Location.SourceSpan) .FirstAncestorOrSelf(); - var typeSymbol = semanticModel.GetSymbolInfo(typeNode).Symbol; + + if (typeSymbol is null) + { + return _document; + } + + if (SymbolUtils.TryUnwrapTaskOfT(typeSymbol, semanticModel, out var innerSymbol)) + { + typeSymbol = innerSymbol; + } + var typeDeclarationSyntaxReference = typeSymbol.DeclaringSyntaxReferences.FirstOrDefault(); if (typeDeclarationSyntaxReference is null) { diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs index 20484ddda..877ffc27a 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs @@ -61,6 +61,16 @@ private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) var returnType = methodDeclaration.ReturnType; var returnTypeSymbol = semanticModel.GetTypeInfo(returnType).Type; + if (returnTypeSymbol is null) + { + return; + } + + if (SymbolUtils.TryUnwrapTaskOfT(returnTypeSymbol, semanticModel, out var innerSymbol)) + { + returnTypeSymbol = innerSymbol; + } + if (IsHttpReturnType(returnTypeSymbol, semanticModel)) { return; diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/SymbolUtils.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/SymbolUtils.cs new file mode 100644 index 000000000..c7a1dbe47 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/SymbolUtils.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore +{ + internal class SymbolUtils + { + private static string TaskWrapperTypeName = "System.Threading.Tasks.Task`1"; + + internal static bool TryUnwrapTaskOfT(ISymbol symbol, SemanticModel semanticModel, out ITypeSymbol resultSymbol) + { + var taskType = semanticModel.Compilation.GetTypeByMetadataName(TaskWrapperTypeName); + + resultSymbol = null; + + if (symbol is INamedTypeSymbol namedTypeSymbol && + namedTypeSymbol.ConstructedFrom is not null && + SymbolEqualityComparer.Default.Equals(namedTypeSymbol.ConstructedFrom, taskType) && + namedTypeSymbol.TypeArguments.Length == 1) + { + resultSymbol = namedTypeSymbol.TypeArguments[0]; + return true; + } + + return false; + } + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Worker.Extensions.Http.AspNetCore.Analyzers.csproj b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Worker.Extensions.Http.AspNetCore.Analyzers.csproj index 6d37a744e..ae5e5b0ae 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Worker.Extensions.Http.AspNetCore.Analyzers.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Worker.Extensions.Http.AspNetCore.Analyzers.csproj @@ -1,7 +1,7 @@  - 1.0.3 + 1.0.4 Library true false diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index b837fa992..2834b8fc1 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -4,10 +4,10 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 2.0.2 - Fix intermittent error `IFeatureCollection has been disposed` exception in multiple-output binding scenarios. (#2896) -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers 1.0.4 -- +- Include case where customer POCO is wrapped in `Task` in the `HttpResultAttribute` analyzer for multiple output binding scenarios. (#3506) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index ac2e612b0..f26b5fe99 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -6,7 +6,7 @@ ASP.NET Core extensions for .NET isolated functions - 2.0.1 + 2.0.2 net6.0;net8.0 diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/HttpResultAttributeExpectedTests.cs b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/HttpResultAttributeExpectedTests.cs index 87603cf34..56552ea59 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/HttpResultAttributeExpectedTests.cs +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/HttpResultAttributeExpectedTests.cs @@ -347,6 +347,179 @@ public class MyOutputType await test.RunAsync(); } + [Fact] + public async Task HttpResultAttribute_WhenReturnTypeIsWrappedInTask_Expected() + { + string testCode = @" + using System.Threading.Tasks; + using Microsoft.AspNetCore.Http; + using Microsoft.Azure.Functions.Worker; + using Microsoft.Azure.Functions.Worker.Http; + + namespace AspNetIntegration + { + public class MultipleOutputBindings + { + [Function(""TaskOfPocoOutput"")] + public Task Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequestData req) + { + throw new System.NotImplementedException(); + } + public class MyOutputType + { + public HttpResponseData Result { get; set; } + + [BlobOutput(""test-samples-output/{name}-output.txt"")] + public string MessageText { get; set; } + } + } + }"; + + var test = new AnalyzerTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = testCode + }; + + test.ExpectedDiagnostics.Add(Verifier.Diagnostic(DiagnosticDescriptors.MultipleOutputWithHttpResponseDataWithoutHttpResultAttribute) + .WithSeverity(DiagnosticSeverity.Warning) + .WithLocation(12, 20) + .WithArguments("\"TaskOfPocoOutput\"")); + + await test.RunAsync(); + } + + [Fact] + public async Task HttpResultAttributeForTaskOfPocoExpected_CodeFixWorks() + { + string inputCode = @" +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; + +namespace AspNetIntegration +{ + public class MultipleOutputBindings + { + [Function(""TaskOfPocoOutput"")] + public Task Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequestData req) + { + throw new System.NotImplementedException(); + } + public class MyOutputType + { + public HttpResponseData Result { get; set; } + + [BlobOutput(""test-samples-output/{name}-output.txt"")] + public string MessageText { get; set; } + } + } +}"; + + string expectedCode = @" +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; + +namespace AspNetIntegration +{ + public class MultipleOutputBindings + { + [Function(""TaskOfPocoOutput"")] + public Task Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequestData req) + { + throw new System.NotImplementedException(); + } + public class MyOutputType + { + [HttpResult] + public HttpResponseData Result { get; set; } + + [BlobOutput(""test-samples-output/{name}-output.txt"")] + public string MessageText { get; set; } + } + } +}"; + + var expectedDiagnosticResult = CodeFixVerifier + .Diagnostic("AZFW0016") + .WithSeverity(DiagnosticSeverity.Warning) + .WithLocation(12, 16) + .WithArguments("\"TaskOfPocoOutput\""); + + var test = new CodeFixTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = inputCode, + FixedCode = expectedCode + }; + + test.ExpectedDiagnostics.Add(expectedDiagnosticResult); + await test.RunAsync(); + } + + [Fact] + public async Task HttpTriggerFunctionWithHttpResponseData_NoDiagnostic() + { + string testCode = @" +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Azure.Functions.Worker; + +namespace AspNetIntegration +{ + public class SimpleHttpFunction + { + [Function(""SimpleHttpTaskOutput"")] + public HttpResponseData Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequestData req) + { + throw new System.NotImplementedException(); + } + } +}"; + + var test = new AnalyzerTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = testCode + }; + + await test.RunAsync(); + } + + [Fact] + public async Task HttpTriggerFunctionWithTaskOfIActionResult_NoDiagnostic() + { + string testCode = @" +using System.Threading.Tasks; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; + +namespace AspNetIntegration +{ + public class SimpleHttpFunction + { + [Function(""SimpleHttpTaskOutput"")] + public Task Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + return Task.FromResult(new OkResult()); + } + } +}"; + + var test = new AnalyzerTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = testCode + }; + + await test.RunAsync(); + } + private static ReferenceAssemblies LoadRequiredDependencyAssemblies() { var referenceAssemblies = ReferenceAssemblies.Net.Net60.WithPackages(ImmutableArray.Create( From a3322053974524aeb46e9da7d3a46d0d924d3cb6 Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Mon, 19 May 2025 14:41:36 -0500 Subject: [PATCH 126/190] Updating `Microsoft.Azure.WebJobs.Extensions.EventHubs` reference to 6.5.1 (#3059) --- extensions/Worker.Extensions.EventHubs/release_notes.md | 4 ++-- .../src/Worker.Extensions.EventHubs.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.EventHubs/release_notes.md b/extensions/Worker.Extensions.EventHubs/release_notes.md index 3d6e918a8..e621874c1 100644 --- a/extensions/Worker.Extensions.EventHubs/release_notes.md +++ b/extensions/Worker.Extensions.EventHubs/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventHubs +### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.4.0 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.EventHubs` reference to 6.5.1 diff --git a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj index 60c9ea99d..860d90d25 100644 --- a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj +++ b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj @@ -6,7 +6,7 @@ Azure Event Hubs extensions for .NET isolated functions - 6.3.6 + 6.4.0 @@ -27,7 +27,7 @@ - + \ No newline at end of file From 0e1edd25a35f18ab924e4f8db374ccbdc4512a2b Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 20 May 2025 13:32:29 -0700 Subject: [PATCH 127/190] Sdk 2.0.3 release prep. (#3062) --- sdk/Sdk.Generators/Sdk.Generators.csproj | 2 +- sdk/Sdk/Sdk.csproj | 4 ++-- sdk/release_notes.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index 93af6de7a..ed64e78c2 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -10,7 +10,7 @@ false true 3 - 4 + 5 true true diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index e1c1715a5..a1c65a3fb 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -2,8 +2,8 @@ 2 - 1 - -preview.1 + 0 + 3 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 68e01c13b..f73ad227b 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,7 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 2.1.0-preview.1 +### Microsoft.Azure.Functions.Worker.Sdk 2.0.3 - Addresses issue with `dotnet build --no-incremental` failing build (PR #2763, Issue #2601) - Addresses issue with setting `OutDir` msbuild property failing build (PR #2763, Issue #2125) From 624781603c75441457a05c2adb3762364e4a9480 Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Tue, 20 May 2025 17:45:56 -0700 Subject: [PATCH 128/190] Reset release notes (#3063) --- .../release_notes.md | 8 ++++---- sdk/release_notes.md | 13 ++++--------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index 2834b8fc1..97bb2a3ba 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -4,10 +4,10 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 2.0.2 +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore -- Fix intermittent error `IFeatureCollection has been disposed` exception in multiple-output binding scenarios. (#2896) +- -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers 1.0.4 +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers -- Include case where customer POCO is wrapped in `Task` in the `HttpResultAttribute` analyzer for multiple output binding scenarios. (#3506) +- diff --git a/sdk/release_notes.md b/sdk/release_notes.md index f73ad227b..216f4dfcd 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,15 +4,10 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 2.0.3 +### Microsoft.Azure.Functions.Worker.Sdk -- Addresses issue with `dotnet build --no-incremental` failing build (PR #2763, Issue #2601) -- Addresses issue with setting `OutDir` msbuild property failing build (PR #2763, Issue #2125) -- Write `worker.config` and `functions.metadata` only if contents have changed. (#2999) -- Updates the generated extension csproj to be net8.0 (from net6.0) -- Setting _ToolingSuffix for V10.0 TargetFrameworkVersion. (#2983) -- Enhanced error message for missing Azure Functions Core Tools in the user's environment. (#2976) +- -### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.5 +### Microsoft.Azure.Functions.Worker.Sdk.Generators -- Update all generated classes to use `GeneratedCodeAttribute`. (#2887) +- From d0024babb16a3aaf537a7a43f15acfab0ad08349 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 21 May 2025 10:38:43 -0700 Subject: [PATCH 129/190] Update official-release.yml to run partner pipeline (#3065) --- eng/ci/official-release.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml index 3e2f5cf1e..3d180e671 100644 --- a/eng/ci/official-release.yml +++ b/eng/ci/official-release.yml @@ -122,4 +122,3 @@ extends: partnerDrop: serviceConnection: azure-sdk-partner-drops targetFolder: $(target_folder)/$(Build.BuildNumber) - runPipeline: false From af45b7437e936dde0712696f3e26388410266bb9 Mon Sep 17 00:00:00 2001 From: Pranava <68387945+aloiva@users.noreply.github.com> Date: Thu, 22 May 2025 22:51:12 +0530 Subject: [PATCH 130/190] Upgrade Kafka Extension version (#3064) --- extensions/Worker.Extensions.Kafka/release_notes.md | 6 +++--- .../src/Worker.Extensions.Kafka.csproj | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index e73c591ab..ecced1441 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka - -- +### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.1 +- Update kafka extension version to 4.1.1 +- Fixes bug that caused failures in reading PEM values from Azure app settings (https://github.com/Azure/azure-functions-kafka-extension/issues/555) diff --git a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj index 278b9a2e2..4148c5e5d 100644 --- a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj +++ b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj @@ -6,7 +6,7 @@ Kafka extensions for .NET isolated functions - 4.1.0 + 4.1.1 false @@ -24,4 +24,4 @@ - \ No newline at end of file + From 91cda31f999cfb6020b768ba1c1f418af7b3d937 Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Thu, 22 May 2025 11:54:20 -0700 Subject: [PATCH 131/190] Reset Kafka Release Notes (#3069) --- extensions/Worker.Extensions.Kafka/release_notes.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index ecced1441..e73c591ab 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.1 -- Update kafka extension version to 4.1.1 -- Fixes bug that caused failures in reading PEM values from Azure app settings (https://github.com/Azure/azure-functions-kafka-extension/issues/555) +### Microsoft.Azure.Functions.Worker.Extensions.Kafka + +- From c662743e38563f0e5c6cc4202e85652c797ea9e2 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 22 May 2025 13:02:23 -0700 Subject: [PATCH 132/190] Fix sdk publish --no-build (#3068) * Fix sdk publish --no-build * Update release notes --- sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 3 ++- sdk/release_notes.md | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index d4832489e..849dc9751 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -141,7 +141,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + -### Microsoft.Azure.Functions.Worker.Sdk +### Microsoft.Azure.Functions.Worker.Sdk 2.0.4 -- +- Address issue with `dotnet publish --no-build` producing an error. (#3068) ### Microsoft.Azure.Functions.Worker.Sdk.Generators From 37484db97f9acf45d198550a9ee61e721d90178c Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 22 May 2025 13:49:44 -0700 Subject: [PATCH 133/190] Rev Sdk.csproj to 2.0.4, fix design time build (#3070) * Rev Sdk.csproj to 2.0.4 * Fix design time build * Add comment --- sdk/Sdk/Sdk.csproj | 2 +- .../Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index a1c65a3fb..33085f5c1 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -3,7 +3,7 @@ 2 0 - 3 + 4 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 849dc9751..eea28ee00 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -146,12 +146,13 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - + - - + + + <_WorkerExtensionTarget>Build <_WorkerExtensionTarget Condition="'$(NoBuild)' == 'true'">GetTargetPath From c45651c43899fb97d60b0000dff8825854f3bccb Mon Sep 17 00:00:00 2001 From: Pranava <68387945+aloiva@users.noreply.github.com> Date: Sat, 31 May 2025 00:01:58 +0530 Subject: [PATCH 134/190] Update RabbitMQ version (#3073) --- extensions/Worker.Extensions.RabbitMQ/release_notes.md | 5 +++-- .../src/Worker.Extensions.RabbitMQ.csproj | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.RabbitMQ/release_notes.md b/extensions/Worker.Extensions.RabbitMQ/release_notes.md index fbb45f266..ebfcd67f3 100644 --- a/extensions/Worker.Extensions.RabbitMQ/release_notes.md +++ b/extensions/Worker.Extensions.RabbitMQ/release_notes.md @@ -4,6 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ +### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ 2.1.0 -- +- Updates `Microsoft.Azure.WebJobs.Extensions.RabbitMQ` to 2.1.0. + - Adds drain mode feature. diff --git a/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj b/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj index 1616cbba6..c3efdc5c9 100644 --- a/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj +++ b/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj @@ -6,7 +6,7 @@ RabbitMQ extensions for .NET isolated functions - 2.0.4 + 2.1.0 false @@ -19,7 +19,7 @@ - + From 78629ac84a4e797a42f672e4764811c7045a9e4c Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 5 Jun 2025 12:57:28 -0700 Subject: [PATCH 135/190] Add dotnet host release pipeline (#3061) * Add dotnet host release pipeline * Remove staging feed from worker host package release --- eng/ci/host/official-release.yml | 104 ++++++++++++++++++ eng/ci/official-release.yml | 82 +++++++------- .../pipelines/release-extension-packages.yml | 46 ++++---- 3 files changed, 168 insertions(+), 64 deletions(-) create mode 100644 eng/ci/host/official-release.yml diff --git a/eng/ci/host/official-release.yml b/eng/ci/host/official-release.yml new file mode 100644 index 000000000..785ddefa6 --- /dev/null +++ b/eng/ci/host/official-release.yml @@ -0,0 +1,104 @@ +pr: none +trigger: none + +resources: + repositories: + - repository: 1es + type: git + name: 1ESPipelineTemplates/1ESPipelineTemplates + ref: refs/tags/release + - repository: eng + type: git + name: engineering + ref: refs/tags/release + pipelines: + - pipeline: build + source: dotnet-host.official + +variables: +- template: ci/variables/cfs.yml@eng +- name: artifact_name + value: NugetPackages + readonly: true +- name: drop_path + value: $(Pipeline.Workspace)/build/${{ parameters.artifactName }} + readonly: true +- name: nuget_feed + value: public/infra + readonly: true +- name: packages_pattern + value: $(drop_path)/*.nupkg;!$(drop_path)/**/*.symbols.nupkg + readonly: true + +extends: + template: v1/1ES.Official.PipelineTemplate.yml@1es + parameters: + pool: + name: 1es-pool-azfunc + image: 1es-ubuntu-22.04 + os: linux + + stages: + - stage: Release + jobs: + - job: Prepare + + templateContext: + type: validationJob + + steps: + - checkout: none + + # validationJob uses retail artifact inputs + - download: build + artifact: $(artifact_name) + + # For dotnet host release, we assume the first package (alphanumerically) in the drop is the one we want to version off of. + # This is a bit of a hack, but it works for our current setup. + # We use a regex to extract the version from the package name and set it as the build number. + - pwsh: | + $ErrorActionPreference = 'Stop' + $packages = Get-ChildItem -Path $(drop_path) -Filter *.nupkg -Recurse + $name = $packages[0].Name + Write-Host "Getting version for $name" + $version = [Regex]::Match($name, '(\d+\.\d+\.\d+(?:\.\d+)?(?:-[\w\.].*)?)(?=\.nupkg$)').Value + Write-Host "##vso[build.updatebuildnumber]$version" + displayName: Get package version + + - job: Approval + dependsOn: Prepare + timeoutInMinutes: 1440 + pool: server + + steps: + - task: ManualValidation@1 + inputs: + notifyUsers: '' # no notification + approvers: '[internal]\Azure Functions Core' + allowApproversToApproveTheirOwnRuns: false + instructions: | + Approve to release packages to: + - feed: $(nuget_feed) + + - job: Publish + displayName: Publish packages + dependsOn: Approval + + templateContext: + type: releaseJob + isProduction: true + + inputs: + - input: pipelineArtifact + targetPath: $(drop_path) + artifactName: $(artifact_name) + pipeline: build + + outputs: + - output: nuget + packagesToPush: $(packages_pattern) + packageParentPath: $(drop_path) + publishVstsFeed: $(nuget_feed) + nuGetFeedType: internal + allowPackageConflicts: true + publishPackageMetadata: true diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml index 3d180e671..32d9d357d 100644 --- a/eng/ci/official-release.yml +++ b/eng/ci/official-release.yml @@ -64,47 +64,47 @@ extends: stages: - stage: Prepare jobs: - - job: Prepare - - variables: - - name: drop_path - value: $(Pipeline.Workspace)/build/$(artifact_name) - - templateContext: - type: validationJob - - steps: - - checkout: none - - # validationJob uses retail artifact inputs - - download: build - artifact: $(artifact_name) - - # Our build does not have a custom version number set. To convey the version number to the release stage, - # we parse out the version from the .nupkg in the drop and set that as the build number. The release stage - # can then reference $(Build.BuildVersion) for the target upload folder. - - pwsh: | - $ErrorActionPreference = 'Stop' - - $name = "$(package_name)".Trim() - Write-Host "Getting version for $name" - $package = Get-ChildItem -Path $(drop_path) -Recurse -Filter "$name.?.*.nupkg" - - if ($package.Count -eq 0) { - Write-Host "##vso[task.LogIssue type=error;]Could not find package $name." - exit 1 - } - - if ($package.Count -gt 1) { - Write-Host "##vso[task.LogIssue type=error;]Too many packages matched $name." - exit 1 - } - - $version = $package.Name.Trim("$name.").Trim('.nupkg') - Write-Host "##vso[build.updatebuildnumber]$version" - Write-Host "##vso[build.addbuildtag]${{ parameters.packages }}" - Write-Host "##vso[build.addbuildtag]$version" - displayName: Get package version + - job: Prepare + + variables: + - name: drop_path + value: $(Pipeline.Workspace)/build/$(artifact_name) + + templateContext: + type: validationJob + + steps: + - checkout: none + + # validationJob uses retail artifact inputs + - download: build + artifact: $(artifact_name) + + # Our build does not have a custom version number set. To convey the version number to the release stage, + # we parse out the version from the .nupkg in the drop and set that as the build number. The release stage + # can then reference $(Build.BuildVersion) for the target upload folder. + - pwsh: | + $ErrorActionPreference = 'Stop' + + $name = "$(package_name)".Trim() + Write-Host "Getting version for $name" + $package = Get-ChildItem -Path $(drop_path) -Recurse -Filter "$name.?.*.nupkg" + + if ($package.Count -eq 0) { + Write-Host "##vso[task.LogIssue type=error;]Could not find package $name." + exit 1 + } + + if ($package.Count -gt 1) { + Write-Host "##vso[task.LogIssue type=error;]Too many packages matched $name." + exit 1 + } + + $version = $package.Name.Trim("$name.").Trim('.nupkg') + Write-Host "##vso[build.updatebuildnumber]$version" + Write-Host "##vso[build.addbuildtag]${{ parameters.packages }}" + Write-Host "##vso[build.addbuildtag]$version" + displayName: Get package version - stage: Release dependsOn: Prepare diff --git a/eng/ci/templates/pipelines/release-extension-packages.yml b/eng/ci/templates/pipelines/release-extension-packages.yml index dac5eb5dd..708e050ab 100644 --- a/eng/ci/templates/pipelines/release-extension-packages.yml +++ b/eng/ci/templates/pipelines/release-extension-packages.yml @@ -31,34 +31,34 @@ extends: - stage: Prepare jobs: - - job: Prepare + - job: Prepare - variables: - - template: ci/variables/cfs.yml@eng - - name: drop_path - value: $(Pipeline.Workspace)/build/${{ parameters.artifactName }} + variables: + - template: ci/variables/cfs.yml@eng + - name: drop_path + value: $(Pipeline.Workspace)/build/${{ parameters.artifactName }} - templateContext: - type: validationJob + templateContext: + type: validationJob - steps: - - checkout: none + steps: + - checkout: none - # validationJob uses retail artifact inputs - - download: build - artifact: ${{ parameters.artifactName }} + # validationJob uses retail artifact inputs + - download: build + artifact: ${{ parameters.artifactName }} - # For extension releases, we assume the first package (alphanumerically) in the drop is the one we want to version off of. - # This is a bit of a hack, but it works for our current setup. - # We use a regex to extract the version from the package name and set it as the build number. - - pwsh: | - $ErrorActionPreference = 'Stop' - $packages = Get-ChildItem -Path $(drop_path) -Filter *.nupkg -Recurse - $name = $packages[0].Name - Write-Host "Getting version for $name" - $version = [Regex]::Match($name, '(\d+\.\d+\.\d+(?:\.\d+)?(?:-[\w\.].*)?)(?=\.nupkg$)').Value - Write-Host "##vso[build.updatebuildnumber]$version" - displayName: Get package version + # For extension releases, we assume the first package (alphanumerically) in the drop is the one we want to version off of. + # This is a bit of a hack, but it works for our current setup. + # We use a regex to extract the version from the package name and set it as the build number. + - pwsh: | + $ErrorActionPreference = 'Stop' + $packages = Get-ChildItem -Path $(drop_path) -Filter *.nupkg -Recurse + $name = $packages[0].Name + Write-Host "Getting version for $name" + $version = [Regex]::Match($name, '(\d+\.\d+\.\d+(?:\.\d+)?(?:-[\w\.].*)?)(?=\.nupkg$)').Value + Write-Host "##vso[build.updatebuildnumber]$version" + displayName: Get package version - stage: Release dependsOn: Prepare From 1b6edd6ecdfd2edf9e84a1661f7ad2756d8a48f4 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 5 Jun 2025 12:57:48 -0700 Subject: [PATCH 136/190] Enable ControlFlowGuard for host (#3078) * Enable ControlFlowGuard for host * Update worker host package version --- host/src/FunctionsNetHost/FunctionsNetHost.csproj | 1 + .../Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/host/src/FunctionsNetHost/FunctionsNetHost.csproj b/host/src/FunctionsNetHost/FunctionsNetHost.csproj index 9b9495015..f62612d17 100644 --- a/host/src/FunctionsNetHost/FunctionsNetHost.csproj +++ b/host/src/FunctionsNetHost/FunctionsNetHost.csproj @@ -9,6 +9,7 @@ true Speed true + Guard diff --git a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec index 9207d8f38..062477d9b 100644 --- a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec +++ b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec @@ -4,7 +4,7 @@ Microsoft.Azure.Functions.DotNetIsolatedNativeHost Microsoft Azure Functions dotnet-isolated native host dotnet-isolated azure-functions azure - 1.0.12 + 1.0.13 Microsoft Microsoft https://github.com/Azure/azure-functions-dotnet-worker From 9ed7ece0564d9db3a30b87d5eea8324a6e7c3d10 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Thu, 5 Jun 2025 13:41:39 -0700 Subject: [PATCH 137/190] Fix parameter -> variable (#3080) --- eng/ci/host/official-release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eng/ci/host/official-release.yml b/eng/ci/host/official-release.yml index 785ddefa6..b3941cebf 100644 --- a/eng/ci/host/official-release.yml +++ b/eng/ci/host/official-release.yml @@ -21,7 +21,7 @@ variables: value: NugetPackages readonly: true - name: drop_path - value: $(Pipeline.Workspace)/build/${{ parameters.artifactName }} + value: $(Pipeline.Workspace)/build/$(artifact_name) readonly: true - name: nuget_feed value: public/infra From ab45bacd09effcc40d046d1451451e74f50d1019 Mon Sep 17 00:00:00 2001 From: Pranava <68387945+aloiva@users.noreply.github.com> Date: Wed, 11 Jun 2025 00:00:47 +0530 Subject: [PATCH 138/190] Update Kafka extension Version (#3075) --- extensions/Worker.Extensions.Kafka/release_notes.md | 6 +++--- .../src/Worker.Extensions.Kafka.csproj | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index e73c591ab..80ac34fa8 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka - -- +### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.2 +- Updates `Microsoft.Azure.WebJobs.Extensions.Kafka` version to 4.1.2 + - Fixes bug that caused failures in reading PEM values from Azure app settings (https://github.com/Azure/azure-functions-kafka-extension/issues/555) diff --git a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj index 4148c5e5d..84df6f91c 100644 --- a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj +++ b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj @@ -6,7 +6,7 @@ Kafka extensions for .NET isolated functions - 4.1.1 + 4.1.2 false @@ -21,7 +21,7 @@ - + From f31bf5b5d5756403bca19c1d54ec69d9d54c1fee Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Mon, 16 Jun 2025 16:01:27 -0700 Subject: [PATCH 139/190] Clear release notes (#3085) --- extensions/Worker.Extensions.Kafka/release_notes.md | 6 +++--- extensions/Worker.Extensions.RabbitMQ/release_notes.md | 5 ++--- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index 80ac34fa8..ca17cb549 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.2 -- Updates `Microsoft.Azure.WebJobs.Extensions.Kafka` version to 4.1.2 - - Fixes bug that caused failures in reading PEM values from Azure app settings (https://github.com/Azure/azure-functions-kafka-extension/issues/555) +### Microsoft.Azure.Functions.Worker.Extensions.Kafka + +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.RabbitMQ/release_notes.md b/extensions/Worker.Extensions.RabbitMQ/release_notes.md index ebfcd67f3..bb1ab4914 100644 --- a/extensions/Worker.Extensions.RabbitMQ/release_notes.md +++ b/extensions/Worker.Extensions.RabbitMQ/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ 2.1.0 +### Microsoft.Azure.Functions.Worker.Extensions.RabbitMQ -- Updates `Microsoft.Azure.WebJobs.Extensions.RabbitMQ` to 2.1.0. - - Adds drain mode feature. +- From a7dbc6fb80efcea816e6c4fffbc71efafaaaab02 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 18 Jun 2025 11:17:14 -0700 Subject: [PATCH 140/190] Add OTel and AppInsights release options (#3060) --- eng/ci/official-release.yml | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/eng/ci/official-release.yml b/eng/ci/official-release.yml index 32d9d357d..fb9f5368f 100644 --- a/eng/ci/official-release.yml +++ b/eng/ci/official-release.yml @@ -10,6 +10,8 @@ parameters: values: - core - sdk + - application-insights + - open-telemetry pr: none trigger: none @@ -41,6 +43,8 @@ variables: value: | Microsoft.Azure.Functions.Worker.*.nupkg !Microsoft.Azure.Functions.Worker.Sdk.*.nupkg + !Microsoft.Azure.Functions.Worker.ApplicationInsights.*.nupkg + !Microsoft.Azure.Functions.Worker.OpenTelemetry.*.nupkg !*.symbols.nupkg - ${{ if eq(parameters.packages, 'sdk') }}: @@ -53,6 +57,26 @@ variables: Microsoft.Azure.Functions.Worker.Sdk.*.nupkg !*.symbols.nupkg +- ${{ if eq(parameters.packages, 'application-insights') }}: + - name: target_folder + value: azure-functions/dotnet/worker-app-insights + - name: package_name + value: Microsoft.Azure.Functions.Worker.ApplicationInsights + - name: package_pattern + value: | + Microsoft.Azure.Functions.Worker.ApplicationInsights.*.nupkg + !*.symbols.nupkg + +- ${{ if eq(parameters.packages, 'open-telemetry') }}: + - name: target_folder + value: azure-functions/dotnet/worker-open-telemetry + - name: package_name + value: Microsoft.Azure.Functions.Worker.OpenTelemetry + - name: package_pattern + value: | + Microsoft.Azure.Functions.Worker.OpenTelemetry.*.nupkg + !*.symbols.nupkg + extends: template: v1/1ES.Official.PipelineTemplate.yml@1es parameters: From 6a8c1a2057876bb900767d97ccb17efb9c3e2cca Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 18 Jun 2025 11:17:28 -0700 Subject: [PATCH 141/190] Use task instead of outputs for nuget publish (#3082) --- eng/ci/host/official-release.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/eng/ci/host/official-release.yml b/eng/ci/host/official-release.yml index b3941cebf..8885134fd 100644 --- a/eng/ci/host/official-release.yml +++ b/eng/ci/host/official-release.yml @@ -94,11 +94,13 @@ extends: artifactName: $(artifact_name) pipeline: build - outputs: - - output: nuget - packagesToPush: $(packages_pattern) - packageParentPath: $(drop_path) - publishVstsFeed: $(nuget_feed) - nuGetFeedType: internal - allowPackageConflicts: true - publishPackageMetadata: true + steps: + - task: 1ES.PublishNuget@1 + displayName: Publish packages + inputs: + packagesToPush: $(packages_pattern) + packageParentPath: $(drop_path) + publishVstsFeed: $(nuget_feed) + nuGetFeedType: internal + allowPackageConflicts: true + publishPackageMetadata: true From a416226e160079cc25f89b0175133d8d5249d61f Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 18 Jun 2025 11:17:48 -0700 Subject: [PATCH 142/190] Fix design time build when not build yet (#3081) * Fix design time build when not build yet * Update release notes, rev sdk version --- sdk/Sdk/Sdk.csproj | 2 +- sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets | 3 ++- sdk/release_notes.md | 4 ++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 33085f5c1..0e00dd207 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -3,7 +3,7 @@ 2 0 - 4 + 5 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 eea28ee00..5deed66cf 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -128,13 +128,14 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 5b72ec524..45c1eac83 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,9 +4,9 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 2.0.4 +### Microsoft.Azure.Functions.Worker.Sdk 2.0.5 -- Address issue with `dotnet publish --no-build` producing an error. (#3068) +- Address issue with design time build producing an error when project had not yet been built yet. (#3081) ### Microsoft.Azure.Functions.Worker.Sdk.Generators From cf017816a0fdcfcba8f179daf352f49d33a1fae3 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 18 Jun 2025 11:18:09 -0700 Subject: [PATCH 143/190] Trigger code mirror on tags (#3079) --- eng/ci/code-mirror.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/eng/ci/code-mirror.yml b/eng/ci/code-mirror.yml index 5d9fcb4cd..82b2298fa 100644 --- a/eng/ci/code-mirror.yml +++ b/eng/ci/code-mirror.yml @@ -4,6 +4,9 @@ trigger: # Keep this set limited as appropriate (don't mirror individual user branches). - main - release/* + tags: + include: + - "*" resources: repositories: From 7c348d1b012f00e7fc3d164cc9670b74208f6b3c Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Mon, 23 Jun 2025 09:52:11 -0700 Subject: [PATCH 144/190] Updating extension dependencies (#3098) --- extensions/Worker.Extensions.EventHubs/release_notes.md | 4 ++-- .../src/Worker.Extensions.EventHubs.csproj | 6 +++--- extensions/Worker.Extensions.ServiceBus/release_notes.md | 4 ++-- .../src/Worker.Extensions.ServiceBus.csproj | 8 ++++---- extensions/Worker.Extensions.Tables/release_notes.md | 3 ++- .../src/Worker.Extensions.Tables.csproj | 6 +++--- 6 files changed, 16 insertions(+), 15 deletions(-) diff --git a/extensions/Worker.Extensions.EventHubs/release_notes.md b/extensions/Worker.Extensions.EventHubs/release_notes.md index e621874c1..aa498c751 100644 --- a/extensions/Worker.Extensions.EventHubs/release_notes.md +++ b/extensions/Worker.Extensions.EventHubs/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.4.0 +### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.5.0 -- Updating `Microsoft.Azure.WebJobs.Extensions.EventHubs` reference to 6.5.1 +- Updating `Microsoft.Azure.WebJobs.Extensions.EventHubs` reference to 6.5.2 (#3098) diff --git a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj index 860d90d25..711ca3711 100644 --- a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj +++ b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj @@ -6,7 +6,7 @@ Azure Event Hubs extensions for .NET isolated functions - 6.4.0 + 6.5.0 @@ -17,7 +17,7 @@ - + @@ -27,7 +27,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index c92b7d33c..eb4cbfcb5 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.23.0 -- \ No newline at end of file +- Update dependency `Microsoft.Azure.WebJobs.Extensions.ServiceBus` to 5.17.0 (#3098) \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj index 69392a826..048f513cc 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj +++ b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj @@ -6,7 +6,7 @@ Azure Service Bus extensions for .NET isolated functions - 5.22.2 + 5.23.0 false @@ -15,9 +15,9 @@ - + - + @@ -36,7 +36,7 @@ - + diff --git a/extensions/Worker.Extensions.Tables/release_notes.md b/extensions/Worker.Extensions.Tables/release_notes.md index 197b1a6c1..bffbc10ad 100644 --- a/extensions/Worker.Extensions.Tables/release_notes.md +++ b/extensions/Worker.Extensions.Tables/release_notes.md @@ -6,4 +6,5 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.5.0 -- Support deferred binding for poco types in Table Input binding (#3003) \ No newline at end of file +- Support deferred binding for poco types in Table Input binding (#3003) +- Update dependency `Microsoft.Azure.WebJobs.Extensions.Tables` to 1.4.0 (#3098) \ No newline at end of file diff --git a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj index ab07ea44e..30c5668e8 100644 --- a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj +++ b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj @@ -18,8 +18,8 @@ - - + + @@ -29,7 +29,7 @@ - + \ No newline at end of file From 4e9f1379e39820df72c4ce22907c2096d307076e Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Mon, 23 Jun 2025 10:08:14 -0700 Subject: [PATCH 145/190] Skip writing functions.metadata when using source gen (#2974) * Skip writing functions.metadata when using source gen * Update SDK tests * update release notes * Fix tests, allow for manual override of writing functions.metadata * Update tests for force write metadata * Fix copy condition, refactor tests * FIx IDisposable * Fix restore with rid * Fix bad merge * Restore separately for test --- ...crosoft.Azure.Functions.Worker.Sdk.targets | 10 +- sdk/Sdk/Tasks/GenerateFunctionMetadata.cs | 9 ++ sdk/release_notes.md | 4 +- .../AspNetCore/CancellationEndToEndTests.cs | 8 +- .../E2ETests/Fixtures/FunctionAppFixture.cs | 5 +- test/Sdk.E2ETests/InnerBuildTests.cs | 42 ++++--- test/Sdk.E2ETests/ProcessWrapper.cs | 33 +++--- test/Sdk.E2ETests/ProjectBuilder.cs | 106 +++++++++++++++++ test/Sdk.E2ETests/PublishTests.cs | 109 +++++++++--------- test/Sdk.E2ETests/TempDirectory.cs | 41 +++++++ test/Sdk.E2ETests/TestUtility.cs | 107 ++--------------- test/Sdk.E2ETests/ZipDeployTests.cs | 28 +++-- 12 files changed, 286 insertions(+), 216 deletions(-) create mode 100644 test/Sdk.E2ETests/ProjectBuilder.cs create mode 100644 test/Sdk.E2ETests/TempDirectory.cs diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 5deed66cf..b08c2e352 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -48,7 +48,9 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and false true $(FunctionsEnableWorkerIndexing) - $(FunctionsEnableWorkerIndexing) + $(FunctionsEnableWorkerIndexing) + false + true true true @@ -184,9 +186,10 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and ReferencePaths="@(ReferencePath)" ExtensionsCsProjFilePath="$(ExtensionsCsProj)" AzureFunctionsVersion="$(AzureFunctionsVersion)" + WriteMetadataFile="$(FunctionsWriteMetadataJson)" TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)" TargetFrameworkVersion="$(TargetFrameworkVersion)" - OutputPath="$(IntermediateOutputPath)"/> + OutputPath="$(IntermediateOutputPath)" /> @@ -240,7 +243,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - <_FunctionsAdditionalFile Include="$(_FunctionsMetadataPath);$(_FunctionsWorkerConfigPath);$(_FunctionsIntermediateExtensionUpdatedJsonPath)" /> + <_FunctionsAdditionalFile Include="$(_FunctionsMetadataPath)" Condition="'$(FunctionsWriteMetadataJson)' == 'true'" /> + <_FunctionsAdditionalFile Include="$(_FunctionsWorkerConfigPath);$(_FunctionsIntermediateExtensionUpdatedJsonPath)" /> <_FunctionsAdditionalFile Include="$(_FunctionsMetadataLoaderExtensionFile)" SubPath="$(_FunctionsExtensionsDirectory)/" /> <_NoneWithTargetPath Include="@(_FunctionsAdditionalFile)" TargetPath="%(_FunctionsAdditionalFile.SubPath)%(Filename)%(Extension)" diff --git a/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs b/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs index e54aa995a..58568268d 100644 --- a/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs +++ b/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs @@ -26,6 +26,8 @@ public class GenerateFunctionMetadata : Task public string? ExtensionsCsProjFilePath { get; set; } + public bool WriteMetadataFile { get; set; } = true; + [Required] public ITaskItem[]? ReferencePaths { get; set; } @@ -67,11 +69,18 @@ public override bool Execute() private void WriteMetadataWithRetry(IEnumerable functions) { + if (!WriteMetadataFile) + { + Log.LogMessage("Skipping writing function metadata file."); + return; + } + int attempt = 0; while (attempt < 10) { try { + Log.LogMessage($"Writing function metadata to {OutputPath} directory."); FunctionMetadataJsonWriter.WriteMetadata(functions, OutputPath!); break; } diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 45c1eac83..3d4479236 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,9 +4,9 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 2.0.5 +### Microsoft.Azure.Functions.Worker.Sdk -- Address issue with design time build producing an error when project had not yet been built yet. (#3081) +- Build no longer generates `functions.metadata` if source-generated metadata provider is enabled. (#2974) ### Microsoft.Azure.Functions.Worker.Sdk.Generators diff --git a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs index 4bfce6034..0fc9dae82 100644 --- a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs +++ b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs @@ -37,10 +37,10 @@ public async Task HttpTriggerFunctions_WithCancellationToken_BehaveAsExpected(st await TestUtility.RetryAsync(() => { invocationStartLog = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains($"Executing 'Functions.{functionName}'")); - return Task.FromResult(invocationStartLog.Count() >= 1); + return Task.FromResult(invocationStartLog.Any()); }); - // The task should be cancelled before it completes, mimicing a client closing the connection. + // The task should be cancelled before it completes, mimicking a client closing the connection. // This should lead to the worker getting an InvocationCancel request from the functions host cts.Cancel(); await Assert.ThrowsAsync(async () => await task); @@ -49,13 +49,13 @@ await TestUtility.RetryAsync(() => await TestUtility.RetryAsync(() => { invocationEndLog = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains($"Executed 'Functions.{functionName}'")); - return Task.FromResult(invocationEndLog.Count() >= 1); + return Task.FromResult(invocationEndLog.Any()); }); Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains(expectedMessage, StringComparison.OrdinalIgnoreCase)); // TODO: 2/3 of the test invocations will fail until the host with the ForwarderProxy fix is released - uncomment this line when the fix is released - Assert.NotEqual(null, invocationResult); // just here to 'use' invocationResult to avoid a warning. + Assert.NotNull(invocationResult); // just here to 'use' invocationResult to avoid a warning. // Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains($"'Functions.{functionName}' ({invocationResult}", StringComparison.OrdinalIgnoreCase)); } diff --git a/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs b/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs index 2eedeb61f..be132df86 100644 --- a/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs +++ b/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs @@ -17,11 +17,11 @@ namespace Microsoft.Azure.Functions.Tests.E2ETests { public class FunctionAppFixture : IAsyncLifetime { + private readonly string _testApp = Constants.TestAppNames.E2EApp; private readonly ILogger _logger; private bool _disposed; private Process _funcProcess; private JobObjectRegistry _jobObjectRegistry; - private string _testApp = Constants.TestAppNames.E2EApp; public FunctionAppFixture(IMessageSink messageSink) { @@ -32,7 +32,8 @@ public FunctionAppFixture(IMessageSink messageSink) _logger = loggerFactory.CreateLogger(); } - internal FunctionAppFixture(IMessageSink messageSink, string testApp) : this(messageSink) + internal FunctionAppFixture(IMessageSink messageSink, string testApp) + : this(messageSink) { _testApp = testApp; } diff --git a/test/Sdk.E2ETests/InnerBuildTests.cs b/test/Sdk.E2ETests/InnerBuildTests.cs index e38822c14..455ec7307 100644 --- a/test/Sdk.E2ETests/InnerBuildTests.cs +++ b/test/Sdk.E2ETests/InnerBuildTests.cs @@ -1,6 +1,7 @@ // 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.IO; using System.Threading.Tasks; using Newtonsoft.Json.Linq; @@ -9,25 +10,27 @@ namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public class InnerBuildTests + public sealed class InnerBuildTests(ITestOutputHelper testOutputHelper) : IDisposable { - private readonly ITestOutputHelper _testOutputHelper; + private readonly ProjectBuilder _builder = new( + testOutputHelper, + Path.Combine(TestUtility.TestResourcesProjectsRoot, "FunctionApp01", "FunctionApp01.csproj")); - public InnerBuildTests(ITestOutputHelper testOutputHelper) + [Theory] + [InlineData("", false)] + [InlineData("-p:FunctionsEnableWorkerIndexing=true", false)] + [InlineData("-p:FunctionsEnableWorkerIndexing=true -p:FunctionsWriteMetadataJson=false", false)] + [InlineData("-p:FunctionsEnableWorkerIndexing=true -p:FunctionsWriteMetadataJson=true", true)] + [InlineData("-p:FunctionsEnableWorkerIndexing=false", true)] + [InlineData("-p:FunctionsEnableWorkerIndexing=false -p:FunctionsWriteMetadataJson=false", false)] + [InlineData("-p:FunctionsEnableWorkerIndexing=false -p:FunctionsWriteMetadataJson=true", true)] + public async Task Build_ScansReferences(string parameters, bool metadataGenerated) { - _testOutputHelper = testOutputHelper; - } - - [Fact] - public async Task Build_ScansReferences() - { - string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Build_ScansReferences)); - string projectFileDirectory = Path.Combine(TestUtility.TestResourcesProjectsRoot, "FunctionApp01", "FunctionApp01.csproj"); - - await TestUtility.RestoreAndBuildProjectAsync(projectFileDirectory, outputDir, null, _testOutputHelper); + await _builder.RestoreAsync(); + await _builder.BuildAsync(parameters, restore: false); // Verify extensions.json contents - string extensionsJsonPath = Path.Combine(outputDir, "extensions.json"); + string extensionsJsonPath = Path.Combine(_builder.OutputPath, "extensions.json"); Assert.True(File.Exists(extensionsJsonPath)); JToken extensionsJsonContents = JObject.Parse(File.ReadAllText(extensionsJsonPath)); @@ -54,8 +57,13 @@ public async Task Build_ScansReferences() Assert.True(JToken.DeepEquals(expectedExtensionsJson, extensionsJsonContents)); // Verify functions.metadata contents - string functionsMetadataPath = Path.Combine(outputDir, "functions.metadata"); - Assert.True(File.Exists(functionsMetadataPath)); + string functionsMetadataPath = Path.Combine(_builder.OutputPath, "functions.metadata"); + Assert.Equal(metadataGenerated, File.Exists(functionsMetadataPath)); + + if (!metadataGenerated) + { + return; + } JToken functionsMetadataContents = JArray.Parse(File.ReadAllText(functionsMetadataPath)); JToken expectedFunctionsMetadata = JArray.Parse(@"[ @@ -115,5 +123,7 @@ public async Task Build_ScansReferences() Assert.True(JToken.DeepEquals(expectedFunctionsMetadata, functionsMetadataContents)); } + + public void Dispose() => _builder.Dispose(); } } diff --git a/test/Sdk.E2ETests/ProcessWrapper.cs b/test/Sdk.E2ETests/ProcessWrapper.cs index ae250e4ae..eb04f284b 100644 --- a/test/Sdk.E2ETests/ProcessWrapper.cs +++ b/test/Sdk.E2ETests/ProcessWrapper.cs @@ -6,26 +6,27 @@ using System.Text; using System.Threading; using System.Threading.Tasks; -using Xunit.Abstractions; namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public class ProcessWrapper + public static class ProcessWrapper { - - public async Task RunProcess(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null) + public static async Task RunProcessAsync( + string fileName, string arguments, string workingDirectory = null, Action log = null) { - return await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper); + return await RunProcessInternalAsync(fileName, arguments, workingDirectory, log); } - public async Task> RunProcessForOutput(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null) + public static async Task> RunProcessForOutputAsync( + string fileName, string arguments, string workingDirectory = null, Action log = null) { StringBuilder processOutputStringBuilder = new StringBuilder(); - var exitCode = await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper, processOutputStringBuilder); + var exitCode = await RunProcessInternalAsync(fileName, arguments, workingDirectory, log, processOutputStringBuilder); return new Tuple(exitCode, processOutputStringBuilder.ToString()); } - private async Task RunProcessInternal(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null, StringBuilder processOutputBuilder = null) + private static async Task RunProcessInternalAsync( + string fileName, string arguments, string workingDirectory = null, Action log = null, StringBuilder processOutputBuilder = null) { SemaphoreSlim processExitSemaphore = new SemaphoreSlim(0, 1); @@ -53,11 +54,8 @@ public class ProcessWrapper { if (o.Data != null) { - testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] Error: {o.Data}"); - if (processOutputBuilder != null) - { - processOutputBuilder.AppendLine(o.Data); - } + log?.Invoke($"[{DateTime.UtcNow:O}] Error: {o.Data}"); + processOutputBuilder?.AppendLine(o.Data); } }; @@ -65,11 +63,8 @@ public class ProcessWrapper { if (o.Data != null) { - testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] {o.Data}"); - if (processOutputBuilder != null) - { - processOutputBuilder.AppendLine(o.Data); - } + log?.Invoke($"[{DateTime.UtcNow:O}] {o.Data}"); + processOutputBuilder?.AppendLine(o.Data); } }; @@ -81,7 +76,7 @@ public class ProcessWrapper int wait = 3 * 60 * 1000; if (!await processExitSemaphore.WaitAsync(wait)) { - testOutputHelper?.WriteLine($"Process '{testProcess.Id}' did not exit in {wait}ms."); + log?.Invoke($"Process '{testProcess.Id}' did not exit in {wait}ms."); testProcess.Kill(); } diff --git a/test/Sdk.E2ETests/ProjectBuilder.cs b/test/Sdk.E2ETests/ProjectBuilder.cs new file mode 100644 index 000000000..9fff6b893 --- /dev/null +++ b/test/Sdk.E2ETests/ProjectBuilder.cs @@ -0,0 +1,106 @@ +// 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.Diagnostics; +using System.IO; +using System.Runtime.CompilerServices; +using System.Threading; +using System.Threading.Tasks; +using Xunit; +using Xunit.Abstractions; + +namespace Microsoft.Azure.Functions.Sdk.E2ETests +{ + public sealed class ProjectBuilder(ITestOutputHelper logger, string project) : IDisposable + { +#if DEBUG + public const string Configuration = "Debug"; +#elif RELEASE + public const string Configuration = "Release"; +#endif + public static readonly string LocalPackages = Path.Combine(TestUtility.PathToRepoRoot, "local"); + public static readonly string SrcRoot = Path.Combine(TestUtility.PathToRepoRoot, "src"); + public static readonly string SdkSolutionRoot = Path.Combine(TestUtility.PathToRepoRoot, "sdk"); + public static readonly string SdkProjectRoot = Path.Combine(SdkSolutionRoot, "Sdk"); + public static readonly string DotNetExecutable = "dotnet"; + public static readonly string SdkVersion = "99.99.99-test"; + public static readonly string SdkBuildProj = Path.Combine(TestUtility.PathToRepoRoot, "build", "Sdk.slnf"); + public static readonly string NuGetOrgPackages = "https://api.nuget.org/v3/index.json"; + + private static Task _initialization; + private static object _sync; + + private readonly TempDirectory _tempDirectory = new(); + + public string OutputPath => _tempDirectory.Path; + + public async Task RestoreAsync() + { + await LazyInitializer.EnsureInitialized(ref _initialization, ref _sync, InitializeAsync); + logger.WriteLine("Restoring..."); + string dotnetArgs = $"restore {project} -s {NuGetOrgPackages} -s {LocalPackages} -p:SdkVersion={SdkVersion}"; + Stopwatch stopwatch = Stopwatch.StartNew(); + int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, dotnetArgs, log: logger.WriteLine); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + logger.WriteLine($"Done. ({stopwatch.ElapsedMilliseconds} ms)"); + } + + public async Task BuildAsync(string additionalParams = null, bool restore = true) + { + await LazyInitializer.EnsureInitialized(ref _initialization, ref _sync, InitializeAsync); + + Stopwatch stopwatch = Stopwatch.StartNew(); + logger.WriteLine("Building..."); + string dotnetArgs = $"build {project} -c {Configuration} -o {OutputPath} -p:SdkVersion={SdkVersion} {additionalParams}"; + + if (!restore) + { + dotnetArgs += " --no-restore"; + } + + if (Debugger.IsAttached) + { + dotnetArgs += " -bl"; + } + + int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, dotnetArgs, log: logger.WriteLine); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + logger.WriteLine($"Done. ({stopwatch.ElapsedMilliseconds} ms)"); + } + + public async Task PublishAsync(string additionalParams = null, bool restore = true) + { + await LazyInitializer.EnsureInitialized(ref _initialization, ref _sync, InitializeAsync); + + Stopwatch stopwatch = Stopwatch.StartNew(); + logger.WriteLine($"Publishing..."); + string dotnetArgs = $"publish {project} -c {Configuration} -o {OutputPath} -p:SdkVersion={SdkVersion} {additionalParams}"; + + if (!restore) + { + dotnetArgs += " --no-restore"; + } + + if (Debugger.IsAttached) + { + dotnetArgs += " -bl"; + } + + int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, dotnetArgs, log: logger.WriteLine); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + logger.WriteLine($"Done. ({stopwatch.ElapsedMilliseconds} ms)"); + } + + private async Task InitializeAsync() + { + logger.WriteLine($"Packing {SdkBuildProj} with version {SdkVersion}"); + string arguments = $"pack {SdkBuildProj} -c {Configuration} -o {LocalPackages} -p:Version={SdkVersion}"; + + int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, arguments, SrcRoot, logger.WriteLine); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + } + + public void Dispose() => _tempDirectory.Dispose(); + } +} diff --git a/test/Sdk.E2ETests/PublishTests.cs b/test/Sdk.E2ETests/PublishTests.cs index d707922e2..9f3cb6544 100644 --- a/test/Sdk.E2ETests/PublishTests.cs +++ b/test/Sdk.E2ETests/PublishTests.cs @@ -11,27 +11,20 @@ namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public class PublishTests + public sealed class PublishTests(ITestOutputHelper testOutputHelper) : IDisposable { - private ITestOutputHelper _testOutputHelper; - - public PublishTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - - [Fact] - public async Task Publish() - { - string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish)); - await RunPublishTest(outputDir); - } - - [Fact] - public async Task Publish_Rid() + private readonly ProjectBuilder _builder = new( + testOutputHelper, + Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj")); + + [Theory] + [InlineData("", false)] + [InlineData("-r win-x86", false)] + [InlineData("-p:FunctionsEnableWorkerIndexing=false", true)] + [InlineData("-p:FunctionsEnableWorkerIndexing=false -r win-x86", true)] + public async Task Publish(string parameters, bool metadataGenerated) { - string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Rid)); - await RunPublishTest(outputDir, "-r win-x86"); + await RunPublishTest(parameters, metadataGenerated); } [Fact] @@ -41,45 +34,51 @@ public async Task Publish_Rid() [Trait("Requirement", "Docker")] public async Task Publish_Container() { - string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Container)); - var repository = nameof(Sdk.E2ETests).ToLower(); + var repository = "sdk." + nameof(E2ETests).ToLower(); var imageTag = nameof(Publish_Container); // setup test environment state in case there is leftover data from previous runs - await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper); + await TestUtility.RemoveDockerTestImage(repository, imageTag, testOutputHelper); - // perform the publish - await RunPublishTest(outputDir, $"--no-restore /t:PublishContainer --property:ContainerRepository={repository} --property:ContainerImageTag={imageTag}"); - - // validate the image base - Tuple inspectResults = await new ProcessWrapper().RunProcessForOutput("docker", $"inspect {repository}:{imageTag} --format \"{{{{ index .Config.Labels \\\"org.opencontainers.image.base.name\\\"}}}}\"", outputDir, _testOutputHelper); - var inspectExitCode = inspectResults.Item1; - var inspectOutput = inspectResults.Item2; - Assert.True(inspectExitCode.HasValue && inspectExitCode.Value == 0); - Assert.Matches("mcr\\.microsoft\\.com/azure-functions/dotnet-isolated:(\\d)+-dotnet-isolated(\\d+\\.\\d+)", inspectOutput); - - // clean up - await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper); + try + { + // perform the publish + await RunPublishTest($"-t:PublishContainer -p:ContainerRepository={repository} -p:ContainerImageTag={imageTag}", false); + + // validate the image base + Tuple inspectResults = await ProcessWrapper.RunProcessForOutputAsync( + "docker", + $"inspect {repository}:{imageTag} --format \"{{{{ index .Config.Labels \\\"org.opencontainers.image.base.name\\\"}}}}\"", + _builder.OutputPath, + testOutputHelper.WriteLine); + + var inspectExitCode = inspectResults.Item1; + var inspectOutput = inspectResults.Item2; + Assert.True(inspectExitCode.HasValue && inspectExitCode.Value == 0); + Assert.Matches("mcr\\.microsoft\\.com/azure-functions/dotnet-isolated:(\\d)+-dotnet-isolated(\\d+\\.\\d+)", inspectOutput); + } + finally + { + // clean up + await TestUtility.RemoveDockerTestImage(repository, imageTag, testOutputHelper); + } } - private async Task RunPublishTest(string outputDir, string additionalParams = null) + private async Task RunPublishTest(string additionalParams, bool metadataGenerated) { - // Name of the csproj - string projectFileDirectory = Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj"); - - await TestUtility.RestoreAndPublishProjectAsync(projectFileDirectory, outputDir, additionalParams, _testOutputHelper); + await _builder.PublishAsync(additionalParams); // Make sure files are in /.azurefunctions - string azureFunctionsDir = Path.Combine(outputDir, ".azurefunctions"); + string azureFunctionsDir = Path.Combine(_builder.OutputPath, ".azurefunctions"); Assert.True(Directory.Exists(azureFunctionsDir)); // Verify files are present string metadataLoaderPath = Path.Combine(azureFunctionsDir, "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"); - string extensionsJsonPath = Path.Combine(outputDir, "extensions.json"); - string functionsMetadataPath = Path.Combine(outputDir, "functions.metadata"); - Assert.True(File.Exists(metadataLoaderPath)); + string extensionsJsonPath = Path.Combine(_builder.OutputPath, "extensions.json"); + string functionsMetadataPath = Path.Combine(_builder.OutputPath, "functions.metadata"); Assert.True(File.Exists(extensionsJsonPath)); - Assert.True(File.Exists(functionsMetadataPath)); + Assert.True(File.Exists(metadataLoaderPath)); + Assert.Equal(metadataGenerated, File.Exists(functionsMetadataPath)); // Verify extensions.json JObject jObjects = JObject.Parse(File.ReadAllText(extensionsJsonPath)); @@ -102,26 +101,24 @@ private async Task RunPublishTest(string outputDir, string additionalParams = nu Assert.True(JToken.DeepEquals(extensionsJsonContents, expected), $"Actual: {extensionsJsonContents}{Environment.NewLine}Expected: {expected}"); // Verify functions.metadata - TestUtility.ValidateFunctionsMetadata(functionsMetadataPath, "Microsoft.Azure.Functions.Sdk.E2ETests.Contents.functions.metadata"); - } - - private class Extension - { - public Extension(string name, string typeName, string hintPath) + if (metadataGenerated) { - Name = name; - TypeName = typeName; - HintPath = hintPath; + TestUtility.ValidateFunctionsMetadata(functionsMetadataPath, "Microsoft.Azure.Functions.Sdk.E2ETests.Contents.functions.metadata"); } + } + + public void Dispose() => _builder.Dispose(); + private class Extension(string name, string typeName, string hintPath) + { [JsonProperty("name")] - public string Name { get; set; } + public string Name { get; set; } = name; [JsonProperty("typeName")] - public string TypeName { get; set; } + public string TypeName { get; set; } = typeName; [JsonProperty("hintPath")] - public string HintPath { get; set; } + public string HintPath { get; set; } = hintPath; } } } diff --git a/test/Sdk.E2ETests/TempDirectory.cs b/test/Sdk.E2ETests/TempDirectory.cs new file mode 100644 index 000000000..8afa936f8 --- /dev/null +++ b/test/Sdk.E2ETests/TempDirectory.cs @@ -0,0 +1,41 @@ +// 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.IO; +using IOPath = System.IO.Path; + +namespace Microsoft.Azure.Functions.Sdk.E2ETests +{ + public sealed class TempDirectory : IDisposable + { + public TempDirectory() : this(IOPath.Combine(IOPath.GetTempPath(), IOPath.GetRandomFileName())) + { + } + + public TempDirectory(string path) + { + ArgumentNullException.ThrowIfNull(path); + Path = path; + + if (!Directory.Exists(Path)) + { + Directory.CreateDirectory(Path); + } + } + + public string Path { get; } + + public void Dispose() + { + try + { + Directory.Delete(Path, true); + } + catch (IOException) + { + // Ignore IO exceptions during cleanup + } + } + } +} diff --git a/test/Sdk.E2ETests/TestUtility.cs b/test/Sdk.E2ETests/TestUtility.cs index b1217ad3f..26f0b6a98 100644 --- a/test/Sdk.E2ETests/TestUtility.cs +++ b/test/Sdk.E2ETests/TestUtility.cs @@ -26,120 +26,29 @@ public static class TestUtility public const string Net50 = "net5.0"; // Paths and executables - public static readonly string DotNetExecutable = "dotnet"; - public static readonly string PathToRepoRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../")); - public static readonly string SrcRoot = Path.Combine(PathToRepoRoot, "src"); - public static readonly string SdkSolutionRoot = Path.Combine(PathToRepoRoot, "sdk"); - public static readonly string SdkProjectRoot = Path.Combine(SdkSolutionRoot, "Sdk"); + public static readonly string PathToRepoRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, @"../../../../../")); public static readonly string TestRoot = Path.Combine(PathToRepoRoot, "test"); public static readonly string SamplesRoot = Path.Combine(PathToRepoRoot, "samples"); - public static readonly string LocalPackages = Path.Combine(PathToRepoRoot, "local"); - public static readonly string TestOutputDir = Path.Combine(Path.GetTempPath(), "FunctionsWorkerSdk.E2ETests"); public static readonly string TestResourcesProjectsRoot = Path.Combine(TestRoot, "Resources", "Projects"); - public static readonly string NuGetOrgPackages = "https://api.nuget.org/v3/index.json"; - public static readonly string NuGetPackageSource = LocalPackages; - public static readonly string SdkVersion = "99.99.99-test"; - public static readonly string SdkBuildProj = Path.Combine(PathToRepoRoot, "build", "Sdk.slnf"); - - private static bool _isInitialized = false; - - public static async Task InitializeTestAsync(ITestOutputHelper testOutputHelper, string testName) - { - if (!_isInitialized) - { - testOutputHelper.WriteLine($"Packing {SdkBuildProj} with version {SdkVersion}"); - string arguments = $"pack {SdkBuildProj} -c {Configuration} -o {LocalPackages} -p:Version={SdkVersion}"; - - int? exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, arguments, SrcRoot, testOutputHelper); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - - _isInitialized = true; - } - - return InitializeOutputDir(testName); - } - public static void ValidateFunctionsMetadata(string actualFilePath, string embeddedResourceName) { JToken functionsMetadataContents = JToken.Parse(File.ReadAllText(actualFilePath)); var assembly = Assembly.GetExecutingAssembly(); string resourceName = assembly.GetManifestResourceNames() .Single(str => str.EndsWith(embeddedResourceName)); - using (Stream stream = assembly.GetManifestResourceStream(resourceName)) - { - using (StreamReader reader = new StreamReader(stream)) - { - using (var jsonReader = new JsonTextReader(reader)) - { - JsonSerializer serializer = new JsonSerializer(); - var expected = serializer.Deserialize(jsonReader); - Assert.True(JToken.DeepEquals(functionsMetadataContents, expected), $"Actual: {functionsMetadataContents}{Environment.NewLine}Expected: {expected}"); - } - } - } - } - - public static async Task RestoreAndBuildProjectAsync(string fullPathToProjFile, string outputDir, string additionalParams, ITestOutputHelper outputHelper) - { - // Name of the csproj - string projectNameToTest = Path.GetFileName(fullPathToProjFile); - string projectFileDirectory = Path.GetDirectoryName(fullPathToProjFile); - - // Restore - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Restoring..."); - string dotnetArgs = $"restore {projectNameToTest} -s {NuGetOrgPackages} -s {LocalPackages} -p:SdkVersion={SdkVersion}"; - int? exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); - - // Build - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Building..."); - dotnetArgs = $"build {projectNameToTest} --configuration {Configuration} -o {outputDir} -p:SdkVersion={SdkVersion} {additionalParams}"; - exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); - } - - public static async Task RestoreAndPublishProjectAsync(string fullPathToProjFile, string outputDir, string additionalParams, ITestOutputHelper outputHelper) - { - // Name of the csproj - string projectNameToTest = Path.GetFileName(fullPathToProjFile); - string projectFileDirectory = Path.GetDirectoryName(fullPathToProjFile); - - // Restore - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Restoring..."); - string dotnetArgs = $"restore {projectNameToTest} -s {NuGetOrgPackages} -s {LocalPackages} -p:SdkVersion={SdkVersion}"; - int? exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); - - // Publish - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Publishing..."); - dotnetArgs = $"publish {projectNameToTest} --configuration {Configuration} -o {outputDir} -p:SdkVersion={SdkVersion} {additionalParams}"; - exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); - } - - private static string InitializeOutputDir(string testName) - { - string outputDir = Path.Combine(TestOutputDir, testName); - - if (Directory.Exists(outputDir)) - { - Directory.Delete(outputDir, recursive: true); - } - - Directory.CreateDirectory(outputDir); - - return outputDir; + using Stream stream = assembly.GetManifestResourceStream(resourceName); + using StreamReader reader = new StreamReader(stream); + using var jsonReader = new JsonTextReader(reader); + JsonSerializer serializer = new JsonSerializer(); + var expected = serializer.Deserialize(jsonReader); + Assert.True(JToken.DeepEquals(functionsMetadataContents, expected), $"Actual: {functionsMetadataContents}{Environment.NewLine}Expected: {expected}"); } public static async Task RemoveDockerTestImage(string repository, string imageTag, ITestOutputHelper outputHelper) { outputHelper.WriteLine($"Removing image {repository}:{imageTag} from local registry"); - int? rmiExitCode = await new ProcessWrapper().RunProcess("docker", $"rmi -f {repository}:{imageTag}", TestOutputDir, outputHelper); + int? rmiExitCode = await ProcessWrapper.RunProcessAsync("docker", $"rmi -f {repository}:{imageTag}", log: outputHelper.WriteLine); Assert.True(rmiExitCode.HasValue && rmiExitCode.Value == 0); // daemon may still error if the image doesn't exist, but it will still return 0 } } diff --git a/test/Sdk.E2ETests/ZipDeployTests.cs b/test/Sdk.E2ETests/ZipDeployTests.cs index 5d8c522a2..b683a5041 100644 --- a/test/Sdk.E2ETests/ZipDeployTests.cs +++ b/test/Sdk.E2ETests/ZipDeployTests.cs @@ -1,6 +1,5 @@ using System; using System.IO; -using System.Runtime.InteropServices; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.Zip; using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; @@ -9,14 +8,11 @@ namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public class ZipDeployTests + public sealed class ZipDeployTests(ITestOutputHelper testOutputHelper) : IDisposable { - private ITestOutputHelper _testOutputHelper; - - public ZipDeployTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } + private readonly ProjectBuilder _builder = new( + testOutputHelper, + Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj")); [Theory] [InlineData("linux-x64", true)] @@ -25,9 +21,7 @@ public ZipDeployTests(ITestOutputHelper testOutputHelper) public async Task CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContained(string rid, bool selfContained) { string testName = nameof(CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContained); - string directoryToZip = await TestUtility.InitializeTestAsync(_testOutputHelper, testName); - - string zipName = Path.Combine(Directory.GetParent(directoryToZip).FullName, $"{testName}.zip"); + string zipName = Path.Combine(Directory.GetParent(_builder.OutputPath).FullName, $"{testName}.zip"); if (File.Exists(zipName)) { @@ -36,13 +30,13 @@ public async Task CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContaine string projectFileDirectory = Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj"); - await TestUtility.RestoreAndPublishProjectAsync( - projectFileDirectory, directoryToZip, $"-r {rid} --self-contained {selfContained}", _testOutputHelper); + await _builder.PublishAsync($"-r {rid} --self-contained {selfContained}"); - CreateZipFileTask.CreateZipFileFromDirectory(directoryToZip, zipName); + CreateZipFileTask.CreateZipFileFromDirectory(_builder.OutputPath, zipName); using var zip = new ZipFile(zipName); - Assert.Equal(Directory.GetFiles(directoryToZip, "*", SearchOption.AllDirectories).Length, zip.Count); + Assert.Equal(Directory.GetFiles(_builder.OutputPath, "*", SearchOption.AllDirectories).Length, zip.Count); + foreach (ZipEntry entry in zip) { if (selfContained && (entry.Name == "FunctionApp" || entry.Name == "FunctionApp.exe")) @@ -64,6 +58,10 @@ await TestUtility.RestoreAndPublishProjectAsync( Assert.NotEqual(0, entry.ExternalFileAttributes); } } + + zip.Close(); } + + public void Dispose() => _builder.Dispose(); } } From ba0f4dc6e0318af9a493198179dc46a29afb7e57 Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Wed, 25 Jun 2025 09:59:53 -0700 Subject: [PATCH 146/190] Clear release notes (#3103) --- extensions/Worker.Extensions.EventHubs/release_notes.md | 4 ++-- extensions/Worker.Extensions.ServiceBus/release_notes.md | 4 ++-- extensions/Worker.Extensions.Tables/release_notes.md | 5 ++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/extensions/Worker.Extensions.EventHubs/release_notes.md b/extensions/Worker.Extensions.EventHubs/release_notes.md index aa498c751..3d6e918a8 100644 --- a/extensions/Worker.Extensions.EventHubs/release_notes.md +++ b/extensions/Worker.Extensions.EventHubs/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.5.0 +### Microsoft.Azure.Functions.Worker.Extensions.EventHubs -- Updating `Microsoft.Azure.WebJobs.Extensions.EventHubs` reference to 6.5.2 (#3098) +- diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index eb4cbfcb5..c92b7d33c 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.23.0 +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus -- Update dependency `Microsoft.Azure.WebJobs.Extensions.ServiceBus` to 5.17.0 (#3098) \ No newline at end of file +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.Tables/release_notes.md b/extensions/Worker.Extensions.Tables/release_notes.md index bffbc10ad..771cce0ca 100644 --- a/extensions/Worker.Extensions.Tables/release_notes.md +++ b/extensions/Worker.Extensions.Tables/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.5.0 +### Microsoft.Azure.Functions.Worker.Extensions.Tables -- Support deferred binding for poco types in Table Input binding (#3003) -- Update dependency `Microsoft.Azure.WebJobs.Extensions.Tables` to 1.4.0 (#3098) \ No newline at end of file +- \ No newline at end of file From 842276ea22342e722e8de1621e3f16084a7b0839 Mon Sep 17 00:00:00 2001 From: Jamie Magee Date: Wed, 16 Jul 2025 12:55:54 -0700 Subject: [PATCH 147/190] Add Dependabot configuration for .NET SDK updates (#3102) --- .github/dependabot.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..a1ef8b6a8 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,12 @@ +version: 2 +updates: + - package-ecosystem: "dotnet-sdk" + directory: "/" + schedule: + interval: "weekly" + day: "wednesday" + ignore: + - dependency-name: "*" + update-types: + - "version-update:semver-major" + - "version-update:semver-minor" From c26e8660c5d1326a9b3822f023df10ede121c22a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=BCrgen=20Steinblock?= Date: Thu, 17 Jul 2025 17:59:04 +0200 Subject: [PATCH 148/190] Fix ServiceBusMessageActions.cs AbandonMessageAsync doc inheritance (#3112) The AbandonMessageAsync method has a /// item, while it should inherit from `ServiceBusReceiver.AbandonMessageAsync` --- .../src/ServiceBusMessageActions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/Worker.Extensions.ServiceBus/src/ServiceBusMessageActions.cs b/extensions/Worker.Extensions.ServiceBus/src/ServiceBusMessageActions.cs index ad8bd4e47..f4b64825c 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/ServiceBusMessageActions.cs +++ b/extensions/Worker.Extensions.ServiceBus/src/ServiceBusMessageActions.cs @@ -81,7 +81,7 @@ public virtual async Task CompleteMessageAsync( await _settlement.CompleteAsync(new() { Locktoken = message.LockToken }, cancellationToken: cancellationToken); } - /// + /// public virtual async Task AbandonMessageAsync( ServiceBusReceivedMessage message, IDictionary? propertiesToModify = default, From d26b46f1a75883908d2367ae3700c3ef9be5fa47 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Tue, 22 Jul 2025 15:25:56 -0700 Subject: [PATCH 149/190] Fix steps indentation (#3117) --- eng/ci/host/official-release.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/eng/ci/host/official-release.yml b/eng/ci/host/official-release.yml index 8885134fd..dac00071a 100644 --- a/eng/ci/host/official-release.yml +++ b/eng/ci/host/official-release.yml @@ -94,13 +94,13 @@ extends: artifactName: $(artifact_name) pipeline: build - steps: - - task: 1ES.PublishNuget@1 - displayName: Publish packages - inputs: - packagesToPush: $(packages_pattern) - packageParentPath: $(drop_path) - publishVstsFeed: $(nuget_feed) - nuGetFeedType: internal - allowPackageConflicts: true - publishPackageMetadata: true + steps: + - task: 1ES.PublishNuget@1 + displayName: Publish packages + inputs: + packagesToPush: $(packages_pattern) + packageParentPath: $(drop_path) + publishVstsFeed: $(nuget_feed) + nuGetFeedType: internal + allowPackageConflicts: true + publishPackageMetadata: true From fe00d7cf39fb9c635edc6a713b675689ead93b6f Mon Sep 17 00:00:00 2001 From: Ciaran Liedeman <3578740+cliedeman@users.noreply.github.com> Date: Thu, 31 Jul 2025 17:11:18 +0200 Subject: [PATCH 150/190] Disable compiler warning CS0618 in DirectFunctionExecutor (#2952) * Disable compiler warning CS0618 in DirectFunctionExecutor * Use SymbolEqualityComparer * fix: removed hardcoded newline character * chore: feedback --- .../FunctionExecutorGenerator.Emitter.cs | 27 +++-- ...ionExecutorGenerator.ExecutableFunction.cs | 5 + .../FunctionExecutorGenerator.Parser.cs | 4 + sdk/Sdk.Generators/KnownTypes.cs | 4 + .../FunctionExecutorGeneratorTests.cs | 99 +++++++++++++++++++ 5 files changed, 129 insertions(+), 10 deletions(-) diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs index 022d5b676..199b4f61c 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs @@ -158,7 +158,7 @@ private static string GetMethodBody(IEnumerable functions, b if (string.Equals(context.FunctionDefinition.EntryPoint, "{{function.EntryPoint}}", StringComparison.Ordinal)) { - {{(fast ? EmitFastPath(function) : EmitSlowPath())}} + {{(fast ? EmitFastPath(function) : EmitSlowPath())}} return; } """); @@ -170,21 +170,22 @@ private static string GetMethodBody(IEnumerable functions, b private static string EmitFastPath(ExecutableFunction function) { var sb = new StringBuilder(); - + if (!function.IsStatic) { sb.Append($""" - var instanceType = types["{function.ParentFunctionClassName}"]; + var instanceType = types["{function.ParentFunctionClassName}"]; var i = _functionActivator.CreateInstance(instanceType, context) as {function.ParentFunctionFullyQualifiedClassName}; + """); } - sb.Append(!function.IsStatic - ? """ - - - """ - : " "); + if (function.IsObsolete) + { + sb.AppendLine("#pragma warning disable CS0618"); + } + + sb.Append(" "); if (function.IsReturnValueAssignable) { @@ -210,13 +211,19 @@ private static string EmitFastPath(ExecutableFunction function) sb.Append(function.IsStatic ? $"{function.ParentFunctionFullyQualifiedClassName}.{function.MethodName}({methodParamsStr});" : $"i.{function.MethodName}({methodParamsStr});"); + + if (function.IsObsolete) + { + sb.Append(Constants.NewLine); + sb.Append("#pragma warning restore CS0618"); + } return sb.ToString(); } private static string EmitSlowPath() { - return " await _defaultExecutor.Value.ExecuteAsync(context);"; + return " await _defaultExecutor.Value.ExecuteAsync(context);"; } } } diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs index 2dbcfe7b6..b9821b305 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.ExecutableFunction.cs @@ -63,5 +63,10 @@ internal class ExecutableFunction /// ex: FooAssembly, Version=1.2.3.4, Culture=neutral, PublicKeyToken=9475d07f10cb09df /// internal string AssemblyIdentity { get; set; } = null!; + + /// + /// Gets or sets if the function is Obsolete. + /// + internal bool IsObsolete { get; set; } } } diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs index fd6c570fc..c4b0b747f 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Parser.cs @@ -42,6 +42,9 @@ internal ICollection GetFunctions(IEnumerable var defaultFormatClassName = method.ContainingSymbol.ToDisplayString(); var fullyQualifiedClassName = method.ContainingSymbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat); + var isObsolete = method.GetAttributes() + .Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, _knownTypes.ObsoleteAttr)); + var function = new ExecutableFunction { EntryPoint = $"{defaultFormatClassName}.{method.Name}", @@ -54,6 +57,7 @@ internal ICollection GetFunctions(IEnumerable ParentFunctionFullyQualifiedClassName = fullyQualifiedClassName, Visibility = method.GetVisibility(), AssemblyIdentity = method.ContainingAssembly.Identity.GetDisplayName(), + IsObsolete = isObsolete, }; functionList.Add(function); diff --git a/sdk/Sdk.Generators/KnownTypes.cs b/sdk/Sdk.Generators/KnownTypes.cs index fc32225cc..81321ef38 100644 --- a/sdk/Sdk.Generators/KnownTypes.cs +++ b/sdk/Sdk.Generators/KnownTypes.cs @@ -27,6 +27,7 @@ internal readonly struct KnownTypes private readonly Lazy _readOnlyMemoryOfBytes; private readonly Lazy _lookupGeneric; private readonly Lazy _dictionaryGeneric; + private readonly Lazy _obsoleteAttr; internal KnownTypes(Compilation compilation) { @@ -44,6 +45,7 @@ internal KnownTypes(Compilation compilation) _readOnlyMemoryOfBytes = new Lazy(() => compilation.GetTypeByMetadataName(typeof(ReadOnlyMemory).FullName)!); _lookupGeneric = new Lazy(() => compilation.GetTypeByMetadataName(typeof(ILookup<,>).FullName)!); _dictionaryGeneric = new Lazy(() => compilation.GetTypeByMetadataName(typeof(IDictionary<,>).FullName)!); + _obsoleteAttr = new Lazy(() => compilation.GetTypeByMetadataName(typeof(ObsoleteAttribute).FullName)!); } public INamedTypeSymbol TaskType { get => _taskType.Value; } @@ -73,5 +75,7 @@ internal KnownTypes(Compilation compilation) public INamedTypeSymbol LookupGeneric { get => _lookupGeneric.Value; } public INamedTypeSymbol DictionaryGeneric { get => _dictionaryGeneric.Value; } + + public INamedTypeSymbol ObsoleteAttr { get => _obsoleteAttr.Value; } } } diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs index 289e8c2c5..dae5ca8db 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs @@ -816,5 +816,104 @@ public static IHostBuilder ConfigureGeneratedFunctionExecutor(this IHostBuilder } """; } + + [Theory] + [InlineData(LanguageVersion.CSharp7_3)] + [InlineData(LanguageVersion.CSharp8)] + [InlineData(LanguageVersion.CSharp9)] + [InlineData(LanguageVersion.CSharp10)] + [InlineData(LanguageVersion.CSharp11)] + [InlineData(LanguageVersion.Latest)] + public async Task ObsoleteFunction(LanguageVersion languageVersion) + { + const string inputSourceCode = @" +using System; +using System.Threading.Tasks; +using Microsoft.Extensions.Hosting; +using Azure.Storage.Queues.Models; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; +using Microsoft.Extensions.Logging; +namespace TestProject +{ + public class TestProject + { + [Function(""FunctionA"")] + [Obsolete(""Do not use"")] + public HttpResponseData Foo([HttpTrigger(AuthorizationLevel.User, ""get"")] HttpRequestData r, FunctionContext c) + { + return r.CreateResponse(System.Net.HttpStatusCode.OK); + } + + [Function(""FunctionB"")] + [Obsolete(""Do not use"")] + public static HttpResponseData FooStatic([HttpTrigger(AuthorizationLevel.User, ""get"")] HttpRequestData r, FunctionContext c) + { + return r.CreateResponse(System.Net.HttpStatusCode.OK); + } + } +} +"; + var expectedOutput = $@"// +using System; +using System.Threading.Tasks; +using System.Collections.Generic; +using Microsoft.Extensions.Hosting; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Context.Features; +using Microsoft.Azure.Functions.Worker.Invocation; +namespace TestProject +{{ + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {Constants.GeneratedCodeAttribute} + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor + {{ + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; + private readonly Dictionary types = new Dictionary() + {{ + {{ ""TestProject.TestProject"", Type.GetType(""TestProject.TestProject, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }} + }}; + + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) + {{ + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); + }} + + /// + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) + {{ + var inputBindingFeature = context.Features.Get(); + var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); + var inputArguments = inputBindingResult.Values; + + if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.Foo"", StringComparison.Ordinal)) + {{ + var instanceType = types[""TestProject.TestProject""]; + var i = _functionActivator.CreateInstance(instanceType, context) as global::TestProject.TestProject; +#pragma warning disable CS0618 + context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); +#pragma warning restore CS0618 + return; + }} + if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.FooStatic"", StringComparison.Ordinal)) + {{ +#pragma warning disable CS0618 + context.GetInvocationResult().Value = global::TestProject.TestProject.FooStatic((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); +#pragma warning restore CS0618 + return; + }} + }} + }} +{GetExpectedExtensionMethodCode()} +}}".Replace("'", "\""); + + await TestHelpers.RunTestAsync( + _referencedAssemblies, + inputSourceCode, + Constants.FileNames.GeneratedFunctionExecutor, + expectedOutput, + languageVersion: languageVersion); + } } } From 2efafa83f9c6e9371a6b6adb2fc366d15c53de23 Mon Sep 17 00:00:00 2001 From: Aishwarya Bhandari <37918412+aishwaryabh@users.noreply.github.com> Date: Fri, 8 Aug 2025 10:18:25 -0700 Subject: [PATCH 151/190] Adding support for running `dotnet run` after installing core tools thru npm (#3127) * adding windows target * updating release notes * addressing comments --- ...Microsoft.Azure.Functions.Worker.Sdk.targets | 17 ++++++++++++----- sdk/release_notes.md | 1 + 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index b08c2e352..8133074c8 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -106,12 +106,19 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - - func - host start $(RunArguments) - $(OutDir) + + + cmd + /C func start $(RunArguments) + $(OutDir) + + + + + func + start $(RunArguments) + $(OutDir) diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 3d4479236..fb9fe089c 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -7,6 +7,7 @@ ### Microsoft.Azure.Functions.Worker.Sdk - Build no longer generates `functions.metadata` if source-generated metadata provider is enabled. (#2974) +- Fixing `dotnet run` to work on Windows when core tools is installed from NPM (#3127) ### Microsoft.Azure.Functions.Worker.Sdk.Generators From 0a74914c7b1fe98d7d75c63b9a19852e32dcb569 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 12:13:56 -0700 Subject: [PATCH 152/190] Bump dotnet-sdk from 9.0.201 to 9.0.304 (#3129) Bumps [dotnet-sdk](https://github.com/dotnet/sdk) from 9.0.201 to 9.0.304. - [Release notes](https://github.com/dotnet/sdk/releases) - [Commits](https://github.com/dotnet/sdk/compare/v9.0.201...v9.0.304) --- updated-dependencies: - dependency-name: dotnet-sdk dependency-version: 9.0.304 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index c8f2593ac..03064daa1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.201", + "version": "9.0.304", "allowPrerelease": true, "rollForward": "latestFeature" }, From d0cf055d5fcff24e324cea9960dd680c2a98c0bf Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Mon, 25 Aug 2025 14:23:19 -0700 Subject: [PATCH 153/190] Adding .NET 10 issue template (#3153) --- .../02b-net10-question-or-issue.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/02b-net10-question-or-issue.yml diff --git a/.github/ISSUE_TEMPLATE/02b-net10-question-or-issue.yml b/.github/ISSUE_TEMPLATE/02b-net10-question-or-issue.yml new file mode 100644 index 000000000..a2b7b595b --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02b-net10-question-or-issue.yml @@ -0,0 +1,15 @@ +name: .NET 10 issue or question +description: Ask questions or raise issues related to .NET 10 +labels: [".NET 10"] +body: +- type: markdown + attributes: + value: | + Please use this template for any issues you have using .NET 10 or for any questions not answered in our [tracking thread for .NET 10 support](https://github.com/Azure/azure-functions-dotnet-worker/issues/3152). +- id: description + type: textarea + attributes: + label: Description + placeholder: Please provide a succinct description of the question or issue. For issue reports, please include the versions of the Azure Functions packages your projects references. + validations: + required: true \ No newline at end of file From d066058a0348f5c84b5ef9c2671ba87d2efd1c26 Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Wed, 27 Aug 2025 14:46:22 -0700 Subject: [PATCH 154/190] Fix Azure Functions logo URL in README.md (#3154) * Initial plan * Fix logo URL in README.md Co-authored-by: liliankasem <2198905+liliankasem@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: liliankasem <2198905+liliankasem@users.noreply.github.com> --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1375a8cbe..4ecf09044 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![Azure Functions Logo](https://raw.githubusercontent.com/Azure/azure-functions-cli/master/src/Azure.Functions.Cli/npm/assets/azure-functions-logo-color-raster.png) +![Azure Functions Logo](https://raw.githubusercontent.com/Azure/azure-functions-cli/refs/heads/main/eng/res/functions.png) |Branch|Status| |---|---| From 23110d03d772ebefae99ae0a265cdf856e9cdc4a Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Wed, 27 Aug 2025 15:13:58 -0700 Subject: [PATCH 155/190] Updating extension dependencies (#3155) --- .../Worker.Extensions.EventGrid/release_notes.md | 4 ++-- .../src/Worker.Extensions.EventGrid.csproj | 4 ++-- .../src/Worker.Extensions.Storage.Blobs.csproj | 6 +++--- .../src/Worker.Extensions.Storage.Queues.csproj | 4 ++-- .../Worker.Extensions.Storage/release_notes.md | 13 +++++++------ .../src/Worker.Extensions.Storage.csproj | 2 +- 6 files changed, 17 insertions(+), 16 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index 65290e0c6..f2aa5ff19 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.6.0 -- \ No newline at end of file +- Updating `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.5.0 (#3155) \ No newline at end of file diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index d45de0ec0..d4f94c919 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -6,7 +6,7 @@ Azure Event Grid extensions for .NET isolated functions - 3.5.0 + 3.6.0 false @@ -24,7 +24,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index b4c9ad017..6475cd6fd 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -6,7 +6,7 @@ Azure Blob Storage extensions for .NET isolated functions - 6.7.0 + 6.8.0 false @@ -20,7 +20,7 @@ - + @@ -29,7 +29,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj index 6333b6c85..7b4590d06 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj +++ b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj @@ -6,7 +6,7 @@ Azure Queue Storage extensions for .NET isolated functions - 5.5.2 + 5.5.3 false @@ -28,7 +28,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 4ab75b73f..32976bcb3 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,14 +4,15 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage +### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.8.0 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.5 (#3155) +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.5 (#3155) -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.8.0 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.5 (#3155) -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.5.3 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.5 (#3155) diff --git a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj index af4803771..6fbeccbaa 100644 --- a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj +++ b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj @@ -6,7 +6,7 @@ Azure Storage extensions for .NET isolated functions - 6.7.0 + 6.8.0 false From 64675cdfe8bfcfbdf59aa11b94e1f9ca6023ba73 Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Wed, 3 Sep 2025 15:46:45 -0700 Subject: [PATCH 156/190] Updating extension dependencies (Cosmos DB) (#3157) --- extensions/Worker.Extensions.CosmosDB/release_notes.md | 5 +++-- .../src/Worker.Extensions.CosmosDB.csproj | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index 921fdcf34..f0faef598 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,6 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.13.0 -- +- Update dependency `Microsoft.Azure.WebJobs.Extensions.CosmosDB` to 4.10.0 (#3157) +- Update dependency `Microsoft.Extensions.Azure` to 1.12.0 (#3157) diff --git a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj index b5cb4b712..8217dac2e 100644 --- a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj +++ b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj @@ -6,7 +6,7 @@ Azure Cosmos DB extensions for .NET isolated functions - 4.12.0 + 4.13.0 false @@ -21,7 +21,7 @@ - + @@ -31,7 +31,7 @@ - + \ No newline at end of file From 194d7849ce9097aab51ee6af9908c5d3398ffd7e Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Thu, 4 Sep 2025 10:32:16 -0700 Subject: [PATCH 157/190] Revert "Updating extension dependencies (#3155)" (#3159) This reverts commit 23110d03d772ebefae99ae0a265cdf856e9cdc4a. --- .../Worker.Extensions.EventGrid/release_notes.md | 4 ++-- .../src/Worker.Extensions.EventGrid.csproj | 4 ++-- .../src/Worker.Extensions.Storage.Blobs.csproj | 6 +++--- .../src/Worker.Extensions.Storage.Queues.csproj | 4 ++-- .../Worker.Extensions.Storage/release_notes.md | 13 ++++++------- .../src/Worker.Extensions.Storage.csproj | 2 +- 6 files changed, 16 insertions(+), 17 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index f2aa5ff19..65290e0c6 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.6.0 +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid -- Updating `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.5.0 (#3155) \ No newline at end of file +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index d4f94c919..d45de0ec0 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -6,7 +6,7 @@ Azure Event Grid extensions for .NET isolated functions - 3.6.0 + 3.5.0 false @@ -24,7 +24,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index 6475cd6fd..b4c9ad017 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -6,7 +6,7 @@ Azure Blob Storage extensions for .NET isolated functions - 6.8.0 + 6.7.0 false @@ -20,7 +20,7 @@ - + @@ -29,7 +29,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj index 7b4590d06..6333b6c85 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj +++ b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj @@ -6,7 +6,7 @@ Azure Queue Storage extensions for .NET isolated functions - 5.5.3 + 5.5.2 false @@ -28,7 +28,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 32976bcb3..4ab75b73f 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,15 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.8.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.5 (#3155) -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.5 (#3155) +- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.8.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.5 (#3155) +- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.5.3 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.5 (#3155) +- diff --git a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj index 6fbeccbaa..af4803771 100644 --- a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj +++ b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj @@ -6,7 +6,7 @@ Azure Storage extensions for .NET isolated functions - 6.8.0 + 6.7.0 false From c0f179a5981eae7568b2aece04c6fdecae065416 Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Thu, 4 Sep 2025 11:10:13 -0700 Subject: [PATCH 158/190] Updating extension dependencies (Event Grid) (#3160) --- extensions/Worker.Extensions.EventGrid/release_notes.md | 4 ++-- .../src/Worker.Extensions.EventGrid.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index 65290e0c6..bda5e6e80 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.6.0 -- \ No newline at end of file +- Updating `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.5.0 (#3160) \ No newline at end of file diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index d45de0ec0..d4f94c919 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj +++ b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj @@ -6,7 +6,7 @@ Azure Event Grid extensions for .NET isolated functions - 3.5.0 + 3.6.0 false @@ -24,7 +24,7 @@ - + \ No newline at end of file From c946a1245b89822aed3ef3e373965426479558c9 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 8 Sep 2025 09:40:00 -0700 Subject: [PATCH 159/190] Updating default file encoding configuration (#3147) --- .editorconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.editorconfig b/.editorconfig index 49de0d370..66212dc13 100644 --- a/.editorconfig +++ b/.editorconfig @@ -5,11 +5,11 @@ # All files [*] indent_style = space +charset = utf-8 # Code files [*.{cs,csx,vb,vbx}] indent_size = 4 insert_final_newline = true -charset = utf-8-bom ############################### # .NET Coding Conventions # ############################### From 00d012f4a110893cb29fd1425e7ae0f3c8a635de Mon Sep 17 00:00:00 2001 From: Matthew Henderson Date: Mon, 15 Sep 2025 11:35:52 -0700 Subject: [PATCH 160/190] Updating extension dependencies (Storage) (#3167) --- .../src/Worker.Extensions.Storage.Blobs.csproj | 6 +++--- .../src/Worker.Extensions.Storage.Queues.csproj | 4 ++-- .../Worker.Extensions.Storage/release_notes.md | 15 +++++++++------ .../src/Worker.Extensions.Storage.csproj | 2 +- 4 files changed, 15 insertions(+), 12 deletions(-) diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj index b4c9ad017..5773fd59e 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Worker.Extensions.Storage.Blobs.csproj @@ -6,7 +6,7 @@ Azure Blob Storage extensions for .NET isolated functions - 6.7.0 + 6.8.0 false @@ -20,7 +20,7 @@ - + @@ -29,7 +29,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj index 6333b6c85..8ca17684f 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj +++ b/extensions/Worker.Extensions.Storage.Queues/src/Worker.Extensions.Storage.Queues.csproj @@ -6,7 +6,7 @@ Azure Queue Storage extensions for .NET isolated functions - 5.5.2 + 5.5.3 false @@ -28,7 +28,7 @@ - + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 4ab75b73f..4c0fae339 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,14 +4,17 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage +### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.8.0 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.6 (#3167) +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.6 (#3167) +- Update dependency `Microsoft.Extensions.Azure` to 1.12.0 (#3167) -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.8.0 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.6 (#3167) +- Update dependency `Microsoft.Extensions.Azure` to 1.12.0 (#3167) -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.5.3 -- +- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.6 (#3167) diff --git a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj index af4803771..6fbeccbaa 100644 --- a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj +++ b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj @@ -6,7 +6,7 @@ Azure Storage extensions for .NET isolated functions - 6.7.0 + 6.8.0 false From f2f4165af3136d8671b2c3d7bdaa366e8b94c45f Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Tue, 16 Sep 2025 10:52:57 -0700 Subject: [PATCH 161/190] Clear release notes (#3168) --- .../Worker.Extensions.CosmosDB/release_notes.md | 5 ++--- .../Worker.Extensions.EventGrid/release_notes.md | 4 ++-- .../Worker.Extensions.Storage/release_notes.md | 15 ++++++--------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index f0faef598..921fdcf34 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.13.0 +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB -- Update dependency `Microsoft.Azure.WebJobs.Extensions.CosmosDB` to 4.10.0 (#3157) -- Update dependency `Microsoft.Extensions.Azure` to 1.12.0 (#3157) +- diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index bda5e6e80..755c456b7 100644 --- a/extensions/Worker.Extensions.EventGrid/release_notes.md +++ b/extensions/Worker.Extensions.EventGrid/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventGrid 3.6.0 +### Microsoft.Azure.Functions.Worker.Extensions.EventGrid -- Updating `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.5.0 (#3160) \ No newline at end of file +- \ No newline at end of file diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 4c0fae339..b47906b12 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,17 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.8.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.6 (#3167) -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.6 (#3167) -- Update dependency `Microsoft.Extensions.Azure` to 1.12.0 (#3167) +- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.8.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` reference to 5.3.6 (#3167) -- Update dependency `Microsoft.Extensions.Azure` to 1.12.0 (#3167) +- -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.5.3 +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues -- Updating `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` reference to 5.3.6 (#3167) +- \ No newline at end of file From 06e630240a14704b228f3606f1953ec2305ad570 Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Wed, 17 Sep 2025 15:26:53 -0700 Subject: [PATCH 162/190] Implementing function metadata transform support (#3145) * Implementing function metadata transform support * Updates to metadata transform feature --------- Co-authored-by: Fabio Cavalcante --- release_notes.md | 4 +- .../DefaultFunctionMetadataManager.cs | 62 ++++++++++++ .../IFunctionMetadataManager.cs | 20 ++++ .../IFunctionMetadataTransformer.cs | 24 +++++ .../Hosting/ServiceCollectionExtensions.cs | 5 +- src/DotNetWorker.Grpc/GrpcWorker.cs | 10 +- .../DefaultFunctionMetadataManagerTests.cs | 99 +++++++++++++++++++ test/DotNetWorkerTests/GrpcWorkerTests.cs | 4 +- 8 files changed, 217 insertions(+), 11 deletions(-) create mode 100644 src/DotNetWorker.Core/FunctionMetadata/DefaultFunctionMetadataManager.cs create mode 100644 src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataManager.cs create mode 100644 src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataTransformer.cs create mode 100644 test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs diff --git a/release_notes.md b/release_notes.md index 173ffd02f..74db65101 100644 --- a/release_notes.md +++ b/release_notes.md @@ -10,8 +10,8 @@ ### Microsoft.Azure.Functions.Worker.Core -- +- Support for function metadata transforms (#3145) ### Microsoft.Azure.Functions.Worker.Grpc -- +- Updated to use the new metadata manage and leverage metadata transforms (#3145) diff --git a/src/DotNetWorker.Core/FunctionMetadata/DefaultFunctionMetadataManager.cs b/src/DotNetWorker.Core/FunctionMetadata/DefaultFunctionMetadataManager.cs new file mode 100644 index 000000000..ff4e03cb4 --- /dev/null +++ b/src/DotNetWorker.Core/FunctionMetadata/DefaultFunctionMetadataManager.cs @@ -0,0 +1,62 @@ +// 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.Collections.Immutable; +using System.Linq; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Azure.Functions.Worker.Core.FunctionMetadata +{ + internal sealed class DefaultFunctionMetadataManager : IFunctionMetadataManager + { + private readonly IFunctionMetadataProvider _functionMetadataProvider; + private readonly ImmutableArray _transformers; + private readonly ILogger _logger; + + public DefaultFunctionMetadataManager(IFunctionMetadataProvider functionMetadataProvider, + IEnumerable transformers, + ILogger logger) + { + _functionMetadataProvider = functionMetadataProvider; + _transformers = transformers.ToImmutableArray(); + _logger = logger; + } + + public async Task> GetFunctionMetadataAsync(string directory) + { + ImmutableArray functionMetadata = await _functionMetadataProvider.GetFunctionMetadataAsync(directory); + + return ApplyTransforms(functionMetadata); + } + + private ImmutableArray ApplyTransforms(ImmutableArray functionMetadata) + { + // Return early if there are no transformers to apply + if (_transformers.Length == 0) + { + return functionMetadata; + } + + var metadataResult = functionMetadata.ToBuilder(); + + foreach (var transformer in _transformers) + { + try + { + _logger?.LogTrace("Applying metadata transformer: {Transformer}.", transformer.Name); + transformer.Transform(metadataResult); + } + catch (Exception exc) + { + _logger?.LogError(exc, "Metadata transformer '{Transformer}' failed.", transformer.Name); + throw; + } + } + + return metadataResult.ToImmutable(); + } + } +} diff --git a/src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataManager.cs b/src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataManager.cs new file mode 100644 index 000000000..c81c26070 --- /dev/null +++ b/src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataManager.cs @@ -0,0 +1,20 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Collections.Immutable; +using System.Threading.Tasks; + +namespace Microsoft.Azure.Functions.Worker.Core.FunctionMetadata +{ + /// + /// Manages function metadata, providing functionality that combines metadata from the registered provider and metadata transforms. + /// + public interface IFunctionMetadataManager + { + /// + /// Retrieves all function metadata for the current application. + /// + /// A representing the asynchronous metadata retrieval operation, where the result is an . + Task> GetFunctionMetadataAsync(string directory); + } +} diff --git a/src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataTransformer.cs b/src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataTransformer.cs new file mode 100644 index 000000000..98cdfdd42 --- /dev/null +++ b/src/DotNetWorker.Core/FunctionMetadata/IFunctionMetadataTransformer.cs @@ -0,0 +1,24 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Collections.Generic; + +namespace Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; + +/// +/// Defines a contract for transforming instances for Azure Functions. +/// Implementations can modify, augment, or filter function metadata before it is used by the host. +/// +public interface IFunctionMetadataTransformer +{ + /// + /// Gets the name of the transformer. + /// + public string Name { get; } + + /// + /// Transforms the provided collection of instances. + /// + /// The original collection of function metadata. This collection may be modified. + void Transform(IList original); +} diff --git a/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs b/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs index 8ee1643de..daf3fca75 100644 --- a/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs +++ b/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs @@ -10,13 +10,13 @@ using Microsoft.Azure.Functions.Worker.Context.Features; using Microsoft.Azure.Functions.Worker.Converters; using Microsoft.Azure.Functions.Worker.Core; +using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; using Microsoft.Azure.Functions.Worker.Diagnostics; using Microsoft.Azure.Functions.Worker.Invocation; using Microsoft.Azure.Functions.Worker.Logging; using Microsoft.Azure.Functions.Worker.OutputBindings; using Microsoft.Azure.Functions.Worker.Pipeline; using Microsoft.Extensions.DependencyInjection.Extensions; -using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; @@ -71,6 +71,9 @@ public static IFunctionsWorkerApplicationBuilder AddFunctionsWorkerCore(this ISe // Worker initialization service services.AddHostedService(); + // Worker metadata management + services.TryAddSingleton(); + // Default serializer settings services.AddOptions(); services.TryAddEnumerable(ServiceDescriptor.Transient, WorkerOptionsSetup>()); diff --git a/src/DotNetWorker.Grpc/GrpcWorker.cs b/src/DotNetWorker.Grpc/GrpcWorker.cs index 581cfce78..4dc19e081 100644 --- a/src/DotNetWorker.Grpc/GrpcWorker.cs +++ b/src/DotNetWorker.Grpc/GrpcWorker.cs @@ -4,7 +4,6 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text.RegularExpressions; using System.Threading; @@ -18,7 +17,6 @@ using Microsoft.Azure.Functions.Worker.Invocation; using Microsoft.Azure.Functions.Worker.Rpc; using Microsoft.Extensions.Hosting; -using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using MsgType = Microsoft.Azure.Functions.Worker.Grpc.Messages.StreamingMessage.ContentOneofCase; @@ -32,14 +30,14 @@ internal partial class GrpcWorker : IWorker, IMessageProcessor private readonly IHostApplicationLifetime _hostApplicationLifetime; private readonly IWorkerClientFactory _workerClientFactory; private readonly IInvocationHandler _invocationHandler; - private readonly IFunctionMetadataProvider _functionMetadataProvider; + private readonly IFunctionMetadataManager _metadataManager; private IWorkerClient? _workerClient; public GrpcWorker(IFunctionsApplication application, IWorkerClientFactory workerClientFactory, IMethodInfoLocator methodInfoLocator, IOptions workerOptions, - IFunctionMetadataProvider functionMetadataProvider, + IFunctionMetadataManager metadataManager, IHostApplicationLifetime hostApplicationLifetime, IInvocationHandler invocationHandler) { @@ -48,7 +46,7 @@ public GrpcWorker(IFunctionsApplication application, _application = application ?? throw new ArgumentNullException(nameof(application)); _methodInfoLocator = methodInfoLocator ?? throw new ArgumentNullException(nameof(methodInfoLocator)); _workerOptions = workerOptions.Value ?? throw new ArgumentNullException(nameof(workerOptions)); - _functionMetadataProvider = functionMetadataProvider ?? throw new ArgumentNullException(nameof(functionMetadataProvider)); + _metadataManager = metadataManager ?? throw new ArgumentNullException(nameof(metadataManager)); _invocationHandler = invocationHandler; } @@ -152,7 +150,7 @@ private async Task GetFunctionMetadataAsync(string fun try { - var functionMetadataList = await _functionMetadataProvider.GetFunctionMetadataAsync(functionAppDirectory); + var functionMetadataList = await _metadataManager.GetFunctionMetadataAsync(functionAppDirectory); foreach (var func in functionMetadataList) { diff --git a/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs b/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs new file mode 100644 index 000000000..c508b9a8b --- /dev/null +++ b/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.Collections.Immutable; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; +using Microsoft.Extensions.Logging; +using Moq; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Tests.FunctionMetadata +{ + public class DefaultFunctionMetadataManagerTests + { + [Fact] + public async Task GetFunctionMetadataAsync_ReturnsTransformedMetadata() + { + var mockProvider = new Mock(MockBehavior.Strict); + var mockTransformer = new Mock(MockBehavior.Strict); + var mockLogger = new Mock>(); + + var metadata = new List { new TestFunctionMetadata() }.ToImmutableArray(); + mockProvider.Setup(p => p.GetFunctionMetadataAsync(It.IsAny())).ReturnsAsync(metadata); + + mockTransformer.SetupGet(t => t.Name).Returns("TestTransformer"); + mockTransformer.Setup(t => t.Transform(It.IsAny>())); + + var manager = new DefaultFunctionMetadataManager( + mockProvider.Object, + new[] { mockTransformer.Object }, + mockLogger.Object); + + var result = await manager.GetFunctionMetadataAsync("test"); + + Assert.Single(result); + mockProvider.Verify(p => p.GetFunctionMetadataAsync("test"), Times.Once); + mockTransformer.Verify(t => t.Transform(It.IsAny>()), Times.Once); + } + + [Fact] + public async Task GetFunctionMetadataAsync_NoTransformers_ReturnsOriginalMetadata() + { + var mockProvider = new Mock(MockBehavior.Strict); + var mockLogger = new Mock>(); + var metadata = new List { new TestFunctionMetadata() }.ToImmutableArray(); + mockProvider.Setup(p => p.GetFunctionMetadataAsync(It.IsAny())).ReturnsAsync(metadata); + + var manager = new DefaultFunctionMetadataManager( + mockProvider.Object, + Array.Empty(), + mockLogger.Object); + + var result = await manager.GetFunctionMetadataAsync("test"); + + Assert.Single(result); + mockProvider.Verify(p => p.GetFunctionMetadataAsync("test"), Times.Once); + } + + [Fact] + public async Task GetFunctionMetadataAsync_TransformerThrows_LogsAndThrows() + { + var mockProvider = new Mock(MockBehavior.Strict); + var mockTransformer = new Mock(MockBehavior.Strict); + var mockLogger = new Mock>(); + var metadata = ImmutableArray.Empty; + + mockProvider.Setup(p => p.GetFunctionMetadataAsync(It.IsAny())).ReturnsAsync(metadata); + mockTransformer.SetupGet(t => t.Name).Returns("ThrowingTransformer"); + mockTransformer.Setup(t => t.Transform(It.IsAny>())) + .Throws(new InvalidOperationException("fail")); + + var manager = new DefaultFunctionMetadataManager( + mockProvider.Object, + new[] { mockTransformer.Object }, + mockLogger.Object); + + var ex = await Assert.ThrowsAsync(() => manager.GetFunctionMetadataAsync("test")); + Assert.Equal("fail", ex.Message); + mockLogger.Verify(l => l.Log( + LogLevel.Error, + It.IsAny(), + It.Is((v, t) => v.ToString().Contains("ThrowingTransformer")), + It.IsAny(), + It.IsAny>()), Times.Once); + } + + private class TestFunctionMetadata : IFunctionMetadata + { + public string? FunctionId => "id"; + public bool IsProxy => false; + public string? Language => "dotnet"; + public bool ManagedDependencyEnabled => false; + public string? Name => "Test"; + public string? EntryPoint => "Test.Run"; + public IList? RawBindings => new List(); + public string? ScriptFile => "Test.dll"; + public IRetryOptions? Retry => null; + } + } +} diff --git a/test/DotNetWorkerTests/GrpcWorkerTests.cs b/test/DotNetWorkerTests/GrpcWorkerTests.cs index f3e10b56f..01c722eb5 100644 --- a/test/DotNetWorkerTests/GrpcWorkerTests.cs +++ b/test/DotNetWorkerTests/GrpcWorkerTests.cs @@ -279,7 +279,7 @@ public async Task Invocation_WhenSynchronous_DoesNotBlock() var clientFactoryMock = new Mock(); var clientMock = new Mock(); - var metadataProvider = new Mock(); + var metadataManager = new Mock(); var invocationHandlerMock = new Mock(); InvocationResponse ValueFunction(InvocationRequest request) @@ -310,7 +310,7 @@ InvocationResponse ValueFunction(InvocationRequest request) clientFactoryMock.Object, _mockMethodInfoLocator.Object, new OptionsWrapper(new WorkerOptions()), - metadataProvider.Object, + metadataManager.Object, new ApplicationLifetime(TestLogger.Create()), invocationHandlerMock.Object); From 6ac6e358ba04b76459b87d0c03fa0db8f95a1da5 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Wed, 17 Sep 2025 16:52:48 -0700 Subject: [PATCH 163/190] Worker packages release prep - 2.1.0 (#3171) * Version bump and release notes updates for worker package release 2.1.0 * Fix assembly version in source gen test. --- release_notes.md | 6 +++--- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- src/DotNetWorker/DotNetWorker.csproj | 2 +- .../FunctionExecutor/DependentAssemblyTest.cs | 4 ++-- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/release_notes.md b/release_notes.md index 74db65101..81290d933 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,14 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) +### Microsoft.Azure.Functions.Worker (metapackage) 2.1.0 - `AZURE_FUNCTIONS_` environment variables are now loaded correctly when using `FunctionsApplicationBuilder`. (#2878) -### Microsoft.Azure.Functions.Worker.Core +### Microsoft.Azure.Functions.Worker.Core 2.1.0 - Support for function metadata transforms (#3145) -### Microsoft.Azure.Functions.Worker.Grpc +### Microsoft.Azure.Functions.Worker.Grpc 2.1.0 - Updated to use the new metadata manage and leverage metadata transforms (#3145) diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 5844b5512..316b1c903 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker.Core true 2 - 0 + 1 0 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 69bc14427..949718c97 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker.Grpc true 2 - 0 + 1 0 true diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index b68c14392..e8ffb02c8 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker true 2 - 0 + 1 0 diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index 3ce6c543f..e76050829 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System.Reflection; @@ -139,7 +139,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.0.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; + var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor; From a566c5471a94ba8592b6a580b6f5ee324849ab19 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 14:04:49 -0700 Subject: [PATCH 164/190] Bump dotnet-sdk from 9.0.304 to 9.0.305 (#3166) Bumps [dotnet-sdk](https://github.com/dotnet/sdk) from 9.0.304 to 9.0.305. - [Release notes](https://github.com/dotnet/sdk/releases) - [Commits](https://github.com/dotnet/sdk/compare/v9.0.304...v9.0.305) --- updated-dependencies: - dependency-name: dotnet-sdk dependency-version: 9.0.305 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 03064daa1..75387d104 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.304", + "version": "9.0.305", "allowPrerelease": true, "rollForward": "latestFeature" }, From 088bd7c6b2171fc3a92ea1053f769af63c781b1a Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Wed, 24 Sep 2025 10:04:26 -0700 Subject: [PATCH 165/190] Updating ASP.NET Core extension to use metadata manager (#3172) --- .../Worker.Extensions.Http.AspNetCore/release_notes.md | 2 +- .../AspNetMiddleware/FunctionsEndpointDataSource.cs | 10 +++++----- .../src/Worker.Extensions.Http.AspNetCore.csproj | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index 97bb2a3ba..459b597e3 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -6,7 +6,7 @@ ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore -- +- Updating ASP.NET Core integration to support the metadata transformation feature (#3172) ### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs index 51285d1f2..73276df24 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/AspNetMiddleware/FunctionsEndpointDataSource.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.IO; using System.Text.Json; @@ -17,7 +17,7 @@ internal class FunctionsEndpointDataSource : EndpointDataSource private const string HostJsonFileName = "host.json"; private const string DefaultRoutePrefix = "api"; - private readonly IFunctionMetadataProvider _functionMetadataProvider; + private readonly IFunctionMetadataManager _functionMetadataManager; private readonly object _lock = new(); private static readonly JsonSerializerOptions _jsonSerializerOptions = new() @@ -30,9 +30,9 @@ internal class FunctionsEndpointDataSource : EndpointDataSource private List? _endpoints; - public FunctionsEndpointDataSource(IFunctionMetadataProvider functionMetadataProvider) + public FunctionsEndpointDataSource(IFunctionMetadataManager functionMetadataManager) { - _functionMetadataProvider = functionMetadataProvider ?? throw new ArgumentNullException(nameof(functionMetadataProvider)); + _functionMetadataManager = functionMetadataManager ?? throw new ArgumentNullException(nameof(functionMetadataManager)); } public override IReadOnlyList Endpoints @@ -58,7 +58,7 @@ private List BuildEndpoints() string scriptRoot = Environment.GetEnvironmentVariable(FunctionsApplicationDirectoryKey) ?? throw new InvalidOperationException("Cannot determine script root directory."); - var metadata = _functionMetadataProvider.GetFunctionMetadataAsync(scriptRoot).GetAwaiter().GetResult(); + var metadata = _functionMetadataManager.GetFunctionMetadataAsync(scriptRoot).GetAwaiter().GetResult(); string routePrefix = GetRoutePrefixFromHostJson(scriptRoot) ?? DefaultRoutePrefix; diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj index f26b5fe99..842c74879 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Worker.Extensions.Http.AspNetCore.csproj @@ -6,7 +6,7 @@ ASP.NET Core extensions for .NET isolated functions - 2.0.2 + 2.1.0 net6.0;net8.0 @@ -23,7 +23,7 @@ - + From 4c231f60ed16e95f080b09e8617c62fbb9b8b08a Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Thu, 25 Sep 2025 14:25:26 -0700 Subject: [PATCH 166/190] Bump ServiceBus extension dependencies (#3178) --- .../Worker.Extensions.ServiceBus/release_notes.md | 9 +++++++-- .../src/Worker.Extensions.ServiceBus.csproj | 12 ++++++------ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index c92b7d33c..bb1c984cc 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,6 +4,11 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.24.0 -- \ No newline at end of file +- Update minor dependencies + - Azure.Identity to 1.16.0 + - Azure.Messaging.ServiceBus to 7.20.1 + - Microsoft.Extensions.Azure to 1.13.0 + - Google.Protobuf to 3.32.1 + - Grpc.Tools to 2.72.0 \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj index 048f513cc..2b0378c42 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj +++ b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj @@ -6,7 +6,7 @@ Azure Service Bus extensions for .NET isolated functions - 5.23.0 + 5.24.0 false @@ -15,11 +15,11 @@ - - - - - + + + + + From f199d208fe9062337d606625e7bd2cd94211769f Mon Sep 17 00:00:00 2001 From: Pranava <68387945+aloiva@users.noreply.github.com> Date: Tue, 30 Sep 2025 23:28:26 +0530 Subject: [PATCH 167/190] Bump Kafka worker extension version to 4.1.3 (#3181) --- extensions/Worker.Extensions.Kafka/release_notes.md | 5 +++-- .../src/Worker.Extensions.Kafka.csproj | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index ca17cb549..3713cf33c 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,6 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka +### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.3 -- \ No newline at end of file +- Fix key avro serialization and deserialization when schema registry URL is provided [(PR Link)](https://github.com/Azure/azure-functions-kafka-extension/pull/569) +- Fix null reference error when using avro deserialization [(PR Link)](https://github.com/Azure/azure-functions-kafka-extension/pull/594) diff --git a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj index 84df6f91c..f58db4145 100644 --- a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj +++ b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj @@ -6,7 +6,7 @@ Kafka extensions for .NET isolated functions - 4.1.2 + 4.1.3 false @@ -21,7 +21,7 @@ - + From 505eb7bbc8aff7f84a49c8bee5413552b95eff3b Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Tue, 30 Sep 2025 16:03:20 -0700 Subject: [PATCH 168/190] Clear ext release notes (#3184) --- extensions/Worker.Extensions.Kafka/release_notes.md | 5 ++--- extensions/Worker.Extensions.ServiceBus/release_notes.md | 9 ++------- 2 files changed, 4 insertions(+), 10 deletions(-) diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index 3713cf33c..e73c591ab 100644 --- a/extensions/Worker.Extensions.Kafka/release_notes.md +++ b/extensions/Worker.Extensions.Kafka/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.1.3 +### Microsoft.Azure.Functions.Worker.Extensions.Kafka -- Fix key avro serialization and deserialization when schema registry URL is provided [(PR Link)](https://github.com/Azure/azure-functions-kafka-extension/pull/569) -- Fix null reference error when using avro deserialization [(PR Link)](https://github.com/Azure/azure-functions-kafka-extension/pull/594) +- diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index bb1c984cc..c92b7d33c 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,11 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.24.0 +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus -- Update minor dependencies - - Azure.Identity to 1.16.0 - - Azure.Messaging.ServiceBus to 7.20.1 - - Microsoft.Extensions.Azure to 1.13.0 - - Google.Protobuf to 3.32.1 - - Grpc.Tools to 2.72.0 \ No newline at end of file +- \ No newline at end of file From ab7b3f25a6cd706aa9906c11b2feced98f59e273 Mon Sep 17 00:00:00 2001 From: Nalu Tripician <27316859+NaluTripician@users.noreply.github.com> Date: Thu, 9 Oct 2025 20:45:16 -0700 Subject: [PATCH 169/190] Updates Cosmos Extensions version to 4.11.0 (#3191) * Updates Cosmos Extensions version * Update release_notes.md --- extensions/Worker.Extensions.CosmosDB/release_notes.md | 4 ++-- .../src/Worker.Extensions.CosmosDB.csproj | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index 921fdcf34..b9c7c90b7 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB <4.14.0> -- +- Updates dependency `Microsoft.Azure.WebJobs.Extensions.CosmosDB` to version 4.11.0 (#3191) diff --git a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj index 8217dac2e..1d0b09477 100644 --- a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj +++ b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj @@ -6,7 +6,7 @@ Azure Cosmos DB extensions for .NET isolated functions - 4.13.0 + 4.14.0 false @@ -31,7 +31,7 @@ - + \ No newline at end of file From 12bad22253251fd1d54aa914e12f432cafdf358c Mon Sep 17 00:00:00 2001 From: Brett Samblanet Date: Thu, 16 Oct 2025 11:04:41 -0400 Subject: [PATCH 170/190] updating Azure.Messaging.EventHubs package for bug fix (#3189) --- .../release_notes.md | 4 +-- .../src/Worker.Extensions.EventHubs.csproj | 4 +-- .../EventHubs/EventDataConverterTests.cs | 36 ++++++++++++++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/extensions/Worker.Extensions.EventHubs/release_notes.md b/extensions/Worker.Extensions.EventHubs/release_notes.md index 3d6e918a8..c01c394dc 100644 --- a/extensions/Worker.Extensions.EventHubs/release_notes.md +++ b/extensions/Worker.Extensions.EventHubs/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.EventHubs +### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.5.1 -- +- updating `Azure.Messaging.EventHubs` to 5.12.2 (#3189) diff --git a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj index 711ca3711..b9fdafa8a 100644 --- a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj +++ b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj @@ -6,7 +6,7 @@ Azure Event Hubs extensions for .NET isolated functions - 6.5.0 + 6.5.1 @@ -18,7 +18,7 @@ - + diff --git a/test/Worker.Extensions.Tests/EventHubs/EventDataConverterTests.cs b/test/Worker.Extensions.Tests/EventHubs/EventDataConverterTests.cs index 3f7c90f23..37e9dcce4 100644 --- a/test/Worker.Extensions.Tests/EventHubs/EventDataConverterTests.cs +++ b/test/Worker.Extensions.Tests/EventHubs/EventDataConverterTests.cs @@ -3,6 +3,7 @@ using System; using System.Threading.Tasks; +using Azure.Core.Amqp; using Azure.Messaging.EventHubs; using Google.Protobuf; using Microsoft.Azure.Functions.Worker.Converters; @@ -167,6 +168,39 @@ public async Task ConvertAsync_Batch_ReturnsFailure_WrongSource() Assert.Equal("Unexpected binding source 'some-other-source'. Only 'AzureEventHubsEventData' is supported.", result.Error.Message); } + [Fact] + public async Task ConvertAsync_EnqueuedTime() + { + // Validate bug fixed in Azure.Messaging.EventHubs 5.12.2 + var amqpMessage = new AmqpAnnotatedMessage(AmqpMessageBody.FromValue("abc")); + var enqueuedTime = new DateTimeOffset(2025, 10, 8, 8, 43, 21, TimeSpan.Zero); + amqpMessage.MessageAnnotations.Add("x-opt-enqueued-time", enqueuedTime.UtcDateTime); + + var eventData = new EventData(amqpMessage); + + var data = new GrpcModelBindingData(new ModelBindingData() + { + Version = "1.0", + Source = "AzureEventHubsEventData", + Content = ByteString.CopyFrom(ConvertEventDataToBinaryData(eventData)), + ContentType = Constants.BinaryContentType + }); + + var context = new TestConverterContext(typeof(string), data); + var converter = new EventDataConverter(); + + // Act + var result = await converter.ConvertAsync(context); + + // Assert + Assert.Equal(ConversionStatus.Succeeded, result.Status); + var output = result.Value as EventData; + Assert.NotNull(output); + + // Check enqueued time + Assert.Equal(enqueuedTime.UtcDateTime, output.EnqueuedTime.UtcDateTime); + } + private static void AssertEventData(EventData output) { Assert.Equal("body", output.EventBody.ToString()); @@ -190,4 +224,4 @@ private static BinaryData ConvertEventDataToBinaryData(EventData @event) return @event.GetRawAmqpMessage().ToBytes(); } } -} \ No newline at end of file +} From e7dc45bd7f43739cab3542f76e277a1222828430 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:53:14 -0700 Subject: [PATCH 171/190] Bump Microsoft.Build.Utilities.Core from 17.12.6 to 17.12.50 (#3197) --- updated-dependencies: - dependency-name: Microsoft.Build.Utilities.Core dependency-version: 17.12.50 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- sdk/Sdk/Sdk.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 0e00dd207..cc22b2609 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -31,7 +31,7 @@ - + From a42e198d0d7ea896ee9a1cd234f8c856a7fff685 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 13:53:24 -0700 Subject: [PATCH 172/190] Bump dotnet-sdk from 9.0.305 to 9.0.306 (#3196) Bumps [dotnet-sdk](https://github.com/dotnet/sdk) from 9.0.305 to 9.0.306. - [Release notes](https://github.com/dotnet/sdk/releases) - [Commits](https://github.com/dotnet/sdk/compare/v9.0.305...v9.0.306) --- updated-dependencies: - dependency-name: dotnet-sdk dependency-version: 9.0.306 dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- global.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/global.json b/global.json index 75387d104..e51901200 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.305", + "version": "9.0.306", "allowPrerelease": true, "rollForward": "latestFeature" }, From 92ebbac0634d0cb665dc253900564f510b2476ea Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 16 Oct 2025 14:25:08 -0700 Subject: [PATCH 173/190] Bump Microsoft.Build.Utilities.Core from 17.11.4 to 17.11.48 (#3201) --- updated-dependencies: - dependency-name: Microsoft.Build.Utilities.Core dependency-version: 17.11.48 dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- test/Sdk.E2ETests/Sdk.E2ETests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sdk.E2ETests/Sdk.E2ETests.csproj b/test/Sdk.E2ETests/Sdk.E2ETests.csproj index ef1dda5e9..8e3743503 100644 --- a/test/Sdk.E2ETests/Sdk.E2ETests.csproj +++ b/test/Sdk.E2ETests/Sdk.E2ETests.csproj @@ -21,7 +21,7 @@ - + From 96f371aaf88b0f3872360d173835988d9013d019 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Fri, 17 Oct 2025 12:01:34 -0700 Subject: [PATCH 174/190] Enable IFunctionExecutor in InvocationFeatures (#3200) * Enable IFunctionExecutor in InvocationFeatures * Update release_notes.md * Fix test & warnings --- release_notes.md | 15 ++-- .../Pipeline/FunctionExecutionMiddleware.cs | 16 +++-- .../DefaultFunctionMetadataManagerTests.cs | 8 ++- .../FunctionsExecutionMiddlewareTests.cs | 69 +++++++++++++++++++ 4 files changed, 89 insertions(+), 19 deletions(-) create mode 100644 test/DotNetWorkerTests/Pipelines/FunctionsExecutionMiddlewareTests.cs diff --git a/release_notes.md b/release_notes.md index 81290d933..c7c0f8cd4 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,14 +4,11 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) 2.1.0 +### Microsoft.Azure.Functions.Worker (metapackage) +- -- `AZURE_FUNCTIONS_` environment variables are now loaded correctly when using `FunctionsApplicationBuilder`. (#2878) +### Microsoft.Azure.Functions.Worker.Core +- Support setting `IFunctionExecutor` in invocation features: `FunctionContext.Features` (#3200) -### Microsoft.Azure.Functions.Worker.Core 2.1.0 - -- Support for function metadata transforms (#3145) - -### Microsoft.Azure.Functions.Worker.Grpc 2.1.0 - -- Updated to use the new metadata manage and leverage metadata transforms (#3145) +### Microsoft.Azure.Functions.Worker.Grpc +- diff --git a/src/DotNetWorker.Core/Pipeline/FunctionExecutionMiddleware.cs b/src/DotNetWorker.Core/Pipeline/FunctionExecutionMiddleware.cs index 449c9afaa..cbde9e85d 100644 --- a/src/DotNetWorker.Core/Pipeline/FunctionExecutionMiddleware.cs +++ b/src/DotNetWorker.Core/Pipeline/FunctionExecutionMiddleware.cs @@ -1,22 +1,24 @@ // 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.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Invocation; namespace Microsoft.Azure.Functions.Worker.Pipeline { - internal class FunctionExecutionMiddleware + internal class FunctionExecutionMiddleware(IFunctionExecutor functionExecutor) { - private readonly IFunctionExecutor _functionExecutor; - - public FunctionExecutionMiddleware(IFunctionExecutor functionExecutor) - { - _functionExecutor = functionExecutor; - } + private readonly IFunctionExecutor _functionExecutor = functionExecutor + ?? throw new ArgumentNullException(nameof(functionExecutor)); public Task Invoke(FunctionContext context) { + if (context.Features.Get() is { } executor) + { + return executor.ExecuteAsync(context).AsTask(); + } + return _functionExecutor.ExecuteAsync(context).AsTask(); } } diff --git a/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs b/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs index c508b9a8b..04d10c6cb 100644 --- a/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs +++ b/test/DotNetWorkerTests/FunctionMetadata/DefaultFunctionMetadataManagerTests.cs @@ -7,6 +7,8 @@ using Moq; using Xunit; +#nullable enable + namespace Microsoft.Azure.Functions.Worker.Tests.FunctionMetadata { public class DefaultFunctionMetadataManagerTests @@ -70,7 +72,7 @@ public async Task GetFunctionMetadataAsync_TransformerThrows_LogsAndThrows() var manager = new DefaultFunctionMetadataManager( mockProvider.Object, - new[] { mockTransformer.Object }, + [mockTransformer.Object], mockLogger.Object); var ex = await Assert.ThrowsAsync(() => manager.GetFunctionMetadataAsync("test")); @@ -78,9 +80,9 @@ public async Task GetFunctionMetadataAsync_TransformerThrows_LogsAndThrows() mockLogger.Verify(l => l.Log( LogLevel.Error, It.IsAny(), - It.Is((v, t) => v.ToString().Contains("ThrowingTransformer")), + It.Is((v, t) => v.ToString()!.Contains("ThrowingTransformer")), It.IsAny(), - It.IsAny>()), Times.Once); + It.IsAny>()), Times.Once); } private class TestFunctionMetadata : IFunctionMetadata diff --git a/test/DotNetWorkerTests/Pipelines/FunctionsExecutionMiddlewareTests.cs b/test/DotNetWorkerTests/Pipelines/FunctionsExecutionMiddlewareTests.cs new file mode 100644 index 000000000..11e8b3ba0 --- /dev/null +++ b/test/DotNetWorkerTests/Pipelines/FunctionsExecutionMiddlewareTests.cs @@ -0,0 +1,69 @@ +// 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.Threading.Tasks; +using Microsoft.Azure.Functions.Worker.Invocation; +using Moq; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Pipeline.Tests +{ + public class FunctionsExecutionMiddlewareTests + { + [Fact] + public void Ctor_ThrowsArgumentNullException_WhenFunctionExecutorIsNull() + { + // Arrange & Act & Assert + var exception = Assert.Throws(() => new FunctionExecutionMiddleware(null!)); + Assert.Equal("functionExecutor", exception.ParamName); + } + + [Fact] + public async Task Invoke_NoFeature_CallsInjectedExecutor() + { + // Arrange + Mock functionExecutorMock = new(MockBehavior.Strict); + FunctionExecutionMiddleware middleware = new(functionExecutorMock.Object); + Mock functionContextMock = new(MockBehavior.Strict); + functionContextMock.Setup(m => m.Features).Returns(new InvocationFeatures([])); + + functionExecutorMock + .Setup(m => m.ExecuteAsync(functionContextMock.Object)) + .Returns(ValueTask.CompletedTask) + .Verifiable(); + + // Act + await middleware.Invoke(functionContextMock.Object); + + // Assert + functionExecutorMock.Verify(f => f.ExecuteAsync(functionContextMock.Object), Times.Once); + } + + [Fact] + public async Task Invoke_Feature_CallsFeatureExecutor() + { + // Arrange + Mock functionExecutorMock1 = new(MockBehavior.Strict); + Mock functionExecutorMock2 = new(MockBehavior.Strict); + FunctionExecutionMiddleware middleware = new(functionExecutorMock1.Object); + Mock functionContextMock = new(MockBehavior.Strict); + + InvocationFeatures features = new([]); + features.Set(functionExecutorMock2.Object); + functionContextMock.Setup(m => m.Features).Returns(features); + + functionExecutorMock2 + .Setup(m => m.ExecuteAsync(functionContextMock.Object)) + .Returns(ValueTask.CompletedTask) + .Verifiable(); + + // Act + await middleware.Invoke(functionContextMock.Object); + + // Assert + functionExecutorMock1.Verify(f => f.ExecuteAsync(It.IsAny()), Times.Never); + functionExecutorMock2.Verify(f => f.ExecuteAsync(functionContextMock.Object), Times.Once); + } + } +} From ad8b090c4e25f30e7597828fb054cd3f4cf1d12e Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Mon, 20 Oct 2025 16:28:42 -0700 Subject: [PATCH 175/190] Updating Worker.ApplicationInsights dependencies (#3204) --- .../DotNetWorker.ApplicationInsights.csproj | 4 ++-- src/DotNetWorker.ApplicationInsights/release_notes.md | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 1ab568c0e..48dfa8621 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -15,8 +15,8 @@ - - + + diff --git a/src/DotNetWorker.ApplicationInsights/release_notes.md b/src/DotNetWorker.ApplicationInsights/release_notes.md index addb34ce4..756698416 100644 --- a/src/DotNetWorker.ApplicationInsights/release_notes.md +++ b/src/DotNetWorker.ApplicationInsights/release_notes.md @@ -2,4 +2,5 @@ ### Microsoft.Azure.Functions.Worker.ApplicationInsights -- +- Updating `Azure.Identity` from 1.12.0 to 1.17.0 +- Updating `Microsoft.ApplicationInsights.PerfCounterCollector` from 2.22.0 to 2.23.0 \ No newline at end of file From 4e60190bd49798f42731d103b1c59ace5bd08c67 Mon Sep 17 00:00:00 2001 From: Surbhi Gupta Date: Mon, 20 Oct 2025 22:18:41 -0500 Subject: [PATCH 176/190] Updating Microsoft.Build.Utilities.Core in Tests project (#3205) --- test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index f0e9e900a..d2192b599 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -30,7 +30,7 @@ - + From e99be73f6c1b0d1a59b1788516675a82272667bb Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Tue, 21 Oct 2025 10:14:34 -0700 Subject: [PATCH 177/190] Prep 2.2.0 release (#3202) * Update core packages to 2.2.0 * Update test --- release_notes.md | 6 +++--- src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- src/DotNetWorker/DotNetWorker.csproj | 2 +- .../FunctionExecutor/DependentAssemblyTest.cs | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/release_notes.md b/release_notes.md index c7c0f8cd4..5bf13c50a 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,11 +4,11 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) +### Microsoft.Azure.Functions.Worker (metapackage) 2.2.0 - -### Microsoft.Azure.Functions.Worker.Core +### Microsoft.Azure.Functions.Worker.Core 2.2.0 - Support setting `IFunctionExecutor` in invocation features: `FunctionContext.Features` (#3200) -### Microsoft.Azure.Functions.Worker.Grpc +### Microsoft.Azure.Functions.Worker.Grpc 2.2.0 - diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 316b1c903..2550b28de 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker.Core true 2 - 1 + 2 0 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 949718c97..910940bb5 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker.Grpc true 2 - 1 + 2 0 true diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index e8ffb02c8..34c9d19e1 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker true 2 - 1 + 2 0 diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index e76050829..b5dc262af 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -139,7 +139,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.1.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; + var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor; From 37f97968dfba16d2a5e2b612aec8569d8b286d42 Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 29 Oct 2025 09:07:42 -0700 Subject: [PATCH 178/190] Remove extra global.json, AppInsights test to net8.0 (#3219) * Remove extra global.json, AppInsights test to net8.0 * Fix install-dotnet.yml update --- build/install-dotnet.yml | 20 ----------------- eng/ci/templates/steps/install-dotnet.yml | 22 ++++++++----------- host/src/FunctionsNetHost/global.json | 6 ----- .../Worker.ApplicationInsights.Tests.csproj | 7 ++---- 4 files changed, 11 insertions(+), 44 deletions(-) delete mode 100644 build/install-dotnet.yml delete mode 100644 host/src/FunctionsNetHost/global.json diff --git a/build/install-dotnet.yml b/build/install-dotnet.yml deleted file mode 100644 index 1cdaa3c38..000000000 --- a/build/install-dotnet.yml +++ /dev/null @@ -1,20 +0,0 @@ -steps: -# Some tests rely on 6.0.412 existing -- task: UseDotNet@2 - displayName: 'Install .NET6 SDK' - inputs: - packageType: 'sdk' - version: "6.x" - -- task: UseDotNet@2 - displayName: 'Install .NET7 SDK' - inputs: - packageType: 'sdk' - version: "7.x" - -# The SDK we use to build -- task: UseDotNet@2 - displayName: 'Install current .NET SDK' - inputs: - packageType: 'sdk' - useGlobalJson: true diff --git a/eng/ci/templates/steps/install-dotnet.yml b/eng/ci/templates/steps/install-dotnet.yml index f373c934f..139c7aeb6 100644 --- a/eng/ci/templates/steps/install-dotnet.yml +++ b/eng/ci/templates/steps/install-dotnet.yml @@ -1,19 +1,15 @@ steps: -- task: UseDotNet@2 # Needed by our projects and CI steps - displayName: Install .NET 6 +# Our tests target net8.0 +- task: UseDotNet@2 + displayName: 'Install .NET8 SDK' inputs: - packageType: sdk - version: 6.x + packageType: 'sdk' + version: "8.x" -- task: UseDotNet@2 # Needed by our projects and CI steps - displayName: Install .NET 7 +# The SDK we use to build +- task: UseDotNet@2 + displayName: 'Install current .NET SDK' inputs: - packageType: sdk - version: 7.x - -- task: UseDotNet@2 # The pinned SDK we use to build - displayName: Install .NET SDK from global.json - inputs: - packageType: sdk + packageType: 'sdk' useGlobalJson: true diff --git a/host/src/FunctionsNetHost/global.json b/host/src/FunctionsNetHost/global.json deleted file mode 100644 index 26228fbdf..000000000 --- a/host/src/FunctionsNetHost/global.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "sdk": { - "version": "8.0.110", - "rollForward": "latestMinor" - } -} \ No newline at end of file diff --git a/test/Worker.ApplicationInsights.Tests/Worker.ApplicationInsights.Tests.csproj b/test/Worker.ApplicationInsights.Tests/Worker.ApplicationInsights.Tests.csproj index 436cff015..6574cc2a5 100644 --- a/test/Worker.ApplicationInsights.Tests/Worker.ApplicationInsights.Tests.csproj +++ b/test/Worker.ApplicationInsights.Tests/Worker.ApplicationInsights.Tests.csproj @@ -1,7 +1,7 @@  - net6.0 + net8.0 false Microsoft.Azure.Functions.Worker.ApplicationInsights.Tests Microsoft.Azure.Functions.Worker.ApplicationInsights.Tests @@ -20,10 +20,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + From 9674a2ccbec59a702be5e00f9c046d8e12f35e3a Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Thu, 6 Nov 2025 11:22:38 -0800 Subject: [PATCH 179/190] [SourceGen] Fix for duplicate properties generated (#3227) --- .../FunctionMetadataLoaderExtension.csproj | 2 +- ...unctionMetadataProviderGenerator.Parser.cs | 4 +- sdk/Sdk.Generators/Sdk.Generators.csproj | 2 +- sdk/release_notes.md | 5 +- .../BindingPropertiesParsingTests.cs | 266 ++++++++++++++++++ .../RetryOptionsTests.cs | 6 +- .../Sdk.Generator.Tests.csproj | 10 +- 7 files changed, 280 insertions(+), 15 deletions(-) create mode 100644 test/Sdk.Generator.Tests/FunctionMetadataProvider/BindingPropertiesParsingTests.cs diff --git a/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj b/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj index d354b3127..9b4c49c6b 100644 --- a/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj +++ b/sdk/FunctionMetadataLoaderExtension/FunctionMetadataLoaderExtension.csproj @@ -11,7 +11,7 @@ - + diff --git a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs index 7acafdcaf..776c555d0 100644 --- a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs +++ b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information.; using System; @@ -612,7 +612,7 @@ private bool TryCreateBindingDictionary(AttributeData bindingAttrData, string bi private bool TryGetAttributeProperties(AttributeData attributeData, Location? attribLocation, out IDictionary? attrProperties) { - attrProperties = new Dictionary(); + attrProperties = new Dictionary(StringComparer.OrdinalIgnoreCase); if (attributeData.ConstructorArguments.Any()) { diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index ed64e78c2..159fe0374 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -10,7 +10,7 @@ false true 3 - 5 + 6 true true diff --git a/sdk/release_notes.md b/sdk/release_notes.md index fb9fe089c..45c44e07c 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -8,7 +8,8 @@ - Build no longer generates `functions.metadata` if source-generated metadata provider is enabled. (#2974) - Fixing `dotnet run` to work on Windows when core tools is installed from NPM (#3127) +- `Microsoft.Azure.Functions.Worker.Sdk.Generators` bumped to `1.3.6`. -### Microsoft.Azure.Functions.Worker.Sdk.Generators +### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.6 -- +- Fix bug that results in duplicate properties recorded for a binding (#3227) diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProvider/BindingPropertiesParsingTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/BindingPropertiesParsingTests.cs new file mode 100644 index 000000000..abda775de --- /dev/null +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/BindingPropertiesParsingTests.cs @@ -0,0 +1,266 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Reflection; +using System.Threading.Tasks; +using Microsoft.Azure.Functions.Sdk.Generator.Tests; +using Microsoft.Azure.Functions.Worker.Sdk.Generators; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Xunit; + +namespace Microsoft.Azure.Functions.Sdk.Generator.FunctionMetadataProvider.Tests +{ + public partial class FunctionMetadataProviderGeneratorTests + { + public class BindingPropertiesParsingTests + { + private readonly Assembly[] _referencedExtensionAssemblies; + + public BindingPropertiesParsingTests() + { + var abstractionsExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Abstractions.dll"); + var httpExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Http.dll"); + var hostingExtension = typeof(HostBuilder).Assembly; + var diExtension = typeof(DefaultServiceProviderFactory).Assembly; + var hostingAbExtension = typeof(IHost).Assembly; + var diAbExtension = typeof(IServiceCollection).Assembly; + var mcpExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Mcp.dll"); + var blobExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs.dll"); + + _referencedExtensionAssemblies = new[] + { + abstractionsExtension, + httpExtension, + hostingExtension, + hostingAbExtension, + diExtension, + diAbExtension, + mcpExtension, + blobExtension + }; + } + + [Theory] + [InlineData(LanguageVersion.CSharp7_3)] + [InlineData(LanguageVersion.CSharp8)] + [InlineData(LanguageVersion.CSharp9)] + [InlineData(LanguageVersion.CSharp10)] + [InlineData(LanguageVersion.CSharp11)] + [InlineData(LanguageVersion.Latest)] + public async Task BindingPropertiesWithDefaultValueDoeNotCreateDuplicatesWhenSetAsNamedArgument(LanguageVersion languageVersion) + { + string inputCode = """ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Functions.Worker; + using Microsoft.Azure.Functions.Worker.Http; + using Microsoft.Azure.Functions.Worker.Extensions.Mcp; + + namespace MyCompany.Task + { + public static class SaveSnippetFunction + { + [Function(nameof(SaveSnippetFunction))] + [BlobOutput("blobPath")] + public static string SaveSnippet( + [McpToolTrigger("someString", "someString")] + ToolInvocationContext context, + [McpToolProperty("someString", "someString", IsRequired = true)] + string name + ) + { + throw new NotImplementedException(); + } + } + } + """; + + string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; + string expectedOutput = $$""" + // + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Text.Json; + using System.Threading.Tasks; + using Microsoft.Azure.Functions.Worker; + using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; + + namespace TestProject + { + /// + /// Custom implementation that returns function metadata definitions for the current worker. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {{Constants.GeneratedCodeAttribute}} + public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider + { + /// + public Task> GetFunctionMetadataAsync(string directory) + { + var metadataList = new List(); + var Function0RawBindings = new List(); + Function0RawBindings.Add(@"{""name"":""$return"",""type"":""blob"",""direction"":""Out"",""blobPath"":""blobPath""}"); + Function0RawBindings.Add(@"{""name"":""context"",""type"":""mcpToolTrigger"",""direction"":""In"",""toolName"":""someString"",""description"":""someString""}"); + Function0RawBindings.Add(@"{""name"":""name"",""type"":""mcpToolProperty"",""direction"":""In"",""propertyName"":""someString"",""description"":""someString"",""isRequired"":true,""dataType"":""String""}"); + + var Function0 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "SaveSnippetFunction", + EntryPoint = "MyCompany.Task.SaveSnippetFunction.SaveSnippet", + RawBindings = Function0RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function0); + + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); + } + } + + /// + /// Extension methods to enable registration of the custom implementation generated for the current worker. + /// + {{Constants.GeneratedCodeAttribute}} + public static class WorkerHostBuilderFunctionMetadataProviderExtension + { + /// + /// Adds the GeneratedFunctionMetadataProvider to the service collection. + /// During initialization, the worker will return generated function metadata instead of relying on the Azure Functions host for function indexing. + /// + public static IHostBuilder ConfigureGeneratedFunctionMetadataProvider(this IHostBuilder builder) + { + builder.ConfigureServices(s => + { + s.AddSingleton(); + }); + return builder; + } + } + } + """; + + await TestHelpers.RunTestAsync( + _referencedExtensionAssemblies, + inputCode, + expectedGeneratedFileName, + expectedOutput, + languageVersion: languageVersion); + } + + [Theory] + [InlineData(LanguageVersion.CSharp7_3)] + [InlineData(LanguageVersion.CSharp8)] + [InlineData(LanguageVersion.CSharp9)] + [InlineData(LanguageVersion.CSharp10)] + [InlineData(LanguageVersion.CSharp11)] + [InlineData(LanguageVersion.Latest)] + public async Task BindingPropertyWithDefaultValueIsSet(LanguageVersion languageVersion) + { + string inputCode = """ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Functions.Worker; + using Microsoft.Azure.Functions.Worker.Http; + using Microsoft.Azure.Functions.Worker.Extensions.Mcp; + + namespace MyCompany.Task + { + public static class SaveSnippetFunction + { + [Function(nameof(SaveSnippetFunction))] + [BlobOutput("blobPath")] + public static string SaveSnippet( + [McpToolTrigger("someString", "someString")] + ToolInvocationContext context, + [McpToolProperty("someString", "someString")] + string name + ) + { + throw new NotImplementedException(); + } + } + } + """; + + string expectedGeneratedFileName = $"GeneratedFunctionMetadataProvider.g.cs"; + string expectedOutput = $$""" + // + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + using System.Text.Json; + using System.Threading.Tasks; + using Microsoft.Azure.Functions.Worker; + using Microsoft.Azure.Functions.Worker.Core.FunctionMetadata; + using Microsoft.Extensions.DependencyInjection; + using Microsoft.Extensions.Hosting; + + namespace TestProject + { + /// + /// Custom implementation that returns function metadata definitions for the current worker. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] + {{Constants.GeneratedCodeAttribute}} + public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider + { + /// + public Task> GetFunctionMetadataAsync(string directory) + { + var metadataList = new List(); + var Function0RawBindings = new List(); + Function0RawBindings.Add(@"{""name"":""$return"",""type"":""blob"",""direction"":""Out"",""blobPath"":""blobPath""}"); + Function0RawBindings.Add(@"{""name"":""context"",""type"":""mcpToolTrigger"",""direction"":""In"",""toolName"":""someString"",""description"":""someString""}"); + Function0RawBindings.Add(@"{""name"":""name"",""type"":""mcpToolProperty"",""direction"":""In"",""propertyName"":""someString"",""description"":""someString"",""isRequired"":false,""dataType"":""String""}"); + + var Function0 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "SaveSnippetFunction", + EntryPoint = "MyCompany.Task.SaveSnippetFunction.SaveSnippet", + RawBindings = Function0RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function0); + + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); + } + } + + /// + /// Extension methods to enable registration of the custom implementation generated for the current worker. + /// + {{Constants.GeneratedCodeAttribute}} + public static class WorkerHostBuilderFunctionMetadataProviderExtension + { + /// + /// Adds the GeneratedFunctionMetadataProvider to the service collection. + /// During initialization, the worker will return generated function metadata instead of relying on the Azure Functions host for function indexing. + /// + public static IHostBuilder ConfigureGeneratedFunctionMetadataProvider(this IHostBuilder builder) + { + builder.ConfigureServices(s => + { + s.AddSingleton(); + }); + return builder; + } + } + } + """; + + await TestHelpers.RunTestAsync( + _referencedExtensionAssemblies, + inputCode, + expectedGeneratedFileName, + expectedOutput, + languageVersion: languageVersion); + } + } + } +} diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs index caec922fb..f201634cf 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProvider/RetryOptionsTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System.Reflection; @@ -27,7 +27,6 @@ public RetryOptionsTests() var diExtension = typeof(DefaultServiceProviderFactory).Assembly; var hostingAbExtension = typeof(IHost).Assembly; var diAbExtension = typeof(IServiceCollection).Assembly; - var cosmosDBExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.CosmosDB.dll"); var timerExtension = Assembly.LoadFrom("Microsoft.Azure.Functions.Worker.Extensions.Timer.dll"); @@ -39,8 +38,7 @@ public RetryOptionsTests() hostingAbExtension, diExtension, diAbExtension, - timerExtension, - cosmosDBExtension + timerExtension }; } diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index d2192b599..cf86f476f 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -16,20 +16,20 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all - + + - - - + + From c7c5e53ef32db523da1d6f6c0bf2f60964be5349 Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Thu, 6 Nov 2025 13:28:10 -0800 Subject: [PATCH 180/190] Prep for SDK release (#3228) --- sdk/Sdk/Sdk.csproj | 2 +- sdk/release_notes.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index cc22b2609..9b3e90b49 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -3,7 +3,7 @@ 2 0 - 5 + 6 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 45c44e07c..da6b6dc60 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,7 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk +### Microsoft.Azure.Functions.Worker.Sdk 2.0.6 - Build no longer generates `functions.metadata` if source-generated metadata provider is enabled. (#2974) - Fixing `dotnet run` to work on Windows when core tools is installed from NPM (#3127) From 6891db223c4f1e6089416350a807011ecc584a6a Mon Sep 17 00:00:00 2001 From: sarah <35204912+satvu@users.noreply.github.com> Date: Thu, 6 Nov 2025 15:37:46 -0800 Subject: [PATCH 181/190] Clear release notes (#3229) --- sdk/release_notes.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sdk/release_notes.md b/sdk/release_notes.md index da6b6dc60..93083cfa3 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,12 +4,10 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk 2.0.6 +### Microsoft.Azure.Functions.Worker.Sdk -- Build no longer generates `functions.metadata` if source-generated metadata provider is enabled. (#2974) -- Fixing `dotnet run` to work on Windows when core tools is installed from NPM (#3127) -- `Microsoft.Azure.Functions.Worker.Sdk.Generators` bumped to `1.3.6`. +- -### Microsoft.Azure.Functions.Worker.Sdk.Generators 1.3.6 +### Microsoft.Azure.Functions.Worker.Sdk.Generators -- Fix bug that results in duplicate properties recorded for a binding (#3227) +- \ No newline at end of file From 3a7d27e45350f19a6550cb184671f0860a7fec8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20=C3=85gren?= Date: Fri, 7 Nov 2025 00:50:53 +0100 Subject: [PATCH 182/190] Use name of function instead of class for input/output example (#3212) The example function with input/output is used standalone on https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-storage-queue-trigger . When copying this the code does not compile because it uses the class name, which is not included in the example (doc snippet), as function name. Renaming the function to something more explicit, and using that as function name, should improve the example. --- samples/Extensions/Queue/QueueFunction.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/samples/Extensions/Queue/QueueFunction.cs b/samples/Extensions/Queue/QueueFunction.cs index cfa26b8b7..5248ce724 100644 --- a/samples/Extensions/Queue/QueueFunction.cs +++ b/samples/Extensions/Queue/QueueFunction.cs @@ -20,9 +20,9 @@ public QueueFunction(ILogger logger) // // - [Function(nameof(QueueFunction))] + [Function(nameof(QueueInputOutputFunction))] [QueueOutput("output-queue")] - public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context) + public string[] QueueInputOutputFunction([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context) // { // Use a string array to return more than one message. From a50707eb2c462098f6885a0c45d82956e05dccfe Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Tue, 11 Nov 2025 10:30:52 -0800 Subject: [PATCH 183/190] 2.50.0 worker packages release prep (#3237) * Adding net10 TFM to worker packages (#3123) * Fix steps indentation (#3117) * .NET 10 TFM support changes. --------- Co-authored-by: Jacob Viau * Updating the dependencies from P6 to NET10. * Switch sdk to 10.0.100 GA --------- Co-authored-by: Jacob Viau --- global.json | 2 +- release_notes.md | 15 +++++++++------ .../DotNetWorker.ApplicationInsights.csproj | 4 ++-- .../DotNetWorker.Core.csproj | 19 ++++++------------- .../DotNetWorker.Grpc.csproj | 6 +++--- src/DotNetWorker/DotNetWorker.csproj | 4 ++-- test/E2ETests/E2EApps/E2EApp/E2EApp.csproj | 2 +- test/E2ETests/E2ETests/E2ETests.csproj | 4 ++-- .../Sdk.Analyzers.Tests.csproj | 2 +- .../FunctionExecutor/DependentAssemblyTest.cs | 2 +- .../Sdk.Generator.Tests.csproj | 10 +++++----- test/TestUtility/TestUtility.csproj | 10 +++++----- .../Blob/StreamTests.cs | 2 +- 13 files changed, 39 insertions(+), 43 deletions(-) diff --git a/global.json b/global.json index e51901200..320ad044d 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "9.0.306", + "version": "10.0.100", "allowPrerelease": true, "rollForward": "latestFeature" }, diff --git a/release_notes.md b/release_notes.md index 5bf13c50a..577f8f61f 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,11 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) 2.2.0 -- +### Microsoft.Azure.Functions.Worker (metapackage) 2.50.0 -### Microsoft.Azure.Functions.Worker.Core 2.2.0 -- Support setting `IFunctionExecutor` in invocation features: `FunctionContext.Features` (#3200) +- Adding `net10.0` TFM support. -### Microsoft.Azure.Functions.Worker.Grpc 2.2.0 -- +### Microsoft.Azure.Functions.Worker.Core 2.50.0 + +- Adding `net10.0` TFM support. + +### Microsoft.Azure.Functions.Worker.Grpc 2.50.0 + +- Adding `net10.0` TFM support. diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 48dfa8621..8f70d04b2 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -6,7 +6,7 @@ Microsoft.Azure.Functions.Worker.ApplicationInsights Microsoft.Azure.Functions.Worker.ApplicationInsights 2 - 0 + 50 0 README.md $(BeforePack);GetReleaseNotes @@ -17,7 +17,7 @@ - + diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 2550b28de..1c4ad650d 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -2,15 +2,15 @@ Library - net6.0;net8.0;net9.0;netstandard2.0 + net6.0;net8.0;net9.0;net10.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Core This library provides the core functionality to build an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker.Core Microsoft.Azure.Functions.Worker.Core true 2 - 2 - 0 + 50 + 0 @@ -22,19 +22,12 @@ + - - - - - - - - - - + + diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 910940bb5..4875586fe 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -2,15 +2,15 @@ Library - net6.0;net7.0;net8.0;net9.0;netstandard2.0 + net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0 Microsoft.Azure.Functions.Worker.Grpc This library provides gRPC support for Azure Functions .NET Worker communication with the Azure Functions Host. Microsoft.Azure.Functions.Worker.Grpc Microsoft.Azure.Functions.Worker.Grpc true 2 - 2 - 0 + 50 + 0 true diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index 34c9d19e1..56863d7d5 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -2,14 +2,14 @@ Library - net6.0;net7.0;net8.0;net9.0;netstandard2.0 + net6.0;net7.0;net8.0;net9.0;net10.0;netstandard2.0 Microsoft.Azure.Functions.Worker This library enables you to create an Azure Functions .NET Worker, adding support for the isolated, out-of-process execution model. Microsoft.Azure.Functions.Worker Microsoft.Azure.Functions.Worker true 2 - 2 + 50 0 diff --git a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj index 45d9b700f..3409c286f 100644 --- a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj +++ b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj @@ -47,6 +47,6 @@ - + \ No newline at end of file diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index 9b23ae8e8..a2908ea02 100644 --- a/test/E2ETests/E2ETests/E2ETests.csproj +++ b/test/E2ETests/E2ETests/E2ETests.csproj @@ -12,10 +12,10 @@ - + - + all diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index 0ca059f81..2067b79d5 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -13,7 +13,7 @@ - + all diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index b5dc262af..6854a4e36 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -139,7 +139,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.2.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; + var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.50.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor; diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index cf86f476f..f17278856 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -36,17 +36,17 @@ - - - - + + + + - + diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index 46e6caf2d..482a2a7a5 100644 --- a/test/TestUtility/TestUtility.csproj +++ b/test/TestUtility/TestUtility.csproj @@ -10,11 +10,11 @@ - - - - - + + + + + diff --git a/test/Worker.Extensions.Tests/Blob/StreamTests.cs b/test/Worker.Extensions.Tests/Blob/StreamTests.cs index d7713f368..8a745326c 100644 --- a/test/Worker.Extensions.Tests/Blob/StreamTests.cs +++ b/test/Worker.Extensions.Tests/Blob/StreamTests.cs @@ -246,7 +246,7 @@ public async Task ConvertAsync_StreamCollection_WithFilePath_Throws_ReturnsFaile // Assert Assert.Equal(ConversionStatus.Failed, conversionResult.Status); Assert.IsType(conversionResult.Error); - Assert.Contains("Deserialization of types without a parameterless constructor, a singular parameterized constructor, or a parameterized constructor annotated with 'JsonConstructorAttribute' is not supported.", conversionResult.Error.Message); + Assert.Contains("Deserialization of interface or abstract types is not supported.", conversionResult.Error.Message); } } } From ebac71217a2e48c2e39b1d7eafd6d901068b3f8f Mon Sep 17 00:00:00 2001 From: Jacob Viau Date: Wed, 12 Nov 2025 14:04:50 -0800 Subject: [PATCH 184/190] Address some warnings from dotnet build -check (#3234) --- Directory.Build.props | 5 -- sdk/Sdk.Analyzers/Sdk.Analyzers.csproj | 4 -- sdk/Sdk.Analyzers/tools/install.ps1 | 58 ----------------- sdk/Sdk.Analyzers/tools/uninstall.ps1 | 65 ------------------- .../DotNetWorker.OpenTelemetry.Tests.csproj | 6 +- .../DotNetWorkerTests.csproj | 6 +- test/Sdk.E2ETests/Sdk.E2ETests.csproj | 4 +- .../Sdk.Generator.Tests.csproj | 2 +- 8 files changed, 4 insertions(+), 146 deletions(-) delete mode 100644 sdk/Sdk.Analyzers/tools/install.ps1 delete mode 100644 sdk/Sdk.Analyzers/tools/uninstall.ps1 diff --git a/Directory.Build.props b/Directory.Build.props index 34cd20ef5..7da35374a 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,10 +1,5 @@ - - - true - - $(MSBuildThisFileDirectory) $(RepoRoot)eng/ diff --git a/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj b/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj index aaef6653a..bfe34892a 100644 --- a/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj +++ b/sdk/Sdk.Analyzers/Sdk.Analyzers.csproj @@ -27,10 +27,6 @@ - - - - diff --git a/sdk/Sdk.Analyzers/tools/install.ps1 b/sdk/Sdk.Analyzers/tools/install.ps1 deleted file mode 100644 index c1c3d8822..000000000 --- a/sdk/Sdk.Analyzers/tools/install.ps1 +++ /dev/null @@ -1,58 +0,0 @@ -param($installPath, $toolsPath, $package, $project) - -if($project.Object.SupportsPackageDependencyResolution) -{ - if($project.Object.SupportsPackageDependencyResolution()) - { - # Do not install analyzers via install.ps1, instead let the project system handle it. - return - } -} - -$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve - -foreach($analyzersPath in $analyzersPaths) -{ - if (Test-Path $analyzersPath) - { - # Install the language agnostic analyzers. - foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll) - { - if($project.Object.AnalyzerReferences) - { - $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName) - } - } - } -} - -# $project.Type gives the language name like (C# or VB.NET) -$languageFolder = "" -if($project.Type -eq "C#") -{ - $languageFolder = "cs" -} -if($project.Type -eq "VB.NET") -{ - $languageFolder = "vb" -} -if($languageFolder -eq "") -{ - return -} - -foreach($analyzersPath in $analyzersPaths) -{ - # Install language specific analyzers. - $languageAnalyzersPath = join-path $analyzersPath $languageFolder - if (Test-Path $languageAnalyzersPath) - { - foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll) - { - if($project.Object.AnalyzerReferences) - { - $project.Object.AnalyzerReferences.Add($analyzerFilePath.FullName) - } - } - } -} \ No newline at end of file diff --git a/sdk/Sdk.Analyzers/tools/uninstall.ps1 b/sdk/Sdk.Analyzers/tools/uninstall.ps1 deleted file mode 100644 index 65a862370..000000000 --- a/sdk/Sdk.Analyzers/tools/uninstall.ps1 +++ /dev/null @@ -1,65 +0,0 @@ -param($installPath, $toolsPath, $package, $project) - -if($project.Object.SupportsPackageDependencyResolution) -{ - if($project.Object.SupportsPackageDependencyResolution()) - { - # Do not uninstall analyzers via uninstall.ps1, instead let the project system handle it. - return - } -} - -$analyzersPaths = Join-Path (Join-Path (Split-Path -Path $toolsPath -Parent) "analyzers") * -Resolve - -foreach($analyzersPath in $analyzersPaths) -{ - # Uninstall the language agnostic analyzers. - if (Test-Path $analyzersPath) - { - foreach ($analyzerFilePath in Get-ChildItem -Path "$analyzersPath\*.dll" -Exclude *.resources.dll) - { - if($project.Object.AnalyzerReferences) - { - $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName) - } - } - } -} - -# $project.Type gives the language name like (C# or VB.NET) -$languageFolder = "" -if($project.Type -eq "C#") -{ - $languageFolder = "cs" -} -if($project.Type -eq "VB.NET") -{ - $languageFolder = "vb" -} -if($languageFolder -eq "") -{ - return -} - -foreach($analyzersPath in $analyzersPaths) -{ - # Uninstall language specific analyzers. - $languageAnalyzersPath = join-path $analyzersPath $languageFolder - if (Test-Path $languageAnalyzersPath) - { - foreach ($analyzerFilePath in Get-ChildItem -Path "$languageAnalyzersPath\*.dll" -Exclude *.resources.dll) - { - if($project.Object.AnalyzerReferences) - { - try - { - $project.Object.AnalyzerReferences.Remove($analyzerFilePath.FullName) - } - catch - { - - } - } - } - } -} \ No newline at end of file diff --git a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj index 23a7cd5d8..b9351243c 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj +++ b/test/DotNetWorker.OpenTelemetry.Tests/DotNetWorker.OpenTelemetry.Tests.csproj @@ -9,7 +9,6 @@ preview ..\..\key.snk disable - true @@ -17,10 +16,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/test/DotNetWorkerTests/DotNetWorkerTests.csproj b/test/DotNetWorkerTests/DotNetWorkerTests.csproj index d7f87d381..fa72e6f1b 100644 --- a/test/DotNetWorkerTests/DotNetWorkerTests.csproj +++ b/test/DotNetWorkerTests/DotNetWorkerTests.csproj @@ -9,7 +9,6 @@ preview ..\..\key.snk disable - true @@ -18,10 +17,7 @@ - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/test/Sdk.E2ETests/Sdk.E2ETests.csproj b/test/Sdk.E2ETests/Sdk.E2ETests.csproj index 8e3743503..5a3bdf227 100644 --- a/test/Sdk.E2ETests/Sdk.E2ETests.csproj +++ b/test/Sdk.E2ETests/Sdk.E2ETests.csproj @@ -36,9 +36,7 @@ - - Always - + diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index f17278856..d07651f08 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -66,7 +66,7 @@ - + \ No newline at end of file From 4aed564646df811322c2ee8ee79ad69893de176e Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Wed, 12 Nov 2025 14:47:11 -0800 Subject: [PATCH 185/190] Reset release notes (post 2.50.0 release) (#3244) --- release_notes.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/release_notes.md b/release_notes.md index 577f8f61f..37057e890 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,14 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) 2.50.0 +### Microsoft.Azure.Functions.Worker (metapackage) -- Adding `net10.0` TFM support. +- -### Microsoft.Azure.Functions.Worker.Core 2.50.0 +### Microsoft.Azure.Functions.Worker.Core -- Adding `net10.0` TFM support. +- -### Microsoft.Azure.Functions.Worker.Grpc 2.50.0 +### Microsoft.Azure.Functions.Worker.Grpc -- Adding `net10.0` TFM support. +- From 85b603f7139bfa671d586dc6a05080d8e7d83f2d Mon Sep 17 00:00:00 2001 From: Lilian Kasem Date: Wed, 12 Nov 2025 14:50:06 -0800 Subject: [PATCH 186/190] Bump "coverlet.collector" to "6.0.4" (#3245) --- test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj | 2 +- test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj | 2 +- .../Worker.Extensions.SignalRService.Tests.csproj | 2 +- .../Worker.Extensions.Http.AspNetCore.Tests.csproj | 2 +- .../Worker.Extensions.Timer.Tests.csproj | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index 2067b79d5..872d41b88 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -19,7 +19,7 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index d07651f08..4e79e725e 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -17,7 +17,7 @@ - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj b/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj index 4e707487e..5bb626984 100644 --- a/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj +++ b/test/Worker.Extensions.SignalRService.Tests/Worker.Extensions.SignalRService.Tests.csproj @@ -16,7 +16,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj index d8e416a7c..74ea72db1 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/Worker.Extensions.Http.AspNetCore.Tests.csproj @@ -24,7 +24,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj b/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj index d6a5b1726..2e55a1320 100644 --- a/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj +++ b/test/extensions/Worker.Extensions.Timer.Tests/Worker.Extensions.Timer.Tests.csproj @@ -13,7 +13,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive From eef3aab11f0d8e6aa9160940204fdbd9ec296aa6 Mon Sep 17 00:00:00 2001 From: Fabio Cavalcante Date: Wed, 12 Nov 2025 16:10:29 -0800 Subject: [PATCH 187/190] Restore `functions.metadata` generation (#3246) Reversed suppression of `functions.metadata` file generation in the SDK targets file, restoring default behavior. --- ...crosoft.Azure.Functions.Worker.Sdk.targets | 10 +- sdk/Sdk/Tasks/GenerateFunctionMetadata.cs | 9 -- sdk/release_notes.md | 4 +- .../AspNetCore/CancellationEndToEndTests.cs | 8 +- .../E2ETests/Fixtures/FunctionAppFixture.cs | 5 +- test/Sdk.E2ETests/InnerBuildTests.cs | 42 +++---- test/Sdk.E2ETests/ProcessWrapper.cs | 33 +++--- test/Sdk.E2ETests/ProjectBuilder.cs | 106 ----------------- test/Sdk.E2ETests/PublishTests.cs | 109 +++++++++--------- test/Sdk.E2ETests/TempDirectory.cs | 41 ------- test/Sdk.E2ETests/TestUtility.cs | 107 +++++++++++++++-- test/Sdk.E2ETests/ZipDeployTests.cs | 28 ++--- 12 files changed, 216 insertions(+), 286 deletions(-) delete mode 100644 test/Sdk.E2ETests/ProjectBuilder.cs delete mode 100644 test/Sdk.E2ETests/TempDirectory.cs diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 8133074c8..dfc2c085d 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -48,9 +48,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and false true $(FunctionsEnableWorkerIndexing) - $(FunctionsEnableWorkerIndexing) - false - true + $(FunctionsEnableWorkerIndexing) true true @@ -193,10 +191,9 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and ReferencePaths="@(ReferencePath)" ExtensionsCsProjFilePath="$(ExtensionsCsProj)" AzureFunctionsVersion="$(AzureFunctionsVersion)" - WriteMetadataFile="$(FunctionsWriteMetadataJson)" TargetFrameworkIdentifier="$(TargetFrameworkIdentifier)" TargetFrameworkVersion="$(TargetFrameworkVersion)" - OutputPath="$(IntermediateOutputPath)" /> + OutputPath="$(IntermediateOutputPath)"/> @@ -250,8 +247,7 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - <_FunctionsAdditionalFile Include="$(_FunctionsMetadataPath)" Condition="'$(FunctionsWriteMetadataJson)' == 'true'" /> - <_FunctionsAdditionalFile Include="$(_FunctionsWorkerConfigPath);$(_FunctionsIntermediateExtensionUpdatedJsonPath)" /> + <_FunctionsAdditionalFile Include="$(_FunctionsMetadataPath);$(_FunctionsWorkerConfigPath);$(_FunctionsIntermediateExtensionUpdatedJsonPath)" /> <_FunctionsAdditionalFile Include="$(_FunctionsMetadataLoaderExtensionFile)" SubPath="$(_FunctionsExtensionsDirectory)/" /> <_NoneWithTargetPath Include="@(_FunctionsAdditionalFile)" TargetPath="%(_FunctionsAdditionalFile.SubPath)%(Filename)%(Extension)" diff --git a/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs b/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs index 58568268d..e54aa995a 100644 --- a/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs +++ b/sdk/Sdk/Tasks/GenerateFunctionMetadata.cs @@ -26,8 +26,6 @@ public class GenerateFunctionMetadata : Task public string? ExtensionsCsProjFilePath { get; set; } - public bool WriteMetadataFile { get; set; } = true; - [Required] public ITaskItem[]? ReferencePaths { get; set; } @@ -69,18 +67,11 @@ public override bool Execute() private void WriteMetadataWithRetry(IEnumerable functions) { - if (!WriteMetadataFile) - { - Log.LogMessage("Skipping writing function metadata file."); - return; - } - int attempt = 0; while (attempt < 10) { try { - Log.LogMessage($"Writing function metadata to {OutputPath} directory."); FunctionMetadataJsonWriter.WriteMetadata(functions, OutputPath!); break; } diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 93083cfa3..b83fe84e1 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,9 +4,9 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk +### Microsoft.Azure.Functions.Worker.Sdk 2.0.7 -- +- Reversal of change to suppress generation of functions.metadata file ### Microsoft.Azure.Functions.Worker.Sdk.Generators diff --git a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs index 0fc9dae82..4bfce6034 100644 --- a/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs +++ b/test/E2ETests/E2ETests/AspNetCore/CancellationEndToEndTests.cs @@ -37,10 +37,10 @@ public async Task HttpTriggerFunctions_WithCancellationToken_BehaveAsExpected(st await TestUtility.RetryAsync(() => { invocationStartLog = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains($"Executing 'Functions.{functionName}'")); - return Task.FromResult(invocationStartLog.Any()); + return Task.FromResult(invocationStartLog.Count() >= 1); }); - // The task should be cancelled before it completes, mimicking a client closing the connection. + // The task should be cancelled before it completes, mimicing a client closing the connection. // This should lead to the worker getting an InvocationCancel request from the functions host cts.Cancel(); await Assert.ThrowsAsync(async () => await task); @@ -49,13 +49,13 @@ await TestUtility.RetryAsync(() => await TestUtility.RetryAsync(() => { invocationEndLog = _fixture.TestLogs.CoreToolsLogs.Where(p => p.Contains($"Executed 'Functions.{functionName}'")); - return Task.FromResult(invocationEndLog.Any()); + return Task.FromResult(invocationEndLog.Count() >= 1); }); Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains(expectedMessage, StringComparison.OrdinalIgnoreCase)); // TODO: 2/3 of the test invocations will fail until the host with the ForwarderProxy fix is released - uncomment this line when the fix is released - Assert.NotNull(invocationResult); // just here to 'use' invocationResult to avoid a warning. + Assert.NotEqual(null, invocationResult); // just here to 'use' invocationResult to avoid a warning. // Assert.Contains(_fixture.TestLogs.CoreToolsLogs, log => log.Contains($"'Functions.{functionName}' ({invocationResult}", StringComparison.OrdinalIgnoreCase)); } diff --git a/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs b/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs index be132df86..2eedeb61f 100644 --- a/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs +++ b/test/E2ETests/E2ETests/Fixtures/FunctionAppFixture.cs @@ -17,11 +17,11 @@ namespace Microsoft.Azure.Functions.Tests.E2ETests { public class FunctionAppFixture : IAsyncLifetime { - private readonly string _testApp = Constants.TestAppNames.E2EApp; private readonly ILogger _logger; private bool _disposed; private Process _funcProcess; private JobObjectRegistry _jobObjectRegistry; + private string _testApp = Constants.TestAppNames.E2EApp; public FunctionAppFixture(IMessageSink messageSink) { @@ -32,8 +32,7 @@ public FunctionAppFixture(IMessageSink messageSink) _logger = loggerFactory.CreateLogger(); } - internal FunctionAppFixture(IMessageSink messageSink, string testApp) - : this(messageSink) + internal FunctionAppFixture(IMessageSink messageSink, string testApp) : this(messageSink) { _testApp = testApp; } diff --git a/test/Sdk.E2ETests/InnerBuildTests.cs b/test/Sdk.E2ETests/InnerBuildTests.cs index 455ec7307..e38822c14 100644 --- a/test/Sdk.E2ETests/InnerBuildTests.cs +++ b/test/Sdk.E2ETests/InnerBuildTests.cs @@ -1,7 +1,6 @@ // 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.IO; using System.Threading.Tasks; using Newtonsoft.Json.Linq; @@ -10,27 +9,25 @@ namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public sealed class InnerBuildTests(ITestOutputHelper testOutputHelper) : IDisposable + public class InnerBuildTests { - private readonly ProjectBuilder _builder = new( - testOutputHelper, - Path.Combine(TestUtility.TestResourcesProjectsRoot, "FunctionApp01", "FunctionApp01.csproj")); + private readonly ITestOutputHelper _testOutputHelper; - [Theory] - [InlineData("", false)] - [InlineData("-p:FunctionsEnableWorkerIndexing=true", false)] - [InlineData("-p:FunctionsEnableWorkerIndexing=true -p:FunctionsWriteMetadataJson=false", false)] - [InlineData("-p:FunctionsEnableWorkerIndexing=true -p:FunctionsWriteMetadataJson=true", true)] - [InlineData("-p:FunctionsEnableWorkerIndexing=false", true)] - [InlineData("-p:FunctionsEnableWorkerIndexing=false -p:FunctionsWriteMetadataJson=false", false)] - [InlineData("-p:FunctionsEnableWorkerIndexing=false -p:FunctionsWriteMetadataJson=true", true)] - public async Task Build_ScansReferences(string parameters, bool metadataGenerated) + public InnerBuildTests(ITestOutputHelper testOutputHelper) { - await _builder.RestoreAsync(); - await _builder.BuildAsync(parameters, restore: false); + _testOutputHelper = testOutputHelper; + } + + [Fact] + public async Task Build_ScansReferences() + { + string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Build_ScansReferences)); + string projectFileDirectory = Path.Combine(TestUtility.TestResourcesProjectsRoot, "FunctionApp01", "FunctionApp01.csproj"); + + await TestUtility.RestoreAndBuildProjectAsync(projectFileDirectory, outputDir, null, _testOutputHelper); // Verify extensions.json contents - string extensionsJsonPath = Path.Combine(_builder.OutputPath, "extensions.json"); + string extensionsJsonPath = Path.Combine(outputDir, "extensions.json"); Assert.True(File.Exists(extensionsJsonPath)); JToken extensionsJsonContents = JObject.Parse(File.ReadAllText(extensionsJsonPath)); @@ -57,13 +54,8 @@ public async Task Build_ScansReferences(string parameters, bool metadataGenerate Assert.True(JToken.DeepEquals(expectedExtensionsJson, extensionsJsonContents)); // Verify functions.metadata contents - string functionsMetadataPath = Path.Combine(_builder.OutputPath, "functions.metadata"); - Assert.Equal(metadataGenerated, File.Exists(functionsMetadataPath)); - - if (!metadataGenerated) - { - return; - } + string functionsMetadataPath = Path.Combine(outputDir, "functions.metadata"); + Assert.True(File.Exists(functionsMetadataPath)); JToken functionsMetadataContents = JArray.Parse(File.ReadAllText(functionsMetadataPath)); JToken expectedFunctionsMetadata = JArray.Parse(@"[ @@ -123,7 +115,5 @@ public async Task Build_ScansReferences(string parameters, bool metadataGenerate Assert.True(JToken.DeepEquals(expectedFunctionsMetadata, functionsMetadataContents)); } - - public void Dispose() => _builder.Dispose(); } } diff --git a/test/Sdk.E2ETests/ProcessWrapper.cs b/test/Sdk.E2ETests/ProcessWrapper.cs index eb04f284b..ae250e4ae 100644 --- a/test/Sdk.E2ETests/ProcessWrapper.cs +++ b/test/Sdk.E2ETests/ProcessWrapper.cs @@ -6,27 +6,26 @@ using System.Text; using System.Threading; using System.Threading.Tasks; +using Xunit.Abstractions; namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public static class ProcessWrapper + public class ProcessWrapper { - public static async Task RunProcessAsync( - string fileName, string arguments, string workingDirectory = null, Action log = null) + + public async Task RunProcess(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null) { - return await RunProcessInternalAsync(fileName, arguments, workingDirectory, log); + return await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper); } - public static async Task> RunProcessForOutputAsync( - string fileName, string arguments, string workingDirectory = null, Action log = null) + public async Task> RunProcessForOutput(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null) { StringBuilder processOutputStringBuilder = new StringBuilder(); - var exitCode = await RunProcessInternalAsync(fileName, arguments, workingDirectory, log, processOutputStringBuilder); + var exitCode = await RunProcessInternal(fileName, arguments, workingDirectory, testOutputHelper, processOutputStringBuilder); return new Tuple(exitCode, processOutputStringBuilder.ToString()); } - private static async Task RunProcessInternalAsync( - string fileName, string arguments, string workingDirectory = null, Action log = null, StringBuilder processOutputBuilder = null) + private async Task RunProcessInternal(string fileName, string arguments, string workingDirectory, ITestOutputHelper testOutputHelper = null, StringBuilder processOutputBuilder = null) { SemaphoreSlim processExitSemaphore = new SemaphoreSlim(0, 1); @@ -54,8 +53,11 @@ public static class ProcessWrapper { if (o.Data != null) { - log?.Invoke($"[{DateTime.UtcNow:O}] Error: {o.Data}"); - processOutputBuilder?.AppendLine(o.Data); + testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] Error: {o.Data}"); + if (processOutputBuilder != null) + { + processOutputBuilder.AppendLine(o.Data); + } } }; @@ -63,8 +65,11 @@ public static class ProcessWrapper { if (o.Data != null) { - log?.Invoke($"[{DateTime.UtcNow:O}] {o.Data}"); - processOutputBuilder?.AppendLine(o.Data); + testOutputHelper.WriteLine($"[{DateTime.UtcNow:O}] {o.Data}"); + if (processOutputBuilder != null) + { + processOutputBuilder.AppendLine(o.Data); + } } }; @@ -76,7 +81,7 @@ public static class ProcessWrapper int wait = 3 * 60 * 1000; if (!await processExitSemaphore.WaitAsync(wait)) { - log?.Invoke($"Process '{testProcess.Id}' did not exit in {wait}ms."); + testOutputHelper?.WriteLine($"Process '{testProcess.Id}' did not exit in {wait}ms."); testProcess.Kill(); } diff --git a/test/Sdk.E2ETests/ProjectBuilder.cs b/test/Sdk.E2ETests/ProjectBuilder.cs deleted file mode 100644 index 9fff6b893..000000000 --- a/test/Sdk.E2ETests/ProjectBuilder.cs +++ /dev/null @@ -1,106 +0,0 @@ -// 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.Diagnostics; -using System.IO; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Xunit; -using Xunit.Abstractions; - -namespace Microsoft.Azure.Functions.Sdk.E2ETests -{ - public sealed class ProjectBuilder(ITestOutputHelper logger, string project) : IDisposable - { -#if DEBUG - public const string Configuration = "Debug"; -#elif RELEASE - public const string Configuration = "Release"; -#endif - public static readonly string LocalPackages = Path.Combine(TestUtility.PathToRepoRoot, "local"); - public static readonly string SrcRoot = Path.Combine(TestUtility.PathToRepoRoot, "src"); - public static readonly string SdkSolutionRoot = Path.Combine(TestUtility.PathToRepoRoot, "sdk"); - public static readonly string SdkProjectRoot = Path.Combine(SdkSolutionRoot, "Sdk"); - public static readonly string DotNetExecutable = "dotnet"; - public static readonly string SdkVersion = "99.99.99-test"; - public static readonly string SdkBuildProj = Path.Combine(TestUtility.PathToRepoRoot, "build", "Sdk.slnf"); - public static readonly string NuGetOrgPackages = "https://api.nuget.org/v3/index.json"; - - private static Task _initialization; - private static object _sync; - - private readonly TempDirectory _tempDirectory = new(); - - public string OutputPath => _tempDirectory.Path; - - public async Task RestoreAsync() - { - await LazyInitializer.EnsureInitialized(ref _initialization, ref _sync, InitializeAsync); - logger.WriteLine("Restoring..."); - string dotnetArgs = $"restore {project} -s {NuGetOrgPackages} -s {LocalPackages} -p:SdkVersion={SdkVersion}"; - Stopwatch stopwatch = Stopwatch.StartNew(); - int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, dotnetArgs, log: logger.WriteLine); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - logger.WriteLine($"Done. ({stopwatch.ElapsedMilliseconds} ms)"); - } - - public async Task BuildAsync(string additionalParams = null, bool restore = true) - { - await LazyInitializer.EnsureInitialized(ref _initialization, ref _sync, InitializeAsync); - - Stopwatch stopwatch = Stopwatch.StartNew(); - logger.WriteLine("Building..."); - string dotnetArgs = $"build {project} -c {Configuration} -o {OutputPath} -p:SdkVersion={SdkVersion} {additionalParams}"; - - if (!restore) - { - dotnetArgs += " --no-restore"; - } - - if (Debugger.IsAttached) - { - dotnetArgs += " -bl"; - } - - int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, dotnetArgs, log: logger.WriteLine); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - logger.WriteLine($"Done. ({stopwatch.ElapsedMilliseconds} ms)"); - } - - public async Task PublishAsync(string additionalParams = null, bool restore = true) - { - await LazyInitializer.EnsureInitialized(ref _initialization, ref _sync, InitializeAsync); - - Stopwatch stopwatch = Stopwatch.StartNew(); - logger.WriteLine($"Publishing..."); - string dotnetArgs = $"publish {project} -c {Configuration} -o {OutputPath} -p:SdkVersion={SdkVersion} {additionalParams}"; - - if (!restore) - { - dotnetArgs += " --no-restore"; - } - - if (Debugger.IsAttached) - { - dotnetArgs += " -bl"; - } - - int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, dotnetArgs, log: logger.WriteLine); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - logger.WriteLine($"Done. ({stopwatch.ElapsedMilliseconds} ms)"); - } - - private async Task InitializeAsync() - { - logger.WriteLine($"Packing {SdkBuildProj} with version {SdkVersion}"); - string arguments = $"pack {SdkBuildProj} -c {Configuration} -o {LocalPackages} -p:Version={SdkVersion}"; - - int? exitCode = await ProcessWrapper.RunProcessAsync(DotNetExecutable, arguments, SrcRoot, logger.WriteLine); - Assert.True(exitCode.HasValue && exitCode.Value == 0); - } - - public void Dispose() => _tempDirectory.Dispose(); - } -} diff --git a/test/Sdk.E2ETests/PublishTests.cs b/test/Sdk.E2ETests/PublishTests.cs index 9f3cb6544..d707922e2 100644 --- a/test/Sdk.E2ETests/PublishTests.cs +++ b/test/Sdk.E2ETests/PublishTests.cs @@ -11,20 +11,27 @@ namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public sealed class PublishTests(ITestOutputHelper testOutputHelper) : IDisposable + public class PublishTests { - private readonly ProjectBuilder _builder = new( - testOutputHelper, - Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj")); - - [Theory] - [InlineData("", false)] - [InlineData("-r win-x86", false)] - [InlineData("-p:FunctionsEnableWorkerIndexing=false", true)] - [InlineData("-p:FunctionsEnableWorkerIndexing=false -r win-x86", true)] - public async Task Publish(string parameters, bool metadataGenerated) + private ITestOutputHelper _testOutputHelper; + + public PublishTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + [Fact] + public async Task Publish() + { + string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish)); + await RunPublishTest(outputDir); + } + + [Fact] + public async Task Publish_Rid() { - await RunPublishTest(parameters, metadataGenerated); + string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Rid)); + await RunPublishTest(outputDir, "-r win-x86"); } [Fact] @@ -34,51 +41,45 @@ public async Task Publish(string parameters, bool metadataGenerated) [Trait("Requirement", "Docker")] public async Task Publish_Container() { - var repository = "sdk." + nameof(E2ETests).ToLower(); + string outputDir = await TestUtility.InitializeTestAsync(_testOutputHelper, nameof(Publish_Container)); + var repository = nameof(Sdk.E2ETests).ToLower(); var imageTag = nameof(Publish_Container); // setup test environment state in case there is leftover data from previous runs - await TestUtility.RemoveDockerTestImage(repository, imageTag, testOutputHelper); + await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper); - try - { - // perform the publish - await RunPublishTest($"-t:PublishContainer -p:ContainerRepository={repository} -p:ContainerImageTag={imageTag}", false); - - // validate the image base - Tuple inspectResults = await ProcessWrapper.RunProcessForOutputAsync( - "docker", - $"inspect {repository}:{imageTag} --format \"{{{{ index .Config.Labels \\\"org.opencontainers.image.base.name\\\"}}}}\"", - _builder.OutputPath, - testOutputHelper.WriteLine); - - var inspectExitCode = inspectResults.Item1; - var inspectOutput = inspectResults.Item2; - Assert.True(inspectExitCode.HasValue && inspectExitCode.Value == 0); - Assert.Matches("mcr\\.microsoft\\.com/azure-functions/dotnet-isolated:(\\d)+-dotnet-isolated(\\d+\\.\\d+)", inspectOutput); - } - finally - { - // clean up - await TestUtility.RemoveDockerTestImage(repository, imageTag, testOutputHelper); - } + // perform the publish + await RunPublishTest(outputDir, $"--no-restore /t:PublishContainer --property:ContainerRepository={repository} --property:ContainerImageTag={imageTag}"); + + // validate the image base + Tuple inspectResults = await new ProcessWrapper().RunProcessForOutput("docker", $"inspect {repository}:{imageTag} --format \"{{{{ index .Config.Labels \\\"org.opencontainers.image.base.name\\\"}}}}\"", outputDir, _testOutputHelper); + var inspectExitCode = inspectResults.Item1; + var inspectOutput = inspectResults.Item2; + Assert.True(inspectExitCode.HasValue && inspectExitCode.Value == 0); + Assert.Matches("mcr\\.microsoft\\.com/azure-functions/dotnet-isolated:(\\d)+-dotnet-isolated(\\d+\\.\\d+)", inspectOutput); + + // clean up + await TestUtility.RemoveDockerTestImage(repository, imageTag, _testOutputHelper); } - private async Task RunPublishTest(string additionalParams, bool metadataGenerated) + private async Task RunPublishTest(string outputDir, string additionalParams = null) { - await _builder.PublishAsync(additionalParams); + // Name of the csproj + string projectFileDirectory = Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj"); + + await TestUtility.RestoreAndPublishProjectAsync(projectFileDirectory, outputDir, additionalParams, _testOutputHelper); // Make sure files are in /.azurefunctions - string azureFunctionsDir = Path.Combine(_builder.OutputPath, ".azurefunctions"); + string azureFunctionsDir = Path.Combine(outputDir, ".azurefunctions"); Assert.True(Directory.Exists(azureFunctionsDir)); // Verify files are present string metadataLoaderPath = Path.Combine(azureFunctionsDir, "Microsoft.Azure.WebJobs.Extensions.FunctionMetadataLoader.dll"); - string extensionsJsonPath = Path.Combine(_builder.OutputPath, "extensions.json"); - string functionsMetadataPath = Path.Combine(_builder.OutputPath, "functions.metadata"); - Assert.True(File.Exists(extensionsJsonPath)); + string extensionsJsonPath = Path.Combine(outputDir, "extensions.json"); + string functionsMetadataPath = Path.Combine(outputDir, "functions.metadata"); Assert.True(File.Exists(metadataLoaderPath)); - Assert.Equal(metadataGenerated, File.Exists(functionsMetadataPath)); + Assert.True(File.Exists(extensionsJsonPath)); + Assert.True(File.Exists(functionsMetadataPath)); // Verify extensions.json JObject jObjects = JObject.Parse(File.ReadAllText(extensionsJsonPath)); @@ -101,24 +102,26 @@ private async Task RunPublishTest(string additionalParams, bool metadataGenerate Assert.True(JToken.DeepEquals(extensionsJsonContents, expected), $"Actual: {extensionsJsonContents}{Environment.NewLine}Expected: {expected}"); // Verify functions.metadata - if (metadataGenerated) - { - TestUtility.ValidateFunctionsMetadata(functionsMetadataPath, "Microsoft.Azure.Functions.Sdk.E2ETests.Contents.functions.metadata"); - } + TestUtility.ValidateFunctionsMetadata(functionsMetadataPath, "Microsoft.Azure.Functions.Sdk.E2ETests.Contents.functions.metadata"); } - public void Dispose() => _builder.Dispose(); - - private class Extension(string name, string typeName, string hintPath) + private class Extension { + public Extension(string name, string typeName, string hintPath) + { + Name = name; + TypeName = typeName; + HintPath = hintPath; + } + [JsonProperty("name")] - public string Name { get; set; } = name; + public string Name { get; set; } [JsonProperty("typeName")] - public string TypeName { get; set; } = typeName; + public string TypeName { get; set; } [JsonProperty("hintPath")] - public string HintPath { get; set; } = hintPath; + public string HintPath { get; set; } } } } diff --git a/test/Sdk.E2ETests/TempDirectory.cs b/test/Sdk.E2ETests/TempDirectory.cs deleted file mode 100644 index 8afa936f8..000000000 --- a/test/Sdk.E2ETests/TempDirectory.cs +++ /dev/null @@ -1,41 +0,0 @@ -// 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.IO; -using IOPath = System.IO.Path; - -namespace Microsoft.Azure.Functions.Sdk.E2ETests -{ - public sealed class TempDirectory : IDisposable - { - public TempDirectory() : this(IOPath.Combine(IOPath.GetTempPath(), IOPath.GetRandomFileName())) - { - } - - public TempDirectory(string path) - { - ArgumentNullException.ThrowIfNull(path); - Path = path; - - if (!Directory.Exists(Path)) - { - Directory.CreateDirectory(Path); - } - } - - public string Path { get; } - - public void Dispose() - { - try - { - Directory.Delete(Path, true); - } - catch (IOException) - { - // Ignore IO exceptions during cleanup - } - } - } -} diff --git a/test/Sdk.E2ETests/TestUtility.cs b/test/Sdk.E2ETests/TestUtility.cs index 26f0b6a98..b1217ad3f 100644 --- a/test/Sdk.E2ETests/TestUtility.cs +++ b/test/Sdk.E2ETests/TestUtility.cs @@ -26,29 +26,120 @@ public static class TestUtility public const string Net50 = "net5.0"; // Paths and executables - public static readonly string PathToRepoRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, @"../../../../../")); + public static readonly string DotNetExecutable = "dotnet"; + public static readonly string PathToRepoRoot = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../")); + public static readonly string SrcRoot = Path.Combine(PathToRepoRoot, "src"); + public static readonly string SdkSolutionRoot = Path.Combine(PathToRepoRoot, "sdk"); + public static readonly string SdkProjectRoot = Path.Combine(SdkSolutionRoot, "Sdk"); public static readonly string TestRoot = Path.Combine(PathToRepoRoot, "test"); public static readonly string SamplesRoot = Path.Combine(PathToRepoRoot, "samples"); + public static readonly string LocalPackages = Path.Combine(PathToRepoRoot, "local"); + public static readonly string TestOutputDir = Path.Combine(Path.GetTempPath(), "FunctionsWorkerSdk.E2ETests"); public static readonly string TestResourcesProjectsRoot = Path.Combine(TestRoot, "Resources", "Projects"); + public static readonly string NuGetOrgPackages = "https://api.nuget.org/v3/index.json"; + public static readonly string NuGetPackageSource = LocalPackages; + public static readonly string SdkVersion = "99.99.99-test"; + public static readonly string SdkBuildProj = Path.Combine(PathToRepoRoot, "build", "Sdk.slnf"); + + private static bool _isInitialized = false; + + public static async Task InitializeTestAsync(ITestOutputHelper testOutputHelper, string testName) + { + if (!_isInitialized) + { + testOutputHelper.WriteLine($"Packing {SdkBuildProj} with version {SdkVersion}"); + string arguments = $"pack {SdkBuildProj} -c {Configuration} -o {LocalPackages} -p:Version={SdkVersion}"; + + int? exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, arguments, SrcRoot, testOutputHelper); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + + _isInitialized = true; + } + + return InitializeOutputDir(testName); + } + public static void ValidateFunctionsMetadata(string actualFilePath, string embeddedResourceName) { JToken functionsMetadataContents = JToken.Parse(File.ReadAllText(actualFilePath)); var assembly = Assembly.GetExecutingAssembly(); string resourceName = assembly.GetManifestResourceNames() .Single(str => str.EndsWith(embeddedResourceName)); - using Stream stream = assembly.GetManifestResourceStream(resourceName); - using StreamReader reader = new StreamReader(stream); - using var jsonReader = new JsonTextReader(reader); - JsonSerializer serializer = new JsonSerializer(); - var expected = serializer.Deserialize(jsonReader); - Assert.True(JToken.DeepEquals(functionsMetadataContents, expected), $"Actual: {functionsMetadataContents}{Environment.NewLine}Expected: {expected}"); + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + { + using (StreamReader reader = new StreamReader(stream)) + { + using (var jsonReader = new JsonTextReader(reader)) + { + JsonSerializer serializer = new JsonSerializer(); + var expected = serializer.Deserialize(jsonReader); + Assert.True(JToken.DeepEquals(functionsMetadataContents, expected), $"Actual: {functionsMetadataContents}{Environment.NewLine}Expected: {expected}"); + } + } + } + } + + public static async Task RestoreAndBuildProjectAsync(string fullPathToProjFile, string outputDir, string additionalParams, ITestOutputHelper outputHelper) + { + // Name of the csproj + string projectNameToTest = Path.GetFileName(fullPathToProjFile); + string projectFileDirectory = Path.GetDirectoryName(fullPathToProjFile); + + // Restore + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Restoring..."); + string dotnetArgs = $"restore {projectNameToTest} -s {NuGetOrgPackages} -s {LocalPackages} -p:SdkVersion={SdkVersion}"; + int? exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); + + // Build + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Building..."); + dotnetArgs = $"build {projectNameToTest} --configuration {Configuration} -o {outputDir} -p:SdkVersion={SdkVersion} {additionalParams}"; + exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); + } + + public static async Task RestoreAndPublishProjectAsync(string fullPathToProjFile, string outputDir, string additionalParams, ITestOutputHelper outputHelper) + { + // Name of the csproj + string projectNameToTest = Path.GetFileName(fullPathToProjFile); + string projectFileDirectory = Path.GetDirectoryName(fullPathToProjFile); + + // Restore + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Restoring..."); + string dotnetArgs = $"restore {projectNameToTest} -s {NuGetOrgPackages} -s {LocalPackages} -p:SdkVersion={SdkVersion}"; + int? exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); + + // Publish + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Publishing..."); + dotnetArgs = $"publish {projectNameToTest} --configuration {Configuration} -o {outputDir} -p:SdkVersion={SdkVersion} {additionalParams}"; + exitCode = await new ProcessWrapper().RunProcess(DotNetExecutable, dotnetArgs, projectFileDirectory, testOutputHelper: outputHelper); + Assert.True(exitCode.HasValue && exitCode.Value == 0); + outputHelper.WriteLine($"[{DateTime.UtcNow:O}] Done."); + } + + private static string InitializeOutputDir(string testName) + { + string outputDir = Path.Combine(TestOutputDir, testName); + + if (Directory.Exists(outputDir)) + { + Directory.Delete(outputDir, recursive: true); + } + + Directory.CreateDirectory(outputDir); + + return outputDir; } public static async Task RemoveDockerTestImage(string repository, string imageTag, ITestOutputHelper outputHelper) { outputHelper.WriteLine($"Removing image {repository}:{imageTag} from local registry"); - int? rmiExitCode = await ProcessWrapper.RunProcessAsync("docker", $"rmi -f {repository}:{imageTag}", log: outputHelper.WriteLine); + int? rmiExitCode = await new ProcessWrapper().RunProcess("docker", $"rmi -f {repository}:{imageTag}", TestOutputDir, outputHelper); Assert.True(rmiExitCode.HasValue && rmiExitCode.Value == 0); // daemon may still error if the image doesn't exist, but it will still return 0 } } diff --git a/test/Sdk.E2ETests/ZipDeployTests.cs b/test/Sdk.E2ETests/ZipDeployTests.cs index b683a5041..5d8c522a2 100644 --- a/test/Sdk.E2ETests/ZipDeployTests.cs +++ b/test/Sdk.E2ETests/ZipDeployTests.cs @@ -1,5 +1,6 @@ using System; using System.IO; +using System.Runtime.InteropServices; using System.Threading.Tasks; using ICSharpCode.SharpZipLib.Zip; using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; @@ -8,11 +9,14 @@ namespace Microsoft.Azure.Functions.Sdk.E2ETests { - public sealed class ZipDeployTests(ITestOutputHelper testOutputHelper) : IDisposable + public class ZipDeployTests { - private readonly ProjectBuilder _builder = new( - testOutputHelper, - Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj")); + private ITestOutputHelper _testOutputHelper; + + public ZipDeployTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } [Theory] [InlineData("linux-x64", true)] @@ -21,7 +25,9 @@ public sealed class ZipDeployTests(ITestOutputHelper testOutputHelper) : IDispos public async Task CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContained(string rid, bool selfContained) { string testName = nameof(CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContained); - string zipName = Path.Combine(Directory.GetParent(_builder.OutputPath).FullName, $"{testName}.zip"); + string directoryToZip = await TestUtility.InitializeTestAsync(_testOutputHelper, testName); + + string zipName = Path.Combine(Directory.GetParent(directoryToZip).FullName, $"{testName}.zip"); if (File.Exists(zipName)) { @@ -30,13 +36,13 @@ public async Task CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContaine string projectFileDirectory = Path.Combine(TestUtility.SamplesRoot, "FunctionApp", "FunctionApp.csproj"); - await _builder.PublishAsync($"-r {rid} --self-contained {selfContained}"); + await TestUtility.RestoreAndPublishProjectAsync( + projectFileDirectory, directoryToZip, $"-r {rid} --self-contained {selfContained}", _testOutputHelper); - CreateZipFileTask.CreateZipFileFromDirectory(_builder.OutputPath, zipName); + CreateZipFileTask.CreateZipFileFromDirectory(directoryToZip, zipName); using var zip = new ZipFile(zipName); - Assert.Equal(Directory.GetFiles(_builder.OutputPath, "*", SearchOption.AllDirectories).Length, zip.Count); - + Assert.Equal(Directory.GetFiles(directoryToZip, "*", SearchOption.AllDirectories).Length, zip.Count); foreach (ZipEntry entry in zip) { if (selfContained && (entry.Name == "FunctionApp" || entry.Name == "FunctionApp.exe")) @@ -58,10 +64,6 @@ public async Task CreateZipFileFromDirectory_SetsExecutableFlag_WhenSelfContaine Assert.NotEqual(0, entry.ExternalFileAttributes); } } - - zip.Close(); } - - public void Dispose() => _builder.Dispose(); } } From 81b2eb1c25a0cf2ac1d5e0ae3e2b72529968aca2 Mon Sep 17 00:00:00 2001 From: Shyju Krishnankutty Date: Wed, 12 Nov 2025 16:54:24 -0800 Subject: [PATCH 188/190] worker SDK 2.0.7 release prep (#3247) * 2.0.7 worker SDK release prep. * revert release note change --- sdk/Sdk/Sdk.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/Sdk/Sdk.csproj b/sdk/Sdk/Sdk.csproj index 9b3e90b49..1da879421 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -3,7 +3,7 @@ 2 0 - 6 + 7 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. From 705a2bfb36a13b40e7b0a694b1670645558fe321 Mon Sep 17 00:00:00 2001 From: Rohit Ranjan <90008725+RohitRanjanMS@users.noreply.github.com> Date: Wed, 12 Nov 2025 20:16:20 -0800 Subject: [PATCH 189/190] Worker instrumentation (#3195) * Updating worker instrumentation. --- .../Context/DefaultTraceContext.cs | 9 +- src/DotNetWorker.Core/Context/TraceContext.cs | 10 +- .../Diagnostics/ActivityExtensions.cs | 110 ---------------- .../FunctionActivitySourceFactory.cs | 66 ---------- .../Diagnostics/FunctionInvocationScope.cs | 61 --------- .../Diagnostics/OpenTelemetrySchemaVersion.cs | 5 +- .../Telemetry/IFunctionTelemetryProvider.cs | 30 +++++ .../Telemetry/TelemetryProvider.cs | 118 ++++++++++++++++++ .../Telemetry/TelemetryProviderV1_17_0.cs | 37 ++++++ .../Telemetry/TelemetryProviderV1_37_0.cs | 57 +++++++++ .../Diagnostics/TraceConstants.cs | 73 +++++++---- src/DotNetWorker.Core/FunctionsApplication.cs | 37 ++---- .../Hosting/ServiceCollectionExtensions.cs | 30 ++++- .../Hosting/WorkerOptions.cs | 4 +- .../GrpcFunctionInvocation.cs | 4 +- .../GrpcFunctionsHostLogWriter.cs | 4 +- .../ConfigureFunctionsOpenTelemetry.cs | 11 +- .../DotNetWorker.OpenTelemetry.csproj | 6 +- .../OpenTelemetryConstants.cs | 8 +- .../ResourceSemanticConventions.cs | 4 +- .../EndToEndTests.cs | 96 ++++++++++++-- .../ApplicationInsights/EndToEndTests.cs | 12 +- .../Diagnostics/GrpcHostLoggerTests.cs | 10 +- .../FunctionsApplicationTests.cs | 8 +- test/TestUtility/TestFunctionInvocation.cs | 14 ++- 25 files changed, 489 insertions(+), 335 deletions(-) delete mode 100644 src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs delete mode 100644 src/DotNetWorker.Core/Diagnostics/FunctionActivitySourceFactory.cs delete mode 100644 src/DotNetWorker.Core/Diagnostics/FunctionInvocationScope.cs create mode 100644 src/DotNetWorker.Core/Diagnostics/Telemetry/IFunctionTelemetryProvider.cs create mode 100644 src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProvider.cs create mode 100644 src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_17_0.cs create mode 100644 src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_37_0.cs diff --git a/src/DotNetWorker.Core/Context/DefaultTraceContext.cs b/src/DotNetWorker.Core/Context/DefaultTraceContext.cs index a3994901f..10e9fdcd9 100644 --- a/src/DotNetWorker.Core/Context/DefaultTraceContext.cs +++ b/src/DotNetWorker.Core/Context/DefaultTraceContext.cs @@ -1,18 +1,23 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System.Collections.Generic; + namespace Microsoft.Azure.Functions.Worker { internal sealed class DefaultTraceContext : TraceContext { - public DefaultTraceContext(string traceParent, string traceState) + public DefaultTraceContext(string traceParent, string traceState, IReadOnlyDictionary attributes) { TraceParent = traceParent; TraceState = traceState; + Attributes = attributes; } public override string TraceParent { get; } public override string TraceState { get; } + + public override IReadOnlyDictionary Attributes { get; } } } diff --git a/src/DotNetWorker.Core/Context/TraceContext.cs b/src/DotNetWorker.Core/Context/TraceContext.cs index d663db340..8ffc1030a 100644 --- a/src/DotNetWorker.Core/Context/TraceContext.cs +++ b/src/DotNetWorker.Core/Context/TraceContext.cs @@ -1,6 +1,9 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. +using System.Collections.Generic; +using System.Collections.Immutable; + namespace Microsoft.Azure.Functions.Worker { /// @@ -17,5 +20,10 @@ public abstract class TraceContext /// Gets the state data. /// public abstract string TraceState { get; } + + /// + /// Gets the attributes associated with the trace. + /// + public virtual IReadOnlyDictionary Attributes => ImmutableDictionary.Empty; } } diff --git a/src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs b/src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs deleted file mode 100644 index 2e53a05c6..000000000 --- a/src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs +++ /dev/null @@ -1,110 +0,0 @@ -// 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.Diagnostics; -using System.Linq.Expressions; -using System.Reflection; - -namespace Microsoft.Azure.Functions.Worker.Diagnostics -{ - internal static class ActivityExtensions - { - - private static readonly Action _setSpanId; - private static readonly Action _setId; - private static readonly Action _setTraceId; - private static readonly Action _setRootId; - - static ActivityExtensions() - { - BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; - var activityType = typeof(Activity); - - // Empty setter serves as a safe fallback mechanism to handle cases where the field is not available. - _setSpanId = activityType.GetField("_spanId", flags)?.CreateSetter() ?? ((_, _) => { /* Ignore */ }); - _setId = activityType.GetField("_id", flags)?.CreateSetter() ?? ((_, _) => { /* Ignore */ }); - _setRootId = activityType.GetField("_rootId", flags)?.CreateSetter() ?? ((_, _) => { /* Ignore */ }); - _setTraceId = activityType.GetField("_traceId", flags)?.CreateSetter() ?? ((_, _) => { /* Ignore */ }); - } - - /// - /// Records an exception as an ActivityEvent. - /// - /// The Activity. - /// The exception. - /// If the exception is re-thrown out of the current span, set to true. - /// See https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/exceptions/#recording-an-exception. - /// - public static void RecordException(this Activity activity, Exception ex, bool escaped) - { - if (ex == null) - { - return; - } - - var tagsCollection = new ActivityTagsCollection - { - { TraceConstants.AttributeExceptionType, ex.GetType().FullName }, - { TraceConstants.AttributeExceptionStacktrace, ex.ToString() } - }; - - if (!string.IsNullOrWhiteSpace(ex.Message)) - { - tagsCollection.Add(TraceConstants.AttributeExceptionMessage, ex.Message); - } - - if (escaped) - { - tagsCollection.Add(TraceConstants.AttributeExceptionEscaped, true); - } - - activity?.AddEvent(new ActivityEvent(TraceConstants.AttributeExceptionEventName, default, tagsCollection)); - } - - public static void SetId(this Activity activity, string id) - => _setId(activity, id); - - public static void SetSpanId(this Activity activity, string spanId) - => _setSpanId(activity, spanId); - - public static void SetRootId(this Activity activity, string rootId) - => _setRootId(activity, rootId); - - public static void SetTraceId(this Activity activity, string traceId) - => _setTraceId(activity, traceId); - } - - internal static class FieldInfoExtensionMethods - { - /// - /// Create a re-usable setter for a . - /// When cached and reused, This is quicker than using . - /// - /// The target type of the object. - /// The value type of the field. - /// The field info. - /// A re-usable action to set the field. - internal static Action CreateSetter(this FieldInfo fieldInfo) - { - if (fieldInfo == null) - { - throw new ArgumentNullException(nameof(fieldInfo)); - } - - ParameterExpression targetExp = Expression.Parameter(typeof(TTarget), "target"); - Expression source = targetExp; - - if (fieldInfo.DeclaringType is { } t && t != typeof(TTarget)) - { - source = Expression.Convert(targetExp, t); - } - - // Creating the setter to set the value to the field - ParameterExpression valueExp = Expression.Parameter(typeof(TValue), "value"); - MemberExpression fieldExp = Expression.Field(source, fieldInfo); - BinaryExpression assignExp = Expression.Assign(fieldExp, valueExp); - return Expression.Lambda>(assignExp, targetExp, valueExp).Compile(); - } - } -} diff --git a/src/DotNetWorker.Core/Diagnostics/FunctionActivitySourceFactory.cs b/src/DotNetWorker.Core/Diagnostics/FunctionActivitySourceFactory.cs deleted file mode 100644 index 6b472deb7..000000000 --- a/src/DotNetWorker.Core/Diagnostics/FunctionActivitySourceFactory.cs +++ /dev/null @@ -1,66 +0,0 @@ -// 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.Collections.Immutable; -using System.Diagnostics; -using Microsoft.Extensions.Options; - -namespace Microsoft.Azure.Functions.Worker.Diagnostics -{ - internal class FunctionActivitySourceFactory - { - private static readonly ActivitySource _activitySource = new(TraceConstants.FunctionsActivitySource, TraceConstants.FunctionsActivitySourceVersion); - private readonly string _schemaVersionUrl; - private readonly Lazy> _attributeMap; - - public FunctionActivitySourceFactory(IOptions options) - { - _attributeMap = new Lazy>(() => GetMapping(options.Value.OpenTelemetrySchemaVersion)); - _schemaVersionUrl = TraceConstants.OpenTelemetrySchemaMap[options.Value.OpenTelemetrySchemaVersion]; - } - - public Activity? StartInvoke(FunctionContext context) - { - Activity? activity = null; - - if (_activitySource.HasListeners()) - { - ActivityContext.TryParse(context.TraceContext.TraceParent, context.TraceContext.TraceState, out ActivityContext activityContext); - - activity = _activitySource.StartActivity(TraceConstants.FunctionsInvokeActivityName, ActivityKind.Server, activityContext, - tags: GetTags(context)); - } - - return activity; - } - - /// - /// Provides key mappings for different schema versions. For example, in early versions the invocation id may be - /// represented by "faas.execution" and then later change to "faas.invocation". We want to allow for each of these as - /// exporters may be relying on them. - /// - /// - /// The mapped key name. - /// - private static IReadOnlyDictionary GetMapping(OpenTelemetrySchemaVersion schemaVersion) - { - return schemaVersion switch - { - OpenTelemetrySchemaVersion.v1_17_0 => ImmutableDictionary.Empty, - _ => throw new InvalidOperationException("Schema not supported."), - }; - } - - private IEnumerable> GetTags(FunctionContext context) - { - yield return new(TraceConstants.AttributeSchemaUrl, _schemaVersionUrl); - - string GetKeyMapping(string key) => _attributeMap.Value.GetValueOrDefault(key, key); - - // Using as an example of how to map if schemas change. - yield return new(GetKeyMapping(TraceConstants.AttributeFaasExecution), context.InvocationId); - } - } -} diff --git a/src/DotNetWorker.Core/Diagnostics/FunctionInvocationScope.cs b/src/DotNetWorker.Core/Diagnostics/FunctionInvocationScope.cs deleted file mode 100644 index 49e5d7e17..000000000 --- a/src/DotNetWorker.Core/Diagnostics/FunctionInvocationScope.cs +++ /dev/null @@ -1,61 +0,0 @@ -// 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; -using System.Collections.Generic; - -namespace Microsoft.Azure.Functions.Worker.Diagnostics -{ - internal class FunctionInvocationScope : IReadOnlyList> - { - internal const string FunctionInvocationIdKey = "AzureFunctions_InvocationId"; - internal const string FunctionNameKey = "AzureFunctions_FunctionName"; - - private readonly string _invocationId; - private readonly string _functionName; - - private string? _cachedToString; - - public FunctionInvocationScope(string functionName, string invocationid) - { - _functionName = functionName; - _invocationId = invocationid; - } - - public KeyValuePair this[int index] - { - get - { - return index switch - { - 0 => new KeyValuePair(FunctionInvocationIdKey, _invocationId), - 1 => new KeyValuePair(FunctionNameKey, _functionName), - _ => throw new ArgumentOutOfRangeException(nameof(index)), - }; - } - } - - public int Count => 2; - - public IEnumerator> GetEnumerator() - { - for (var i = 0; i < Count; ++i) - { - yield return this[i]; - } - } - - IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); - - public override string ToString() - { - if (_cachedToString == null) - { - _cachedToString = FormattableString.Invariant($"{FunctionNameKey}:{_functionName} {FunctionInvocationIdKey}:{_invocationId}"); - } - - return _cachedToString; - } - } -} diff --git a/src/DotNetWorker.Core/Diagnostics/OpenTelemetrySchemaVersion.cs b/src/DotNetWorker.Core/Diagnostics/OpenTelemetrySchemaVersion.cs index 8b2e17a92..c24727bfd 100644 --- a/src/DotNetWorker.Core/Diagnostics/OpenTelemetrySchemaVersion.cs +++ b/src/DotNetWorker.Core/Diagnostics/OpenTelemetrySchemaVersion.cs @@ -1,10 +1,11 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. namespace Microsoft.Azure.Functions.Worker.Diagnostics { internal enum OpenTelemetrySchemaVersion { - v1_17_0 + V1_17_0, + V1_37_0 } } diff --git a/src/DotNetWorker.Core/Diagnostics/Telemetry/IFunctionTelemetryProvider.cs b/src/DotNetWorker.Core/Diagnostics/Telemetry/IFunctionTelemetryProvider.cs new file mode 100644 index 000000000..e9560ffb0 --- /dev/null +++ b/src/DotNetWorker.Core/Diagnostics/Telemetry/IFunctionTelemetryProvider.cs @@ -0,0 +1,30 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.Azure.Functions.Worker.Diagnostics; + +/// +/// Provides methods for telemetry data collection related to function invocations. +/// +/// This interface defines methods to retrieve telemetry attributes and manage the activity lifecycle for +/// function invocations, enabling detailed monitoring and diagnostics. +internal interface IFunctionTelemetryProvider +{ + /// + /// Returns the attributes to be applied to the Scope for this invocation. + /// + IEnumerable> GetScopeAttributes(FunctionContext ctx); + + /// + /// Returns the attributes to be applied to the Activity for this invocation. + /// + IEnumerable> GetTagAttributes(FunctionContext ctx); + + /// + /// Starts the Activity for this invocation. + /// + Activity? StartActivityForInvocation(FunctionContext ctx); +} diff --git a/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProvider.cs b/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProvider.cs new file mode 100644 index 000000000..d5c224dad --- /dev/null +++ b/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProvider.cs @@ -0,0 +1,118 @@ +// 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.Diagnostics; + +namespace Microsoft.Azure.Functions.Worker.Diagnostics; + +internal abstract class TelemetryProvider : IFunctionTelemetryProvider +{ + private static readonly ActivitySource _source + = new(TraceConstants.ActivityAttributes.Name, TraceConstants.ActivityAttributes.Version); + + protected abstract OpenTelemetrySchemaVersion SchemaVersion { get; } + + protected abstract ActivityKind Kind { get; } + + /// + /// Creates a telemetry provider based on the provided schema version string. + /// Returns the default (1.17.0) if no version is provided. + /// + /// + /// + public static TelemetryProvider Create(string? schema = null) + { + if (string.IsNullOrWhiteSpace(schema)) + { + return Create(OpenTelemetrySchemaVersion.V1_17_0); + } + + var version = ParseSchemaVersion(schema!); + return Create(version); + } + + /// + /// Returns a telemetry provider for the specified version. + /// + /// + /// + /// + public static TelemetryProvider Create(OpenTelemetrySchemaVersion version) + { + return version switch + { + OpenTelemetrySchemaVersion.V1_17_0 => new TelemetryProviderV1_17_0(), + OpenTelemetrySchemaVersion.V1_37_0 => new TelemetryProviderV1_37_0(), + _ => throw new ArgumentException($"Unsupported OpenTelemetry schema version: {version}") + }; + } + + /// + /// Starts an activity for the function invocation. + /// + /// + /// + public Activity? StartActivityForInvocation(FunctionContext context) + { + if (!_source.HasListeners()) + { + return null; + } + + ActivityContext.TryParse( + context.TraceContext.TraceParent, + context.TraceContext.TraceState, + out var parent); + + // If there is no parent, we still want to create a new root activity. + return _source.StartActivity( + GetActivityName(context), + Kind, + parent, + tags: GetTagAttributes(context)!); + } + + /// + /// Returns common scope attributes for a schema versions. + /// + /// + /// + public virtual IEnumerable> GetScopeAttributes(FunctionContext context) + { + // Live-logs session + if (context.TraceContext.Attributes.TryGetValue(TraceConstants.InternalKeys.AzFuncLiveLogsSessionId, out var liveId) + && !string.IsNullOrWhiteSpace(liveId)) + { + yield return new(TraceConstants.InternalKeys.AzFuncLiveLogsSessionId, liveId); + } + } + + protected virtual string GetActivityName(FunctionContext context) + { + return TraceConstants.ActivityAttributes.InvokeActivityName; + } + + /// + /// Returns common tag attributes for a schema versions. + /// + /// + /// + public abstract IEnumerable> GetTagAttributes(FunctionContext context); + + /// + /// Maps only known version strings to the enum. + /// If the string is anything else (and was explicitly set), we throw. + /// + private static OpenTelemetrySchemaVersion ParseSchemaVersion(string version) + { + return version switch + { + "1.17.0" => OpenTelemetrySchemaVersion.V1_17_0, + "1.37.0" => OpenTelemetrySchemaVersion.V1_37_0, + _ => throw new ArgumentException( + $"Invalid OpenTelemetry schema version '{version}'. ", nameof(version)) + }; + } +} diff --git a/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_17_0.cs b/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_17_0.cs new file mode 100644 index 000000000..1e5517253 --- /dev/null +++ b/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_17_0.cs @@ -0,0 +1,37 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.Azure.Functions.Worker.Diagnostics; + +internal sealed class TelemetryProviderV1_17_0 : TelemetryProvider +{ + private static readonly KeyValuePair SchemaUrlAttribute = + new(TraceConstants.OTelAttributes_1_17_0.SchemaUrl, TraceConstants.OTelAttributes_1_17_0.SchemaVersion); + + protected override OpenTelemetrySchemaVersion SchemaVersion + => OpenTelemetrySchemaVersion.V1_17_0; + + protected override ActivityKind Kind + => ActivityKind.Server; + + public override IEnumerable> GetScopeAttributes(FunctionContext context) + { + foreach (var kv in base.GetScopeAttributes(context)) + { + yield return kv; + } + + yield return SchemaUrlAttribute; + yield return new(TraceConstants.InternalKeys.FunctionInvocationId, context.InvocationId); + yield return new(TraceConstants.InternalKeys.FunctionName, context.FunctionDefinition.Name); + } + + public override IEnumerable> GetTagAttributes(FunctionContext context) + { + yield return SchemaUrlAttribute; + yield return new(TraceConstants.OTelAttributes_1_17_0.InvocationId, context.InvocationId); + } +} diff --git a/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_37_0.cs b/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_37_0.cs new file mode 100644 index 000000000..64cca693f --- /dev/null +++ b/src/DotNetWorker.Core/Diagnostics/Telemetry/TelemetryProviderV1_37_0.cs @@ -0,0 +1,57 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using System.Collections.Generic; +using System.Diagnostics; + +namespace Microsoft.Azure.Functions.Worker.Diagnostics; + +internal sealed class TelemetryProviderV1_37_0 : TelemetryProvider +{ + private static readonly KeyValuePair SchemaUrlAttribute = + new(TraceConstants.OTelAttributes_1_37_0.SchemaUrl, TraceConstants.OTelAttributes_1_37_0.SchemaVersion); + protected override OpenTelemetrySchemaVersion SchemaVersion + => OpenTelemetrySchemaVersion.V1_37_0; + + protected override ActivityKind Kind + => ActivityKind.Internal; + + public override IEnumerable> GetScopeAttributes(FunctionContext context) + { + foreach (var kv in base.GetScopeAttributes(context)) + { + yield return kv; + } + + foreach (var kv in GetCommonAttributes(context)) + { + yield return kv; + } + } + + public override IEnumerable> GetTagAttributes(FunctionContext context) + { + foreach (var kv in GetCommonAttributes(context)) + { + yield return kv; + } + } + + protected override string GetActivityName(FunctionContext context) + { + return $"{TraceConstants.ActivityAttributes.FunctionActivityName} {context.FunctionDefinition.Name}"; + } + + private IEnumerable> GetCommonAttributes(FunctionContext context) + { + yield return SchemaUrlAttribute; + yield return new(TraceConstants.OTelAttributes_1_37_0.InvocationId, context.InvocationId); + yield return new(TraceConstants.OTelAttributes_1_37_0.FunctionName, context.FunctionDefinition.Name); + + if (context.TraceContext.Attributes.TryGetValue(TraceConstants.InternalKeys.HostInstanceId, out var host) + && !string.IsNullOrEmpty(host)) + { + yield return new(TraceConstants.OTelAttributes_1_37_0.Instance, host); + } + } +} diff --git a/src/DotNetWorker.Core/Diagnostics/TraceConstants.cs b/src/DotNetWorker.Core/Diagnostics/TraceConstants.cs index c8d7ecafc..f2c086f6e 100644 --- a/src/DotNetWorker.Core/Diagnostics/TraceConstants.cs +++ b/src/DotNetWorker.Core/Diagnostics/TraceConstants.cs @@ -1,31 +1,58 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System.Collections.Generic; -namespace Microsoft.Azure.Functions.Worker.Diagnostics +namespace Microsoft.Azure.Functions.Worker.Diagnostics; + +internal static class TraceConstants { - internal class TraceConstants + public static class ActivityAttributes + { + public static readonly string Version = typeof(ActivityAttributes).Assembly.GetName().Version?.ToString() ?? string.Empty; + public const string Name = "Microsoft.Azure.Functions.Worker"; + public const string InvokeActivityName = "Invoke"; + public const string FunctionActivityName = "function"; + } + + public static class ExceptionAttributes + { + public const string EventName = "exception"; + public const string Type = "exception.type"; + public const string Message = "exception.message"; + public const string Stacktrace = "exception.stacktrace"; + public const string Escaped = "exception.escaped"; + } + + public static class OTelAttributes_1_17_0 + { + // v1.17.0 + public const string InvocationId = "faas.execution"; + public const string SchemaUrl = "az.schema_url"; + public const string SchemaVersion = "https://opentelemetry.io/schemas/1.17.0"; + } + + public static class OTelAttributes_1_37_0 + { + // v1.37.0 + public const string InvocationId = "faas.invocation_id"; + public const string FunctionName = "faas.name"; + public const string Instance = "faas.instance"; + public const string SchemaUrl = "schema.url"; + public const string SchemaVersion = "https://opentelemetry.io/schemas/1.37.0"; + } + + public static class InternalKeys + { + public const string FunctionInvocationId = "AzureFunctions_InvocationId"; + public const string FunctionName = "AzureFunctions_FunctionName"; + public const string HostInstanceId = "HostInstanceId"; + public const string AzFuncLiveLogsSessionId = "#AzFuncLiveLogsSessionId"; + } + + public static class CapabilityFlags { - public const string FunctionsActivitySource = "Microsoft.Azure.Functions.Worker"; - public const string FunctionsActivitySourceVersion = "1.0.0.0"; - public const string FunctionsInvokeActivityName = "Invoke"; - - public const string AttributeExceptionEventName = "exception"; - public const string AttributeExceptionType = "exception.type"; - public const string AttributeExceptionMessage = "exception.message"; - public const string AttributeExceptionStacktrace = "exception.stacktrace"; - public const string AttributeExceptionEscaped = "exception.escaped"; - - public const string AttributeSchemaUrl = "az.schema_url"; - public static IReadOnlyDictionary OpenTelemetrySchemaMap = - new Dictionary() - { - [OpenTelemetrySchemaVersion.v1_17_0] = "https://opentelemetry.io/schemas/1.17.0" - }; - - // from: https://opentelemetry.io/docs/reference/specification/trace/semantic_conventions/faas/ - // https://opentelemetry.io/docs/reference/specification/resource/semantic_conventions/faas/ - public const string AttributeFaasExecution = "faas.execution"; + public const string WorkerOTelEnabled = "WorkerOpenTelemetryEnabled"; + public const string WorkerOTelSchemaVersion = "WorkerOpenTelemetrySchemaVersion"; } } diff --git a/src/DotNetWorker.Core/FunctionsApplication.cs b/src/DotNetWorker.Core/FunctionsApplication.cs index 11db9d003..40157f9c0 100644 --- a/src/DotNetWorker.Core/FunctionsApplication.cs +++ b/src/DotNetWorker.Core/FunctionsApplication.cs @@ -1,9 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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.Concurrent; using System.Diagnostics; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Diagnostics; @@ -22,7 +23,7 @@ internal partial class FunctionsApplication : IFunctionsApplication private readonly IOptions _workerOptions; private readonly ILogger _logger; private readonly IWorkerDiagnostics _diagnostics; - private readonly FunctionActivitySourceFactory _functionActivitySourceFactory; + private readonly IFunctionTelemetryProvider _functionTelemetryProvider; public FunctionsApplication( FunctionExecutionDelegate functionExecutionDelegate, @@ -30,14 +31,14 @@ public FunctionsApplication( IOptions workerOptions, ILogger logger, IWorkerDiagnostics diagnostics, - FunctionActivitySourceFactory functionActivitySourceFactory) + IFunctionTelemetryProvider functionTelemetryProvider) { _functionExecutionDelegate = functionExecutionDelegate ?? throw new ArgumentNullException(nameof(functionExecutionDelegate)); _functionContextFactory = functionContextFactory ?? throw new ArgumentNullException(nameof(functionContextFactory)); _workerOptions = workerOptions ?? throw new ArgumentNullException(nameof(workerOptions)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _diagnostics = diagnostics ?? throw new ArgumentNullException(nameof(diagnostics)); - _functionActivitySourceFactory = functionActivitySourceFactory ?? throw new ArgumentNullException(nameof(functionActivitySourceFactory)); + _functionTelemetryProvider = functionTelemetryProvider ?? throw new ArgumentNullException(nameof(functionTelemetryProvider)); } public FunctionContext CreateContext(IInvocationFeatures features, CancellationToken token = default) @@ -67,29 +68,8 @@ public void LoadFunction(FunctionDefinition definition) public async Task InvokeFunctionAsync(FunctionContext context) { - Activity? activity = null; - - if (Activity.Current is null) - { - // This will act as an internal activity that represents remote Host activity. This cannot be tracked as this is not associate to an ActivitySource. - activity = new Activity(nameof(InvokeFunctionAsync)); - activity.Start(); - - if (ActivityContext.TryParse(context.TraceContext.TraceParent, context.TraceContext.TraceState, true, out ActivityContext activityContext)) - { - activity.SetId(context.TraceContext.TraceParent); - activity.SetSpanId(activityContext.SpanId.ToString()); - activity.SetTraceId(activityContext.TraceId.ToString()); - activity.SetRootId(activityContext.TraceId.ToString()); - activity.ActivityTraceFlags = activityContext.TraceFlags; - activity.TraceStateString = activityContext.TraceState; - } - } - - var scope = new FunctionInvocationScope(context.FunctionDefinition.Name, context.InvocationId); - - using var logScope = _logger.BeginScope(scope); - using Activity? invokeActivity = _functionActivitySourceFactory.StartInvoke(context); + using var logScope = _logger.BeginScope(_functionTelemetryProvider.GetScopeAttributes(context).ToList()); + using Activity? invokeActivity = _functionTelemetryProvider.StartActivityForInvocation(context); try { @@ -103,9 +83,6 @@ public async Task InvokeFunctionAsync(FunctionContext context) throw; } - - invokeActivity?.Stop(); - activity?.Stop(); } } } diff --git a/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs b/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs index daf3fca75..66fe25808 100644 --- a/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs +++ b/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -84,8 +84,7 @@ public static IFunctionsWorkerApplicationBuilder AddFunctionsWorkerCore(this ISe services.TryAddSingleton(s => s.GetRequiredService()); services.TryAddSingleton(s => s.GetRequiredService()); services.TryAddSingleton(s => s.GetRequiredService()); - services.TryAddSingleton(); - + if (configure != null) { services.Configure(configure); @@ -114,6 +113,8 @@ public static IFunctionsWorkerApplicationBuilder AddFunctionsWorkerCore(this ISe RunExtensionStartupCode(builder); } + services.AddFunctionTelemetry(); + return builder; } @@ -126,6 +127,29 @@ internal static IServiceCollection AddDefaultInputConvertersToWorkerOptions(this return services; } + /// + /// Adds function telemetry services to the specified . + /// + /// This method registers a singleton + /// implementation based on the OpenTelemetry schema version specified in the worker options. The schema version is determined + /// from the "WorkerOpenTelemetrySchemaVersion" capability. If the schema version is unsupported, an is thrown. + /// The to which the telemetry services are added. + /// The modified with telemetry services registered. + /// Thrown if the specified OpenTelemetry schema version is unsupported. + internal static IServiceCollection AddFunctionTelemetry(this IServiceCollection services) + { + services.TryAddSingleton(sp => + { + WorkerOptions options = sp.GetRequiredService>().Value; + + options.Capabilities.TryGetValue(TraceConstants.CapabilityFlags.WorkerOTelSchemaVersion, out var schemaVersion); + return TelemetryProvider.Create(schemaVersion); + }); + + return services; + } + /// /// Run extension startup execution code. /// Our source generator creates a class(WorkerExtensionStartupCodeExecutor) diff --git a/src/DotNetWorker.Core/Hosting/WorkerOptions.cs b/src/DotNetWorker.Core/Hosting/WorkerOptions.cs index c71b6dc1e..a360e4183 100644 --- a/src/DotNetWorker.Core/Hosting/WorkerOptions.cs +++ b/src/DotNetWorker.Core/Hosting/WorkerOptions.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -66,7 +66,7 @@ public bool IncludeEmptyEntriesInMessagePayload /// Gets or sets a value that determines the schema to use when generating Activities. Currently internal as there is only /// one schema, but stubbing this out for future use. /// - internal OpenTelemetrySchemaVersion OpenTelemetrySchemaVersion { get; set; } = OpenTelemetrySchemaVersion.v1_17_0; + internal OpenTelemetrySchemaVersion OpenTelemetrySchemaVersion { get; set; } = OpenTelemetrySchemaVersion.V1_17_0; private bool GetBoolCapability(string name) { diff --git a/src/DotNetWorker.Grpc/GrpcFunctionInvocation.cs b/src/DotNetWorker.Grpc/GrpcFunctionInvocation.cs index 0cf79374d..3e14df92d 100644 --- a/src/DotNetWorker.Grpc/GrpcFunctionInvocation.cs +++ b/src/DotNetWorker.Grpc/GrpcFunctionInvocation.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using Microsoft.Azure.Functions.Worker.Grpc.Messages; @@ -13,7 +13,7 @@ internal sealed class GrpcFunctionInvocation : FunctionInvocation, IExecutionRet public GrpcFunctionInvocation(InvocationRequest invocationRequest) { _invocationRequest = invocationRequest; - TraceContext = new DefaultTraceContext(_invocationRequest.TraceContext.TraceParent, _invocationRequest.TraceContext.TraceState); + TraceContext = new DefaultTraceContext(_invocationRequest.TraceContext.TraceParent, _invocationRequest.TraceContext.TraceState, _invocationRequest.TraceContext.Attributes); } public override string Id => _invocationRequest.InvocationId; diff --git a/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs b/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs index f04cd3a5d..84245fe6a 100644 --- a/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs +++ b/src/DotNetWorker.Grpc/GrpcFunctionsHostLogWriter.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -88,7 +88,7 @@ private RpcLog AppendInvocationIdToLog(RpcLog rpcLog, IExternalScopeProvider sco { foreach (var pair in properties) { - if (pair.Key == FunctionInvocationScope.FunctionInvocationIdKey) + if (pair.Key == TraceConstants.InternalKeys.FunctionInvocationId) { log.InvocationId = pair.Value?.ToString(); break; diff --git a/src/DotNetWorker.OpenTelemetry/ConfigureFunctionsOpenTelemetry.cs b/src/DotNetWorker.OpenTelemetry/ConfigureFunctionsOpenTelemetry.cs index a31ab6e8a..0e5d04328 100644 --- a/src/DotNetWorker.OpenTelemetry/ConfigureFunctionsOpenTelemetry.cs +++ b/src/DotNetWorker.OpenTelemetry/ConfigureFunctionsOpenTelemetry.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -18,13 +18,20 @@ public static IOpenTelemetryBuilder UseFunctionsWorkerDefaults(this IOpenTelemet builder.Services // Tells the host to no longer emit telemetry on behalf of the worker. - .Configure(workerOptions => workerOptions.Capabilities["WorkerOpenTelemetryEnabled"] = bool.TrueString); + .Configure(workerOptions => workerOptions.Capabilities[OpenTelemetryConstants.WorkerOTelEnabled] = bool.TrueString) + .Configure(workerOptions => workerOptions.Capabilities[OpenTelemetryConstants.WorkerOTelSchemaVersion] = OpenTelemetryConstants.WorkerDefaultSchemaVersion); builder.ConfigureResource((resourceBuilder) => { resourceBuilder.AddDetector(new FunctionsResourceDetector()); }); + // Add the ActivitySource so traces from the Functions Worker are captured + builder.WithTracing(tracerProviderBuilder => + { + tracerProviderBuilder.AddSource(OpenTelemetryConstants.WorkerActivitySourceName); + }); + return builder; } } diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index e9d0947e4..d38c753b6 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -16,9 +16,9 @@ - - - + + + diff --git a/src/DotNetWorker.OpenTelemetry/OpenTelemetryConstants.cs b/src/DotNetWorker.OpenTelemetry/OpenTelemetryConstants.cs index 5cdca79b3..e6124d7e3 100644 --- a/src/DotNetWorker.OpenTelemetry/OpenTelemetryConstants.cs +++ b/src/DotNetWorker.OpenTelemetry/OpenTelemetryConstants.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. namespace Microsoft.Azure.Functions.Worker.OpenTelemetry @@ -12,5 +12,11 @@ internal class OpenTelemetryConstants internal const string RegionNameEnvVar = "REGION_NAME"; internal const string ResourceGroupEnvVar = "WEBSITE_RESOURCE_GROUP"; internal const string OwnerNameEnvVar = "WEBSITE_OWNER_NAME"; + internal const string WorkerDefaultSchemaVersion = "1.37.0"; + internal const string WorkerActivitySourceName = "Microsoft.Azure.Functions.Worker"; + + // Capability variables + internal const string WorkerOTelEnabled = "WorkerOpenTelemetryEnabled"; + internal const string WorkerOTelSchemaVersion = "WorkerOpenTelemetrySchemaVersion"; } } diff --git a/src/DotNetWorker.OpenTelemetry/ResourceSemanticConventions.cs b/src/DotNetWorker.OpenTelemetry/ResourceSemanticConventions.cs index 1cc8b07b3..28d9017a7 100644 --- a/src/DotNetWorker.OpenTelemetry/ResourceSemanticConventions.cs +++ b/src/DotNetWorker.OpenTelemetry/ResourceSemanticConventions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Text; @@ -14,7 +14,7 @@ internal static class ResourceSemanticConventions internal const string CloudProvider = "cloud.provider"; internal const string CloudPlatform = "cloud.platform"; internal const string CloudRegion = "cloud.region"; - internal const string CloudResourceId = "cloud.resource.id"; + internal const string CloudResourceId = "cloud.resource_id"; // Process internal const string ProcessId = "process.pid"; diff --git a/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs b/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs index 1a60ba907..15031e67f 100644 --- a/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs +++ b/test/DotNetWorker.OpenTelemetry.Tests/EndToEndTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -32,7 +32,7 @@ public class EndToEndTests private IInvocationFeaturesFactory _invocationFeaturesFactory; private readonly OtelFunctionDefinition _funcDefinition = new(); - private IHost InitializeHost() + private IHost InitializeHost(string schemaVersion = null) { var host = new HostBuilder() .ConfigureServices(services => @@ -45,6 +45,13 @@ private IHost InitializeHost() services.AddSingleton(_ => new Mock().Object); }) + .ConfigureFunctionsWorkerDefaults((WorkerOptions options) => + { + if (schemaVersion is not null) + { + options.Capabilities["WorkerOpenTelemetrySchemaVersion"] = schemaVersion; + } + }) .Build(); _application = host.Services.GetService(); @@ -72,6 +79,7 @@ private FunctionContext CreateContext(IHost host) [Fact] public async Task ContextPropagation() { + using var testListener = new ActivityTestListener("Microsoft.Azure.Functions.Worker"); using var host = InitializeHost(); var context = CreateContext(host); await _application.InvokeFunctionAsync(context); @@ -79,12 +87,11 @@ public async Task ContextPropagation() if (ActivityContext.TryParse(context.TraceContext.TraceParent, context.TraceContext.TraceState, true, out ActivityContext activityContext)) { - Assert.Equal(activity.Id, context.TraceContext.TraceParent); - Assert.Equal("InvokeFunctionAsync", activity.OperationName); - Assert.Equal(activity.SpanId, activityContext.SpanId); + Assert.Equal("function TestName", activity.OperationName); Assert.Equal(activity.TraceId, activityContext.TraceId); - Assert.Equal(activity.ActivityTraceFlags, activityContext.TraceFlags); Assert.Equal(activity.TraceStateString, activityContext.TraceState); + Assert.Equal(ActivityKind.Internal, activity.Kind); + Assert.Contains(activity.Tags, t => t.Key == TraceConstants.OTelAttributes_1_37_0.InvocationId && t.Value == context.InvocationId); } else { @@ -92,6 +99,55 @@ public async Task ContextPropagation() } } + [Fact] + public async Task ContextPropagationV17() + { + using var testListener = new ActivityTestListener("Microsoft.Azure.Functions.Worker"); + using var host = InitializeHost("1.17.0"); + var context = CreateContext(host); + await _application.InvokeFunctionAsync(context); + var activity = OtelFunctionDefinition.LastActivity; + + if (ActivityContext.TryParse(context.TraceContext.TraceParent, context.TraceContext.TraceState, true, out ActivityContext activityContext)) + { + Assert.Equal("Invoke", activity.OperationName); + Assert.Equal(activity.TraceId, activityContext.TraceId); + Assert.Equal(activity.TraceStateString, activityContext.TraceState); + Assert.Equal(ActivityKind.Server, activity.Kind); + Assert.Contains(activity.Tags, t => t.Key == TraceConstants.OTelAttributes_1_17_0.InvocationId && t.Value == context.InvocationId); + } + else + { + Assert.Fail("Failed to parse ActivityContext"); + } + } + + [Fact] + public async Task ContextPropagation_InvalidVersion() + { + try + { + using var host = InitializeHost("0.0.0"); + var context = CreateContext(host); + await _application.InvokeFunctionAsync(context); + } + catch (Exception ex) + { + Assert.IsType(ex); + } + } + + [Fact] + public async Task ContextPropagation_EmptyVersion() + { + using var host = InitializeHost(string.Empty); + var context = CreateContext(host); + await _application.InvokeFunctionAsync(context); + + var activity = OtelFunctionDefinition.LastActivity; + Assert.Null(activity); + } + [Fact] public async Task ContextPropagationWithTriggerInstrumentation() { @@ -129,7 +185,7 @@ public void ResourceDetector() Resource resource = detector.Detect(); Assert.Equal($"/subscriptions/AAAAA-AAAAA-AAAAA-AAA/resourceGroups/rg/providers/Microsoft.Web/sites/appName" - , resource.Attributes.FirstOrDefault(a => a.Key == "cloud.resource.id").Value); + , resource.Attributes.FirstOrDefault(a => a.Key == "cloud.resource_id").Value); Assert.Equal($"EastUS", resource.Attributes.FirstOrDefault(a => a.Key == "cloud.region").Value); } @@ -175,7 +231,7 @@ public OtelFunctionDefinition() public async Task TestFunction(FunctionContext context) { LastActivity = Activity.Current; - Activity.Current.AddTag("CustomKey", "CustomValue"); + Activity.Current?.AddTag("CustomKey", "CustomValue"); var response = new HttpResponseMessage(HttpStatusCode.OK); var handler = new MockHttpMessageHandler(response); @@ -198,4 +254,28 @@ protected override async Task SendAsync(HttpRequestMessage return await Task.FromResult(_response); } } + + internal sealed class ActivityTestListener : IDisposable + { + public List Activities { get; } = new List(); + private readonly ActivityListener _listener; + + public ActivityTestListener(string sourceName) + { + _listener = new ActivityListener + { + ShouldListenTo = s => s.Name == sourceName, + Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllDataAndRecorded, + ActivityStarted = activity => Activities.Add(activity), + ActivityStopped = _ => { } + }; + + ActivitySource.AddActivityListener(_listener); + } + + public void Dispose() + { + _listener.Dispose(); + } + } } diff --git a/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs b/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs index f4914517f..ed7144bf2 100644 --- a/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs +++ b/test/DotNetWorkerTests/ApplicationInsights/EndToEndTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; @@ -205,11 +205,11 @@ private static void ValidateDependencyTelemetry(DependencyTelemetry dependency, { Assert.Equal("CustomValue", dependency.Properties["CustomKey"]); - Assert.Equal(TraceConstants.FunctionsInvokeActivityName, dependency.Name); + Assert.Equal(TraceConstants.ActivityAttributes.InvokeActivityName, dependency.Name); Assert.Equal(activity.RootId, dependency.Context.Operation.Id); - Assert.Equal(context.InvocationId, dependency.Properties[TraceConstants.AttributeFaasExecution]); - Assert.Contains(TraceConstants.AttributeSchemaUrl, dependency.Properties.Keys); + Assert.Equal(context.InvocationId, dependency.Properties[TraceConstants.OTelAttributes_1_17_0.InvocationId]); + Assert.Contains(TraceConstants.OTelAttributes_1_17_0.SchemaUrl, dependency.Properties.Keys); ValidateCommonTelemetry(dependency); } @@ -220,8 +220,8 @@ private static void ValidateTraceTelemetry(TraceTelemetry trace, FunctionContext Assert.Equal(SeverityLevel.Warning, trace.SeverityLevel); // Check that scopes show up by default - Assert.Equal("TestName", trace.Properties[FunctionInvocationScope.FunctionNameKey]); - Assert.Equal(context.InvocationId, trace.Properties[FunctionInvocationScope.FunctionInvocationIdKey]); + Assert.Equal("TestName", trace.Properties[TraceConstants.InternalKeys.FunctionName]); + Assert.Equal(context.InvocationId, trace.Properties[TraceConstants.InternalKeys.FunctionInvocationId]); Assert.Equal(activity.RootId, trace.Context.Operation.Id); diff --git a/test/DotNetWorkerTests/Diagnostics/GrpcHostLoggerTests.cs b/test/DotNetWorkerTests/Diagnostics/GrpcHostLoggerTests.cs index 73d457c08..8e7afbb04 100644 --- a/test/DotNetWorkerTests/Diagnostics/GrpcHostLoggerTests.cs +++ b/test/DotNetWorkerTests/Diagnostics/GrpcHostLoggerTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -95,7 +95,13 @@ public async Task SystemLog_WithException_AndScope() { Exception thrownException = null; - using (_scopeProvider.Push(new FunctionInvocationScope("MyFunction", "MyInvocationId"))) + var scopeValues = new Dictionary + { + ["AzureFunctions_InvocationId"] = "MyInvocationId", + ["AzureFunctions_FunctionName"] = "MyFunction" + }; + + using (_scopeProvider.Push(scopeValues)) { try { diff --git a/test/DotNetWorkerTests/FunctionsApplicationTests.cs b/test/DotNetWorkerTests/FunctionsApplicationTests.cs index 05c84c669..eb5149e4e 100644 --- a/test/DotNetWorkerTests/FunctionsApplicationTests.cs +++ b/test/DotNetWorkerTests/FunctionsApplicationTests.cs @@ -1,4 +1,4 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. using System; @@ -114,16 +114,16 @@ private static FunctionsApplication CreateApplication(FunctionExecutionDelegate var options = new OptionsWrapper(new WorkerOptions()); var contextFactory = new Mock(); var diagnostics = new Mock(); - var activityFactory = new FunctionActivitySourceFactory(new OptionsWrapper(new WorkerOptions())); + var telemetryProvider = new TelemetryProviderV1_17_0(); - return new FunctionsApplication(invoke, contextFactory.Object, options, logger, diagnostics.Object, activityFactory); + return new FunctionsApplication(invoke, contextFactory.Object, options, logger, diagnostics.Object, telemetryProvider); } private static ActivityListener CreateListener(Action onStopped) { var listener = new ActivityListener { - ShouldListenTo = source => source.Name.StartsWith(TraceConstants.FunctionsActivitySource), + ShouldListenTo = source => source.Name.StartsWith(TraceConstants.ActivityAttributes.Name), ActivityStarted = activity => { }, ActivityStopped = onStopped, Sample = (ref ActivityCreationOptions _) => ActivitySamplingResult.AllData, diff --git a/test/TestUtility/TestFunctionInvocation.cs b/test/TestUtility/TestFunctionInvocation.cs index 2004d5e61..85b4ffe42 100644 --- a/test/TestUtility/TestFunctionInvocation.cs +++ b/test/TestUtility/TestFunctionInvocation.cs @@ -1,8 +1,10 @@ -// Copyright (c) .NET Foundation. All rights reserved. +// 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.Diagnostics; +using Microsoft.Azure.Functions.Worker.Diagnostics; namespace Microsoft.Azure.Functions.Worker.Tests { @@ -21,8 +23,14 @@ public TestFunctionInvocation(string id = null, string functionId = null) } // create/dispose activity to pull off its ID. - using Activity activity = new Activity(string.Empty).Start(); - TraceContext = new DefaultTraceContext(activity.Id, Guid.NewGuid().ToString()); + using Activity activity = new Activity("Test").Start(); + Dictionary attributes = new Dictionary + { + { TraceConstants.InternalKeys.FunctionInvocationId, Guid.NewGuid().ToString() }, + { TraceConstants.InternalKeys.AzFuncLiveLogsSessionId, Guid.NewGuid().ToString() }, + }; + + TraceContext = new DefaultTraceContext(activity.Id, Guid.NewGuid().ToString(), attributes); } public override string Id { get; } = Guid.NewGuid().ToString(); From 456cca3aa0f0f42db5f21f8ed7a1277278b6eb2a Mon Sep 17 00:00:00 2001 From: Rohit Ranjan <90008725+RohitRanjanMS@users.noreply.github.com> Date: Thu, 13 Nov 2025 13:58:58 -0800 Subject: [PATCH 190/190] 2.51.0 worker packages release prep (#3250) * 2.51.0 release prep. --- release_notes.md | 12 ++++++------ src/DotNetWorker.Core/DotNetWorker.Core.csproj | 2 +- src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj | 2 +- .../DotNetWorker.OpenTelemetry.csproj | 1 - src/DotNetWorker.OpenTelemetry/release_notes.md | 4 ++-- src/DotNetWorker/DotNetWorker.csproj | 2 +- .../FunctionExecutor/DependentAssemblyTest.cs | 2 +- 7 files changed, 12 insertions(+), 13 deletions(-) diff --git a/release_notes.md b/release_notes.md index 37057e890..114ce75d3 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,14 +4,14 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) +### Microsoft.Azure.Functions.Worker (metapackage) 2.51.0 -- +- Updated worker instrumentation to improve telemetry handling. (#3195) -### Microsoft.Azure.Functions.Worker.Core +### Microsoft.Azure.Functions.Worker.Core 2.51.0 -- +- Improved telemetry handling, added OpenTelemetry schema compatibility, and streamlined context propagation. (#3195) -### Microsoft.Azure.Functions.Worker.Grpc +### Microsoft.Azure.Functions.Worker.Grpc 2.51.0 -- +- Added `Attributes` to FunctionContext.TraceContext. (#3195) diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index 1c4ad650d..a0fb1b759 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker.Core true 2 - 50 + 51 0 diff --git a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj index 4875586fe..77b177dd7 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker.Grpc true 2 - 50 + 51 0 true diff --git a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj index d38c753b6..ddebf8307 100644 --- a/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj +++ b/src/DotNetWorker.OpenTelemetry/DotNetWorker.OpenTelemetry.csproj @@ -8,7 +8,6 @@ 1 1 0 - -preview6 README.md $(BeforePack);GetReleaseNotes diff --git a/src/DotNetWorker.OpenTelemetry/release_notes.md b/src/DotNetWorker.OpenTelemetry/release_notes.md index dcad72ebb..d347a6b81 100644 --- a/src/DotNetWorker.OpenTelemetry/release_notes.md +++ b/src/DotNetWorker.OpenTelemetry/release_notes.md @@ -1,5 +1,5 @@ ## What's Changed -### Microsoft.Azure.Functions.Worker.OpenTelemetry 1.0.0 (Preview 2) +### Microsoft.Azure.Functions.Worker.OpenTelemetry 1.1.0 -- `UseFunctionsWorkerDefaults` signature now uses `IOpenTelemetryBuilder` (from `OpenTelemetryBuilder`) (#2839) \ No newline at end of file +- Updated OpenTelemetry NuGet packages and aligned implementation with Semantic Conventions v1.37. (#3195) \ No newline at end of file diff --git a/src/DotNetWorker/DotNetWorker.csproj b/src/DotNetWorker/DotNetWorker.csproj index 56863d7d5..c0e7ed7d6 100644 --- a/src/DotNetWorker/DotNetWorker.csproj +++ b/src/DotNetWorker/DotNetWorker.csproj @@ -9,7 +9,7 @@ Microsoft.Azure.Functions.Worker true 2 - 50 + 51 0 diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index 6854a4e36..ce829732e 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -139,7 +139,7 @@ public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunction private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.50.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; + var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, Microsoft.Azure.Functions.Worker.Core, Version=2.51.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor;