Add portable volume path environment variables - #19404
Add portable volume path environment variables#19404Mitch Denny (mitchdenny) wants to merge 9 commits into
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 19404Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 19404" |
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Pull request overview
Adds portable volume-path environment variables across local execution and container deployment targets.
Changes:
- Adds workload-scoped local volume paths for projects and executables.
- Extends Kubernetes persistent-volume handling and validation.
- Updates Docker Compose, Kubernetes, Azure Container Apps, TypeScript generation, documentation, and tests.
Show a summary per file
| File | Description |
|---|---|
tests/Aspire.Hosting.Tests/WithVolumeTests.cs |
Tests core volume-path behavior. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#06.verified.yaml |
Verifies published environment values. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#05.verified.yaml |
Verifies executable PVC. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#04.verified.yaml |
Verifies executable StatefulSet. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#03.verified.yaml |
Verifies executable configuration. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#02.verified.yaml |
Verifies container PVC. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#01.verified.yaml |
Verifies container StatefulSet. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithPersistentVolumeEnvironment_OnContainerAndExecutable#00.verified.yaml |
Verifies container configuration. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithFirstClassPersistentVolume_EnvironmentUsesDeploymentMountPath#03.verified.yaml |
Verifies deployment path value. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithFirstClassPersistentVolume_EnvironmentUsesDeploymentMountPath#02.verified.yaml |
Verifies customized PVC. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithFirstClassPersistentVolume_EnvironmentUsesDeploymentMountPath#01.verified.yaml |
Verifies project StatefulSet. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_WithFirstClassPersistentVolume_EnvironmentUsesDeploymentMountPath#00.verified.yaml |
Verifies project configuration. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ProjectAndExecutableVolumesUseDefaultStorageAndEnvironmentPaths#04.verified.yaml |
Verifies published path values. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ProjectAndExecutableVolumesUseDefaultStorageAndEnvironmentPaths#03.verified.yaml |
Verifies executable deployment. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ProjectAndExecutableVolumesUseDefaultStorageAndEnvironmentPaths#02.verified.yaml |
Verifies executable configuration. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ProjectAndExecutableVolumesUseDefaultStorageAndEnvironmentPaths#01.verified.yaml |
Verifies project deployment. |
tests/Aspire.Hosting.Kubernetes.Tests/Snapshots/KubernetesPublisherTests.PublishAsync_ProjectAndExecutableVolumesUseDefaultStorageAndEnvironmentPaths#00.verified.yaml |
Verifies project configuration. |
tests/Aspire.Hosting.Kubernetes.Tests/KubernetesPublisherTests.cs |
Adds Kubernetes publishing tests. |
tests/Aspire.Hosting.Kubernetes.Tests/KubernetesPersistentVolumeRunModeTests.cs |
Tests local persistent-volume behavior. |
tests/Aspire.Hosting.Kubernetes.Tests/KubernetesEnvironmentResourceTests.cs |
Tests cross-environment validation. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_ProjectAndExecutableVolumesIncludeEnvironmentPaths.verified.yaml |
Verifies Compose volume paths. |
tests/Aspire.Hosting.Docker.Tests/Snapshots/DockerComposePublisherTests.PublishAsync_MixedBindMountsAndVolumes.verified.yaml |
Verifies container environment output. |
tests/Aspire.Hosting.Docker.Tests/DockerComposePublisherTests.cs |
Adds Docker Compose coverage. |
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts |
Updates generated TypeScript API. |
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/HostingContainerResourceCapabilities.verified.txt |
Updates capability target metadata. |
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/AtsTypeScriptCodeGeneratorTests.cs |
Tests generated volume options. |
tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests.csproj |
References Kubernetes for generation tests. |
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.VolumesAndBindMountsAreTranslation.verified.bicep |
Verifies ACA environment output. |
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ProjectAndExecutableVolumesIncludeEnvironmentPaths#01.verified.json |
Verifies project manifest. |
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ProjectAndExecutableVolumesIncludeEnvironmentPaths#01.verified.bicep |
Verifies project Bicep. |
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ProjectAndExecutableVolumesIncludeEnvironmentPaths#00.verified.json |
Verifies executable manifest. |
tests/Aspire.Hosting.Azure.Tests/Snapshots/AzureContainerAppsTests.ProjectAndExecutableVolumesIncludeEnvironmentPaths#00.verified.bicep |
Verifies executable Bicep. |
tests/Aspire.Hosting.Azure.Tests/AzureContainerAppsTests.cs |
Adds ACA publishing coverage. |
tests/Aspire.Hosting.Azure.Kubernetes.Tests/AzureKubernetesPersistentVolumeTests.cs |
Tests AKS local path resolution. |
tests/Aspire.Deployment.EndToEnd.Tests/AksPersistentVolumeDeploymentTests.cs |
Uses portable paths in AKS E2E. |
tests/Aspire.Cli.EndToEnd.Tests/KubernetesDeployWithProjectPersistentVolumeTests.cs |
Updates C# Kubernetes E2E. |
tests/Aspire.Cli.EndToEnd.Tests/KubernetesDeployTypeScriptWithPersistentVolumeTests.cs |
Updates TypeScript Kubernetes E2E. |
src/Aspire.Hosting/VolumeResourceBuilderExtensions.cs |
Implements portable volume environments. |
src/Aspire.Hosting/VolumeMountPathResolver.cs |
Generates safe local paths. |
src/Aspire.Hosting/ContainerResourceBuilderExtensions.cs |
Delegates existing volume overloads. |
src/Aspire.Hosting/Ats/CoreExports.cs |
Exports volume support for compute resources. |
src/Aspire.Hosting/ApplicationModel/VolumeMountPathResolverAnnotation.cs |
Stores target-specific path resolvers. |
src/Aspire.Hosting.Kubernetes/README.md |
Documents Kubernetes volume usage. |
src/Aspire.Hosting.Kubernetes/KubernetesPersistentVolumeResource.cs |
Updates persistent-volume documentation. |
src/Aspire.Hosting.Kubernetes/KubernetesPersistentVolumeLocalStorage.cs |
Resolves shared local PV storage. |
src/Aspire.Hosting.Kubernetes/KubernetesPersistentVolumeExtensions.cs |
Adds environment-enabled PV overloads. |
src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentResource.cs |
Moves binding validation globally. |
src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentExtensions.cs |
Validates and finalizes PV bindings. |
src/Aspire.Hosting.Kubernetes/Annotations/KubernetesPersistentVolumeBindingAnnotation.cs |
Tracks environment and local-volume metadata. |
src/Aspire.Hosting.Docker/README.md |
Documents Compose volume paths. |
src/Aspire.Hosting.Azure.Kubernetes/README.md |
Documents AKS portable paths. |
src/Aspire.Hosting.Azure.Kubernetes/AzureKubernetesPersistentVolumeExtensions.cs |
Updates AKS API example. |
Review details
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Suppressed comments (1)
src/Aspire.Hosting.Kubernetes/KubernetesEnvironmentExtensions.cs:173
- This publish-time configuration error is thrown inside
validate-kubernetesasInvalidOperationException, so the pipeline wraps it with a step-failure prefix. ThrowDistributedApplicationExceptionto preserve the clean, actionable cross-environment message; update the test's expected exception type accordingly.
throw new InvalidOperationException(
$"Resource '{resource.Name}' is assigned to compute environment '{targetName}' but binds " +
$"Kubernetes persistent volume '{annotation.Volume.Name}' which belongs to environment " +
$"'{volumeEnvironment.Name}'. A workload can only bind persistent volumes declared on its " +
$"Kubernetes compute environment. Declare the volume on the workload's Kubernetes environment, " +
$"or assign the workload to '{supportedTargetName}' with WithComputeEnvironment.");
- Files reviewed: 52/52 changed files
- Comments generated: 3
- Review effort level: Balanced
There was a problem hiding this comment.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Aspire.Hosting/VolumeResourceBuilderExtensions.cs:65
- Reject an empty
targethere. The new project/executable API otherwise accepts"", sets the published environment variable to an empty value, and emits a mount with an empty destination, which Docker/Kubernetes cannot deploy. Validate this at the public API boundary rather than deferring the failure to a target publisher.
ArgumentNullException.ThrowIfNull(target);
- Files reviewed: 52/52 changed files
- Comments generated: 0 new
- Review effort level: Balanced
This comment has been minimized.
This comment has been minimized.
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
PR Testing ReportPR Information
Artifact Version Verification
Changes AnalyzedChange Categories
Main Changed Surfaces
Test Scenarios ExecutedScenario 1: PR Artifact Version VerificationObjective: Verify testing uses the CLI artifact built from the current PR head. Steps:
Evidence:
Observations:
Scenario 2: Executable Inner-Loop Path and Data ReuseObjective: Verify a local executable receives an Steps:
Evidence:
Observations:
Scenario 3: Project Inner-Loop Path and Data ReuseObjective: Verify a real .NET project resource receives and reuses its workload-scoped local path. Steps:
Evidence:
Observations:
Scenario 4: Named Container Volume ReuseObjective: Verify container env injection and named runtime-volume persistence across session container recreation. Steps:
Evidence:
Observations:
Scenario 5: Docker Compose PublishObjective: Verify project, executable, and container volumes project into Compose consistently. Steps:
Evidence:
Observations:
Scenario 6: Kubernetes Generic and First-Class Persistent Volume PublishObjective: Verify generic and first-class volume semantics for project, executable, and container workloads. Steps:
Evidence:
Observations:
Scenario 7: TypeScript Generated SDKObjective: Verify the PR-generated TypeScript API shape compiles and publishes. Steps:
Evidence:
Observations:
Scenario 8: Live KinD Deploy and Pod RestartObjective: Verify real-cluster acceptance and persistent data after pod replacement. Steps:
Evidence:
Observations:
Scenario 9: Azure Container Apps PublishObjective: Verify ACA projects all compute resource types to Azure Files-backed storage and matching env paths. Steps:
Evidence:
Observations:
Scenario 10: Missing
|
| Scenario | Status | Notes |
|---|---|---|
| PR artifact/version | ✅ Passed | Installed CLI matches PR head |
| Executable inner-loop reuse | ✅ Passed | Same path/data across AppHost runs |
| Project inner-loop reuse | ✅ Passed | Real .NET project reused marker |
| Named container-volume reuse | ✅ Passed | New container reused persistent named volume |
| Docker Compose publish | ✅ Passed | Project/executable/container env + mounts |
| Kubernetes publish | ✅ Passed | Generic + PVC semantics verified |
| TypeScript generated SDK | ✅ Passed | Lint, type-check, publish |
| Live KinD deployment | ✅ Passed | PVC survives pod replacement |
| ACA Bicep publish | ✅ Passed | Azure Files + env for all compute shapes |
| Project volume without env | ✅ Passed | Expected compile-time rejection |
| Kubernetes PV targeting Docker | ✅ Passed | Expected ownership validation |
| Mixed host/container PV | ✅ Passed | Expected backing-store validation |
Overall Result
Recommendations
- The PR behavior is consistent across local processes, local containers, Docker Compose, Kubernetes, KinD deployment, Azure Container Apps, and TypeScript AppHosts.
- Investigate and resolve the failing polyglot code-generation/API-compatibility checks before merge.
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review details
Suppressed comments (1)
src/Aspire.Hosting/Ats/CoreExports.cs:126
nameandenvare documented as required but exposed as optional, while the implementation throws whenever either is omitted. This makes generated executable APIs such aswithVolume(target)compile successfully and then fail only during capability invocation. Make these members required in the executable export contract, or define usable defaults.
string? name = null,
bool isReadOnly = false,
string? env = null)
- Files reviewed: 55/55 changed files
- Comments generated: 3
- Review effort level: Balanced
|
/deployment-test |
|
🚀 Deployment tests starting on PR #19404... This will deploy to real Azure infrastructure. Results will be posted here when complete. |
|
/deployment-test |
|
🚀 Deployment tests starting on PR #19404... This will deploy to real Azure infrastructure. Results will be posted here when complete. |
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c14c394f-3a84-4e28-a6a6-9faceabbb7fa
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c14c394f-3a84-4e28-a6a6-9faceabbb7fa
Remove-then-Add relocated the renamed mount to the end of the annotation collection, and because ContainerMountAnnotation is a record the Remove matched by value and could drop a value-identical sibling. Assigning through the indexer preserves position and swaps atomically. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c14c394f-3a84-4e28-a6a6-9faceabbb7fa
This comment has been minimized.
This comment has been minimized.
The Docker README TypeScript sample still passed name and env through the options bag. They became required positional parameters when the polyglot exports were tightened, so the documented call no longer type-checked. Also adds a publish-mode regression test for a workload that binds an AKS persistent volume without calling WithComputeEnvironment. AKS is the sole compute environment in that case, and the implicit binding must survive the publish-mode validation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c14c394f-3a84-4e28-a6a6-9faceabbb7fa
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
src/Aspire.Hosting/Ats/CoreExports.cs:116
- The PR's user-facing TypeScript example still calls
api.withVolume("/data", { name: "data", env: "DATA_PATH" }), but this exported contract requirestarget,name, andenvas positional arguments; the generated TypeScript signature iswithVolume(target, name, env, options?). Update the PR description to useapi.withVolume("/data", "data", "DATA_PATH")so the advertised example type-checks.
[AspireExport("withProjectVolume", MethodName = "withVolume")]
public static IResourceBuilder<ProjectResource> WithProjectVolumeForPolyglot(
this IResourceBuilder<ProjectResource> resource,
string target,
string name,
string env,
bool isReadOnly = false)
- Files reviewed: 55/55 changed files
- Comments generated: 0 new
- Review effort level: Balanced
…nt tests Adds DockerComposeDeployWithVolumeTests, the Compose counterpart to the Kubernetes project persistent-volume test. It deploys a project that learns its mount path only from DATA_PATH, then asserts both the generated compose file and the running container (env var present, named volume mounted at that path). Generation alone cannot show the wiring reaches the deployed workload. The durability round-trip (write, force-recreate, read back) is deliberately omitted: .NET images run non-root while a fresh Docker named volume is created root-owned, so the app cannot write to its own volume. Kubernetes avoids this via fsGroup; Compose has no equivalent. Tracked by #19422. Also re-enables the two existing Compose deployment tests. Both were disabled twice over and neither reason still applies: the QuarantinedTest traced to a CS1705 assembly version mismatch on release branches (#15511), and the ActiveIssue (#15930) was correct when applied — the tests then used a bare terminal with no CI install fallback — but went stale once harness unification moved them to CreateDockerTestTerminal and added that fallback. Both attributes had to go: split-test-projects-for-ci.ps1 enumerates classes with --filter-not-trait quarantined=true, so removing only ActiveIssue would have left the class with no CI job at all. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c14c394f-3a84-4e28-a6a6-9faceabbb7fa
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Review details
Suppressed comments (2)
Previously missed (1) — in code that hasn't changed since the last review.
src/Aspire.Hosting/Ats/CoreExports.cs:116
- The PR description's TypeScript example still calls
api.withVolume("/data", { name: "data", env: "DATA_PATH" }), but this exported contract generateswithVolume(target, name, env, options?); the documented call does not type-check. Update the PR's user-facing example to pass"data"and"DATA_PATH"positionally, matching the generated API and the updated READMEs.
string target,
string name,
string env,
bool isReadOnly = false)
tests/Aspire.Hosting.CodeGeneration.Python.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.py:11358
ExecutableResourceKwargs.volumereusesVolumeParameters, whose TypedDict omitsenvand treatsnameas optional, but the constructor unconditionally reads both fields. This advertises dictionary inputs that fail withKeyErrorand rejects the actual required shape during static checking. Generate an executable-specific parameter TypedDict with requiredtarget,name, andenvfields (or otherwise disambiguate it from the container capability).
volume: tuple[str, str, str] | VolumeParameters
- Files reviewed: 57/57 changed files
- Comments generated: 1
- Review effort level: Balanced
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
James Newton-King (JamesNK)
left a comment
There was a problem hiding this comment.
I found three compatibility/extensibility issues that should be addressed before merge: existing mixed Kubernetes bindings now fail in run mode without using the new env feature, existing name-match containers switch to a different persisted local volume, and custom compute resources are accepted by the public API but fail during environment evaluation.
Focused proof passed for core volume behavior (11 tests), Kubernetes run-mode behavior (11 tests), the cross-environment negative case (1 test), and Docker publisher output (2 tests). Live Docker Compose proof was not completed because building the source-matched LocalHive archive exceeded the 15-minute test budget; the publisher output was the strongest completed substitute.
Fixes three issues raised in review of the volume env-path convention. Capability-scoped polyglot parameter types. Three exports project to the method name `withVolume` but accept different parameter shapes: the container form takes an optional `name` and no `env`, while the project and executable forms require both `name` and `env`. The Python and TypeScript generators derived the parameter carrier from the projected method name, so the container shape won and the other two silently reused it. Generated Python declared no `env` key yet indexed it unconditionally, making the dict form raise KeyError for the shape that type-checked and reject the shape that worked. Generated TypeScript let callers pass `name` to an implementation that only reads `isReadOnly`. Both generators now fall back to the capability ID when a shared method name carries a different shape, and Python throws rather than silently reusing an incompatible carrier. Go, Java, and Rust already disambiguated. Run-mode backing-store check no longer rejects publish-only bindings. Only host processes that requested the environment path materialize an IAspireStore directory, so a project bound to a publish-only persistent volume cannot conflict with a container's named runtime volume. The check previously considered every binding and failed `aspire run` for AppHosts that predate the env overload. Generic store fallback for custom compute resources. The public WithVolume overload accepts any IComputeResource, but resolution threw for anything that was not a project, executable, or container. Containers and publish mode return earlier, so the remaining resources all run as host processes and can use the existing store path instead of failing during environment evaluation. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: c14c394f-3a84-4e28-a6a6-9faceabbb7fa
…-volume-convention
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. 51 / 101 test projects · 6 jobs, from 56 changed files. Selected test projects (51 / 101)
Selected jobs (6)
How these were chosen — grouped by what changed
🔧 show 34
🧪 🔧 🔧 📦 affected project 🔧 🔧 🔧 🔧 🔧 🔧 🔧 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 🧪 Job reasons
Selection computed for commit |
| public static IResourceBuilder<T> WithVolume<T>( | ||
| this IResourceBuilder<T> builder, | ||
| string name, | ||
| string target, | ||
| string env, | ||
| bool isReadOnly = false) |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
|
Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt. |
Description
Volume mount paths often differ between local process execution and deployed containers. Projects and executables need a host filesystem path during the inner loop, while Docker Compose, Kubernetes, and Azure Container Apps need the in-container mount path.
This change adds an environment-variable convention so applications can consume one path setting in both modes:
WithVolume(..., env: "DATA_PATH")now supports projects, executables, and containers.IAspireStore.WithPersistentVolume(..., env: "DATA_PATH")composes the generic behavior while retaining shared PVC identity, capacity, storage class, access modes, and cross-environment validation.User-facing usage
C# AppHost:
TypeScript AppHost:
Validation
kubectlEnd-to-end deployment coverage
Docker Compose is covered by
DockerComposeDeployWithVolumeTests, the Compose counterpart to the Kubernetes project persistent-volume test. Neither needs a cloud subscription, so both run on every PR. It deploys a project that learns its mount path only fromDATA_PATH, then asserts the generated compose file and the running container —DATA_PATH=/dataplus a real named volume mounted there (volume|aspire-compose-<hash>_serverdata|/data), since generation alone cannot show the wiring reaches the deployed workload. Verified locally, passes in ~1m20s.The durability round-trip (write -> force-recreate -> read back) is deliberately omitted because it cannot pass today: .NET images run as a non-root user while a fresh Docker named volume is created root-owned, so a project cannot write to its own volume. Kubernetes avoids this by setting
fsGroup; Compose has no equivalent. Filed as #19422 with a verified fix proposal, and the round-trip should be added once that lands.This PR also re-enables the two pre-existing Compose deployment tests in
DockerDeploymentTests, which had been disabled by a stale[ActiveIssue](#15930) and[QuarantinedTest](#15882 / #15871) — neither cause still applies. Both attributes had to be removed together:eng/scripts/split-test-projects-for-ci.ps1enumerates test classes with--filter-not-trait quarantined=true, so removing only[ActiveIssue]would have left the class with no CI job at all.Fixes # (issue)
Checklist
<remarks />and<code />elements on your triple slash comments?