Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

durable task scheduler auth extension support #362

Merged
merged 58 commits into from
Jan 16, 2025
Merged
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
fc053ec
durable task scheduler auth extension
YunchuWang Jan 7, 2025
6f1d2bc
support local conn with no auth and via http
YunchuWang Jan 9, 2025
51e39bd
be consistent with azuremanaged targetversion
YunchuWang Jan 9, 2025
6987f1b
clean
YunchuWang Jan 9, 2025
e162815
namespace
YunchuWang Jan 9, 2025
e19de44
fix
YunchuWang Jan 9, 2025
3a6dc52
fix
YunchuWang Jan 9, 2025
65dfb85
doc
YunchuWang Jan 9, 2025
29445a0
ppl
YunchuWang Jan 9, 2025
e63f12a
remove
YunchuWang Jan 9, 2025
5c72ee7
test proj to sln
YunchuWang Jan 9, 2025
c6e42c5
fix warning
YunchuWang Jan 9, 2025
6a66aaa
remove dup
YunchuWang Jan 9, 2025
131c575
fix
YunchuWang Jan 9, 2025
65fa607
Revert "fix"
YunchuWang Jan 9, 2025
4f45ec5
save
YunchuWang Jan 10, 2025
d4607e4
fix
YunchuWang Jan 10, 2025
552a9c8
save
YunchuWang Jan 10, 2025
54dba76
save
YunchuWang Jan 10, 2025
5e97555
some fb
YunchuWang Jan 10, 2025
9c890c5
fix
YunchuWang Jan 10, 2025
49c6282
update
YunchuWang Jan 10, 2025
1adf7cc
update tests
YunchuWang Jan 10, 2025
14b94eb
sample
YunchuWang Jan 10, 2025
5696b2f
save
YunchuWang Jan 11, 2025
62e2b30
save
YunchuWang Jan 11, 2025
02b02c7
update
YunchuWang Jan 11, 2025
ee517d2
save
YunchuWang Jan 11, 2025
34a47ad
save
YunchuWang Jan 11, 2025
2decb79
save
YunchuWang Jan 11, 2025
ee295d0
save
YunchuWang Jan 11, 2025
522d4b0
fix
YunchuWang Jan 11, 2025
d289c10
fix
YunchuWang Jan 11, 2025
0d2a20c
Revert "sample"
YunchuWang Jan 11, 2025
f4f03fc
fix tests
YunchuWang Jan 11, 2025
59c5e9c
test accesstokencache
YunchuWang Jan 11, 2025
3dfbb72
split
YunchuWang Jan 12, 2025
5083703
fix shared
YunchuWang Jan 12, 2025
a505004
save
YunchuWang Jan 12, 2025
443613e
fix client managed
YunchuWang Jan 12, 2025
8744f8a
fix worker
YunchuWang Jan 12, 2025
37d3d5e
fix shared tests
YunchuWang Jan 12, 2025
c7f499a
fix client tests
YunchuWang Jan 12, 2025
f077e98
fix worker tests
YunchuWang Jan 12, 2025
89b7071
fix tests path
YunchuWang Jan 12, 2025
77cd2d9
update sln
YunchuWang Jan 12, 2025
3af8b62
add sample
YunchuWang Jan 10, 2025
549e105
Update src/Shared/AzureManaged/Shared.AzureManaged.csproj
YunchuWang Jan 13, 2025
3a40d09
fix compile
YunchuWang Jan 13, 2025
c697fbc
refactor
YunchuWang Jan 14, 2025
55eea54
fix
YunchuWang Jan 14, 2025
1ede0d4
fb
YunchuWang Jan 15, 2025
02d5992
fb
YunchuWang Jan 15, 2025
e0bd4e2
fb
YunchuWang Jan 15, 2025
5b4f648
fb
YunchuWang Jan 15, 2025
6f28efc
remove validateonstart
YunchuWang Jan 16, 2025
3334130
change ver
YunchuWang Jan 16, 2025
d87eed6
Update CHANGELOG and mark packages as preview
cgillum Jan 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/workflows/validate-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,12 @@ jobs:
with:
submodules: true

- name: Setup .NET
- name: Setup .NET 6.0
uses: actions/setup-dotnet@v3
with:
dotnet-version: '6.0.x'
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved

- name: Setup .NET from global.json
uses: actions/setup-dotnet@v3
with:
global-json-file: global.json
Expand Down
37 changes: 37 additions & 0 deletions Microsoft.DurableTask.sln
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Analyzers.Tests", "test\Ana
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AzureFunctionsApp.Tests", "samples\AzureFunctionsUnitTests\AzureFunctionsApp.Tests.csproj", "{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.AzureManaged", "src\Worker\AzureManaged\Worker.AzureManaged.csproj", "{6106872F-A730-4A75-9267-1B2E2C2DC18C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.AzureManaged", "src\Client\AzureManaged\Client.AzureManaged.csproj", "{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Shared.AzureManaged.Tests", "test\Shared\AzureManaged.Tests\Shared.AzureManaged.Tests.csproj", "{11357B31-9A63-4A5A-9BC5-091952B25BC0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Client.AzureManaged.Tests", "test\Client\AzureManaged.Tests\Client.AzureManaged.Tests.csproj", "{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Worker.AzureManaged.Tests", "test\Worker\AzureManaged.Tests\Worker.AzureManaged.Tests.csproj", "{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AspNetWebApp", "samples\portable-sdk\dotnet\AspNetWebApp\AspNetWebApp.csproj", "{869D2D51-9372-4764-B059-C43B6C1180A3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -185,6 +197,26 @@ Global
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9}.Release|Any CPU.Build.0 = Release|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6106872F-A730-4A75-9267-1B2E2C2DC18C}.Release|Any CPU.Build.0 = Release|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3}.Release|Any CPU.Build.0 = Release|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{11357B31-9A63-4A5A-9BC5-091952B25BC0}.Release|Any CPU.Build.0 = Release|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737}.Release|Any CPU.Build.0 = Release|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -220,6 +252,11 @@ Global
{998E9D97-BD36-4A9D-81FC-5DAC1CE40083} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{541FCCCE-1059-4691-B027-F761CD80DE92} = {E5637F81-2FB9-4CD7-900D-455363B142A7}
{FC2692E7-79AE-400E-A50F-8E0BCC8C9BD9} = {EFF7632B-821E-4CFC-B4A0-ED4B24296B17}
{6106872F-A730-4A75-9267-1B2E2C2DC18C} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{EAA6BE9B-E1A5-4E41-9511-EFEA24A51BA3} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{11357B31-9A63-4A5A-9BC5-091952B25BC0} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{A15BA625-DC6B-4C6D-8673-0CB08F1B9737} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
{B78F1FFD-47AC-45BE-8FF9-0BF8C9F35DEF} = {8AFC9781-F6F1-4696-BB4A-9ED7CA9D612B}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {AB41CB55-35EA-4986-A522-387AB3402E71}
Expand Down
26 changes: 26 additions & 0 deletions samples/AspNetWebApp/AspNetWebApp.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)Generated</CompilerGeneratedFilesOutputPath>

<!-- Disable automatic assembly attribute generation -->
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateTargetFrameworkAttribute>false</GenerateTargetFrameworkAttribute>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Azure.Identity" Version="1.13.1" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
<PackageReference Include="Microsoft.DurableTask.Generators" Version="1.0.0-preview.1" OutputItemType="Analyzer" />

<!-- Reference to the Azure Managed client and worker projects -->
<ProjectReference Include="../../src/Client/AzureManaged/Client.AzureManaged.csproj" />
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
<ProjectReference Include="../../src/Worker/AzureManaged/Worker.AzureManaged.csproj" />
<ProjectReference Include="../../src/Shared/AzureManaged/Shared.AzureManaged.csproj" />
</ItemGroup>

</Project>
22 changes: 22 additions & 0 deletions samples/AspNetWebApp/DockerFile
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#See https://aka.ms/containerfastmode to understand how Visual Studio uses this Dockerfile to build your images for faster debugging.

FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS base
WORKDIR /app
EXPOSE 8080

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY ["AspNetWebApp.csproj", "."]
RUN dotnet restore "./AspNetWebApp.csproj"
COPY . .
WORKDIR "/src/."
RUN dotnet build "AspNetWebApp.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "AspNetWebApp.csproj" -c Release -o /app/publish /p:UseAppHost=false

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENV ASPNETCORE_ENVIRONMENT=Production
ENTRYPOINT ["dotnet", "AspNetWebApp.dll"]
30 changes: 30 additions & 0 deletions samples/AspNetWebApp/Orchestrations/HelloCities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;

namespace AspNetWebApp.Scenarios;

[DurableTask]
class HelloCities : TaskOrchestrator<string, List<string>>
{
public override async Task<List<string>> RunAsync(TaskOrchestrationContext context, string input)
{
List<string> results =
[
await context.CallSayHelloAsync("Seattle"),
await context.CallSayHelloAsync("Amsterdam"),
await context.CallSayHelloAsync("Hyderabad"),
await context.CallSayHelloAsync("Shanghai"),
await context.CallSayHelloAsync("Tokyo"),
];
return results;
}
}

[DurableTask]
class SayHello : TaskActivity<string, string>
{
public override Task<string> RunAsync(TaskActivityContext context, string cityName)
{
return Task.FromResult($"Hello, {cityName}!");
}
}
56 changes: 56 additions & 0 deletions samples/AspNetWebApp/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Text.Json.Serialization;
using Azure.Core;
using Azure.Identity;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.DurableTask.Worker;
using Microsoft.DurableTask.Worker.AzureManaged;
using Microsoft.DurableTask.Client.AzureManaged;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);

string endpointAddress = builder.Configuration["DURABLE_TASK_SCHEDULER_ENDPOINT_ADDRESS"]
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
?? throw new InvalidOperationException("Missing required configuration 'DURABLE_TASK_SCHEDULER_ENDPOINT_ADDRESS'");

string taskHubName = builder.Configuration["DURABLE_TASK_SCHEDULER_TASK_HUB_NAME"]
?? throw new InvalidOperationException("Missing required configuration 'DURABLE_TASK_SCHEDULER_TASK_HUB_NAME'");

TokenCredential credential = builder.Environment.IsProduction()
? new DefaultAzureCredential(new DefaultAzureCredentialOptions { ManagedIdentityClientId = builder.Configuration["CONTAINER_APP_UMI_CLIENT_ID"] })
: new DefaultAzureCredential();

// Add all the generated orchestrations and activities automatically
builder.Services.AddDurableTaskWorker(builder =>
{
builder.AddTasks(r => r.AddAllGeneratedTasks());
builder.UseDurableTaskScheduler(endpointAddress, taskHubName, credential);
});

// Register the client, which can be used to start orchestrations
builder.Services.AddDurableTaskClient(builder =>
{
builder.UseDurableTaskScheduler(endpointAddress, taskHubName, credential);
});

// Configure console logging using the simpler, more compact format
builder.Services.AddLogging(logging =>
{
logging.AddSimpleConsole(options =>
{
options.SingleLine = true;
options.UseUtcTimestamp = true;
options.TimestampFormat = "yyyy-MM-ddTHH:mm:ss.fffZ ";
});
});

// Configure the HTTP request pipeline
builder.Services.AddControllers().AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter());
options.JsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
});

// The actual listen URL can be configured in environment variables named "ASPNETCORE_URLS" or "ASPNETCORE_URLS_HTTPS"
WebApplication app = builder.Build();
app.MapControllers();
app.Run();
23 changes: 23 additions & 0 deletions samples/AspNetWebApp/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:36209",
"sslPort": 0
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"applicationUrl": "http://localhost:5008",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development",
"DURABLE_TASK_SCHEDULER_ENDPOINT_ADDRESS": "https://wbtestdts02-g7ahczeycua9.westus2.durabletask.io",
"DURABLE_TASK_SCHEDULER_TASK_HUB_NAME": "wbtb100"
}
}
}
}
50 changes: 50 additions & 0 deletions samples/AspNetWebApp/ScenariosController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;

namespace AspNetWebApp;

[Route("scenarios")]
[ApiController]
public partial class ScenariosController(
DurableTaskClient durableTaskClient,
ILogger<ScenariosController> logger) : ControllerBase
{
readonly DurableTaskClient durableTaskClient = durableTaskClient;
readonly ILogger<ScenariosController> logger = logger;

[HttpPost("hellocities")]
public async Task<ActionResult> RunHelloCities([FromQuery] int? count, [FromQuery] string? prefix)
{
if (count is null || count < 1)
{
return this.BadRequest(new { error = "A 'count' query string parameter is required and it must contain a positive number." });
}

// Generate a semi-unique prefix for the instance IDs to simplify tracking
prefix ??= $"hellocities-{count}-";
prefix += DateTime.UtcNow.ToString("yyyyMMdd-hhmmss");

this.logger.LogInformation("Scheduling {count} orchestrations with a prefix of '{prefix}'...", count, prefix);

Stopwatch sw = Stopwatch.StartNew();
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
await Enumerable.Range(0, count.Value).ParallelForEachAsync(1000, i =>
{
string instanceId = $"{prefix}-{i:X16}";
return this.durableTaskClient.ScheduleNewHelloCitiesInstanceAsync(
input: null!,
new StartOrchestrationOptions(instanceId));
});

sw.Stop();
this.logger.LogInformation(
"All {count} orchestrations were scheduled successfully in {time}ms!",
count,
sw.ElapsedMilliseconds);
return this.Ok(new
{
message = $"Scheduled {count} orchestrations prefixed with '{prefix}' in {sw.ElapsedMilliseconds}."
});
}
}
38 changes: 38 additions & 0 deletions samples/AspNetWebApp/Utils.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
namespace AspNetWebApp;

static class Utils
{
public static async Task ParallelForEachAsync<T>(this IEnumerable<T> items, int maxConcurrency, Func<T, Task> action)
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
{
List<Task> tasks;
if (items is ICollection<T> itemCollection)
{
tasks = new List<Task>(itemCollection.Count);
}
else
{
tasks = [];
}

using SemaphoreSlim semaphore = new(maxConcurrency);
foreach (T item in items)
{
tasks.Add(InvokeThrottledAction(item, action, semaphore));
}

await Task.WhenAll(tasks);
}

static async Task InvokeThrottledAction<T>(T item, Func<T, Task> action, SemaphoreSlim semaphore)
{
await semaphore.WaitAsync();
try
{
await action(item);
}
finally
{
semaphore.Release();
}
}
}
8 changes: 8 additions & 0 deletions samples/AspNetWebApp/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Debug",
"Microsoft.AspNetCore": "Warning"
}
}
}
11 changes: 11 additions & 0 deletions samples/AspNetWebApp/appsettings.Production.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"DURABLE_TASK_SCHEDULER_ENDPOINT_ADDRESS": "https://{your-durable-task-endpoint}.durabletask.io",
"DURABLE_TASK_SCHEDULER_TASK_HUB_NAME": "{your-task-hub-name}",
"CONTAINER_APP_UMI_CLIENT_ID": "{your-user-managed-identity-client-id}"
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
}
9 changes: 9 additions & 0 deletions samples/AspNetWebApp/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
14 changes: 14 additions & 0 deletions src/Client/AzureManaged/Client.AzureManaged.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0</TargetFrameworks>
YunchuWang marked this conversation as resolved.
Show resolved Hide resolved
<PackageDescription>Azure Managed extensions for the Durable Task Framework client.</PackageDescription>
<EnableStyleCop>true</EnableStyleCop>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="../../Client/Grpc/Client.Grpc.csproj" />
<ProjectReference Include="../../Shared/AzureManaged/Shared.AzureManaged.csproj" />
</ItemGroup>

</Project>
Loading
Loading