Skip to content

Commit 81def0d

Browse files
authored
Merge pull request #148 from dotnet-presentations/end-to-end-test
Complete end-to-end workshop test (Parts 1-9) with snapshot updates
2 parents d8e9bed + 4873a9b commit 81def0d

File tree

172 files changed

+23239
-3293
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

172 files changed

+23239
-3293
lines changed

.github/prompts/test-workshop.prompt.md

Lines changed: 350 additions & 42 deletions
Large diffs are not rendered by default.

.github/scripts/setup-workshop-credentials.ps1

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -77,36 +77,7 @@ function Set-WorkshopCredentials {
7777
$azureKey = Read-Host -Prompt "Enter your Azure OpenAI API key" -AsSecureString
7878
if ($azureKey.Length -gt 0) {
7979
$env:WORKSHOP_AZURE_OPENAI_KEY = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($azureKey))
80-
[Environment]::SetEnvironmentVariable("WORKSHOP_AZURE_OPENAI_KEY", $AzureOpenAIKey, "User")
81-
}
82-
83-
# Check for Azure Subscription ID
84-
$AzureSubscriptionId = [Environment]::GetEnvironmentVariable("WORKSHOP_AZURE_SUBSCRIPTION_ID", "User")
85-
if (-not $AzureSubscriptionId) {
86-
Write-Host "`n🔑 Azure Subscription ID not found. Please provide your Azure subscription ID for deployment." -ForegroundColor Yellow
87-
Write-Host "You can find this in the Azure Portal under Subscriptions." -ForegroundColor Gray
88-
89-
do {
90-
$AzureSubscriptionId = Read-Host "Enter Azure Subscription ID"
91-
} while ([string]::IsNullOrWhiteSpace($AzureSubscriptionId))
92-
93-
Write-Host "✅ Saving Azure Subscription ID to environment variables..." -ForegroundColor Green
94-
[Environment]::SetEnvironmentVariable("WORKSHOP_AZURE_SUBSCRIPTION_ID", $AzureSubscriptionId, "User")
95-
}
96-
97-
# Check for Azure Location
98-
$AzureLocation = [Environment]::GetEnvironmentVariable("WORKSHOP_AZURE_LOCATION", "User")
99-
if (-not $AzureLocation) {
100-
Write-Host "`n🌍 Azure Location not found. Please provide your preferred Azure region for deployment." -ForegroundColor Yellow
101-
Write-Host "Common options: eastus, westus2, centralus, westeurope, eastasia" -ForegroundColor Gray
102-
103-
do {
104-
$AzureLocation = Read-Host "Enter Azure Location (e.g., eastus)"
105-
} while ([string]::IsNullOrWhiteSpace($AzureLocation))
106-
107-
Write-Host "✅ Saving Azure Location to environment variables..." -ForegroundColor Green
108-
[Environment]::SetEnvironmentVariable("WORKSHOP_AZURE_LOCATION", $AzureLocation, "User")
109-
}
80+
[Environment]::SetEnvironmentVariable("WORKSHOP_AZURE_OPENAI_KEY", $env:WORKSHOP_AZURE_OPENAI_KEY, "User")
11081
Write-Host "✓ Azure OpenAI key saved to environment variable WORKSHOP_AZURE_OPENAI_KEY" -ForegroundColor Green
11182
} else {
11283
Write-Host "⚠ Azure OpenAI key was empty, skipping..." -ForegroundColor Yellow
@@ -115,6 +86,48 @@ if (-not $AzureLocation) {
11586
Write-Host "✓ Azure OpenAI key found in environment variable WORKSHOP_AZURE_OPENAI_KEY" -ForegroundColor Green
11687
}
11788

89+
90+
Write-Host ""
91+
92+
# Check for Azure Subscription ID
93+
if (-not $env:WORKSHOP_AZURE_SUBSCRIPTION_ID) {
94+
Write-Host "Azure Subscription ID not found in environment variable WORKSHOP_AZURE_SUBSCRIPTION_ID" -ForegroundColor Yellow
95+
Write-Host "This is needed for Azure deployment in Part 6" -ForegroundColor Gray
96+
Write-Host ""
97+
98+
$azureSubscriptionId = Read-Host -Prompt "Enter your Azure Subscription ID (or press Enter to skip)"
99+
if ($azureSubscriptionId.Length -gt 0) {
100+
$env:WORKSHOP_AZURE_SUBSCRIPTION_ID = $azureSubscriptionId
101+
[Environment]::SetEnvironmentVariable("WORKSHOP_AZURE_SUBSCRIPTION_ID", $azureSubscriptionId, "User")
102+
Write-Host "✓ Azure Subscription ID saved to environment variable WORKSHOP_AZURE_SUBSCRIPTION_ID" -ForegroundColor Green
103+
} else {
104+
Write-Host "⚠ Azure Subscription ID was empty, skipping..." -ForegroundColor Yellow
105+
}
106+
} else {
107+
Write-Host "✓ Azure Subscription ID found in environment variable WORKSHOP_AZURE_SUBSCRIPTION_ID" -ForegroundColor Green
108+
}
109+
110+
Write-Host ""
111+
112+
# Check for Azure Location
113+
if (-not $env:WORKSHOP_AZURE_LOCATION) {
114+
Write-Host "Azure Location not found in environment variable WORKSHOP_AZURE_LOCATION" -ForegroundColor Yellow
115+
Write-Host "This is needed for Azure deployment in Part 6" -ForegroundColor Gray
116+
Write-Host "Common options: eastus, westus2, centralus, westeurope, eastasia" -ForegroundColor Gray
117+
Write-Host ""
118+
119+
$azureLocation = Read-Host -Prompt "Enter your Azure Location (or press Enter to skip)"
120+
if ($azureLocation.Length -gt 0) {
121+
$env:WORKSHOP_AZURE_LOCATION = $azureLocation
122+
[Environment]::SetEnvironmentVariable("WORKSHOP_AZURE_LOCATION", $azureLocation, "User")
123+
Write-Host "✓ Azure Location saved to environment variable WORKSHOP_AZURE_LOCATION" -ForegroundColor Green
124+
} else {
125+
Write-Host "⚠ Azure Location was empty, skipping..." -ForegroundColor Yellow
126+
}
127+
} else {
128+
Write-Host "✓ Azure Location found in environment variable WORKSHOP_AZURE_LOCATION" -ForegroundColor Green
129+
}
130+
118131
Write-Host ""
119132

120133
# Check for Azure AI Search credentials (optional)

.github/workflows/dotnet-build.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ jobs:
3232
dotnet-version: '9.0.x'
3333
# No solution file exists for MyMcpServer; using project file directly
3434
- solution: "Part 7 - MCP Server Basics/MyMcpServer/MyMcpServer.csproj"
35-
dotnet-version: '8.0.x'
35+
dotnet-version: '9.0.x'
3636
# No solution file exists for ContosoOrdersMcpServer; using project file directly
3737
- solution: "Part 8 - Enhanced MCP Server/ContosoOrdersMcpServer/ContosoOrdersMcpServer.csproj"
38-
dotnet-version: '8.0.x'
38+
dotnet-version: '9.0.x'
3939

4040
steps:
4141
- name: Checkout code

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,9 @@ csx/
216216
ecf/
217217
rcf/
218218

219+
# Azure Developer CLI (azd) environment files
220+
.azure/
221+
219222
# Windows Store app package directories and files
220223
AppPackages/
221224
BundleArtifacts/

Part 2 - Project Creation/GenAiLab/GenAiLab.AppHost/Program.cs renamed to Part 2 - Project Creation/GenAiLab/GenAiLab.AppHost/AppHost.cs

File renamed without changes.

Part 2 - Project Creation/GenAiLab/GenAiLab.AppHost/GenAiLab.AppHost.csproj

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

3-
<Sdk Name="Aspire.AppHost.Sdk" Version="9.3.0" />
3+
<Sdk Name="Aspire.AppHost.Sdk" Version="9.5.0" />
44

55
<PropertyGroup>
66
<OutputType>Exe</OutputType>
77
<TargetFramework>net9.0</TargetFramework>
88
<ImplicitUsings>enable</ImplicitUsings>
99
<Nullable>enable</Nullable>
10-
<IsAspireHost>true</IsAspireHost>
11-
<UserSecretsId>6e0ddb18-9421-4d8b-a3cc-9ddde029d949</UserSecretsId>
10+
<UserSecretsId>7cb971c7-91be-4e8c-a48d-0d33a430b84f</UserSecretsId>
1211
</PropertyGroup>
1312

1413
<ItemGroup>
15-
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.4.2" />
16-
<PackageReference Include="Aspire.Hosting.Qdrant" Version="9.4.2" />
14+
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.5.0" />
15+
<PackageReference Include="Aspire.Hosting.Qdrant" Version="9.5.0" />
1716
</ItemGroup>
1817

1918
<ItemGroup>

Part 2 - Project Creation/GenAiLab/GenAiLab.AppHost/Properties/launchSettings.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,24 @@
55
"commandName": "Project",
66
"dotnetRunMessages": true,
77
"launchBrowser": true,
8-
"applicationUrl": "https://localhost:17197;http://localhost:15107",
8+
"applicationUrl": "https://localhost:17043;http://localhost:15249",
99
"environmentVariables": {
1010
"ASPNETCORE_ENVIRONMENT": "Development",
1111
"DOTNET_ENVIRONMENT": "Development",
12-
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21209",
13-
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22284"
12+
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "https://localhost:21118",
13+
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "https://localhost:22011"
1414
}
1515
},
1616
"http": {
1717
"commandName": "Project",
1818
"dotnetRunMessages": true,
1919
"launchBrowser": true,
20-
"applicationUrl": "http://localhost:15107",
20+
"applicationUrl": "http://localhost:15249",
2121
"environmentVariables": {
2222
"ASPNETCORE_ENVIRONMENT": "Development",
2323
"DOTNET_ENVIRONMENT": "Development",
24-
"DOTNET_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19167",
25-
"DOTNET_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20071"
24+
"ASPIRE_DASHBOARD_OTLP_ENDPOINT_URL": "http://localhost:19095",
25+
"ASPIRE_RESOURCE_SERVICE_ENDPOINT_URL": "http://localhost:20258"
2626
}
2727
}
2828
}

Part 2 - Project Creation/GenAiLab/GenAiLab.ServiceDefaults/Extensions.cs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@
1010

1111
namespace Microsoft.Extensions.Hosting;
1212

13-
// Adds common .NET Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
13+
// Adds common Aspire services: service discovery, resilience, health checks, and OpenTelemetry.
1414
// This project should be referenced by each service project in your solution.
1515
// To learn more about using this project, see https://aka.ms/dotnet/aspire/service-defaults
1616
public static class Extensions
1717
{
18+
private const string HealthEndpointPath = "/health";
19+
private const string AlivenessEndpointPath = "/alive";
20+
1821
public static TBuilder AddServiceDefaults<TBuilder>(this TBuilder builder) where TBuilder : IHostApplicationBuilder
1922
{
2023
builder.ConfigureOpenTelemetry();
@@ -64,7 +67,12 @@ public static TBuilder ConfigureOpenTelemetry<TBuilder>(this TBuilder builder) w
6467
.WithTracing(tracing =>
6568
{
6669
tracing.AddSource(builder.Environment.ApplicationName)
67-
.AddAspNetCoreInstrumentation()
70+
.AddAspNetCoreInstrumentation(tracing =>
71+
// Exclude health check requests from tracing
72+
tracing.Filter = context =>
73+
!context.Request.Path.StartsWithSegments(HealthEndpointPath)
74+
&& !context.Request.Path.StartsWithSegments(AlivenessEndpointPath)
75+
)
6876
// Uncomment the following line to enable gRPC instrumentation (requires the OpenTelemetry.Instrumentation.GrpcNetClient package)
6977
//.AddGrpcClientInstrumentation()
7078
.AddHttpClientInstrumentation()
@@ -111,10 +119,10 @@ public static WebApplication MapDefaultEndpoints(this WebApplication app)
111119
if (app.Environment.IsDevelopment())
112120
{
113121
// All health checks must pass for app to be considered ready to accept traffic after starting
114-
app.MapHealthChecks("/health");
122+
app.MapHealthChecks(HealthEndpointPath);
115123

116124
// Only health checks tagged with the "live" tag must pass for app to be considered alive
117-
app.MapHealthChecks("/alive", new HealthCheckOptions
125+
app.MapHealthChecks(AlivenessEndpointPath, new HealthCheckOptions
118126
{
119127
Predicate = r => r.Tags.Contains("live")
120128
});

Part 2 - Project Creation/GenAiLab/GenAiLab.ServiceDefaults/GenAiLab.ServiceDefaults.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
<FrameworkReference Include="Microsoft.AspNetCore.App" />
1212

1313
<PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="9.9.0" />
14-
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="9.5.0" />
14+
<PackageReference Include="Microsoft.Extensions.ServiceDiscovery" Version="9.3.1" />
1515
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.12.0" />
1616
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.12.0" />
1717
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.12.0" />

Part 2 - Project Creation/GenAiLab/GenAiLab.Web/Components/Pages/Chat/Chat.razor

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
Don't refer to the presence of citations; just emit these tags right at the end, with no surrounding text.
4141
";
4242

43+
private int statefulMessageCount;
4344
private readonly ChatOptions chatOptions = new();
4445
private readonly List<ChatMessage> messages = new();
4546
private CancellationTokenSource? currentResponseCancellation;
@@ -49,6 +50,7 @@
4950

5051
protected override void OnInitialized()
5152
{
53+
statefulMessageCount = 0;
5254
messages.Add(new(ChatRole.System, SystemPrompt));
5355
chatOptions.Tools = [AIFunctionFactory.Create(SearchAsync)];
5456
}
@@ -66,15 +68,17 @@
6668
var responseText = new TextContent("");
6769
currentResponseMessage = new ChatMessage(ChatRole.Assistant, [responseText]);
6870
currentResponseCancellation = new();
69-
await foreach (var update in ChatClient.GetStreamingResponseAsync([.. messages], chatOptions, currentResponseCancellation.Token))
71+
await foreach (var update in ChatClient.GetStreamingResponseAsync(messages.Skip(statefulMessageCount), chatOptions, currentResponseCancellation.Token))
7072
{
7173
messages.AddMessages(update, filter: c => c is not TextContent);
7274
responseText.Text += update.Text;
75+
chatOptions.ConversationId = update.ConversationId;
7376
ChatMessageItem.NotifyChanged(currentResponseMessage);
7477
}
7578

7679
// Store the final response in the conversation, and begin getting suggestions
7780
messages.Add(currentResponseMessage!);
81+
statefulMessageCount = chatOptions.ConversationId is not null ? messages.Count : 0;
7882
currentResponseMessage = null;
7983
chatSuggestions?.Update(messages);
8084
}
@@ -96,6 +100,8 @@
96100
CancelAnyCurrentResponse();
97101
messages.Clear();
98102
messages.Add(new(ChatRole.System, SystemPrompt));
103+
chatOptions.ConversationId = null;
104+
statefulMessageCount = 0;
99105
chatSuggestions?.Clear();
100106
await chatInput!.FocusAsync();
101107
}

0 commit comments

Comments
 (0)