Skip to content

Port the Vacation Planner web app samples to .NET 10 - #120

Merged
paolosalvatori merged 13 commits into
mainfrom
dotnet_vacation_planner
Sep 8, 2026
Merged

Port the Vacation Planner web app samples to .NET 10#120
paolosalvatori merged 13 commits into
mainfrom
dotnet_vacation_planner

Conversation

@paolosalvatori

@paolosalvatori paolosalvatori commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Motivation

Every "Vacation Planner" web app sample existed only in Python, while the two Azure Functions samples were already .NET. This PR ports all seven web-app-* permutations to .NET 10 so each one ships in both languages, with the same deployment options (Azure CLI scripts, Terraform, Bicep) and the same validation scripts.

The emulator could not run a .NET Linux web app deployed as code until two changes landed in localstack-pro, both merged: #8734 (accept DOTNETCORE|<major.minor>, use the oryx/dotnetcore runtime images, build into oryx_publish_output) and #8749 (preserve repeated Set-Cookie headers, without which a Razor Pages form POST fails with 400 through the emulator endpoint). These samples therefore require an emulator image built from localstack-pro main.

Fixes SMF-877

Changes

Seven new samples/web-app-*/dotnet samples — ASP.NET Core Razor Pages ports of the Vacation Planner, one per storage backend: Cosmos DB for MongoDB (MongoDB.Driver), Cosmos DB for NoSQL (Microsoft.Azure.Cosmos, Gateway mode), Blob Storage with managed identity (Azure.Identity), Azure SQL Database (Microsoft.Data.SqlClient + Key Vault secret and certificate, HTTPS on 8443), MySQL flexible server (MySqlConnector), PostgreSQL flexible server (Npgsql) and a custom container image. Each keeps the Python routes, form fields, flash messages, environment variable names and WEBSITES_PORT, and adds a GET /health endpoint.

  • Behaviour fixed while porting: activities are deleted by their store id instead of their position in a process-global list (which deleted the wrong row with more than one worker); the SQL Database certificate check fails loudly instead of comparing two empty thumbprints; HTTPS on 8443 is served by Kestrel rather than by a code path that only ran under python app.py.
  • Logging parity: a one-line access log per request, the store operation (documents for Cosmos DB, blob names and sizes for Blob Storage, affected rows and ids for SQL, retrieval counts elsewhere) and Activity added/updated/deleted from the page handlers — the three layers the Flask samples produce.
  • Deployment artifacts mirror each Python sibling: scripts/ deploy with --runtime DOTNETCORE:10.0 and zip the project source (the emulator, like App Service with build-during-deployment, runs the Oryx build), Terraform uses dotnet_version, Bicep uses runtimeName = 'dotnetcore'.
  • CI: the new samples are registered in run-samples.sh, which is what the generated matrix reads — .github/workflows/run-samples.yml needs no change. The matrix now builds 17 web-app-*/dotnet jobs (8 scripts, 5 Terraform, 4 Bicep; the custom-image sample also runs on arm64, the code-deployment ones are amd64-only because the Oryx build image is).
  • SQL Database call script is now call-web-app.sh in both languages — the name every other sample uses and the one the Python README already documented — and the .NET copy exits non-zero when the certificate endpoint, the thumbprint or the TLS certificate is missing.
  • Root README: the Outline table gains an introduction, a longer description per sample, the implementation language in parentheses, and separate Python and .NET links for the web apps.
  • Terraform: metadata_host points at azure.localhost.localstack.cloud:4566 in every sample's providers.tf and in the Terraform READMEs.

Testing

Every .NET sample was deployed against the emulator and exercised through the emulator endpoint (https://<app>.azurewebsites.azure.localhost.localstack.cloud:4566), not only against the container port:

az group delete --name local-rg --yes
cd samples/<sample>/dotnet/scripts && bash deploy.sh && bash validate.sh && bash call-web-app.sh
  • All seven pass deploy.shvalidate.shcall-web-app.sh, plus a functional check of add / list / update / delete (with the Razor antiforgery token) and GET /health.
  • web-app-managed-identity was additionally verified end to end through terraform/deploy.sh and bicep/deploy.sh, which confirms dotnet_version = "10.0" on azurerm 5.1.0 and DOTNETCORE|10.0 from Bicep.
  • web-app-sql-database was verified including the strict certificate check (the thumbprint from /api/certificate matches the certificate served on 8443).
  • All seven projects build with dotnet build -c Release with zero warnings.

🤖 Generated with Claude Code

paolosalvatori and others added 10 commits September 7, 2026 16:23
Use the Azure-scoped emulator host as the azurerm provider metadata_host in
every sample's providers.tf and in the Terraform READMEs that quote it, so
the documented configuration matches what the deploy scripts apply.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…mples

Introduce the ASP.NET Core Razor Pages port of the Vacation Planner used by
every web-app sample: one Index page with TempData flash messages, a Delete
page keyed on the store id, an IActivityStore abstraction initialized at
startup, a /health endpoint, and Kestrel binding to the PORT that App Service
and the emulator inject. The custom-image variant serves the same info page
and /api/status from a multi-stage sdk:10.0 -> aspnet:10.0 image; the
managed-identity variant stores one blob per activity through
DefaultAzureCredential.

Deployment artifacts mirror the Python siblings: DOTNETCORE|10.0 code
deployment with the project source zipped for the Oryx build, dotnet_version
in Terraform, runtimeName 'dotnetcore' in Bicep, unchanged WEBSITES_PORT
values and validation scripts. Register both samples in run-samples.sh, link
them from the root README and normalize line endings for C# sources.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ry sample in the root README

The Vacation Planner reads its SQL connection string from the Key Vault
secret (falling back to SQL_* variables or a Microsoft Entra token), serves
HTTPS on port 8443 with the Key Vault certificate, and exposes /update/{id}
and /api/certificate like the Python sample; get-web-app-url.sh now fails
when the 8443 endpoint or its certificate cannot be retrieved instead of
comparing two empty thumbprints. InvariantGlobalization is dropped from the
template because Microsoft.Data.SqlClient cannot open connections in
invariant mode.

The root README outline gains an introduction, a longer description per
sample, the implementation language in parentheses, and separate Python and
.NET links for the web-app samples.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MySqlConnector store with the same idempotent DDL, md5 ids, 30x2s startup
retry and TLS-without-verification semantics (MYSQL_SSL) as the Python
sample; artifacts switch to DOTNETCORE|10.0 with a source zip for the Oryx
build, dotnet_version in Terraform and 'dotnetcore' in Bicep.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Npgsql store with the same DDL, indexes, md5 ids, 30x2s startup retry and
libpq "prefer" TLS semantics as the Python sample; artifacts switch to
DOTNETCORE|10.0 with a source zip for the Oryx build, dotnet_version in
Terraform and 'dotnetcore' in Bicep.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
MongoDB.Driver store keeping the {_id, username, activity, timestamp}
documents, md5 ids and the three indexes of the Python sample, created once at
startup instead of on every operation; artifacts switch to DOTNETCORE|10.0
with a source zip for the Oryx build, dotnet_version in Terraform and
'dotnetcore' in Bicep. call-web-app.sh probes container port 8000, the port
this sample sets through WEBSITES_PORT, instead of 80.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Microsoft.Azure.Cosmos store in Gateway mode (the emulator exposes the account
endpoint over HTTPS only), keeping the {id, username, activity, timestamp}
items partitioned by /username, the 400 RU container created on demand and
id-keyed deletes of the Python sample; scripts-only deployment as in the
Python sibling, switched to DOTNETCORE:10.0 with a source zip.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The port kept only the startup and store-initialization logs, so nothing
appeared in the container log while adding, updating or deleting an activity —
unlike the Python samples, which log a gunicorn access line per request, the
store operation (with the affected documents) and an application-level
"Activity added/updated" line.

Add the same three layers to every .NET sample: a one-line access log
("POST / -> 302 in 45.3ms") from a small middleware, the store operation with
its documents or affected-row counts, and "Activity added/updated/deleted" from
the page handlers. Each store logs at the granularity its Python counterpart
does: full documents for Cosmos DB (MongoDB and NoSQL APIs), blob names and
sizes for Blob Storage, row counts and ids for SQL Database, retrieval counts
for the MySQL and PostgreSQL flexible servers.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The .NET sample now carries its own Visio drawing and rendered PNG instead of
the copies inherited from the Python sibling.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ample in CI

The .NET SQL Database sample's get-web-app-url.sh becomes call-web-app.sh, the
name every other sample uses and the one its Python sibling's README already
documented; the Python script is renamed with it so both run-samples.sh entries
resolve. The renamed .NET copy keeps the strict certificate checks (a failed
call, an empty thumbprint or a missing TLS certificate now exit 1 instead of
comparing two empty strings).

Also from manual validation of the samples: the Terraform deployments use the
local-* resource naming of the script deployments and pass secret_name through,
and the validate/README instructions show how to read the web app host name.

Register samples/web-app-cosmosdb-nosql-api/dotnet in run-samples.sh; it was
the only validated .NET web app missing from the matrix, which now builds 17
web-app-*/dotnet jobs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 8, 2026 15:15
@paolosalvatori
paolosalvatori requested a review from a team as a code owner September 8, 2026 15:15

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

There are Terraform type errors in newly added modules and at least one .NET sample diverges from the PR-stated “flash message parity” requirement.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR ports the “Vacation Planner” Azure Web App samples to .NET 10 (ASP.NET Core Razor Pages) and aligns deployment artifacts (scripts/Terraform/Bicep) so the samples ship in both Python and .NET with consistent emulator-friendly configuration.

Changes:

  • Adds new .NET 10 sample implementations (Razor Pages) plus supporting scripts/infra for multiple web-app-* variants.
  • Updates Terraform provider configuration across samples to use metadata_host = "azure.localhost.localstack.cloud:4566".
  • Extends .gitattributes to enforce LF endings for C#-related files.
File summaries
File Description
samples/web-app-sql-database/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/web-app-sql-database/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/web-app-sql-database/python/terraform/deploy.sh Adjusts naming and passes secret_name into Terraform plan.
samples/web-app-sql-database/dotnet/terraform/terraform.tfvars Adds location and dotnet_version inputs for Terraform.
samples/web-app-sql-database/dotnet/terraform/providers.tf Adds Terraform provider configuration for .NET sample.
samples/web-app-sql-database/dotnet/terraform/outputs.tf Exposes Terraform outputs for deployed resources.
samples/web-app-sql-database/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project and package dependencies.
samples/web-app-sql-database/dotnet/src/Services/StoreInitializer.cs Adds hosted startup initialization/retry helper.
samples/web-app-sql-database/dotnet/src/Services/IActivityStore.cs Defines storage abstraction for activity persistence.
samples/web-app-sql-database/dotnet/src/Pages/Update.cshtml.cs Implements update redirect handler.
samples/web-app-sql-database/dotnet/src/Pages/Update.cshtml Adds Razor page route for update.
samples/web-app-sql-database/dotnet/src/Pages/Index.cshtml.cs Implements list/add/update UI handler logic.
samples/web-app-sql-database/dotnet/src/Pages/Delete.cshtml.cs Implements delete handler logic.
samples/web-app-sql-database/dotnet/src/Pages/Delete.cshtml Adds Razor page route for delete.
samples/web-app-sql-database/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-sql-database/dotnet/src/Models/Activity.cs Introduces shared activity model.
samples/web-app-sql-database/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-sql-database/dotnet/scripts/validate.sh Adds CLI validation script for deployed resources.
samples/web-app-sql-database/dotnet/bicep/main.bicepparam Adds Bicep parameterization for .NET runtime.
samples/web-app-postgresql-flexible-server/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/web-app-postgresql-flexible-server/dotnet/terraform/terraform.tfvars Adds prefix/suffix/location inputs for Terraform.
samples/web-app-postgresql-flexible-server/dotnet/terraform/providers.tf Adds Terraform provider configuration for .NET sample.
samples/web-app-postgresql-flexible-server/dotnet/terraform/outputs.tf Exposes Terraform outputs for deployed resources.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/web_app/outputs.tf Outputs for web app module resources.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/web_app/main.tf Defines Linux Web App with .NET stack and diagnostics.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/virtual_network/variables.tf Inputs for virtual network module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/virtual_network/outputs.tf Outputs for virtual network module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/private_endpoint/outputs.tf Outputs for private endpoint module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/private_endpoint/main.tf Defines Private Endpoint + DNS zone group.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/private_dns_zone/variables.tf Inputs for private DNS zone module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/private_dns_zone/outputs.tf Outputs for private DNS zone module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/private_dns_zone/main.tf Creates private DNS zone and VNet links.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/postgres_flexible_server/outputs.tf Outputs for PostgreSQL flexible server module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/postgres_flexible_server/main.tf Defines PostgreSQL flexible server + DB + firewall + diagnostics.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/network_security_group/variables.tf Inputs for NSG module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/network_security_group/outputs.tf Outputs for NSG module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/nat_gateway/variables.tf Inputs for NAT gateway module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/nat_gateway/output.tf Outputs for NAT gateway module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/nat_gateway/main.tf Defines NAT gateway + associations.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/log_analytics/variables.tf Inputs for Log Analytics module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/log_analytics/output.tf Outputs for Log Analytics module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/log_analytics/main.tf Defines Log Analytics workspace.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/app_service_plan/variables.tf Inputs for App Service Plan module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/app_service_plan/outputs.tf Outputs for App Service Plan module.
samples/web-app-postgresql-flexible-server/dotnet/terraform/modules/app_service_plan/main.tf Defines service plan + diagnostics.
samples/web-app-postgresql-flexible-server/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project and Npgsql dependency.
samples/web-app-postgresql-flexible-server/dotnet/src/Services/StoreInitializer.cs Adds hosted startup initialization/retry helper.
samples/web-app-postgresql-flexible-server/dotnet/src/Services/PostgresOptions.cs Reads and validates env-var configuration.
samples/web-app-postgresql-flexible-server/dotnet/src/Services/IActivityStore.cs Defines activity store abstraction.
samples/web-app-postgresql-flexible-server/dotnet/src/Services/ActivityId.cs Implements shared activity ID generation.
samples/web-app-postgresql-flexible-server/dotnet/src/Program.cs Configures Razor Pages app, access logging, /health.
samples/web-app-postgresql-flexible-server/dotnet/src/Pages/Index.cshtml.cs Implements list/add/update UI handler logic.
samples/web-app-postgresql-flexible-server/dotnet/src/Pages/Delete.cshtml.cs Implements delete handler logic.
samples/web-app-postgresql-flexible-server/dotnet/src/Pages/Delete.cshtml Adds Razor page route for delete.
samples/web-app-postgresql-flexible-server/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-postgresql-flexible-server/dotnet/src/Models/Activity.cs Introduces shared activity model.
samples/web-app-postgresql-flexible-server/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-postgresql-flexible-server/dotnet/bicep/modules/private-dns-zone.bicep Adds Bicep module for private DNS zone.
samples/web-app-postgresql-flexible-server/dotnet/bicep/modules/log-analytics.bicep Adds Bicep module for Log Analytics workspace.
samples/web-app-postgresql-flexible-server/dotnet/bicep/main.bicepparam Adds Bicep parameterization for .NET runtime and PG settings.
samples/web-app-mysql-flexible-server/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/web-app-mysql-flexible-server/dotnet/terraform/terraform.tfvars Adds prefix/suffix/location inputs for Terraform.
samples/web-app-mysql-flexible-server/dotnet/terraform/providers.tf Adds Terraform provider configuration for .NET sample.
samples/web-app-mysql-flexible-server/dotnet/terraform/outputs.tf Exposes Terraform outputs for deployed resources.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/web_app/outputs.tf Outputs for web app module resources.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/web_app/main.tf Defines Linux Web App with .NET stack and diagnostics.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/virtual_network/variables.tf Inputs for virtual network module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/virtual_network/outputs.tf Outputs for virtual network module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/private_endpoint/outputs.tf Outputs for private endpoint module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/private_endpoint/main.tf Defines Private Endpoint + DNS zone group.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/private_dns_zone/variables.tf Inputs for private DNS zone module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/private_dns_zone/outputs.tf Outputs for private DNS zone module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/private_dns_zone/main.tf Creates private DNS zone and VNet links.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/network_security_group/variables.tf Inputs for NSG module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/network_security_group/outputs.tf Outputs for NSG module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/nat_gateway/variables.tf Inputs for NAT gateway module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/nat_gateway/output.tf Outputs for NAT gateway module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/nat_gateway/main.tf Defines NAT gateway + associations.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/mysql_flexible_server/outputs.tf Outputs for MySQL flexible server module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/log_analytics/variables.tf Inputs for Log Analytics module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/log_analytics/output.tf Outputs for Log Analytics module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/log_analytics/main.tf Defines Log Analytics workspace.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/app_service_plan/variables.tf Inputs for App Service Plan module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/app_service_plan/outputs.tf Outputs for App Service Plan module.
samples/web-app-mysql-flexible-server/dotnet/terraform/modules/app_service_plan/main.tf Defines service plan + diagnostics.
samples/web-app-mysql-flexible-server/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project and MySqlConnector dependency.
samples/web-app-mysql-flexible-server/dotnet/src/Services/StoreInitializer.cs Adds hosted startup initialization/retry helper.
samples/web-app-mysql-flexible-server/dotnet/src/Services/MySqlOptions.cs Reads and validates env-var configuration.
samples/web-app-mysql-flexible-server/dotnet/src/Services/IActivityStore.cs Defines activity store abstraction.
samples/web-app-mysql-flexible-server/dotnet/src/Services/ActivityId.cs Implements shared activity ID generation.
samples/web-app-mysql-flexible-server/dotnet/src/Program.cs Configures Razor Pages app, access logging, /health.
samples/web-app-mysql-flexible-server/dotnet/src/Pages/Index.cshtml.cs Implements list/add/update UI handler logic.
samples/web-app-mysql-flexible-server/dotnet/src/Pages/Delete.cshtml.cs Implements delete handler logic.
samples/web-app-mysql-flexible-server/dotnet/src/Pages/Delete.cshtml Adds Razor page route for delete.
samples/web-app-mysql-flexible-server/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-mysql-flexible-server/dotnet/src/Models/Activity.cs Introduces shared activity model.
samples/web-app-mysql-flexible-server/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-mysql-flexible-server/dotnet/bicep/modules/private-dns-zone.bicep Adds Bicep module for private DNS zone.
samples/web-app-mysql-flexible-server/dotnet/bicep/modules/log-analytics.bicep Adds Bicep module for Log Analytics workspace.
samples/web-app-mysql-flexible-server/dotnet/bicep/main.bicepparam Adds Bicep parameterization for .NET runtime and MySQL settings.
samples/web-app-managed-identity/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/web-app-managed-identity/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/web-app-managed-identity/dotnet/terraform/terraform.tfvars Adds location and dotnet_version inputs for Terraform.
samples/web-app-managed-identity/dotnet/terraform/providers.tf Adds Terraform provider configuration for .NET sample.
samples/web-app-managed-identity/dotnet/terraform/outputs.tf Exposes Terraform outputs for deployed resources.
samples/web-app-managed-identity/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project and Azure SDK deps.
samples/web-app-managed-identity/dotnet/src/Services/StoreInitializer.cs Adds hosted startup initialization/retry helper.
samples/web-app-managed-identity/dotnet/src/Services/IActivityStore.cs Defines activity store abstraction.
samples/web-app-managed-identity/dotnet/src/Services/BlobStorageOptions.cs Reads env-var configuration for blob storage.
samples/web-app-managed-identity/dotnet/src/Program.cs Configures Razor Pages app, access logging, /health.
samples/web-app-managed-identity/dotnet/src/Pages/Index.cshtml.cs Implements list/add/update UI handler logic.
samples/web-app-managed-identity/dotnet/src/Pages/Delete.cshtml.cs Implements delete handler logic.
samples/web-app-managed-identity/dotnet/src/Pages/Delete.cshtml Adds Razor page route for delete.
samples/web-app-managed-identity/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-managed-identity/dotnet/src/Models/Activity.cs Introduces shared activity model.
samples/web-app-managed-identity/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-managed-identity/dotnet/bicep/main.bicepparam Adds Bicep parameterization for .NET runtime.
samples/web-app-custom-image/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/web-app-custom-image/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/web-app-custom-image/dotnet/terraform/terraform.tfvars Adds prefix/suffix/location inputs for Terraform.
samples/web-app-custom-image/dotnet/terraform/push_image.sh Adds image build/tag/push helper for ACR.
samples/web-app-custom-image/dotnet/terraform/providers.tf Adds Terraform provider configuration for .NET sample.
samples/web-app-custom-image/dotnet/terraform/outputs.tf Exposes Terraform outputs for deployed resources.
samples/web-app-custom-image/dotnet/terraform/modules/web_app/outputs.tf Outputs for web app module resources.
samples/web-app-custom-image/dotnet/terraform/modules/virtual_network/variables.tf Inputs for virtual network module.
samples/web-app-custom-image/dotnet/terraform/modules/virtual_network/outputs.tf Outputs for virtual network module.
samples/web-app-custom-image/dotnet/terraform/modules/virtual_network/main.tf Defines virtual network/subnets/diagnostics.
samples/web-app-custom-image/dotnet/terraform/modules/private_endpoint/variables.tf Inputs for private endpoint module.
samples/web-app-custom-image/dotnet/terraform/modules/private_endpoint/outputs.tf Outputs for private endpoint module.
samples/web-app-custom-image/dotnet/terraform/modules/private_endpoint/main.tf Defines Private Endpoint + DNS zone group.
samples/web-app-custom-image/dotnet/terraform/modules/private_dns_zone/variables.tf Inputs for private DNS zone module.
samples/web-app-custom-image/dotnet/terraform/modules/private_dns_zone/outputs.tf Outputs for private DNS zone module.
samples/web-app-custom-image/dotnet/terraform/modules/private_dns_zone/main.tf Creates private DNS zone and VNet links.
samples/web-app-custom-image/dotnet/terraform/modules/network_security_group/variables.tf Inputs for NSG module.
samples/web-app-custom-image/dotnet/terraform/modules/network_security_group/outputs.tf Outputs for NSG module.
samples/web-app-custom-image/dotnet/terraform/modules/nat_gateway/variables.tf Inputs for NAT gateway module.
samples/web-app-custom-image/dotnet/terraform/modules/nat_gateway/output.tf Outputs for NAT gateway module.
samples/web-app-custom-image/dotnet/terraform/modules/nat_gateway/main.tf Defines NAT gateway with IP prefix + associations.
samples/web-app-custom-image/dotnet/terraform/modules/managed_identity/variables.tf Inputs for managed identity module.
samples/web-app-custom-image/dotnet/terraform/modules/managed_identity/output.tf Outputs for managed identity module.
samples/web-app-custom-image/dotnet/terraform/modules/managed_identity/main.tf Defines user-assigned identity + AcrPull role.
samples/web-app-custom-image/dotnet/terraform/modules/log_analytics/variables.tf Inputs for Log Analytics module.
samples/web-app-custom-image/dotnet/terraform/modules/log_analytics/output.tf Outputs for Log Analytics module.
samples/web-app-custom-image/dotnet/terraform/modules/log_analytics/main.tf Defines Log Analytics workspace.
samples/web-app-custom-image/dotnet/terraform/modules/container_registry/variables.tf Inputs for ACR module.
samples/web-app-custom-image/dotnet/terraform/modules/container_registry/output.tf Outputs for ACR module.
samples/web-app-custom-image/dotnet/terraform/modules/container_registry/main.tf Defines ACR + identity + diagnostics.
samples/web-app-custom-image/dotnet/terraform/modules/app_service_plan/variables.tf Inputs for App Service Plan module.
samples/web-app-custom-image/dotnet/terraform/modules/app_service_plan/outputs.tf Outputs for App Service Plan module.
samples/web-app-custom-image/dotnet/terraform/modules/app_service_plan/main.tf Defines service plan + diagnostics.
samples/web-app-custom-image/dotnet/terraform/deploy.sh Adds Terraform deployment script for custom-image variant.
samples/web-app-custom-image/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project for container image.
samples/web-app-custom-image/dotnet/src/Program.cs Configures status endpoints and /health.
samples/web-app-custom-image/dotnet/src/Pages/Index.cshtml.cs Renders deployment metadata into page.
samples/web-app-custom-image/dotnet/src/Pages/Index.cshtml Adds Razor UI for custom-image sample.
samples/web-app-custom-image/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-custom-image/dotnet/src/Dockerfile Adds multi-stage .NET 10 Docker build/publish image.
samples/web-app-custom-image/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-custom-image/dotnet/src/AppInfo.cs Adds helper for app/image/host metadata.
samples/web-app-custom-image/dotnet/src/.dockerignore Adds Docker ignore patterns for build context.
samples/web-app-custom-image/dotnet/scripts/call-web-app.sh Adds simple script to call status endpoint.
samples/web-app-custom-image/dotnet/bicep/modules/private-dns-zone.bicep Adds Bicep module for private DNS zone.
samples/web-app-custom-image/dotnet/bicep/modules/managed-identity.bicep Adds Bicep module for ACR pull identity.
samples/web-app-custom-image/dotnet/bicep/modules/log-analytics.bicep Adds Bicep module for Log Analytics workspace.
samples/web-app-custom-image/dotnet/bicep/main.bicepparam Adds Bicep parameters for image deployment.
samples/web-app-custom-image/dotnet/bicep/acr.bicepparam Adds Bicep parameters for ACR provisioning.
samples/web-app-cosmosdb-nosql-api/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project and Cosmos SDK deps.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Services/StoreInitializer.cs Adds hosted startup initialization/retry helper.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Services/IActivityStore.cs Defines activity store abstraction.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Services/CosmosOptions.cs Reads and validates env-var configuration.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Services/ActivityId.cs Implements shared activity ID generation.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Services/ActivityDocument.cs Defines Cosmos document shape shared with Python.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Program.cs Configures Razor Pages app, access logging, /health.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Pages/Index.cshtml.cs Implements list/add/update UI handler logic.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Pages/Delete.cshtml.cs Implements delete handler logic.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Pages/Delete.cshtml Adds Razor page route for delete.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-cosmosdb-nosql-api/dotnet/src/Models/Activity.cs Introduces shared activity model.
samples/web-app-cosmosdb-nosql-api/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-cosmosdb-nosql-api/dotnet/scripts/validate.sh Adds CLI validation script for deployed resources.
samples/web-app-cosmosdb-mongodb-api/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/web-app-cosmosdb-mongodb-api/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/terraform.tfvars Adds prefix/suffix/location inputs for Terraform.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/providers.tf Adds Terraform provider configuration for .NET sample.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/outputs.tf Exposes Terraform outputs for deployed resources.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/web_app/outputs.tf Outputs for web app module resources.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/virtual_network/variables.tf Inputs for virtual network module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/virtual_network/outputs.tf Outputs for virtual network module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/virtual_network/main.tf Defines virtual network/subnets/diagnostics.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/storage_account/outputs.tf Outputs for storage account module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/storage_account/main.tf Defines storage account with network rules + identity.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/private_endpoint/outputs.tf Outputs for private endpoint module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/private_endpoint/main.tf Defines Private Endpoint + DNS zone group.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/private_dns_zone/variables.tf Inputs for private DNS zone module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/private_dns_zone/outputs.tf Outputs for private DNS zone module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/private_dns_zone/main.tf Creates private DNS zone and VNet links.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/network_security_group/variables.tf Inputs for NSG module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/network_security_group/outputs.tf Outputs for NSG module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/nat_gateway/variables.tf Inputs for NAT gateway module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/nat_gateway/output.tf Outputs for NAT gateway module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/nat_gateway/main.tf Defines NAT gateway + associations.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/log_analytics/variables.tf Inputs for Log Analytics module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/log_analytics/output.tf Outputs for Log Analytics module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/log_analytics/main.tf Defines Log Analytics workspace.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/cosmosdb_mongodb/outputs.tf Outputs for Cosmos Mongo module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/app_service_plan/variables.tf Inputs for App Service Plan module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/app_service_plan/outputs.tf Outputs for App Service Plan module.
samples/web-app-cosmosdb-mongodb-api/dotnet/terraform/modules/app_service_plan/main.tf Defines service plan + diagnostics.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/VacationPlanner.csproj Introduces .NET 10 web project and MongoDB.Driver dependency.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Services/StoreInitializer.cs Adds hosted startup initialization/retry helper.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Services/MongoOptions.cs Reads and validates env-var configuration.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Services/IActivityStore.cs Defines activity store abstraction.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Services/ActivityId.cs Implements shared activity ID generation.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Program.cs Configures Razor Pages app, access logging, /health.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Pages/Index.cshtml.cs Implements list/add/update UI handler logic.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Pages/Delete.cshtml.cs Implements delete handler logic.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Pages/Delete.cshtml Adds Razor page route for delete.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Pages/_ViewImports.cshtml Adds Razor imports/tag helpers.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/Models/Activity.cs Introduces shared activity model.
samples/web-app-cosmosdb-mongodb-api/dotnet/src/appsettings.json Adds ASP.NET Core logging defaults.
samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/modules/private-dns-zone.bicep Adds Bicep module for private DNS zone.
samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/modules/log-analytics.bicep Adds Bicep module for Log Analytics workspace.
samples/web-app-cosmosdb-mongodb-api/dotnet/bicep/main.bicepparam Adds Bicep parameterization for .NET runtime and Cosmos settings.
samples/url-shortener/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/servicebus/java/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/servicebus/java/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/function-app-storage-http/dotnet/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/function-app-storage-http/dotnet/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/function-app-service-bus/dotnet/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/function-app-service-bus/dotnet/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/function-app-managed-identity/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/function-app-managed-identity/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/eventhubs/python/terraform/README.md Updates README reference to new metadata_host.
samples/eventhubs/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/eventhubs-eventgrid/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/container-apps-blob-storage/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/container-apps-blob-storage/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
samples/aci-blob-storage/python/terraform/README.md Updates azurerm metadata_host for emulator usage.
samples/aci-blob-storage/python/terraform/providers.tf Updates azurerm metadata_host for emulator usage.
.gitattributes Enforces LF EOL for C# source/project/Razor files.
Review details
  • Files reviewed: 226/411 changed files
  • Comments generated: 5
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

resource_group_name = var.resource_group_name
sku = var.sku
tags = var.tags
retention_in_days = var.retention_in_days != "" ? var.retention_in_days : null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applying this one: the expression is byte-identical to the Python module it was copied from (samples/web-app-cosmosdb-mongodb-api/python/terraform/modules/log_analytics/main.tf), which runs terraform apply in CI on every push, and terraform validate passes on this module too. Terraform's equality operators are type-tolerant — unlike arithmetic, ==/!= across mismatched primitive types evaluate to "not equal" rather than erroring — so with the number default of 30 the guard is simply always true and retention_in_days = 30 is applied. Changing it only in the .NET copy would make the two language variants diverge for no behavioural gain; if the guard should become != null, that is a cleanup worth doing across both variants in its own PR.

resource_group_name = var.resource_group_name
sku = var.sku
tags = var.tags
retention_in_days = var.retention_in_days != "" ? var.retention_in_days : null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applying this one: the expression is byte-identical to the Python module it was copied from (samples/web-app-mysql-flexible-server/python/terraform/modules/log_analytics/main.tf), which runs terraform apply in CI on every push, and terraform validate passes on this module too. Terraform's equality operators are type-tolerant — unlike arithmetic, ==/!= across mismatched primitive types evaluate to "not equal" rather than erroring — so with the number default of 30 the guard is simply always true and retention_in_days = 30 is applied. Changing it only in the .NET copy would make the two language variants diverge for no behavioural gain; if the guard should become != null, that is a cleanup worth doing across both variants in its own PR.

resource_group_name = var.resource_group_name
sku = var.sku
tags = var.tags
retention_in_days = var.retention_in_days != "" ? var.retention_in_days : null

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not applying this one: the expression is byte-identical to the Python module it was copied from (samples/web-app-postgresql-flexible-server/python/terraform/modules/log_analytics/main.tf), which runs terraform apply in CI on every push, and terraform validate passes on this module too. Terraform's equality operators are type-tolerant — unlike arithmetic, ==/!= across mismatched primitive types evaluate to "not equal" rather than erroring — so with the number default of 30 the guard is simply always true and retention_in_days = 30 is applied. Changing it only in the .NET copy would make the two language variants diverge for no behavioural gain; if the guard should become != null, that is a cleanup worth doing across both variants in its own PR.

Comment thread samples/web-app-custom-image/dotnet/scripts/call-web-app.sh Outdated
paolosalvatori and others added 3 commits September 8, 2026 18:05
…ubject check

Two CI failures that survived four re-runs were deterministic, not flaky:

- web-app-cosmosdb-nosql-api/scripts/deploy.sh did `cd "../src"` without
  anchoring to the script's own location, so it worked when run from scripts/
  but not as `bash scripts/deploy.sh` from the sample root, which is how
  run-samples.sh invokes it: `cd: ../src: No such file or directory`. Both
  language variants now set CURRENT_DIR the way every other sample does.
- The SQL Database certificate check compared distinguished names literally,
  so OpenSSL 3's "CN = sample-web-app-sql" never matched Key Vault's
  "CN=sample-web-app-sql". Both are normalized before comparing (leading "/"
  and the spaces around "=" of the OpenSSL 1 and 3 spellings), and the match
  is a fixed-string one so a CN with regex metacharacters cannot misfire.

The Python copy of that check also stops reporting success when there is
nothing to check: its app only serves HTTPS on 8443 when started directly, so
under gunicorn the old code compared two empty thumbprints and called them
equal. It now says the port is not served and skips.

From the Copilot review: the NoSQL delete flash message reads "Activity
deleted." like the Python sample, and the unused Docker helper functions are
gone from the custom-image call script.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…g the job

Of the 11 jobs that failed on the first run of the samples workflow, 8 were in
samples this branch does not touch and went green when re-run by hand: two
never reached the sample at all (`localstack wait -t 600` expired while ~80
jobs competed for runner I/O and image pulls) and one hit a transient 500 from
the emulator while creating a MySQL firewall rule.

Automate what the manual re-runs were doing:

- the emulator start gets one clean retry, printing the container's last log
  lines when the first wait expires;
- the sample runs with continue-on-error and, on failure, once more against a
  freshly restarted emulator, because the deploy scripts are not idempotent and
  would otherwise re-run against half-provisioned resources. A genuinely broken
  sample fails both attempts, so it still fails the job.

The job also gets a 90-minute bound: a sample takes 10-25 minutes, a retry
doubles the worst case, and a hung deployment would otherwise hold a runner for
GitHub's 6-hour default.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ator start

The samples workflow came back with 2 failures out of 78 (from 11), and both
were emulator-side transients rather than sample defects:

- web-app-mysql-flexible-server/dotnet failed twice, both times on
  `az mysql flexible-server firewall-rule create` answering 500. The Azure
  CLI's own retries all land within ~5 seconds of each other, which is too
  early: the PUT succeeds once the server finishes provisioning. The create is
  now retried five times at 10-second intervals in the MySQL and PostgreSQL
  samples (both languages, since the blocks were identical), and a persistent
  failure warns instead of aborting: the rule only governs public network
  access, which the emulator does not enforce, and the database bootstrap a few
  lines later fails loudly if the server is genuinely unreachable.
- aci-blob-storage/python/bicep failed on an arm64 runner because the emulator
  never became ready - the container logged nothing for the last ten minutes of
  each 600-second wait, so the boot had stalled rather than slowed. The
  readiness retry now makes three 400-second attempts instead of two
  600-second ones: the same overall budget, one more chance, and a stalled
  container is replaced sooner.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants