Skip to content

Fix DevTunnel endpoint URL publication - #19590

Merged
David Negstad (danegsta) merged 2 commits into
mainfrom
dev/karolz/fix-devtunnel-endpoints
Aug 24, 2026
Merged

Fix DevTunnel endpoint URL publication#19590
David Negstad (danegsta) merged 2 commits into
mainfrom
dev/karolz/fix-devtunnel-endpoints

Conversation

@karolz-ms

@karolz-ms Karol Zadora-Przylecki (karolz-ms) commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Description

After upgrading to Aspire 13.5, DevTunnel port resources could reach Running and Healthy while the Dashboard and MCP resource snapshots still reported no URLs.

The proxyless endpoint allocator introduced in #17924 assigned a temporary localhost port to every unported proxyless endpoint, including DevTunnelPortResource. Because DevTunnels used an existing allocation as the signal that ResourceEndpointsAllocatedEvent had already run, it replaced the temporary endpoint with the public tunnel endpoint without publishing the URL update.

This change limits automatic proxyless port allocation to IComputeResource instances and containers. Executable, container, and project resources retain the allocation behavior from #17924, while integration-owned endpoints such as DevTunnel ports remain unallocated until their integration publishes the real endpoint. Regression coverage also explicitly guards DotnetProjectResource as a compute resource.

User-facing usage

Existing DevTunnel AppHosts now publish their public URLs again without code changes.

C#

builder.AddDevTunnel("public-tunnel")
    .WithReference(gateway)
    .WithAnonymousAccess();

TypeScript

const tunnel = await builder.addDevTunnel("public-tunnel")
  .withReference(gateway);

Validation

  • Targeted proxyless allocation coverage for executable, container, project, and DevTunnel port resources.
  • DotnetProjectResource compute-resource classification coverage.
  • DCP-backed DevTunnel reproduction using an isolated fake CLI, resulting in a healthy resource snapshot with active public tunnel and inspect URLs.

Fixes #19496

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

Copilot AI balanced review requested due to automatic review settings August 21, 2026 23:40
@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 -- 19590

Or

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

@github-actions github-actions Bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Aug 21, 2026
@github-actions

This comment has been minimized.

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.

Pull request overview

Restricts proxyless port allocation to compute resources, restoring DevTunnel URL publication.

Changes:

  • Gates automatic port allocation on IComputeResource.
  • Adds DevTunnel regression coverage.
  • Verifies DotnetProjectResource remains a compute resource.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
src/Aspire.Hosting/Dcp/DcpExecutor.cs Limits proxyless port allocation to compute resources.
tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs Tests compute and DevTunnel allocation behavior.
tests/Aspire.Hosting.Dotnet.Tests/DotnetProjectResourceTests.cs Verifies .NET project compute classification.

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

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.

Reviewed the change and verified the core behavior locally. Summary: 1 blocking correctness/regression issue, 1 incorrect comment, and 3 test-coverage gaps.

The headline problem is that IComputeResource does not mean "has a DCP workload" — DCP selects container workloads by ContainerImageAnnotation, which RunAsEmulator adds directly to Azure resources that are not IComputeResource. I reproduced a startup crash for that case on this branch; details are inline.

Comment thread src/Aspire.Hosting/Dcp/DcpExecutor.cs Outdated
Comment thread src/Aspire.Hosting/Dcp/DcpExecutor.cs Outdated
Comment thread src/Aspire.Hosting/Dcp/DcpExecutor.cs
Comment thread tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs
Comment thread tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Copilot AI review requested due to automatic review settings August 22, 2026 04:15
@github-actions

This comment has been minimized.

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.

Pull request overview

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

@karolz-ms

Copy link
Copy Markdown
Contributor Author

PR Testing Report

PR Information

  • PR Number: Fix DevTunnel endpoint URL publication #19590
  • Title: Fix DevTunnel endpoint URL publication
  • Head Commit: 89ace5c10080a0ada314431a98a5da487e7d8a69
  • Tested At: 2026-08-22T04:33:54Z
  • Execution Target: Local macOS ARM64 workspace; Podman 6.0.2 Linux ARM64 VM for the container scenario

Artifact Version Verification

  • Expected Commit: 89ace5c10080a0ada314431a98a5da487e7d8a69
  • Installed Version: 13.6.0-pr.19590.g89ace5c1
  • Source Checkout: 89ace5c10080a0ada314431a98a5da487e7d8a69
  • Status: PASS - the dogfood artifact and source checkout matched the latest PR head before and after testing.

Changes Analyzed

Files Changed

  • src/Aspire.Hosting/Dcp/DcpExecutor.cs - allocates unported proxyless endpoints for IComputeResource and annotation-backed container workloads.
  • tests/Aspire.Hosting.DevTunnels.Tests/DevTunnelResourceBuilderExtensionsTests.cs - adds a DCP-backed DevTunnel URL-publication test.
  • tests/Aspire.Hosting.Dotnet.Tests/DotnetProjectResourceTests.cs - asserts that DotnetProjectResource is an IComputeResource.
  • tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs - covers DevTunnel exclusion and non-compute container allocation.

Change Categories

  • Hosting core changes
  • DevTunnel behavior
  • Test changes
  • CLI command changes
  • Dashboard UI changes
  • Template changes
  • Client/component changes
  • VS Code extension changes
  • CI infrastructure changes

Test Scenarios Executed

Scenario 1: DCP proxyless allocator regression suite

Objective: Verify the new workload predicate and preserve executable, project, ordinary container, and fixed-port behavior.

Coverage Type: Regression and boundary

Status: PASS

Tests:

  1. ProxylessPortAllocatorOnlyAllocatesPortsForDcpWorkloads
  2. ProxylessPortAllocatorAllocatesPortForNonComputeContainerResource
  3. EndpointPortsExecutableNotReplicatedProxylessNoPortNoTargetPortAllocated
  4. EndpointPortsProjectWithEndpointProxySupportUsesProxylessEndpoint
  5. EndpointPortsContainerProxylessNoPortTargetPortSet
  6. ProxylessPortAllocatorExcludesFixedPublicPorts

Result: 6 passed, 0 failed.

Evidence: hosting-proxyless-tests.log

Scenario 2: DevTunnel lifecycle and DotnetProject classification

Objective: Verify DCP publishes DevTunnel URLs and DotnetProjectResource remains eligible for automatic allocation.

Coverage Type: Regression

Status: PASS

Tests:

  1. DcpStartupPublishesDevTunnelUrls
  2. ResourceReady_PublishesUrlProperties
  3. AddDotnetProject_ResourceSupportsServiceDiscoveryAndIsComputeResource

Result: 3 passed, 0 failed.

Evidence:

  • devtunnel-source-tests.log
  • dotnet-project-compute-test.log

Scenario 3: Previously failing Azure Storage emulator compatibility

Objective: Verify an annotation-backed, non-compute container resource receives and reuses host ports across persistent restarts.

Coverage Type: Regression and persistent-lifetime boundary

Status: PASS

Test: AzureStorageEmulator_WithPersistentLifetime_ReusesContainersAndPorts

Result: 1 passed, 0 failed under Podman.

Evidence:

  • azure-storage-persistent-test.log
  • podman-version.txt

Scenario 4: Fresh dogfood DevTunnel reproduction

Objective: Reproduce the reported lifecycle with a new AppHost from the updated PR package hive and a deterministic fake devtunnel CLI.

Coverage Type: Happy path and boundary

Status: PASS

Steps:

  1. Created a fresh aspire-empty AppHost from the PR hive.
  2. Added Aspire.Hosting.DevTunnels@13.6.0-pr.19590.g89ace5c1.
  3. Started an executable HTTP resource and exposed it through AddDevTunnel.
  4. Waited for public-tunnel-gateway-http to become healthy.
  5. Captured and asserted the live aspire describe --format Json snapshot.
  6. Confirmed both the local target and Dashboard responded.
  7. Stopped the AppHost and confirmed its process exited.

Observed Resource State:

  • Resource type: DevTunnelPort
  • State: Running
  • Health: Healthy
  • Tunnel URL: https://pr19590tunnel-5109.use.devtunnels.ms
  • Inspect URL: https://pr19590tunnel-5109-inspect.use.devtunnels.ms
  • No localhost URL appeared in the resource's urls collection.

Evidence:

  • devtunnel-port-describe.json
  • all-resources-describe.json
  • devtunnel-snapshot-assertion.txt
  • fake-devtunnel-calls.log
  • apphost-detached.log

Scenario 5: Full Hosting.Azure CI corroboration

Objective: Confirm the fix survives the complete Azure hosting suites on both CI operating systems.

Coverage Type: Full project CI

Status: PASS

Results:

  • Linux: 1,691 passed, 0 failed, 5 skipped.
  • Windows: 1,660 passed, 0 failed, 0 skipped.

CI Jobs:

Evidence:

  • hosting-azure-linux-ci.log
  • hosting-azure-windows-ci.log

Additional CI Signal

At the final snapshot, the PR had 363 passing, 13 pending, 1 skipped, and 1 failing check. The failure is the untouched VS Code extension workspace-target-proof E2E shard: one test passed and one project-folder-picker test timed out waiting for an element to become visible. No causal relationship to this four-file hosting/test diff was found.

CI Job: https://github.com/microsoft/aspire/actions/runs/32551198408/job/96979500951

Summary

Scenario Status Notes
Artifact and source SHA verification PASS Both matched the latest PR head
DCP allocator regression suite PASS 6/6
DevTunnel and DotnetProject source tests PASS 3/3
Azure Storage persistent emulator PASS 1/1 under Podman
Fresh DevTunnel dogfood reproduction PASS Public and inspect URLs published
Hosting.Azure CI Linux/Windows PASS 3,351 passed, 0 failed
VS Code workspace-target-proof E2E WARNING Unrelated UI timeout in untouched area

Overall Result

PASS - PR CHANGES VERIFIED

All approved changed-area scenarios passed. The prior Azure Storage emulator regression is fixed locally and in both full Hosting.Azure CI jobs. The remaining VS Code E2E timeout should be rerun or triaged separately before merge if a fully green check set is required.

Artifacts

All preserved logs, snapshots, the repro AppHost, fake CLI, latest PR diff, CI evidence, and a compressed local evidence bundle are in this report directory.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

Limit automatic proxyless port allocation to compute resources so integration-owned endpoints can publish their own addresses.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot-Session: e3b04d22-d265-49d0-861a-09aac8be80d6
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ec7aab9b-2163-45b7-89f6-c349fef7f07f
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

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.

Pull request overview

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

@github-actions

Copy link
Copy Markdown
Contributor

Tests selector (audit mode)

The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement.

50 / 102 test projects · 4 jobs, from 4 changed files.

Selected test projects (50 / 102)

Aspire.EndToEnd.Tests, Aspire.Hosting.Analyzers.Tests, Aspire.Hosting.Azure.Kubernetes.Tests, Aspire.Hosting.Azure.Kusto.Tests, Aspire.Hosting.Azure.Tests, Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Browsers.Tests, Aspire.Hosting.CodeGeneration.Go.Tests, Aspire.Hosting.CodeGeneration.Java.Tests, Aspire.Hosting.CodeGeneration.Python.Tests, Aspire.Hosting.CodeGeneration.Rust.Tests, Aspire.Hosting.CodeGeneration.TypeScript.Tests, Aspire.Hosting.Containers.Tests, Aspire.Hosting.DevTunnels.Tests, Aspire.Hosting.Docker.Tests, Aspire.Hosting.Dotnet.Tests, Aspire.Hosting.DotnetTool.Tests, Aspire.Hosting.EntityFrameworkCore.Tests, Aspire.Hosting.Foundry.Tests, Aspire.Hosting.Garnet.Tests, Aspire.Hosting.GitHub.Models.Tests, Aspire.Hosting.Go.Tests, Aspire.Hosting.Java.Tests, Aspire.Hosting.JavaScript.Tests, Aspire.Hosting.Kafka.Tests, Aspire.Hosting.Keycloak.Tests, Aspire.Hosting.Kubernetes.Tests, Aspire.Hosting.Maui.Tests, Aspire.Hosting.Milvus.Tests, Aspire.Hosting.MongoDB.Tests, Aspire.Hosting.MySql.Tests, Aspire.Hosting.Nats.Tests, Aspire.Hosting.OpenAI.Tests, Aspire.Hosting.Oracle.Tests, Aspire.Hosting.Orleans.Tests, Aspire.Hosting.PostgreSQL.Tests, Aspire.Hosting.Python.Tests, Aspire.Hosting.Qdrant.Tests, Aspire.Hosting.RabbitMQ.Tests, Aspire.Hosting.Radius.Tests, Aspire.Hosting.Redis.Tests, Aspire.Hosting.RemoteHost.Tests, Aspire.Hosting.Rust.Tests, Aspire.Hosting.Seq.Tests, Aspire.Hosting.SqlServer.Tests, Aspire.Hosting.Testing.Tests, Aspire.Hosting.Tests, Aspire.Hosting.Valkey.Tests, Aspire.Hosting.Yarp.Tests, Aspire.Playground.Tests

Selected jobs (4)

deployment-e2e, extension-e2e, polyglot, typescript-api-compat


How these were chosen — grouped by what changed

⚠️ 44 of the 50 selected test projects come from a single change — src/Aspire.Hosting/Dcp/DcpExecutor.cs.

🔧 src/Aspire.Hosting/Dcp/DcpExecutor.cs (changed source)
44 via the project graph

show 44

Aspire.Hosting.Analyzers.Tests (2 hops), Aspire.Hosting.Azure.Kubernetes.Tests (2 hops), Aspire.Hosting.Azure.Kusto.Tests (2 hops), Aspire.Hosting.Azure.Tests, Aspire.Hosting.Browsers.Tests (2 hops), Aspire.Hosting.CodeGeneration.Go.Tests, Aspire.Hosting.CodeGeneration.Java.Tests, Aspire.Hosting.CodeGeneration.Python.Tests, Aspire.Hosting.CodeGeneration.Rust.Tests, Aspire.Hosting.CodeGeneration.TypeScript.Tests, Aspire.Hosting.Containers.Tests (2 hops), Aspire.Hosting.Docker.Tests (2 hops), Aspire.Hosting.DotnetTool.Tests (2 hops), Aspire.Hosting.EntityFrameworkCore.Tests (2 hops), Aspire.Hosting.Foundry.Tests (2 hops), Aspire.Hosting.Garnet.Tests (2 hops), Aspire.Hosting.GitHub.Models.Tests (2 hops), Aspire.Hosting.Go.Tests (2 hops), Aspire.Hosting.Java.Tests (2 hops), Aspire.Hosting.JavaScript.Tests (2 hops), Aspire.Hosting.Kafka.Tests (2 hops), Aspire.Hosting.Keycloak.Tests (2 hops), Aspire.Hosting.Kubernetes.Tests (2 hops), Aspire.Hosting.Maui.Tests, Aspire.Hosting.Milvus.Tests (2 hops), Aspire.Hosting.MongoDB.Tests (2 hops), Aspire.Hosting.MySql.Tests (2 hops), Aspire.Hosting.Nats.Tests (2 hops), Aspire.Hosting.OpenAI.Tests (2 hops), Aspire.Hosting.Oracle.Tests (2 hops), Aspire.Hosting.Orleans.Tests (2 hops), Aspire.Hosting.PostgreSQL.Tests (2 hops), Aspire.Hosting.Python.Tests (2 hops), Aspire.Hosting.Qdrant.Tests (2 hops), Aspire.Hosting.RabbitMQ.Tests (2 hops), Aspire.Hosting.Redis.Tests (2 hops), Aspire.Hosting.RemoteHost.Tests, Aspire.Hosting.Rust.Tests (2 hops), Aspire.Hosting.Seq.Tests (2 hops), Aspire.Hosting.SqlServer.Tests (2 hops), Aspire.Hosting.Testing.Tests (2 hops), Aspire.Hosting.Valkey.Tests (2 hops), Aspire.Hosting.Yarp.Tests (2 hops), Aspire.Playground.Tests

🧪 tests/Aspire.Hosting.Tests/Dcp/DcpExecutorTests.cs (changed test)
1 directly: Aspire.Hosting.Tests
2 via the project graph: Aspire.Hosting.Blazor.Tests, Aspire.Hosting.Radius.Tests

📦 affected project Aspire.Hosting
1 test: Aspire.EndToEnd.Tests

🧪 tests/Aspire.Hosting.DevTunnels.Tests/DevTunnelResourceBuilderExtensionsTests.cs (changed test)
1 directly: Aspire.Hosting.DevTunnels.Tests

🧪 tests/Aspire.Hosting.Dotnet.Tests/DotnetProjectResourceTests.cs (changed test)
1 directly: Aspire.Hosting.Dotnet.Tests

Job reasons

Job Triggered by
deployment-e2e affected project Aspire.Hosting.Azure
extension-e2e src/Aspire.Hosting/Dcp/DcpExecutor.cs
• affected project Aspire.Hosting
polyglot affected project Aspire.Hosting.Rust
typescript-api-compat affected project Aspire.Hosting

Selection computed for commit ec17237.

Rene Bentes Pinto (renebentes) pushed a commit to renebentes/3054 that referenced this pull request Aug 28, 2026
Updated [Aspire.Hosting.Testing](https://github.com/microsoft/aspire)
from 13.5.2 to 13.5.3.

<details>
<summary>Release notes</summary>

_Sourced from [Aspire.Hosting.Testing's
releases](https://github.com/microsoft/aspire/releases)._

## 13.5.3

## What's New in Aspire 13.5.3

Patch release for Aspire 13.5 that fixes Dashboard Graph view crashes
for resources with multi-path icons and restores missing public URLs for
DevTunnel resources.

### 🐛 Fixes

- 📊 **Dashboard Graph view could crash for Azure Blob resources** —
Resources such as those created with `AddBlobs` use icons containing
multiple SVG paths, which caused an XML parsing exception and broke the
dashboard circuit. The graph now combines multi-path icons correctly.
Regression introduced in 13.5. Fixes
[#​19489](microsoft/aspire#19489).
([#​19585](microsoft/aspire#19585), backport of
[#​19579](microsoft/aspire#19579),
`@​sebastienros`)

- 🌐 **DevTunnel public URLs were missing from the Dashboard and MCP
snapshots** — DevTunnel port resources could report `Running` and
`Healthy` while showing no public URLs. Proxyless port allocation is now
limited to compute and container resources, allowing DevTunnels to
publish their actual public endpoints. Regression introduced in 13.5.
Fixes [#​19496](microsoft/aspire#19496).
([#​19625](microsoft/aspire#19625), backport of
[#​19590](microsoft/aspire#19590),
`@​karolz-ms`, `@​danegsta`)

### 🏷️ Housekeeping

- 🚀 Bumped branding to 13.5.3

---

*Full Changelog:
[v13.5.2...v13.5.3](microsoft/aspire@v13.5.2...v13.5.3)*

*Full commit:
[b5f143315ffb6968ea939a9978797a5b20e4c688](microsoft/aspire@b5f143315ffb6968ea939a9978797a5b20e4c688)*

Commits viewable in [compare
view](microsoft/aspire@v13.5.2...v13.5.3).
</details>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
This was referenced Aug 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DevTunnel port resources are Running but Dashboard URLs are empty in 13.5.0

3 participants