Skip to content

Show Azure Portal links in deployment summaries#16173

Closed
spboyer wants to merge 2 commits intomicrosoft:mainfrom
spboyer:feat/portal-links-in-deploy-summary
Closed

Show Azure Portal links in deployment summaries#16173
spboyer wants to merge 2 commits intomicrosoft:mainfrom
spboyer:feat/portal-links-in-deploy-summary

Conversation

@spboyer
Copy link
Copy Markdown
Member

@spboyer spboyer commented Apr 14, 2026

Description

Adds Azure Portal links for individual deployed resources to the pipeline summary output after aspire deploy completes.

Before

✅ Pipeline succeeded

  ☁️ Target: Azure
  📦 Resource Group: rg-myapp (portal link)
  🔑 Subscription: 12345...
  🌐 Location: eastus
  webfrontend: https://webfrontend.azurecontainerapps.io
  api: No public endpoints

After

✅ Pipeline succeeded

  ☁️ Target: Azure
  📦 Resource Group: rg-myapp (portal link)
  🔑 Subscription: 12345...
  🌐 Location: eastus
  webfrontend: https://webfrontend.azurecontainerapps.io
  🔗 webfrontend: Azure Portal   ← NEW
  api: No public endpoints
  🔗 api: Azure Portal            ← NEW

Changes

  • AzurePortalUrls.cs — Added GetResourceUrl(resourceId, tenantId?) method that generates portal URLs from full ARM resource IDs (supports child resources like deployment slots)
  • AzureContainerAppResource.cs — Updated print-summary step to include portal link for both external-endpoint and no-endpoint cases
  • AzureAppServiceWebSiteResource.cs — Updated print-summary step to include portal link with deployment slot URL support
  • Aspire.Hosting.Azure.csproj — Added InternalsVisibleTo for Aspire.Hosting.Azure.AppContainers to access AzurePortalUrls helper
  • AzurePortalUrlsTests.cs — 8 unit tests covering all URL generation methods

Implementation Notes

  • Portal links read subscription/resource-group/tenant from IDeploymentStateManager (the "Azure" section populated during provisioning) — no internal member access needed from AppContainers/AppService assemblies
  • Resource IDs use full ARM format (/subscriptions/.../providers/Microsoft.App/containerApps/...) which handles nested resources like App Service slots naturally
  • Portal links appear in the summary regardless of whether the resource has public endpoints

Testing

  • 8 unit tests for AzurePortalUrls (all methods, with/without tenant, slots)
  • Build passes for all affected projects
  • Screenshots from live deployment (posted in comments)

Fixes #16119

Add portal links for individual deployed resources (Container Apps, App Service)
to the pipeline summary output after deployment completes.

Changes:
- Add GetResourceUrl method to AzurePortalUrls for generating portal links
  from ARM resource IDs (supports child resources like deployment slots)
- Update AzureContainerAppResource print-summary step to include portal link
  for both external-endpoint and no-endpoint cases
- Update AzureAppServiceWebSiteResource print-summary step to include portal
  link, with support for deployment slot URLs
- Both read subscription/RG/tenant from IDeploymentStateManager (populated
  during provisioning) — no internal member access needed
- Add InternalsVisibleTo for Aspire.Hosting.Azure.AppContainers to access
  AzurePortalUrls helper
- Add unit tests for all AzurePortalUrls methods

Fixes microsoft#16119

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@spboyer
Copy link
Copy Markdown
Member Author

spboyer commented Apr 14, 2026

✅ Live Deployment Verification

Deployed a minimal Container Apps AppHost to Azure (eastus2, shboyer subscription). The portal link appears in the summary:

✅ Pipeline succeeded

  ☁️ Target: Azure
  📦 Resource Group: https://portal.azure.com/#@.../rg-aspire-portallinktest/overview
  🔑 Subscription: 5ca082f3-38f2-4bb0-b0a4-c401184ae3a8
  🌐 Location: eastus2
  📊 Dashboard: https://aspire-dashboard.ext.livelypond-779a23bf.eastus2.azurecontainerapps.io
  hello: https://hello.livelypond-779a23bf.eastus2.azurecontainerapps.io
  🔗 hello: https://portal.azure.com/#/resource/.../Microsoft.App/containerApps/hello   ← NEW

The 🔗 hello line is the new portal link. It points directly to the Container App resource in the Azure Portal.

Full pipeline output:

All 12/12 steps succeeded (4m 56s)
16:53:03 (pipeline-execution) → Starting pipeline-execution...
16:53:03 (process-parameters) ✓ process-parameters completed successfully
16:53:03 (deploy-prereq) ✓ deploy-prereq completed successfully
16:53:04 (validate-azure-login) ✓ Azure CLI authentication validated successfully
16:53:07 (create-provisioning-context) ✓ create-provisioning-context completed successfully
16:53:19 (provision-infra-acr) ✓ Successfully provisioned infra-acr (11.7s)
16:57:39 (provision-infra) ✓ Successfully provisioned infra (260.8s)
16:57:59 (provision-hello-containerapp) ✓ Successfully provisioned hello-containerapp (19.6s)
16:57:59 (print-hello-summary) ✓ print-hello-summary completed successfully
16:57:59 (provision-azure-bicep-resources) ✓ provision-azure-bicep-resources completed
16:57:59 (print-dashboard-url-infra) ✓ Dashboard available
16:57:59 (deploy) ✓ deploy completed successfully

Resources cleaned up (az group delete --no-wait).

@spboyer spboyer marked this pull request as ready for review April 14, 2026 21:16
Copilot AI review requested due to automatic review settings April 14, 2026 21:16
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

Note

Copilot was unable to run its full agentic suite in this review.

Adds Azure Portal links for deployed Azure resources to the pipeline deployment summary, enabling quick navigation from CI/CD output to the Azure Portal.

Changes:

  • Introduced AzurePortalUrls.GetResourceUrl(resourceId, tenantId?) for generating portal links from full ARM resource IDs.
  • Updated Azure App Service and Azure Container Apps summary steps to include portal links regardless of public endpoint presence.
  • Added unit tests for portal URL generation and expanded InternalsVisibleTo to allow cross-assembly access.
Show a summary per file
File Description
tests/Aspire.Hosting.Azure.Tests/AzurePortalUrlsTests.cs Adds tests for resource group, resource, and deployment portal URL generation.
src/Aspire.Hosting.Azure/AzurePortalUrls.cs Adds a base portal URL constant and a new helper to build portal URLs from ARM resource IDs.
src/Aspire.Hosting.Azure/Aspire.Hosting.Azure.csproj Grants AppContainers assembly access to internal portal URL helpers.
src/Aspire.Hosting.Azure.AppService/AzureAppServiceWebSiteResource.cs Adds portal link entries to App Service deployment summary; includes slot support.
src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppResource.cs Adds portal link entries to Container Apps deployment summary.

Copilot's findings

  • Files reviewed: 5/5 changed files
  • Comments generated: 5

Comment thread src/Aspire.Hosting.Azure.AppService/AzureAppServiceWebSiteResource.cs Outdated
Comment thread src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppResource.cs Outdated
Comment thread src/Aspire.Hosting.Azure.AppContainers/AzureContainerAppResource.cs Outdated
Comment thread tests/Aspire.Hosting.Azure.Tests/AzurePortalUrlsTests.cs
Comment thread src/Aspire.Hosting.Azure/AzurePortalUrls.cs Outdated
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

🚀 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 -- 16173

Or

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

- Compose PortalDeploymentOverviewUrl from PortalBaseUrl constant
- Use GetService instead of GetRequiredService for graceful degradation
  when IDeploymentStateManager is not registered
- Remove ToLowerInvariant() from ACA resource name in ARM resource ID
- Pass base site name (not hostname) to GetPortalUrlAsync for App Service
- Strengthen test assertions from Contains to full equality

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions
Copy link
Copy Markdown
Contributor

Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
GitHub was asked to rerun all failed jobs for that attempt, and the rerun is being tracked in the rerun attempt.
The job links below point to the failed attempt jobs that matched the retry-safe transient failure rules.

@spboyer
Copy link
Copy Markdown
Member Author

spboyer commented Apr 15, 2026

Closing — this is superseded by #16142 (merged by @davidfowl), which implements the same feature with a cleaner approach: shared source for AzurePortalUrls, per-service URL helpers (ContainerAppUrls, AppSvcUrls), and subscription/RG derived from the environment resource ID rather than deployment state. Thanks David!

@spboyer spboyer closed this Apr 15, 2026
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.

Show Azure Portal links in deployment summaries

2 participants