From 1c5ff1a19e7b8fbee88ad45a80e2053c4281cc92 Mon Sep 17 00:00:00 2001 From: Anatoli Beliaev Date: Mon, 28 Jul 2025 22:13:42 -0700 Subject: [PATCH 1/3] Add Version parameter to Start-DurableOrchestration and Invoke-SubOrchestrator --- ...AzureFunctions.PowerShell.Durable.SDK.psm1 | 12 ++++- .../Actions/CallSubOrchestratorAction.cs | 8 ++- .../CallSubOrchestratorWithRetryAction.cs | 8 ++- src/DurableEngine/DurableEngine.csproj | 4 +- .../Tasks/SubOrchestratorTask.cs | 15 ++++-- .../APIs/InvokeSubOrchestratorCommand.cs | 9 +++- src/Help/Invoke-DurableSubOrchestrator.md | 28 +++++++++- src/Help/Start-DurableOrchestration.md | 24 ++++++++- .../ActivityTests.cs | 6 +-- .../Constants.cs | 2 +- .../DurableClientTests.cs | 53 +++++++++++++++++++ .../DurableTests.cs | 6 +-- .../ExternalEventTests.cs | 2 +- .../Utilities.cs | 2 +- test/E2E/durableApp/DurableClient/run.ps1 | 19 ++++++- .../VersionedOrchestrator/function.json | 9 ++++ .../durableApp/VersionedOrchestrator/run.ps1 | 14 +++++ .../VersionedSubOrchestrator/function.json | 9 ++++ .../VersionedSubOrchestrator/run.ps1 | 9 ++++ test/E2E/durableApp/extensions.csproj | 2 +- 20 files changed, 219 insertions(+), 22 deletions(-) create mode 100644 test/E2E/durableApp/VersionedOrchestrator/function.json create mode 100644 test/E2E/durableApp/VersionedOrchestrator/run.ps1 create mode 100644 test/E2E/durableApp/VersionedSubOrchestrator/function.json create mode 100644 test/E2E/durableApp/VersionedSubOrchestrator/run.ps1 diff --git a/src/AzureFunctions.PowerShell.Durable.SDK.psm1 b/src/AzureFunctions.PowerShell.Durable.SDK.psm1 index 8c6dc51..5a6998a 100644 --- a/src/AzureFunctions.PowerShell.Durable.SDK.psm1 +++ b/src/AzureFunctions.PowerShell.Durable.SDK.psm1 @@ -100,7 +100,11 @@ function Start-DurableOrchestration { [Parameter( ValueFromPipelineByPropertyName=$true)] - [string] $InstanceId + [string] $InstanceId, + + [Parameter( + ValueFromPipelineByPropertyName=$true)] + [string] $Version ) $ErrorActionPreference = 'Stop' @@ -126,6 +130,12 @@ function Start-DurableOrchestration { $UriTemplate.Replace('{functionName}', $FunctionName).Replace('[/{instanceId}]', "/$InstanceId") } + # Add version parameter to query string if provided + if ($Version) { + $separator = if ($Uri.Contains('?')) { '&' } else { '?' } + $Uri += "$separator" + "version=$([System.Web.HttpUtility]::UrlEncode($Version))" + } + $Body = $InputObject | ConvertTo-Json -Compress -Depth 100 $null = Invoke-RestMethod -Uri $Uri -Method 'POST' -ContentType 'application/json' -Body $Body -Headers $headers diff --git a/src/DurableEngine/Actions/CallSubOrchestratorAction.cs b/src/DurableEngine/Actions/CallSubOrchestratorAction.cs index 66d9309..e6152b4 100644 --- a/src/DurableEngine/Actions/CallSubOrchestratorAction.cs +++ b/src/DurableEngine/Actions/CallSubOrchestratorAction.cs @@ -22,12 +22,18 @@ internal class CallSubOrchestratorAction : OrchestrationAction /// public readonly object Input; - internal CallSubOrchestratorAction(string functionName, object input, string instanceId) + /// + /// The version of the sub-orchestrator function. + /// + public readonly string Version; + + internal CallSubOrchestratorAction(string functionName, object input, string instanceId, string version) : base(ActionType.CallSubOrchestrator) { FunctionName = functionName; Input = input; InstanceId = instanceId; + Version = version; } } } diff --git a/src/DurableEngine/Actions/CallSubOrchestratorWithRetryAction.cs b/src/DurableEngine/Actions/CallSubOrchestratorWithRetryAction.cs index bb27a18..ca97063 100644 --- a/src/DurableEngine/Actions/CallSubOrchestratorWithRetryAction.cs +++ b/src/DurableEngine/Actions/CallSubOrchestratorWithRetryAction.cs @@ -29,13 +29,19 @@ internal class CallSubOrchestratorWithRetryAction : OrchestrationAction /// public readonly Dictionary RetryOptions; - internal CallSubOrchestratorWithRetryAction(string functionName, object input, string instanceId, RetryPolicy retryOptions) + /// + /// The version of the sub-orchestrator function. + /// + public readonly string Version; + + internal CallSubOrchestratorWithRetryAction(string functionName, object input, string instanceId, RetryPolicy retryOptions, string version) : base(ActionType.CallSubOrchestratorWithRetry) { FunctionName = functionName; InstanceId = instanceId; Input = input; RetryOptions = retryOptions.RetryPolicyDictionary; + Version = version; } } } diff --git a/src/DurableEngine/DurableEngine.csproj b/src/DurableEngine/DurableEngine.csproj index 8cb2b32..6e11fab 100644 --- a/src/DurableEngine/DurableEngine.csproj +++ b/src/DurableEngine/DurableEngine.csproj @@ -7,8 +7,8 @@ - - + + diff --git a/src/DurableEngine/Tasks/SubOrchestratorTask.cs b/src/DurableEngine/Tasks/SubOrchestratorTask.cs index e68c471..aba2398 100644 --- a/src/DurableEngine/Tasks/SubOrchestratorTask.cs +++ b/src/DurableEngine/Tasks/SubOrchestratorTask.cs @@ -20,11 +20,14 @@ public class SubOrchestratorTask : DurableTask private RetryPolicy RetryOptions { get; } + internal string Version { get; } + public SubOrchestratorTask( string functionName, string instanceId, object functionInput, RetryPolicy retryOptions, + string version, SwitchParameter noWait, Hashtable privateData) : base(noWait, privateData) { @@ -32,6 +35,7 @@ public SubOrchestratorTask( InstanceId = instanceId; Input = functionInput; RetryOptions = retryOptions; + Version = version; } internal override Task CreateDTFxTask() @@ -45,14 +49,19 @@ internal override Task CreateDTFxTask() ? taskOptions : taskOptions.WithInstanceId(InstanceId); - return DTFxContext.CallSubOrchestratorAsync(FunctionName, Input, taskOptions); + var subOrchestrationOptions = new SubOrchestrationOptions(taskOptions, InstanceId) + { + Version = this.Version + }; + + return DTFxContext.CallSubOrchestratorAsync(FunctionName, Input, subOrchestrationOptions); } internal override OrchestrationAction CreateOrchestrationAction() { return RetryOptions == null - ? new CallSubOrchestratorAction(FunctionName, Input, InstanceId) - : new CallSubOrchestratorWithRetryAction(FunctionName, Input, InstanceId, RetryOptions); + ? new CallSubOrchestratorAction(FunctionName, Input, InstanceId, Version) + : new CallSubOrchestratorWithRetryAction(FunctionName, Input, InstanceId, RetryOptions, Version); } } } diff --git a/src/DurableSDK/Commands/APIs/InvokeSubOrchestratorCommand.cs b/src/DurableSDK/Commands/APIs/InvokeSubOrchestratorCommand.cs index 8821d65..2a25c20 100644 --- a/src/DurableSDK/Commands/APIs/InvokeSubOrchestratorCommand.cs +++ b/src/DurableSDK/Commands/APIs/InvokeSubOrchestratorCommand.cs @@ -43,6 +43,13 @@ public class InvokeSubOrchestratorCommand : DurableSDKCmdlet [ValidateNotNull] public RetryPolicy RetryOptions { get; set; } + /// + /// Version of the SubOrchestrator to invoke. + /// + [Parameter] + [ValidateNotNull] + public string Version { get; set; } + /// /// If provided, the Task will block and be scheduled immediately. /// Otherwise, a Task object is returned and the Task is not scheduled yet. @@ -53,7 +60,7 @@ public class InvokeSubOrchestratorCommand : DurableSDKCmdlet internal override DurableTask CreateDurableTask() { var privateData = (Hashtable)MyInvocation.MyCommand.Module.PrivateData; - SubOrchestratorTask task = new SubOrchestratorTask(FunctionName, InstanceId, Input, RetryOptions, NoWait, privateData); + SubOrchestratorTask task = new SubOrchestratorTask(FunctionName, InstanceId, Input, RetryOptions, Version, NoWait, privateData); return task; } } diff --git a/src/Help/Invoke-DurableSubOrchestrator.md b/src/Help/Invoke-DurableSubOrchestrator.md index 75986a8..ff70712 100644 --- a/src/Help/Invoke-DurableSubOrchestrator.md +++ b/src/Help/Invoke-DurableSubOrchestrator.md @@ -14,7 +14,7 @@ Invokes a sub-orchestrator function. ## SYNTAX ``` -Invoke-DurableSubOrchestrator -FunctionName [-InstanceId ] [-Input ] [-RetryOptions ] [-NoWait] [] +Invoke-DurableSubOrchestrator -FunctionName [-InstanceId ] [-Input ] [-RetryOptions ] [-Version ] [-NoWait] [] ``` ## DESCRIPTION @@ -46,6 +46,15 @@ Write-Host "Sub-orchestrator completed with result: $batchResult" This example shows how to invoke a sub-orchestrator function asynchronously using -NoWait, which returns a task object that can be awaited later. +### Example 3 - Specifying a version + +```powershell +$result = Invoke-DurableSubOrchestrator -FunctionName "ChildOrchestrator" -Version "2.0" -Input @{ ProcessId = "proc456" } +Write-Host "Sub-orchestrator (version 2.0) completed with result: $result" +``` + +This example shows how to invoke a sub-orchestrator with a specific version, overriding the default version configured in host.json. + ## PARAMETERS ### -FunctionName @@ -96,6 +105,22 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Version + +An optional version string for the sub-orchestrator function. When specified, this version overrides the default version configured in host.json for this specific sub-orchestrator invocation. This allows you to invoke specific versions of orchestrator functions. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -NoWait When specified, the cmdlet returns a task object immediately without waiting for completion. By default, the cmdlet blocks and waits for the sub-orchestrator to complete before returning the result. @@ -152,6 +177,7 @@ Returns the result of the sub-orchestrator execution by default. If -NoWait is s - Use the -NoWait parameter when you need to invoke multiple sub-orchestrators concurrently. - Sub-orchestrators inherit the fault-tolerance and replay characteristics of the parent orchestration. - The sub-orchestrator function name must match a function defined in your Azure Functions app with an orchestration trigger. +- The -Version parameter allows you to invoke specific versions of orchestrator functions, overriding the default version from host.json. - Consider using sub-orchestrators to break down complex workflows into manageable, reusable components. ## RELATED LINKS diff --git a/src/Help/Start-DurableOrchestration.md b/src/Help/Start-DurableOrchestration.md index 1fd19ac..f3b71bb 100644 --- a/src/Help/Start-DurableOrchestration.md +++ b/src/Help/Start-DurableOrchestration.md @@ -14,7 +14,7 @@ Start a durable orchestration. ## SYNTAX ``` -Start-DurableOrchestration [-FunctionName] [[-InputObject] ] [-DurableClient ] [-InstanceId ] [] +Start-DurableOrchestration [-FunctionName] [[-InputObject] ] [-DurableClient ] [-InstanceId ] [-Version ] [] ``` ## DESCRIPTION @@ -99,6 +99,24 @@ Accept pipeline input: True (ByPropertyName) Accept wildcard characters: False ``` +### -Version + +Optional orchestration version. +The provided value will be available as `$Context.Version` within the orchestrator function context. +If not specified, the default version specified by the `defaultVersion` property in the Function app's host.json will be used. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: True (ByPropertyName) +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -ProgressAction, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). @@ -117,6 +135,10 @@ You can pipe objects to the -InputObject parameter to provide input data for the You can pipe strings to the -InstanceId parameter to specify a custom instance ID for the orchestration. +### System.String (Version) + +You can pipe strings to the -Version parameter to specify a version for the orchestration function. + ## OUTPUTS ### System.String diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ActivityTests.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ActivityTests.cs index d449866..2ebb947 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ActivityTests.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ActivityTests.cs @@ -23,7 +23,7 @@ public async Task ActivityCanHaveQueueBinding() Assert.Equal(HttpStatusCode.Accepted, initialResponse.StatusCode); var initialResponseBodyString = await initialResponse.Content.ReadAsStringAsync(); - dynamic initialResponseBody = JsonConvert.DeserializeObject(initialResponseBodyString); + dynamic initialResponseBody = JsonConvert.DeserializeObject(initialResponseBodyString)!; var statusQueryGetUri = (string)initialResponseBody.statusQueryGetUri; var startTime = DateTime.UtcNow; @@ -41,7 +41,7 @@ public async Task ActivityCanHaveQueueBinding() { if (DateTime.UtcNow > startTime + _orchestrationCompletionTimeout) { - Assert.True(false, $"The orchestration has not completed after {_orchestrationCompletionTimeout}"); + Assert.Fail($"The orchestration has not completed after {_orchestrationCompletionTimeout}"); } await Task.Delay(TimeSpan.FromSeconds(2)); break; @@ -56,7 +56,7 @@ public async Task ActivityCanHaveQueueBinding() } default: - Assert.True(false, $"Unexpected orchestration status code: {statusResponse.StatusCode}"); + Assert.Fail($"Unexpected orchestration status code: {statusResponse.StatusCode}"); break; } } diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Constants.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Constants.cs index e81e8cd..bc6188c 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Constants.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Constants.cs @@ -13,7 +13,7 @@ public static class Constants public static class Queue { public static string QueueName = "outqueue"; - public static string StorageConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsStorage"); + public static string StorageConnectionStringSetting = Environment.GetEnvironmentVariable("AzureWebJobsStorage") ?? "AzureWebJobsStorage placeholder"; public static string OutputBindingName = "test-output-ps"; public static string InputBindingName = "test-input-ps"; } diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs index 7807c26..982d360 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs @@ -3,6 +3,7 @@ using AzureFunctions.PowerShell.Durable.SDK.Tests.E2E; using Newtonsoft.Json; +using System.Collections.Generic; using System.Net; using Xunit; @@ -260,5 +261,57 @@ await ValidateDurableWorkflowResults( Assert.Equal("SecondExternalEvent", finalStatusResponseBody.output[1].ToString()); }); } + + [Theory] + // [InlineData(null, null, "1.0", "1.0")] // No version specified, should use defaultVersion from host.json for both + // [InlineData("0.5", null, "0.5", "1.0")] // Version specified for orchestrator, orchestrator should use it, suborchestrator should use defaultVersion + // [InlineData(null, "0.7", "1.0", "0.7")] // Version specified for suborchestrator only, orchestrator should use defaultVersion, suborchestrator should use specified version + [InlineData("0.5", "0.7", "0.5", "0.7")] // Both versions specified, each should use their respective versions + public async Task OrchestrationVersionIsPropagatedToContext( + string orchestratorVersion, + string subOrchestratorVersion, + string expectedOrchestratorVersion, + string expectedSubOrchestratorVersion) + { + var queryParams = new List(); + if (orchestratorVersion != null) + queryParams.Add($"Version={orchestratorVersion}"); + if (subOrchestratorVersion != null) + queryParams.Add($"SubOrchestratorVersion={subOrchestratorVersion}"); + + string queryString = queryParams.Count > 0 ? "?" + string.Join("&", queryParams) : string.Empty; + + var initialResponse = await Utilities.GetHttpStartResponse("VersionedOrchestrator", queryString); + Assert.Equal(HttpStatusCode.Accepted, initialResponse.StatusCode); + + var location = initialResponse.Headers.Location; + Assert.NotNull(location); + + await ValidateDurableWorkflowResults( + initialResponse, + validateInitialResponse: (dynamic initialResponseBody) => + { + Assert.NotNull(initialResponseBody.id); + var statusQueryGetUri = (string)initialResponseBody.statusQueryGetUri; + Assert.Equal(location?.ToString(), statusQueryGetUri); + Assert.NotNull(initialResponseBody.sendEventPostUri); + Assert.NotNull(initialResponseBody.purgeHistoryDeleteUri); + Assert.NotNull(initialResponseBody.terminatePostUri); + Assert.NotNull(initialResponseBody.rewindPostUri); + }, + validateIntermediateResponse: (dynamic intermediateStatusResponseBody) => + { + var runtimeStatus = (string)intermediateStatusResponseBody.runtimeStatus; + Assert.True( + runtimeStatus == "Running" || runtimeStatus == "Pending", + $"Unexpected runtime status: {runtimeStatus}"); + }, + validateFinalResponse: (dynamic finalStatusResponseBody) => + { + Assert.Equal("Completed", (string)finalStatusResponseBody.runtimeStatus); + Assert.Equal(expectedOrchestratorVersion, finalStatusResponseBody.output[0].ToString()); + Assert.Equal(expectedSubOrchestratorVersion, finalStatusResponseBody.output[1].ToString()); + }); + } } } \ No newline at end of file diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableTests.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableTests.cs index a8fd5d1..9fe1c83 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableTests.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableTests.cs @@ -39,7 +39,7 @@ protected internal async Task ValidateDurableWorkflowResults( Action? validateFinalResponse = null) { var initialResponseBodyString = await initialResponse.Content.ReadAsStringAsync(); - dynamic initialResponseBody = JsonConvert.DeserializeObject(initialResponseBodyString); + dynamic initialResponseBody = JsonConvert.DeserializeObject(initialResponseBodyString)!; var statusQueryGetUri = (string)initialResponseBody.statusQueryGetUri; validateInitialResponse?.Invoke(initialResponseBody); @@ -63,7 +63,7 @@ protected internal async Task ValidateDurableWorkflowResults( { if (DateTime.UtcNow > startTime + _orchestrationCompletionTimeout) { - Assert.True(false, $"The orchestration has not completed after {_orchestrationCompletionTimeout}"); + Assert.Fail($"The orchestration has not completed after {_orchestrationCompletionTimeout}"); } validateIntermediateResponse?.Invoke(statusResponseBody); @@ -78,7 +78,7 @@ protected internal async Task ValidateDurableWorkflowResults( } default: - Assert.True(false, $"Unexpected orchestration status code: {statusResponse.StatusCode}"); + Assert.Fail($"Unexpected orchestration status code: {statusResponse.StatusCode}"); break; } } diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ExternalEventTests.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ExternalEventTests.cs index 6c90ade..fcf2878 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ExternalEventTests.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/ExternalEventTests.cs @@ -26,7 +26,7 @@ await ValidateDurableWorkflowResults( sendExternalEvents: async (HttpClient httpClient) => { var initialResponseBodyString = await initialResponse.Content.ReadAsStringAsync(); - dynamic initialResponseBody = JsonConvert.DeserializeObject(initialResponseBodyString); + dynamic initialResponseBody = JsonConvert.DeserializeObject(initialResponseBodyString)!; var raiseEventUri = (string)initialResponseBody.sendEventPostUri; raiseEventUri = raiseEventUri.Replace("{eventName}", "TESTEVENTNAME"); diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Utilities.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Utilities.cs index b0f1a43..75b140e 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Utilities.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/Utilities.cs @@ -51,7 +51,7 @@ public static async Task GetHttpStartResponse( public static async Task GetResponseBodyAsync(HttpResponseMessage response) { var responseBody = await response.Content.ReadAsStringAsync(); - return JsonConvert.DeserializeObject(responseBody); + return JsonConvert.DeserializeObject(responseBody)!; } } } \ No newline at end of file diff --git a/test/E2E/durableApp/DurableClient/run.ps1 b/test/E2E/durableApp/DurableClient/run.ps1 index af8b2cc..50bea4a 100644 --- a/test/E2E/durableApp/DurableClient/run.ps1 +++ b/test/E2E/durableApp/DurableClient/run.ps1 @@ -6,7 +6,24 @@ $ErrorActionPreference = 'Stop' Write-Host "DurableClient started" $FunctionName = $Request.Params.FunctionName -$InstanceId = Start-DurableOrchestration -FunctionName $FunctionName + +$Version = $Request.Query.Version +$SubOrchestratorVersion = $Request.Query.SubOrchestratorVersion + +$InputObject = if ($SubOrchestratorVersion) { + @{ SubOrchestratorVersion = $SubOrchestratorVersion } +} else { + $null +} + +if ($Version) { + Write-Host "Starting orchestration '$FunctionName' with Version '$Version'" + $InstanceId = Start-DurableOrchestration -FunctionName $FunctionName -Version $Version -InputObject $InputObject +} else { + Write-Host "Starting orchestration '$FunctionName' with default version" + $InstanceId = Start-DurableOrchestration -FunctionName $FunctionName -InputObject $InputObject +} + Write-Host "Started orchestration with ID = '$InstanceId'" $Response = New-DurableOrchestrationCheckStatusResponse -Request $Request -InstanceId $InstanceId diff --git a/test/E2E/durableApp/VersionedOrchestrator/function.json b/test/E2E/durableApp/VersionedOrchestrator/function.json new file mode 100644 index 0000000..0c950e3 --- /dev/null +++ b/test/E2E/durableApp/VersionedOrchestrator/function.json @@ -0,0 +1,9 @@ +{ + "bindings": [ + { + "name": "Context", + "type": "orchestrationTrigger", + "direction": "in" + } + ] +} diff --git a/test/E2E/durableApp/VersionedOrchestrator/run.ps1 b/test/E2E/durableApp/VersionedOrchestrator/run.ps1 new file mode 100644 index 0000000..6107b6f --- /dev/null +++ b/test/E2E/durableApp/VersionedOrchestrator/run.ps1 @@ -0,0 +1,14 @@ +using namespace System.Net + +param($Context) + +$ErrorActionPreference = 'Stop' + +$reportedSubOrchestratorVersion = + if ($Context.Input -and $Context.Input.SubOrchestratorVersion) { + Invoke-DurableSubOrchestrator -FunctionName "VersionedSubOrchestrator" -Version $Context.Input.SubOrchestratorVersion + } else { + Invoke-DurableSubOrchestrator -FunctionName "VersionedSubOrchestrator" + } + +return @($Context.Version, $reportedSubOrchestratorVersion) diff --git a/test/E2E/durableApp/VersionedSubOrchestrator/function.json b/test/E2E/durableApp/VersionedSubOrchestrator/function.json new file mode 100644 index 0000000..0c950e3 --- /dev/null +++ b/test/E2E/durableApp/VersionedSubOrchestrator/function.json @@ -0,0 +1,9 @@ +{ + "bindings": [ + { + "name": "Context", + "type": "orchestrationTrigger", + "direction": "in" + } + ] +} diff --git a/test/E2E/durableApp/VersionedSubOrchestrator/run.ps1 b/test/E2E/durableApp/VersionedSubOrchestrator/run.ps1 new file mode 100644 index 0000000..ca2c6b1 --- /dev/null +++ b/test/E2E/durableApp/VersionedSubOrchestrator/run.ps1 @@ -0,0 +1,9 @@ +using namespace System.Net + +param($Context) + +$ErrorActionPreference = 'Stop' + +Write-Warning "VersionedSubOrchestrator: $($Context.Version)" + +return $Context.Version diff --git a/test/E2E/durableApp/extensions.csproj b/test/E2E/durableApp/extensions.csproj index c86ed72..6c01379 100644 --- a/test/E2E/durableApp/extensions.csproj +++ b/test/E2E/durableApp/extensions.csproj @@ -5,7 +5,7 @@ ** - + From 5511c5ff7747d6d68b359fe5e171dbf0f3f24b00 Mon Sep 17 00:00:00 2001 From: Anatoli Beliaev Date: Fri, 3 Oct 2025 13:14:55 -0700 Subject: [PATCH 2/3] Set Microsoft.Azure.WebJobs.Extensions.DurableTask version to 3.5.0 --- test/E2E/durableApp/extensions.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/E2E/durableApp/extensions.csproj b/test/E2E/durableApp/extensions.csproj index 6c01379..878d208 100644 --- a/test/E2E/durableApp/extensions.csproj +++ b/test/E2E/durableApp/extensions.csproj @@ -5,7 +5,7 @@ ** - + From ec09e6954a2048ab5b2111ed60b9c0132bb12acf Mon Sep 17 00:00:00 2001 From: Anatoli Beliaev Date: Fri, 3 Oct 2025 13:31:28 -0700 Subject: [PATCH 3/3] Re-enable temporarily disabled tests in DurableClientTests --- .../DurableClientTests.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs index 982d360..3eecf59 100644 --- a/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs +++ b/test/E2E/AzureFunctions.PowerShell.Durable.SDK.E2E/DurableClientTests.cs @@ -263,9 +263,9 @@ await ValidateDurableWorkflowResults( } [Theory] - // [InlineData(null, null, "1.0", "1.0")] // No version specified, should use defaultVersion from host.json for both - // [InlineData("0.5", null, "0.5", "1.0")] // Version specified for orchestrator, orchestrator should use it, suborchestrator should use defaultVersion - // [InlineData(null, "0.7", "1.0", "0.7")] // Version specified for suborchestrator only, orchestrator should use defaultVersion, suborchestrator should use specified version + [InlineData(null, null, "1.0", "1.0")] // No version specified, should use defaultVersion from host.json for both + [InlineData("0.5", null, "0.5", "1.0")] // Version specified for orchestrator, orchestrator should use it, suborchestrator should use defaultVersion + [InlineData(null, "0.7", "1.0", "0.7")] // Version specified for suborchestrator only, orchestrator should use defaultVersion, suborchestrator should use specified version [InlineData("0.5", "0.7", "0.5", "0.7")] // Both versions specified, each should use their respective versions public async Task OrchestrationVersionIsPropagatedToContext( string orchestratorVersion,