From 01f0634031954035188bde30aa97673c62f2f58c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 9 Dec 2025 23:16:39 +0000
Subject: [PATCH 1/6] Add Azure Functions smoke tests with Docker support
Co-authored-by: YunchuWang <12449837+YunchuWang@users.noreply.github.com>
---
.../workflows/azure-functions-smoke-tests.yml | 48 ++++
Directory.Packages.props | 2 +
.../AzureFunctionsSmokeTests.csproj | 35 +++
test/AzureFunctionsSmokeTests/Dockerfile | 10 +
.../HelloCitiesOrchestration.cs | 62 +++++
test/AzureFunctionsSmokeTests/Program.cs | 18 ++
test/AzureFunctionsSmokeTests/README.md | 83 ++++++
test/AzureFunctionsSmokeTests/host.json | 21 ++
.../local.settings.json | 7 +
.../run-smoketests.ps1 | 247 ++++++++++++++++++
10 files changed, 533 insertions(+)
create mode 100644 .github/workflows/azure-functions-smoke-tests.yml
create mode 100644 test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
create mode 100644 test/AzureFunctionsSmokeTests/Dockerfile
create mode 100644 test/AzureFunctionsSmokeTests/HelloCitiesOrchestration.cs
create mode 100644 test/AzureFunctionsSmokeTests/Program.cs
create mode 100644 test/AzureFunctionsSmokeTests/README.md
create mode 100644 test/AzureFunctionsSmokeTests/host.json
create mode 100644 test/AzureFunctionsSmokeTests/local.settings.json
create mode 100644 test/AzureFunctionsSmokeTests/run-smoketests.ps1
diff --git a/.github/workflows/azure-functions-smoke-tests.yml b/.github/workflows/azure-functions-smoke-tests.yml
new file mode 100644
index 000000000..3fe835bc3
--- /dev/null
+++ b/.github/workflows/azure-functions-smoke-tests.yml
@@ -0,0 +1,48 @@
+name: Azure Functions Smoke Tests
+
+on:
+ push:
+ branches:
+ - main
+ - 'feature/**'
+ paths-ignore: [ '**.md' ]
+ pull_request:
+ branches:
+ - main
+ - 'feature/**'
+ paths-ignore: [ '**.md' ]
+ workflow_dispatch:
+
+jobs:
+ smoke-tests:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v3
+
+ - name: Setup .NET
+ uses: actions/setup-dotnet@v3
+ with:
+ dotnet-version: '8.0.x'
+
+ - name: Setup .NET from global.json
+ uses: actions/setup-dotnet@v3
+ with:
+ global-json-file: global.json
+
+ - name: Restore dependencies
+ run: dotnet restore test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
+
+ - name: Run smoke tests
+ run: |
+ cd test/AzureFunctionsSmokeTests
+ pwsh -File run-smoketests.ps1
+
+ - name: Upload smoke test logs on failure
+ if: failure()
+ uses: actions/upload-artifact@v4
+ with:
+ name: smoke-test-logs
+ path: test/AzureFunctionsSmokeTests/logs/
+ if-no-files-found: ignore
diff --git a/Directory.Packages.props b/Directory.Packages.props
index b36897e3f..74acc7d67 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -25,6 +25,8 @@
+
+
diff --git a/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj b/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
new file mode 100644
index 000000000..0130536a8
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
@@ -0,0 +1,35 @@
+
+
+
+ net8.0
+ v4
+ Exe
+ enable
+
+ false
+ false
+
+ false
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+ PreserveNewest
+
+
+ PreserveNewest
+ Never
+
+
+
+
diff --git a/test/AzureFunctionsSmokeTests/Dockerfile b/test/AzureFunctionsSmokeTests/Dockerfile
new file mode 100644
index 000000000..4df636799
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/Dockerfile
@@ -0,0 +1,10 @@
+# Use the Azure Functions base image for .NET 8.0 isolated
+FROM mcr.microsoft.com/azure-functions/dotnet-isolated:4-dotnet-isolated8.0
+
+# Set environment variables
+ENV AzureWebJobsScriptRoot=/home/site/wwwroot \
+ AzureFunctionsJobHost__Logging__Console__IsEnabled=true \
+ FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
+
+# Copy the published app
+COPY ./publish /home/site/wwwroot
diff --git a/test/AzureFunctionsSmokeTests/HelloCitiesOrchestration.cs b/test/AzureFunctionsSmokeTests/HelloCitiesOrchestration.cs
new file mode 100644
index 000000000..14a5b5f53
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/HelloCitiesOrchestration.cs
@@ -0,0 +1,62 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.Azure.Functions.Worker;
+using Microsoft.Azure.Functions.Worker.Http;
+using Microsoft.DurableTask;
+using Microsoft.DurableTask.Client;
+using Microsoft.Extensions.Logging;
+
+namespace AzureFunctionsSmokeTests;
+
+///
+/// Smoke test orchestration functions for Azure Functions with Durable Task.
+///
+public static class HelloCitiesOrchestration
+{
+ [Function(nameof(HelloCitiesOrchestration))]
+ public static async Task> RunOrchestrator(
+ [OrchestrationTrigger] TaskOrchestrationContext context)
+ {
+ ILogger logger = context.CreateReplaySafeLogger(nameof(HelloCitiesOrchestration));
+ logger.LogInformation("Starting HelloCities orchestration.");
+
+ List outputs = new List();
+
+ // Call activities in sequence
+ outputs.Add(await context.CallActivityAsync(nameof(SayHello), "Tokyo"));
+ outputs.Add(await context.CallActivityAsync(nameof(SayHello), "Seattle"));
+ outputs.Add(await context.CallActivityAsync(nameof(SayHello), "London"));
+
+ logger.LogInformation("HelloCities orchestration completed.");
+
+ // returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
+ return outputs;
+ }
+
+ [Function(nameof(SayHello))]
+ public static string SayHello([ActivityTrigger] string name, FunctionContext executionContext)
+ {
+ ILogger logger = executionContext.GetLogger(nameof(SayHello));
+ logger.LogInformation($"Saying hello to {name}.");
+ return $"Hello {name}!";
+ }
+
+ [Function("HelloCitiesOrchestration_HttpStart")]
+ public static async Task HttpStart(
+ [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")] HttpRequestData req,
+ [DurableClient] DurableTaskClient client,
+ FunctionContext executionContext)
+ {
+ ILogger logger = executionContext.GetLogger("HelloCitiesOrchestration_HttpStart");
+
+ // Function input comes from the request content.
+ string instanceId = await client
+ .ScheduleNewOrchestrationInstanceAsync(nameof(HelloCitiesOrchestration));
+
+ logger.LogInformation($"Started orchestration with ID = '{instanceId}'.");
+
+ // Returns an HTTP 202 response with an instance management payload.
+ return client.CreateCheckStatusResponse(req, instanceId);
+ }
+}
diff --git a/test/AzureFunctionsSmokeTests/Program.cs b/test/AzureFunctionsSmokeTests/Program.cs
new file mode 100644
index 000000000..eddb3547e
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/Program.cs
@@ -0,0 +1,18 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using Microsoft.Extensions.Hosting;
+
+namespace AzureFunctionsSmokeTests;
+
+public class Program
+{
+ public static void Main()
+ {
+ IHost host = new HostBuilder()
+ .ConfigureFunctionsWorkerDefaults()
+ .Build();
+
+ host.Run();
+ }
+}
diff --git a/test/AzureFunctionsSmokeTests/README.md b/test/AzureFunctionsSmokeTests/README.md
new file mode 100644
index 000000000..bfdf4241c
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/README.md
@@ -0,0 +1,83 @@
+# Azure Functions Smoke Tests
+
+This directory contains smoke tests for Azure Functions with Durable Task, designed to validate the SDK and Source Generator functionality in a real Azure Functions isolated .NET environment.
+
+## Overview
+
+The smoke tests ensure that:
+- The Durable Task SDK works correctly with Azure Functions isolated worker
+- Source generators produce valid code
+- Orchestrations can be triggered and completed successfully
+- The complete end-to-end workflow functions as expected
+
+## Structure
+
+- **HelloCitiesOrchestration.cs** - Simple orchestration that calls multiple activities
+- **Program.cs** - Azure Functions host entry point
+- **host.json** - Azure Functions host configuration
+- **local.settings.json** - Local development settings
+- **Dockerfile** - Docker image configuration for the Functions app
+- **run-smoketests.ps1** - PowerShell script to run smoke tests locally or in CI
+
+## Running Smoke Tests Locally
+
+### Prerequisites
+
+- Docker installed and running
+- PowerShell Core (pwsh) installed
+- .NET 8.0 SDK or later
+
+### Run the Tests
+
+From the `test/AzureFunctionsSmokeTests` directory:
+
+```bash
+pwsh -File run-smoketests.ps1
+```
+
+The script will:
+1. Build and publish the Azure Functions project
+2. Create a Docker image
+3. Start Azurite (Azure Storage emulator) in a Docker container
+4. Start the Azure Functions app in a Docker container
+5. Trigger the HelloCities orchestration via HTTP
+6. Poll for orchestration completion
+7. Validate the result
+8. Clean up all containers
+
+### Parameters
+
+The script accepts the following optional parameters:
+
+```powershell
+pwsh -File run-smoketests.ps1 `
+ -ImageName "custom-image-name" `
+ -ContainerName "custom-container-name" `
+ -Port 8080 `
+ -Timeout 120
+```
+
+## CI Integration
+
+The smoke tests are automatically run in GitHub Actions via the `.github/workflows/azure-functions-smoke-tests.yml` workflow on:
+- Push to `main` or `feature/**` branches
+- Pull requests targeting `main` or `feature/**` branches
+- Manual workflow dispatch
+
+## Troubleshooting
+
+If the smoke tests fail:
+
+1. **Check container logs**: The script will display logs automatically on failure
+2. **Verify Azurite is running**: Ensure port 10000-10002 are available
+3. **Check Functions app port**: Ensure the configured port (default 8080) is available
+4. **Build errors**: Ensure all dependencies are restored with `dotnet restore`
+
+## Adding New Smoke Tests
+
+To add new orchestration scenarios:
+
+1. Create new function classes following the pattern in `HelloCitiesOrchestration.cs`
+2. Ensure proper XML documentation comments
+3. Add test logic to validate the new scenario
+4. Update this README with the new test case
diff --git a/test/AzureFunctionsSmokeTests/host.json b/test/AzureFunctionsSmokeTests/host.json
new file mode 100644
index 000000000..305e9bf49
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/host.json
@@ -0,0 +1,21 @@
+{
+ "version": "2.0",
+ "logging": {
+ "logLevel": {
+ "Default": "Information",
+ "DurableTask.AzureStorage": "Warning",
+ "DurableTask.Core": "Warning"
+ },
+ "applicationInsights": {
+ "samplingSettings": {
+ "isEnabled": true,
+ "excludedTypes": "Request"
+ }
+ }
+ },
+ "extensions": {
+ "durableTask": {
+ "hubName": "DotNetIsolatedSmokeTests"
+ }
+ }
+}
diff --git a/test/AzureFunctionsSmokeTests/local.settings.json b/test/AzureFunctionsSmokeTests/local.settings.json
new file mode 100644
index 000000000..8eea88f48
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/local.settings.json
@@ -0,0 +1,7 @@
+{
+ "IsEncrypted": false,
+ "Values": {
+ "AzureWebJobsStorage": "UseDevelopmentStorage=true",
+ "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
+ }
+}
diff --git a/test/AzureFunctionsSmokeTests/run-smoketests.ps1 b/test/AzureFunctionsSmokeTests/run-smoketests.ps1
new file mode 100644
index 000000000..3935c91e4
--- /dev/null
+++ b/test/AzureFunctionsSmokeTests/run-smoketests.ps1
@@ -0,0 +1,247 @@
+#!/usr/bin/env pwsh
+
+<#
+.SYNOPSIS
+ Runs smoke tests for the Azure Functions app using Docker containers.
+.DESCRIPTION
+ This script builds and publishes the Azure Functions smoke test app,
+ starts required containers (Azurite for storage emulation and the Functions app),
+ triggers the orchestration, and validates successful completion.
+.PARAMETER ImageName
+ Docker image name for the Functions app (default: "azurefunctions-smoketests")
+.PARAMETER ContainerName
+ Docker container name for the Functions app (default: "azurefunctions-smoketests-container")
+.PARAMETER Port
+ Port to expose the Functions app on (default: 8080)
+.PARAMETER Timeout
+ Timeout in seconds to wait for orchestration completion (default: 120)
+#>
+
+param(
+ [string]$ImageName = "azurefunctions-smoketests",
+ [string]$ContainerName = "azurefunctions-smoketests-container",
+ [int]$Port = 8080,
+ [int]$Timeout = 120
+)
+
+$ErrorActionPreference = "Stop"
+
+# Get the directory where the script is located
+$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
+$projectDir = $scriptDir
+$publishDir = Join-Path $projectDir "publish"
+
+Write-Host "=== Azure Functions Smoke Test Runner ===" -ForegroundColor Cyan
+Write-Host ""
+
+# Function to clean up containers
+function Cleanup {
+ Write-Host "Cleaning up containers..." -ForegroundColor Yellow
+
+ # Stop and remove the Functions app container
+ docker stop $ContainerName 2>$null
+ docker rm $ContainerName 2>$null
+
+ # Stop and remove Azurite container
+ docker stop azurite-smoketest 2>$null
+ docker rm azurite-smoketest 2>$null
+
+ # Remove the Docker network
+ docker network rm smoketest-network 2>$null
+}
+
+# Cleanup on script exit
+trap {
+ Write-Host "Error occurred. Cleaning up..." -ForegroundColor Red
+ Cleanup
+ exit 1
+}
+
+try {
+ # Step 1: Build the project
+ Write-Host "Step 1: Building the Azure Functions project..." -ForegroundColor Green
+ dotnet build $projectDir -c Release
+ if ($LASTEXITCODE -ne 0) {
+ throw "Build failed with exit code $LASTEXITCODE"
+ }
+ Write-Host "Build completed successfully." -ForegroundColor Green
+ Write-Host ""
+
+ # Step 2: Publish the project
+ Write-Host "Step 2: Publishing the Azure Functions project..." -ForegroundColor Green
+ if (Test-Path $publishDir) {
+ Remove-Item $publishDir -Recurse -Force
+ }
+ dotnet publish $projectDir -c Release -o $publishDir
+ if ($LASTEXITCODE -ne 0) {
+ throw "Publish failed with exit code $LASTEXITCODE"
+ }
+ Write-Host "Publish completed successfully." -ForegroundColor Green
+ Write-Host ""
+
+ # Step 3: Build Docker image
+ Write-Host "Step 3: Building Docker image '$ImageName'..." -ForegroundColor Green
+ docker build -t $ImageName $projectDir
+ if ($LASTEXITCODE -ne 0) {
+ throw "Docker build failed with exit code $LASTEXITCODE"
+ }
+ Write-Host "Docker image built successfully." -ForegroundColor Green
+ Write-Host ""
+
+ # Step 4: Create Docker network
+ Write-Host "Step 4: Creating Docker network..." -ForegroundColor Green
+ docker network create smoketest-network 2>$null
+ Write-Host "Docker network created or already exists." -ForegroundColor Green
+ Write-Host ""
+
+ # Step 5: Start Azurite container
+ Write-Host "Step 5: Starting Azurite storage emulator..." -ForegroundColor Green
+ docker run -d `
+ --name azurite-smoketest `
+ --network smoketest-network `
+ -p 10000:10000 `
+ -p 10001:10001 `
+ -p 10002:10002 `
+ mcr.microsoft.com/azure-storage/azurite:latest
+
+ if ($LASTEXITCODE -ne 0) {
+ throw "Failed to start Azurite container"
+ }
+
+ # Wait for Azurite to be ready
+ Write-Host "Waiting for Azurite to be ready..." -ForegroundColor Yellow
+ Start-Sleep -Seconds 5
+ Write-Host "Azurite is ready." -ForegroundColor Green
+ Write-Host ""
+
+ # Step 6: Start Azure Functions container
+ Write-Host "Step 6: Starting Azure Functions container..." -ForegroundColor Green
+
+ # Azurite connection string for Docker network
+ $storageConnectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite-smoketest:10000/devstoreaccount1;QueueEndpoint=http://azurite-smoketest:10001/devstoreaccount1;TableEndpoint=http://azurite-smoketest:10002/devstoreaccount1;"
+
+ docker run -d `
+ --name $ContainerName `
+ --network smoketest-network `
+ -p "${Port}:80" `
+ -e AzureWebJobsStorage="$storageConnectionString" `
+ -e FUNCTIONS_WORKER_RUNTIME=dotnet-isolated `
+ $ImageName
+
+ if ($LASTEXITCODE -ne 0) {
+ throw "Failed to start Functions container"
+ }
+
+ # Wait for Functions host to start
+ Write-Host "Waiting for Azure Functions host to start..." -ForegroundColor Yellow
+ $maxRetries = 30
+ $retryCount = 0
+ $isReady = $false
+
+ while ($retryCount -lt $maxRetries) {
+ Start-Sleep -Seconds 2
+ $retryCount++
+
+ try {
+ $response = Invoke-WebRequest -Uri "http://localhost:$Port/admin/host/status" -UseBasicParsing -TimeoutSec 2 -ErrorAction SilentlyContinue
+ if ($response.StatusCode -eq 200) {
+ $isReady = $true
+ break
+ }
+ }
+ catch {
+ # Continue retrying
+ }
+
+ Write-Host "." -NoNewline
+ }
+
+ Write-Host ""
+
+ if (-not $isReady) {
+ Write-Host "Functions host failed to start. Checking logs..." -ForegroundColor Red
+ docker logs $ContainerName
+ throw "Functions host did not start within the expected time"
+ }
+
+ Write-Host "Azure Functions host is ready." -ForegroundColor Green
+ Write-Host ""
+
+ # Step 7: Trigger orchestration
+ Write-Host "Step 7: Triggering orchestration..." -ForegroundColor Green
+ $startUrl = "http://localhost:$Port/api/HelloCitiesOrchestration_HttpStart"
+
+ try {
+ $startResponse = Invoke-WebRequest -Uri $startUrl -Method Post -UseBasicParsing
+ if ($startResponse.StatusCode -ne 202) {
+ throw "Unexpected status code: $($startResponse.StatusCode)"
+ }
+ }
+ catch {
+ Write-Host "Failed to trigger orchestration. Error: $_" -ForegroundColor Red
+ Write-Host "Container logs:" -ForegroundColor Yellow
+ docker logs $ContainerName
+ throw
+ }
+
+ $responseContent = $startResponse.Content | ConvertFrom-Json
+ $statusQueryGetUri = $responseContent.statusQueryGetUri
+ $instanceId = $responseContent.id
+
+ Write-Host "Orchestration started with instance ID: $instanceId" -ForegroundColor Green
+ Write-Host "Status query URI: $statusQueryGetUri" -ForegroundColor Cyan
+ Write-Host ""
+
+ # Step 8: Poll for completion
+ Write-Host "Step 8: Polling for orchestration completion..." -ForegroundColor Green
+ $startTime = Get-Date
+ $completed = $false
+
+ while (((Get-Date) - $startTime).TotalSeconds -lt $Timeout) {
+ Start-Sleep -Seconds 2
+
+ try {
+ $statusResponse = Invoke-WebRequest -Uri $statusQueryGetUri -UseBasicParsing
+ $status = $statusResponse.Content | ConvertFrom-Json
+
+ Write-Host "Current status: $($status.runtimeStatus)" -ForegroundColor Yellow
+
+ if ($status.runtimeStatus -eq "Completed") {
+ $completed = $true
+ Write-Host ""
+ Write-Host "Orchestration completed successfully!" -ForegroundColor Green
+ Write-Host "Output: $($status.output)" -ForegroundColor Cyan
+ break
+ }
+ elseif ($status.runtimeStatus -eq "Failed" -or $status.runtimeStatus -eq "Terminated") {
+ throw "Orchestration ended with status: $($status.runtimeStatus)"
+ }
+ }
+ catch {
+ Write-Host "Error polling status: $_" -ForegroundColor Red
+ }
+ }
+
+ if (-not $completed) {
+ Write-Host "Container logs:" -ForegroundColor Yellow
+ docker logs $ContainerName
+ throw "Orchestration did not complete within timeout period"
+ }
+
+ Write-Host ""
+ Write-Host "=== Smoke test completed successfully! ===" -ForegroundColor Green
+}
+finally {
+ # Cleanup
+ Cleanup
+
+ # Cleanup publish directory
+ if (Test-Path $publishDir) {
+ Write-Host "Cleaning up publish directory..." -ForegroundColor Yellow
+ Remove-Item $publishDir -Recurse -Force
+ }
+}
+
+Write-Host ""
+Write-Host "All smoke tests passed!" -ForegroundColor Green
+exit 0
From df335ee29920e9c894821b06086ed8e038a117cc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 9 Dec 2025 23:26:09 +0000
Subject: [PATCH 2/6] Fix smoke test script - add WEBSITE_HOSTNAME and improve
health check
Co-authored-by: YunchuWang <12449837+YunchuWang@users.noreply.github.com>
---
.../run-smoketests.ps1 | 60 +++++++++----------
1 file changed, 29 insertions(+), 31 deletions(-)
diff --git a/test/AzureFunctionsSmokeTests/run-smoketests.ps1 b/test/AzureFunctionsSmokeTests/run-smoketests.ps1
index 3935c91e4..8ed270083 100644
--- a/test/AzureFunctionsSmokeTests/run-smoketests.ps1
+++ b/test/AzureFunctionsSmokeTests/run-smoketests.ps1
@@ -39,15 +39,15 @@ function Cleanup {
Write-Host "Cleaning up containers..." -ForegroundColor Yellow
# Stop and remove the Functions app container
- docker stop $ContainerName 2>$null
- docker rm $ContainerName 2>$null
+ docker stop $ContainerName 2>$null | Out-Null
+ docker rm $ContainerName 2>$null | Out-Null
# Stop and remove Azurite container
- docker stop azurite-smoketest 2>$null
- docker rm azurite-smoketest 2>$null
+ docker stop azurite-smoketest 2>$null | Out-Null
+ docker rm azurite-smoketest 2>$null | Out-Null
# Remove the Docker network
- docker network rm smoketest-network 2>$null
+ docker network rm smoketest-network 2>$null | Out-Null
}
# Cleanup on script exit
@@ -58,6 +58,11 @@ trap {
}
try {
+ # Cleanup any existing containers first
+ Write-Host "Cleaning up any existing containers..." -ForegroundColor Yellow
+ Cleanup
+ Write-Host ""
+
# Step 1: Build the project
Write-Host "Step 1: Building the Azure Functions project..." -ForegroundColor Green
dotnet build $projectDir -c Release
@@ -126,6 +131,7 @@ try {
-p "${Port}:80" `
-e AzureWebJobsStorage="$storageConnectionString" `
-e FUNCTIONS_WORKER_RUNTIME=dotnet-isolated `
+ -e WEBSITE_HOSTNAME="localhost:$Port" `
$ImageName
if ($LASTEXITCODE -ne 0) {
@@ -134,37 +140,29 @@ try {
# Wait for Functions host to start
Write-Host "Waiting for Azure Functions host to start..." -ForegroundColor Yellow
- $maxRetries = 30
- $retryCount = 0
- $isReady = $false
- while ($retryCount -lt $maxRetries) {
- Start-Sleep -Seconds 2
- $retryCount++
-
- try {
- $response = Invoke-WebRequest -Uri "http://localhost:$Port/admin/host/status" -UseBasicParsing -TimeoutSec 2 -ErrorAction SilentlyContinue
- if ($response.StatusCode -eq 200) {
- $isReady = $true
- break
- }
- }
- catch {
- # Continue retrying
- }
-
- Write-Host "." -NoNewline
- }
+ # Give the host time to fully initialize
+ # The admin/host/status endpoint is not available in all configurations,
+ # so we'll wait a reasonable amount of time and check logs
+ Start-Sleep -Seconds 15
- Write-Host ""
-
- if (-not $isReady) {
- Write-Host "Functions host failed to start. Checking logs..." -ForegroundColor Red
+ # Check if the container is still running
+ $containerStatus = docker inspect --format='{{.State.Status}}' $ContainerName
+ if ($containerStatus -ne "running") {
+ Write-Host "Functions container is not running. Checking logs..." -ForegroundColor Red
docker logs $ContainerName
- throw "Functions host did not start within the expected time"
+ throw "Functions container failed to start"
}
- Write-Host "Azure Functions host is ready." -ForegroundColor Green
+ # Check logs for successful startup
+ $logs = docker logs $ContainerName 2>&1 | Out-String
+ if ($logs -match "Job host started" -or $logs -match "Host started") {
+ Write-Host "Azure Functions host is ready." -ForegroundColor Green
+ }
+ else {
+ Write-Host "Warning: Could not confirm host startup from logs." -ForegroundColor Yellow
+ Write-Host "Attempting to continue with orchestration trigger..." -ForegroundColor Yellow
+ }
Write-Host ""
# Step 7: Trigger orchestration
From 8819ac948df3f489bf68792a33536add6e215ee9 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 9 Dec 2025 23:29:16 +0000
Subject: [PATCH 3/6] Address code review feedback - improve error handling and
code readability
Co-authored-by: YunchuWang <12449837+YunchuWang@users.noreply.github.com>
---
.../run-smoketests.ps1 | 30 +++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
diff --git a/test/AzureFunctionsSmokeTests/run-smoketests.ps1 b/test/AzureFunctionsSmokeTests/run-smoketests.ps1
index 8ed270083..185b9e3df 100644
--- a/test/AzureFunctionsSmokeTests/run-smoketests.ps1
+++ b/test/AzureFunctionsSmokeTests/run-smoketests.ps1
@@ -123,7 +123,21 @@ try {
Write-Host "Step 6: Starting Azure Functions container..." -ForegroundColor Green
# Azurite connection string for Docker network
- $storageConnectionString = "DefaultEndpointsProtocol=http;AccountName=devstoreaccount1;AccountKey=Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw==;BlobEndpoint=http://azurite-smoketest:10000/devstoreaccount1;QueueEndpoint=http://azurite-smoketest:10001/devstoreaccount1;TableEndpoint=http://azurite-smoketest:10002/devstoreaccount1;"
+ # Using the default Azurite development account credentials
+ $accountName = "devstoreaccount1"
+ $accountKey = "Eby8vdM02xNOcqFlqUwJPLlmEtlCDXJ1OUzFT50uSRZ6IFsuFq2UVErCz4I6tq/K1SZFPTOtr/KBHBeksoGMGw=="
+ $blobEndpoint = "http://azurite-smoketest:10000/$accountName"
+ $queueEndpoint = "http://azurite-smoketest:10001/$accountName"
+ $tableEndpoint = "http://azurite-smoketest:10002/$accountName"
+
+ $storageConnectionString = @(
+ "DefaultEndpointsProtocol=http"
+ "AccountName=$accountName"
+ "AccountKey=$accountKey"
+ "BlobEndpoint=$blobEndpoint"
+ "QueueEndpoint=$queueEndpoint"
+ "TableEndpoint=$tableEndpoint"
+ ) -join ";"
docker run -d `
--name $ContainerName `
@@ -194,6 +208,8 @@ try {
Write-Host "Step 8: Polling for orchestration completion..." -ForegroundColor Green
$startTime = Get-Date
$completed = $false
+ $consecutiveErrors = 0
+ $maxConsecutiveErrors = 3
while (((Get-Date) - $startTime).TotalSeconds -lt $Timeout) {
Start-Sleep -Seconds 2
@@ -202,6 +218,9 @@ try {
$statusResponse = Invoke-WebRequest -Uri $statusQueryGetUri -UseBasicParsing
$status = $statusResponse.Content | ConvertFrom-Json
+ # Reset error counter on successful poll
+ $consecutiveErrors = 0
+
Write-Host "Current status: $($status.runtimeStatus)" -ForegroundColor Yellow
if ($status.runtimeStatus -eq "Completed") {
@@ -216,7 +235,14 @@ try {
}
}
catch {
- Write-Host "Error polling status: $_" -ForegroundColor Red
+ $consecutiveErrors++
+ Write-Host "Error polling status (attempt $consecutiveErrors/$maxConsecutiveErrors): $_" -ForegroundColor Red
+
+ if ($consecutiveErrors -ge $maxConsecutiveErrors) {
+ Write-Host "Container logs:" -ForegroundColor Yellow
+ docker logs $ContainerName
+ throw "Too many consecutive errors polling orchestration status"
+ }
}
}
From d3a87b3d48d1051746b4ac15326c4117415e8941 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Sat, 13 Dec 2025 22:27:01 +0000
Subject: [PATCH 4/6] Use project references for all DurableTask packages in
smoke tests
Replace transitive NuGet package dependencies with direct project references to:
- Microsoft.DurableTask.Abstractions
- Microsoft.DurableTask.Client
- Microsoft.DurableTask.Client.Grpc
- Microsoft.DurableTask.Worker
- Microsoft.DurableTask.Worker.Grpc
- Microsoft.DurableTask.Grpc
- Microsoft.DurableTask.Analyzers
This ensures the smoke tests validate code from this repo rather than published packages.
Co-authored-by: YunchuWang <12449837+YunchuWang@users.noreply.github.com>
---
.../AzureFunctionsSmokeTests.csproj | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj b/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
index 0130536a8..219d5bc98 100644
--- a/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
+++ b/test/AzureFunctionsSmokeTests/AzureFunctionsSmokeTests.csproj
@@ -14,11 +14,22 @@
+
-
+
+
+
+
+
+
+
+
+
+
+
From f25814e2e2123604944dbcaacd129351ed9e5a84 Mon Sep 17 00:00:00 2001
From: wangbill
Date: Tue, 16 Dec 2025 09:13:41 -0800
Subject: [PATCH 5/6] Remove branch filters from pull_request event
---
.github/workflows/azure-functions-smoke-tests.yml | 3 ---
1 file changed, 3 deletions(-)
diff --git a/.github/workflows/azure-functions-smoke-tests.yml b/.github/workflows/azure-functions-smoke-tests.yml
index 3fe835bc3..9ee868fda 100644
--- a/.github/workflows/azure-functions-smoke-tests.yml
+++ b/.github/workflows/azure-functions-smoke-tests.yml
@@ -7,9 +7,6 @@ on:
- 'feature/**'
paths-ignore: [ '**.md' ]
pull_request:
- branches:
- - main
- - 'feature/**'
paths-ignore: [ '**.md' ]
workflow_dispatch:
From d46fd5b15e85a1827fcc4f201be157cc830a5138 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 16 Dec 2025 17:42:05 +0000
Subject: [PATCH 6/6] Update Azure Functions package versions to 3.3.0 and
2.0.7
Updated package versions in Directory.Packages.props:
- Microsoft.Azure.Functions.Worker.Extensions.Http: 3.0.13 -> 3.3.0
- Microsoft.Azure.Functions.Worker.Sdk: 1.16.2 -> 2.0.7
Co-authored-by: YunchuWang <12449837+YunchuWang@users.noreply.github.com>
---
Directory.Packages.props | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 74acc7d67..d4a8354ce 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -25,8 +25,8 @@
-
-
+
+