Skip to content

Deploy DTS resources with application#16050

Open
philliphoff wants to merge 11 commits intomicrosoft:mainfrom
philliphoff:philliphoff-dts-publish-2
Open

Deploy DTS resources with application#16050
philliphoff wants to merge 11 commits intomicrosoft:mainfrom
philliphoff:philliphoff-dts-publish-2

Conversation

@philliphoff
Copy link
Copy Markdown
Member

Description

Enables Durable Task Scheduler resources to be deployed to Azure when publishing an Aspire application. Previously, the DTS integration only supported local emulator and existing-connection-string modes — users could not provision new scheduler infrastructure through Aspire. With this change, AddDurableTaskScheduler and AddTaskHub generate the necessary Bicep templates, role assignments, and connection configuration for Azure deployment, matching the patterns established by other Aspire Azure hosting integrations.

What's included

  • Azure provisioning: Schedulers and task hubs are provisioned as Microsoft.DurableTask/schedulers and Microsoft.DurableTask/schedulers/taskhubs resources via generated Bicep, with support for PublishAsExisting and ConfigureInfrastructure customization.
  • Role assignments: Referencing applications are automatically assigned the Durable Task Data Contributor role, with WithRoleAssignments APIs for customization (scoped to either the scheduler or a specific task hub).
  • Dashboard URLs: A background service automatically adds dashboard URL annotations to task hub resources, linking to the DTS dashboard in both emulator and Azure modes.

Fixes # (issue)

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No
  • Does the change require an update in our Aspire docs?

@philliphoff philliphoff requested a review from eerhardt as a code owner April 10, 2026 22:27
Copilot AI review requested due to automatic review settings April 10, 2026 22:27
@github-actions
Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 16050

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 16050"

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds Azure deployment/provisioning support for the Durable Task Scheduler (DTS) Aspire hosting integration, so AddDurableTaskScheduler/AddTaskHub can generate Bicep + role assignments and provide dashboard URLs when publishing.

Changes:

  • Introduces custom Azure.Provisioning resources for Microsoft.DurableTask/schedulers and .../taskhubs, and wires them into DTS resource builders/Bicep outputs.
  • Adds default and customizable role assignments for scheduler/task hub references (with ATS-compatible overloads).
  • Adds a background service that annotates task hub resources with DTS dashboard URLs (emulator + Azure), plus snapshot-based Bicep verification tests and README updates.

Reviewed changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/Aspire.Hosting.Azure.Tests/DurableTaskResourceExtensionsTests.cs Expands coverage for publish-mode connection strings, role assignments, Bicep generation, and dashboard URL service behavior.
tests/Aspire.Hosting.Azure.Tests/Snapshots/DurableTaskResourceExtensionsTests.AddDurableTaskScheduler_GeneratesBicep.verified.bicep Snapshot of generated Bicep for scheduler provisioning.
tests/Aspire.Hosting.Azure.Tests/Snapshots/DurableTaskResourceExtensionsTests.AddDurableTaskScheduler_WithTaskHub_GeneratesBicep.verified.bicep Snapshot including a single task hub sub-resource.
tests/Aspire.Hosting.Azure.Tests/Snapshots/DurableTaskResourceExtensionsTests.AddDurableTaskScheduler_WithNamedTaskHub_GeneratesBicep.verified.bicep Snapshot for explicitly named task hub provisioning.
tests/Aspire.Hosting.Azure.Tests/Snapshots/DurableTaskResourceExtensionsTests.AddDurableTaskScheduler_WithMultipleTaskHubs_GeneratesBicep.verified.bicep Snapshot for multiple task hubs under one scheduler.
tests/Aspire.Hosting.Azure.Tests/Snapshots/DurableTaskResourceExtensionsTests.AddDurableTaskScheduler_PublishAsExisting_GeneratesBicep.verified.bicep Snapshot for referencing an existing scheduler at publish time.
tests/Aspire.Hosting.Azure.Tests/Snapshots/DurableTaskResourceExtensionsTests.AddDurableTaskScheduler_PublishAsExisting_WithResourceGroup_GeneratesBicep.verified.bicep Snapshot for existing scheduler with RG parameterization.
src/Aspire.Hosting.Azure.Functions/README.md Documents Azure provisioning, PublishAsExisting, infra customization, and role assignment usage for DTS.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskSchedulerRole.cs Adds ATS-compatible role enum used by exported role-assignment overloads.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskSchedulerBuiltInRole.cs Introduces built-in role IDs + role-name mapping for role assignment generation.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskSchedulerProvisioningResource.cs Custom ProvisionableResource for schedulers until an official package exists.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskHubProvisioningResource.cs Custom ProvisionableResource for task hub sub-resources.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskSchedulerResource.cs Converts scheduler to AzureProvisioningResource, adds outputs + existing-resource support + Azure Functions config.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskHubResource.cs Converts hub to AzureProvisioningResource, adds provisioning conversion + existing-resource support.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskDashboardUrlService.cs Adds hosted service to compute and apply dashboard URL annotations based on emulator endpoints / Azure outputs.
src/Aspire.Hosting.Azure.Functions/DurableTask/DurableTaskResourceExtensions.cs Wires up Azure provisioning, task hub creation under scheduler infra, default roles, and role assignment APIs.

Comment on lines +84 to +88
}

var hubName = hub.HubName;
return $"{allocated.UriString}/subscriptions/default/schedulers/default/taskhubs/{hubName}";
}
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

hub.HubName is a ReferenceExpression and ReferenceExpression does not override ToString(), so string interpolation here will produce the type name (e.g., Aspire.Hosting.ApplicationModel.ReferenceExpression) instead of the actual hub name. This will generate incorrect dashboard URLs (and should break the associated tests). Resolve the hub name via await hub.TaskHubName.GetValueAsync(...) (or equivalent) and make the URL builder async so parameter-based hub names work too.

Copilot uses AI. Check for mistakes.
Comment on lines +108 to +113
scheduler.Outputs.TryGetValue("tenantId", out var tenantObj);
var tenantId = tenantObj?.ToString();
var taskHubName = hub.HubName;

var encodedEndpoint = Uri.EscapeDataString(endpoint);
var url = $"https://dashboard.durabletask.io/subscriptions/{subscriptionId}/schedulers/{schedulerName}/taskhubs/{taskHubName}?endpoint={encodedEndpoint}";
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

Same issue as emulator mode: hub.HubName is a ReferenceExpression, so interpolating it into the URL will produce the type name rather than the resolved Task Hub name. This will yield broken Azure dashboard deep links, especially when WithTaskHubName(ParameterResource) is used. Resolve the Task Hub name string via GetValueAsync before building the URL.

Copilot uses AI. Check for mistakes.
Comment on lines +51 to +57
if (this.TryGetLastAnnotation<DurableTaskHubNameAnnotation>(out var taskHubNameAnnotation))
{
return taskHubNameAnnotation.HubName switch
{
string hubName => hubName,
_ => Name // Default to resource name if parameter is used
};
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

When WithTaskHubName(ParameterResource) is used, provisioning currently falls back to Name for the ARM/Bicep task hub resource name. That means Azure will provision a task hub named after the resource (e.g., "taskhub") while the app config/connection string uses the parameter value (e.g., "mytaskhub"), causing a mismatch at runtime. The provisioning path should use the parameter value (e.g., convert the ParameterResource to a ProvisioningParameter via AsProvisioningParameter(...)) instead of discarding it.

Copilot uses AI. Check for mistakes.
Comment on lines +61 to +65
Name = infra.AspireResource.Name,
Location = new ProvisioningParameter(AzureBicepResource.KnownParameters.Location, typeof(string)),
SkuName = skuParameter,
IpAllowlist = ["0.0.0.0/0"]
};
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

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

Defaulting the scheduler ipAllowlist to 0.0.0.0/0 makes the provisioned scheduler publicly reachable from any IPv4 address. Unless this is a documented requirement for DTS, this is an insecure default; consider omitting ipAllowlist (let service defaults apply) or making it opt-in/configurable (and ideally aligning with the repo’s private-endpoint/public-network-access patterns).

Copilot uses AI. Check for mistakes.
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