You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tracking issue for the CLI packaging, distribution, and channel overhaul. This covers the design changes needed to make the CLI's distribution mode, channel, and self-update behavior intrinsic to the binary rather than runtime-configurable.
Goals
The CLI knows what it is — stable, daily, or PR build — via build-time metadata, not config files.
Distribution mode drives behavior — self-extraction, self-update, hive discovery, and package feed selection are all determined by how the CLI was built and distributed.
PR dogfooding is fully isolated — all artifacts under a single directory, no interference with stable installs.
Package manager installs are first-class — WinGet/Homebrew installs opt out of self-update cleanly.
Legend: ✅ Done · 🔧 In progress (has PR) · 📐 Design · 🟡 Open (no PR) · ⚠️ Prerequisite/blocker · ⏸️ On hold
Design: How the pieces fit together
Embedded metadata over config files
Replace the runtime "channel" setting in aspire.config.json with [assembly: AssemblyMetadata("CliChannel", "stable")] baked at build time. The CLI's channel is an identity, not a preference.
Consolidated detection
Today there are multiple overlapping mechanisms for the CLI to determine "what kind of install am I":
IsRunningAsDotNetTool() — checks if ProcessPath filename is dotnet
Presence/absence of embedded bundle.tar.gz resource
"channel" setting in aspire.config.json
These should converge. #15947 embeds the channel (stable/daily/pr) and #15938 embeds the self-extraction flag. Together with .aspire-update.json for package-manager installs, the full behavior matrix becomes:
Today UpdateCommand.cs checks Path.GetFileNameWithoutExtension(Environment.ProcessPath) == "dotnet". Once the dotnet tool ships a NativeAOT binary, ProcessPath becomes aspire, so IsRunningAsDotNetTool() returns false. This means aspire update --self would try to overwrite the binary inside NuGet's managed .store/ directory instead of showing "run dotnet tool update". Must be addressed before or alongside #15797 — the embedded channel (stable + dotnet-tool distribution) or .aspire-update.json inside the NuGet package can replace this heuristic.
Switching from self-extracting binary to pre-extracted layout changes what's inside the archive:
Old: aspire-cli-{rid}.tar.gz → bin/aspire (single binary, self-extracts on first run)
New: aspire-cli-{rid}.tar.gz → bin/aspire + managed/ + dcp/ (full layout)
Older get-aspire-cli.sh scripts expect the old format. Needs lockstep rollout — update install scripts before or simultaneously with the archive format change.
The install scripts (get-aspire-cli.sh, get-aspire-cli.ps1, dogfood.sh, localhive.sh) are being modified across multiple PRs. Script tests (Track 2) should validate archive format changes in #15798+#15938 and script changes in #15951.
⚠️ NuGet package size limit
NativeAOT binary (~30 MB) + embedded bundle.tar.gz (DCP + managed ≈ 150-250 MB) may exceed NuGet.org's 250 MB package limit. Options: download-on-first-run for dotnet tool, separate dependency package, or ship without bundle.
PR CLI at ~/.aspire/dogfood/pr-1234/aspire discovers hives relative to its own install root (#15951 implements this via GetInstallRootDirectory()). This is working in the draft PR.
⚠️ PR installs need self-update disabled
A PR-installed CLI has no .aspire-update.json today. If a user runs aspire update --self, it would download a stable release and silently replace the PR build. The embedded pr channel (#15947) solves this — aspire update --self would be disabled for pr channel builds.
Related
Installer work #15284 — Installer work (broader tracking issue covering install scripts, signing, package managers)
Tracking issue for the CLI packaging, distribution, and channel overhaul. This covers the design changes needed to make the CLI's distribution mode, channel, and self-update behavior intrinsic to the binary rather than runtime-configurable.
Goals
Dependency Graph
Work Items
Track 1: Self-Identity → Packaging → Scripts (critical path)
.aspire-update.json+ #15947 — Embed channelaspire-update-json/dotnet-tool-naot/pr-dogfood-self-contained/aspire updateversion checkTrack 2: Script Tests (independent)
test-cli-installers/Parked
NO-MERGE)Design: How the pieces fit together
Embedded metadata over config files
Replace the runtime
"channel"setting inaspire.config.jsonwith[assembly: AssemblyMetadata("CliChannel", "stable")]baked at build time. The CLI's channel is an identity, not a preference.Consolidated detection
Today there are multiple overlapping mechanisms for the CLI to determine "what kind of install am I":
IsRunningAsDotNetTool()— checks ifProcessPathfilename isdotnet.aspire-update.jsonsidecar file (aspire update --selfshould support opt-out via.aspire-update.jsonnext to the CLI binary #15932)SelfExtractingBundleassembly metadata (Make CLI bundle self-extraction conditional based on distribution mode #15938)bundle.tar.gzresource"channel"setting inaspire.config.jsonThese should converge. #15947 embeds the channel (stable/daily/pr) and #15938 embeds the self-extraction flag. Together with
.aspire-update.jsonfor package-manager installs, the full behavior matrix becomes:~/.aspire/hives/dotnet tool update)~/.aspire/hives/.aspire-update.json)~/.aspire/hives/~/.aspire/dogfood/pr-{N}/hives/Known risks and dependencies
IsRunningAsDotNetTool()Today
UpdateCommand.cschecksPath.GetFileNameWithoutExtension(Environment.ProcessPath) == "dotnet". Once the dotnet tool ships a NativeAOT binary,ProcessPathbecomesaspire, soIsRunningAsDotNetTool()returns false. This meansaspire update --selfwould try to overwrite the binary inside NuGet's managed.store/directory instead of showing "rundotnet tool update". Must be addressed before or alongside #15797 — the embedded channel (stable+ dotnet-tool distribution) or.aspire-update.jsoninside the NuGet package can replace this heuristic.Switching from self-extracting binary to pre-extracted layout changes what's inside the archive:
Older
get-aspire-cli.shscripts expect the old format. Needs lockstep rollout — update install scripts before or simultaneously with the archive format change.The install scripts (
get-aspire-cli.sh,get-aspire-cli.ps1,dogfood.sh,localhive.sh) are being modified across multiple PRs. Script tests (Track 2) should validate archive format changes in #15798+#15938 and script changes in #15951.NativeAOT binary (~30 MB) + embedded
bundle.tar.gz(DCP + managed ≈ 150-250 MB) may exceed NuGet.org's 250 MB package limit. Options: download-on-first-run for dotnet tool, separate dependency package, or ship without bundle.✅ Hive discovery for PR installs (#15935)
PR CLI at
~/.aspire/dogfood/pr-1234/aspirediscovers hives relative to its own install root (#15951 implements this viaGetInstallRootDirectory()). This is working in the draft PR.A PR-installed CLI has no
.aspire-update.jsontoday. If a user runsaspire update --self, it would download a stable release and silently replace the PR build. The embeddedprchannel (#15947) solves this —aspire update --selfwould be disabled forprchannel builds.Related
/cc @mitchdenny @davidfowl @maddymontaquila @DamianEdwards