Skip to content

CLI packaging, distribution mode, and channel overhaul #15949

@radical

Description

@radical

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

  1. The CLI knows what it is — stable, daily, or PR build — via build-time metadata, not config files.
  2. 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.
  3. PR dogfooding is fully isolated — all artifacts under a single directory, no interference with stable installs.
  4. Package manager installs are first-class — WinGet/Homebrew installs opt out of self-update cleanly.

Dependency Graph

 #15946 + #15947           #10288            Mitch's E2E PR
 (self-identity)        (script tests)       (external)
        │                    │                    │
        ▼                    │                    ▼
 #15798 + #15938 ◄───────────┘               #15919
 (NativeAOT + conditional                   (E2E test fixes)
  self-extraction)
        │
        ▼
   #15951 (PR dogfood scripts)
        │
        ▼
   #15604 (version check)

Work Items

Track 1: Self-Identity → Packaging → Scripts (critical path)

Issue PR Worktree Status
🔧 #15932.aspire-update.json + #15947 — Embed channel #15946 (draft) aspire-update-json/ In progress — fold #15947 into this PR
🔧 #15797 — NativeAOT dotnet tool + #15938 — Conditional self-extraction #15798 (draft) dotnet-tool-naot/ In progress — blocked on #15946+#15947
🔧 #15935 — PR dogfood isolation #15951 (draft) pr-dogfood-self-contained/ In progress — blocked on #15798+#15938
🟡 #15604aspire update version check Open — blocked on #15947

Track 2: Script Tests (independent)

Issue PR Worktree Status
⚠️ #10288 — CLI scripts tests test-cli-installers/ In progress locally — validates archive format changes in #15798+#15938

Parked

Issue PR Status
⏸️ #15919 — Fix 5 CLI E2E tests #15919 (draft, NO-MERGE) On hold — waiting for Mitch's E2E test infra PR

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":

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:

Distribution Channel Self-Extract Self-Update Hive Location
Script install (archive) stable/daily No (pre-extracted layout) Yes (within channel) ~/.aspire/hives/
dotnet tool (NuGet) stable Yes (NuGet constraints) No (dotnet tool update) ~/.aspire/hives/
WinGet / Homebrew stable No No (.aspire-update.json) ~/.aspire/hives/
PR dogfood pr No No ~/.aspire/dogfood/pr-{N}/hives/

Known risks and dependencies

⚠️ NativeAOT dotnet tool (#15797) breaks IsRunningAsDotNetTool()

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.

⚠️ Archive format change (#15938)

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.

⚠️ CLI scripts need test coverage (#10288)

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.

✅ Hive discovery for PR installs (#15935)

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)

/cc @mitchdenny @davidfowl @maddymontaquila @DamianEdwards

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions