Pin published Aspire Dashboard image to a reproducible tag - #19249
Conversation
The Docker Compose and Kubernetes publishers injected the dashboard as `mcr.microsoft.com/dotnet/nightly/aspire-dashboard` with no tag, which both runtimes resolve to the mutable `:latest`. Generated compose files and Helm charts were therefore not reproducible and could pull a dashboard build that does not match the app's Aspire version. Add a shared `DashboardImage` helper that pins the image to the app's Aspire `major.minor` version (for example `13.5`), derived from the running assembly's informational version. `major.minor` always exists on the registry -- including for prerelease/CI builds where a full `major.minor.patch-prerelease` tag is not published -- and stays deterministic across builds so publish snapshots remain stable. Fixes #19239. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19249Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19249" |
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. 5 / 100 test projects · 3 jobs, from 33 changed files. Selected test projects (5 / 100)
Selected jobs (3)
How these were chosen — grouped by what changed🔧 🔧 🔧 🔧 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 Job reasons
Selection computed for commit |
There was a problem hiding this comment.
Pull request overview
Attempts to improve dashboard image version alignment by replacing :latest with an Aspire major.minor tag.
Changes:
- Adds shared dashboard tag-resolution logic.
- Applies the tag to Docker Compose and Kubernetes publishing.
- Updates unit tests and generated snapshots.
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
src/Shared/DashboardImage.cs |
Resolves the dashboard image tag. |
src/Aspire.Hosting.Docker/DockerComposeAspireDashboardResourceBuilderExtensions.cs |
Applies the resolved Compose image tag. |
src/Aspire.Hosting.Docker/Aspire.Hosting.Docker.csproj |
Includes the shared helper. |
src/Aspire.Hosting.Kubernetes/KubernetesAspireDashboardResourceBuilderExtensions.cs |
Applies the resolved Kubernetes image tag. |
src/Aspire.Hosting.Kubernetes/Aspire.Hosting.Kubernetes.csproj |
Includes the shared helper. |
tests/Aspire.Hosting.Kubernetes.Tests/DashboardImageTests.cs |
Tests tag resolution and fallback behavior. |
tests/Aspire.Hosting.Yarp.Tests/Snapshots/YarpConfigGeneratorTests.GenerateEnvVariablesConfigurationDockerCompose.verified.env |
Updates the YARP Compose snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ResourceWithProbes#00.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_HandlesSpecialResourceName#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_HandlesConditionalReferenceExpressionWithParameterCondition#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_HandlesConditionalReferenceExpression#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_GeneratesValidHelmChart#02.verified.yaml |
Updates the Helm chart snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_CustomWorkloadAndResourceType#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ConditionalWithParameterBranch_UsesIfElseSyntax#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.KubernetesWithProjectResources#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.KubernetesMapsPortsForBaitAndSwitchResources#02.verified.yaml |
Updates the dashboard image snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesEnvironmentResourceTests.MultipleKubernetesEnvironmentsSupported/env2/templates/env2-dashboard/deployment.verified.yaml |
Updates the second environment snapshot. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesEnvironmentResourceTests.MultipleKubernetesEnvironmentsSupported/env1/templates/env1-dashboard/deployment.verified.yaml |
Updates the first environment snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposeTests.MultipleDockerComposeEnvironmentsSupported/env2/docker-compose.verified.yaml |
Updates the second Compose environment snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposeTests.MultipleDockerComposeEnvironmentsSupported/env1/docker-compose.verified.yaml |
Updates the first Compose environment snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposeTests.DockerSwarmUpdateConfigSerializedCorrectly.verified.yaml |
Updates the Swarm snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposeTests.DockerSwarmDeploymentLabelsSerializedCorrectly.verified.yaml |
Updates the Swarm labels snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposeTests.DockerComposeOnlyExposesExternalEndpoints.verified.yaml |
Updates the endpoint snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposeTests.DashboardWithForwardedHeadersWritesEnvVar.verified.yaml |
Updates the forwarded-headers snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_WithDashboardEnabled_IncludesDashboardService.verified.yaml |
Updates the dashboard service snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_MultipleResourcesWithOtlp_ConfiguresAllForDashboard.verified.yaml |
Updates the OTLP snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_HandlesConditionalReferenceExpressionWithParameterCondition.verified.yaml |
Updates the conditional snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_HandlesConditionalReferenceExpression.verified.yaml |
Updates the conditional snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_GeneratesValidDockerComposeFile.verified.yaml |
Updates the primary Compose snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PrepareStep_ResolvesArbitraryIValueProviderSource.verified.yaml |
Updates the value-provider snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.DockerComposeWithProjectResources.verified.yaml |
Updates the project resources snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.DockerComposeCorrectlyEmitsPortMappings.verified.yaml |
Updates the port mappings snapshot. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.DockerComposeAppliesServiceCustomizations.verified.yaml |
Updates the customization snapshot. |
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
| /// let the dashboard drift away from the app's Aspire version. Pinning to <c>major.minor</c> keeps | ||
| /// the dashboard on the same Aspire line that generated the manifest and always resolves to a tag | ||
| /// that exists on the registry — including for prerelease/CI builds, where a full | ||
| /// <c>major.minor.patch-prerelease</c> tag is not published. |
PR Testing ReportPR Information
Artifact Version Verification
Changes AnalyzedFiles Changed (source)
Change Categories
Test Scenarios ExecutedScenario 1: Version verificationObjective: Confirm the installed dogfood CLI corresponds to the PR head commit. Evidence:
Observations: Version suffix Scenario 2: Docker Compose publish (happy path)Objective: Verify Steps:
Evidence ( compose-dashboard:
image: "mcr.microsoft.com/dotnet/nightly/aspire-dashboard:13.5"Observations: Dashboard pinned to Scenario 3: Kubernetes publish (happy path)Objective: Verify Steps:
Evidence ( containers:
- image: "mcr.microsoft.com/dotnet/nightly/aspire-dashboard:13.5"
name: "k8s-dashboard"Observations: Dashboard pinned to Scenario 4: Reproducibility / boundaryObjective: Confirm the pinned tag is deterministic and never regresses to Steps: Published each app a second time to a fresh output directory and compared the dashboard image line. Assertions (all True):
Expected Unhappy-Path Outcome: Prevents the pre-fix regressions — non-reproducible drift and the mutable Scenario 5: Resolver unit-test logic (edge cases)Objective: Cover the resolver branches that publish cannot reach (assembly-version fallback, unparseable input, no-version → Steps: Compiled the PR's exact Evidence:
Summary
Overall Result✅ PR VERIFIED The Docker Compose and Kubernetes publishers now emit the Aspire Dashboard image pinned to the app's Aspire Recommendations
|
Jose Perez Rodriguez (joperezr)
left a comment
There was a problem hiding this comment.
I was kind of on the fence on this one since we own the image ourselves, so technically we do want to stay on latest specially since we try to keep backward compat, but I think that this is a good change anyway.
42d56ff
into
release/13.5
Description
aspire publishfor Docker Compose and Kubernetes injected the Aspire Dashboard asmcr.microsoft.com/dotnet/nightly/aspire-dashboardwithout a tag. Both Docker and Kubernetes resolve an untagged image to the mutable:latest, so generateddocker-compose.yamlfiles and Helm charts were not reproducible and could pull a nightly dashboard build that doesn't match the app's Aspire version.This change adds a shared
DashboardImagehelper that pins the dashboard image to the app's Aspiremajor.minorversion (for example13.5), derived from the running assembly's informational version. Derivingmajor.minorat runtime:major.minor.patch-prereleasetag is never published;Both the Docker Compose and Kubernetes dashboard resources now emit
mcr.microsoft.com/dotnet/nightly/aspire-dashboard:13.5on thisrelease/13.5line (the helper self-adjusts on other branches). Publish snapshots were regenerated accordingly, and a focused unit test covers the tag-resolution logic (prerelease, stable, 4-part assembly version, and the:latestfallback when no version is available).Fixes #19239.
Checklist
<remarks />and<code />elements on your triple slash comments?