[docs] Add portable volume path environment variables - #1593
Conversation
Documents changes from microsoft/aspire#19404 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Frontend HTML artifact readyThe latest frontend build uploaded the This comment updates automatically when a new frontend build artifact is uploaded. |
There was a problem hiding this comment.
Pull request overview
Documents new Aspire hosting APIs that let workloads consume a single environment variable representing the “effective” volume path across run mode (local execution) and publish/deploy modes (Compose/Kubernetes/ACA). This updates existing volume and Kubernetes persistent-volume guidance to reflect the new env parameter behavior introduced in microsoft/aspire#19404.
Changes:
- Adds a new fundamentals section describing
WithVolume(..., env: ...)and its portable path behavior (C# + TypeScript). - Adds a Kubernetes subsection documenting
WithPersistentVolume(..., env: ...)/withKubernetesPersistentVolumeMount(..., { env }), including local container naming behavior and limitations.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/frontend/src/content/docs/fundamentals/persist-data-volumes.mdx | Adds guidance for portable volume path env vars via WithVolume(..., env: ...), with a cross-link to Kubernetes PV details. |
| src/frontend/src/content/docs/deployment/kubernetes/persistent-volumes.mdx | Adds Kubernetes PV binding guidance for portable path env vars via env, plus notes on local container behavior and limitations. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
David Pine (IEvangelist)
left a comment
There was a problem hiding this comment.
Automated docs-accuracy review
Source of truth: microsoft/aspire @ main (HEAD 1cdf7d17248ae78ee018abbc314f772ace5e624d).
⚠️ Branch note (non-blocking): This PR targetsrelease/13.6, which does not exist inmicrosoft/aspire. The portable volume-pathenvfeature ships via microsoft/aspire#19404 (merge54c1f929ae), which is present onmainbut not yet in a GA release (latest tag isv13.5.3; there is nov13.6tag). I therefore verified every claim againstupstream/main. If arelease/13.6branch is later cut, these claims should be re-confirmed against it.
Phase A — claims: 14 non-narrative claims extracted → ✅ 14 verified, 0 verified-with-nuance, 0 unverifiable, 0 contradicted.
Phase B — doc-tester: 2 routes exercised (/fundamentals/persist-data-volumes/, /deployment/kubernetes/persistent-volumes/) → 0 critical, 0 warnings; 1 knowledge gap (local build predates PR — mitigated).
This is a high-fidelity PR: the prose tracks the product README (src/Aspire.Hosting.Kubernetes/README.md) almost verbatim, and both the C# and TypeScript examples use the correct per-language parameter order.
Phase A — Claim verification
No contradicted or unverifiable claims, so there are no inline blocking comments. All evidence is below for audit.
✅ 14 verified claims (click to expand)
Fundamentals — fundamentals/persist-data-volumes.mdx
| id | claim | evidence (microsoft/aspire @ main) |
|---|---|---|
| F1 | WithVolume gains an optional env parameter |
src/Aspire.Hosting/VolumeResourceBuilderExtensions.cs:39 — WithVolume<T>(builder, string name, string target, string env, bool isReadOnly = false) where T : IComputeResource, IResourceWithEnvironment |
| F2 | C# WithVolume("data", "/data", env: "DATA_PATH") on a project (order: name, target, env) |
same signature; a project satisfies IComputeResource, IResourceWithEnvironment |
| F3 | TS withVolume("/data", "data", "DATA_PATH") on a project (order: target, name, env) |
generated TS API tests/Aspire.Hosting.CodeGeneration.TypeScript.Tests/Snapshots/TwoPassScanningGeneratedAspire.verified.ts — project promise exposes withVolume(target, name, env, options?) |
| F4 | Run mode → project/executable gets a deterministic workload-scoped dir under the AppHost local store as DATA_PATH |
VolumeResourceBuilderExtensions.cs remarks: "Projects and executables receive a workload-scoped IAspireStore directory in run mode" |
| F5 | Containers, and any workload in publish/deploy, receive /data (the target) |
same remarks: "Containers receive target in run and publish modes"; publish = target |
| F6 | env only on projects/executables; container equivalent is .WithEnvironment("DATA_PATH", "/data") |
C# container WithVolume overloads have no env (ContainerResourceBuilderExtensions.cs:228,265); polyglot container export remark in Ats/CoreExports.cs: container is "exactly equivalent to withVolume(target, name).withEnvironment(env, target)" |
| F7 | Cross-link to …/persistent-volumes/#bind-with-a-portable-path-environment-variable |
K page (this PR) adds H3 "Bind with a portable path environment variable" → slug matches; self-consistent |
Kubernetes — deployment/kubernetes/persistent-volumes.mdx
| id | claim | evidence (microsoft/aspire @ main) |
|---|---|---|
| K1 | C# AddPersistentVolume("data").WithCapacity("20Gi") + .WithPersistentVolume(data, "/data", env: "DATA_PATH") |
src/Aspire.Hosting.Kubernetes/KubernetesPersistentVolumeExtensions.cs — AddPersistentVolume(builder, [ResourceName] string name) L46; WithCapacity(builder, string capacity) L119; WithPersistentVolume<T>(builder, volume, string mountPath, string env, bool isReadOnly = false) where T : IComputeResource, IResourceWithEnvironment L364 (doc-comment example uses env: "DATA_PATH") |
| K2 | TS addPersistentVolume / withCapacity / withKubernetesPersistentVolumeMount(data, '/data', { env: 'DATA_PATH' }) |
[AspireExport] on AddPersistentVolume & WithCapacity; [AspireExport("withKubernetesPersistentVolumeMount")] on WithPersistentVolumeMountForExport<T>(builder, volume, mountPath, bool isReadOnly = false, string? env = null) → trailing optionals become an options bag { env }; env-carrying C# overload is [AspireExportIgnore(Reason = "Polyglot AppHosts use the withKubernetesPersistentVolumeMount adapter.")] |
| K3 | Run mode → DATA_PATH is a persistent dir in the local store, normally under the intermediate-output dir (cleaning build outputs can remove it) |
KubernetesPersistentVolumeLocalStorage.cs:27-28 "IAspireStore is scoped to the AppHost's intermediate output directory…"; README.md:83 |
| K4 | Publish/deploy → DATA_PATH contains the mount path /data |
README.md:85 "When published or deployed, DATA_PATH contains /data" |
| K5 | Local containers use a worktree-scoped container volume when the mount names an env var; mounts without one keep the PV's own name | README.md:83; KubernetesPersistentVolumeExtensions.cs:467 "Computes the worktree-scoped local volume name for a run-mode container binding" |
| K6 | A single PV can't be shared between local containers and local projects/executables | KubernetesEnvironmentExtensions.cs:191 throws: "Run mode cannot provide one shared backing store across those execution types. Use only containers or only projects/executables for this volume." + README.md:83 |
| K7 | isReadOnly is enforced after deployment, but Aspire can't make a directory read-only for a host process |
README.md:85 verbatim; run-mode resolver returns a writable GetOrCreatePath dir; isReadOnly flows only to the pod volume source (Extensions/ResourceExtensions.cs:245) |
Note (not a defect): C# uses (name, target) = ("data","/data") while TS reorders to (target, name) = ("/data","data"). Both are correct per their respective generated signatures — the polyglot TS surface is target-first by design.
Phase B — Doc-tester results
Playwright-only run against the local docs frontend; no
microsoft/aspiresource was consulted in this phase.
Routes exercised: /fundamentals/persist-data-volumes/, /deployment/kubernetes/persistent-volumes/
| Category | Passed | Failed | Warnings |
|---|---|---|---|
| Page health (HTTP/console) | 2 | 0 | 0 |
| Reused component rendering | 2 | 0 | 0 |
| Insertion-region integrity | 2 | 0 | 0 |
| Links | 1 | 0 | 0 |
Critical issues: none.
Warnings: none (from a blind-user perspective).
Passed checks
/fundamentals/persist-data-volumes/— HTTP 200; 0 console errors (3 benign Vite dev-serverNo popup container foundwarnings, content-independent). Renders multipleTabs syncKey="aspire-lang"(C#/TypeScript) +title="AppHost.cs"code figures./deployment/kubernetes/persistent-volumes/— HTTP 200; 0 console errors, 0 warnings. Renders 6 TypeScript tabs, the pre-existingwithKubernetesPersistentVolumeMountexample, and the existingAddPersistentVolume(...).WithCapacity(...)example.- Insertion regions intact: the Kubernetes
Aside type="caution""Workloads are promoted to StatefulSet" (the node the new H3 is inserted before) renders as a landmark; the Fundamentals "Use bind mounts" H2 (the node the new H2 is inserted before) renders. The PR introduces no new component types — only new instances of already-rendering components. - Link (F7): the new internal link targets a page that returns HTTP 200; the anchor heading is added by this same PR.
Knowledge gap — local docs build predates this PR: Neither new heading ("Use a portable volume path environment variable" / "Bind with a portable path environment variable") nor the string DATA_PATH is present in the served HTML, so I could not exercise the new prose/examples directly as a blind user. Mitigation: validated page health, confirmed every reused component already renders on both target pages, confirmed both insertion anchors are intact, and confirmed the one new link points to an existing page. This is a test-environment limitation, not a documentation defect.
Verdict: APPROVE
Every non-narrative claim (14/14) is verified against microsoft/aspire @ main, both the C# and TypeScript examples use the correct per-language signatures, and the doc-tester run found no critical issues or warnings. The only caveat is the informational branch-name mismatch (release/13.6 not present in microsoft/aspire); re-confirm against that branch if/when it is cut.
🤖 Automated Phase A (source-of-truth claims) + Phase B (doc-tester) review. Phase A read microsoft/aspire @ main; Phase B used Playwright against the local docs site only.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Documents changes from microsoft/aspire#19404
@mitchdennyTargeting
release/13.6based on the source PR milestone13.6.Why
microsoft/aspire#19404 adds an
envparameter toWithVolume(and to KubernetesWithPersistentVolume) so a project or executable can read one environment variable for its storage path in both local run mode and published/deployed modes:IAspireStore.WithPersistentVolume(..., env: ...)overload composes the same behavior for first-class persistent volumes.This is new public API (
new_public_type,integration_readme_changedsignals both fired) with a "User-facing usage" section in the PR body, so it needed a docs update.What changed
src/frontend/src/content/docs/fundamentals/persist-data-volumes.mdx: added a new "Use a portable volume path environment variable" section describing theenvparameter onWithVolume, its run-mode vs. publish-mode behavior, and a note that it's only available for projects/executables (containers always gettarget).src/frontend/src/content/docs/deployment/kubernetes/persistent-volumes.mdx: added a new "Bind with a portable path environment variable" subsection under "Bind a volume to a workload", describing theWithPersistentVolume(volume, mountPath, env: ...)overload, local-container-volume naming behavior, and the one-volume-per-execution-type limitation.Both pages are existing pages that already covered
WithVolume/WithPersistentVolume; no new pages were created.