Add tests and plumb .aspire-update.json into distribution archives#15946
Add tests and plumb .aspire-update.json into distribution archives#15946radical wants to merge 8 commits intomicrosoft:mainfrom
Conversation
Introduce IInstallationDetector service that detects how the CLI was installed and whether self-update is available. When a .aspire-update.json file is present next to the CLI binary with selfUpdateDisabled: true, all three self-update paths are guarded: - aspire update --self: shows disabled message and update instructions - Post-project-update prompt: shows instructions instead of prompting - No-project-found fallback: shows instructions instead of prompting The CliUpdateNotifier also suppresses background update notifications when self-update is disabled (e.g., WinGet/Homebrew installs). Key design decisions: - Symlink resolution before config lookup (critical for Homebrew) - Fail-closed on malformed/unreadable JSON (safer for package managers) - Cached result (computed once per process lifetime) - DotNet tool detection takes priority over config file - Fixes pre-existing bug where post-project-update prompt didn't check IsRunningAsDotNetTool Co-authored-by: Copilot <[email protected]>
Tests: - UpdateCommand --self when SelfUpdateDisabled shows disabled message - UpdateCommand post-project-update skips confirm prompt when disabled - UpdateCommand no-project-found shows instructions without prompt - CliUpdateNotifier suppresses notification when SelfUpdateDisabled=true Distribution plumbing: - Common.projitems: Write .aspire-update.json per-RID (win→winget, osx→brew) - Bundle.proj: Forward UpdateInstructions property to CreateLayout - CreateLayout: Add --update-instructions option for bundle layout - Homebrew cask template: postflight writes .aspire-update.json - Install scripts (sh/ps1): Delete .aspire-update.json after extraction so script-installed users retain self-update capability Co-authored-by: Copilot <[email protected]>
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 15946Or
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 15946" |
…oft#15947) Replace the mutable 'channel' property in aspire.config.json with a compile-time CliChannel assembly metadata attribute baked into the CLI binary. This ensures stable-channel binaries inherently know they are stable without relying on a mutable config file that can get out of sync. Changes: - Add CliChannel MSBuild property and AssemblyMetadata to Aspire.Cli.csproj - Add PackagingService.GetEmbeddedChannel() to read channel at runtime - UpdateCommand uses embedded channel as self-update default (no prompt) - Remove Channel property from AspireConfigFile; add JsonExtensionData to preserve unknown properties on round-trip - All channel consumers fall back to embedded channel when no explicit --channel flag or local config channel is set - Build infrastructure: Common.projitems defaults CliChannel=stable, Bundle.proj forwards CliChannel, localhive scripts use CliChannel=pr - Update tests to remove references to removed Channel property Channel resolution priority (highest to lowest): 1. --channel CLI flag 2. Local .aspire/settings.json channel (polyglot backward compat) 3. Global aspire.config.json channel (backward compat via ExtensionData) 4. Embedded CliChannel assembly metadata 5. Implicit channel (NuGet feed defaults) Co-authored-by: Copilot <[email protected]>
…n, and GetEmbeddedChannel - ExtensionData round-trip: verify unknown JSON properties (like legacy 'channel') survive load → save → reload - ExtensionData preservation: verify unknown properties captured on load - ExtensionData null: verify no ExtensionData when all props are known - FromLegacy channel exclusion: verify channel is NOT migrated from legacy config (now embedded in binary instead) - FromLegacy other fields: verify all non-channel fields still migrate - GetEmbeddedChannel dev build: verify returns null when no assembly metadata is set (test/dev builds) Co-authored-by: Copilot <[email protected]>
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
|
Re-running the failed jobs in the CI workflow for this pull request because 1 job was identified as retry-safe transient failures in the CI run attempt.
|
FromLegacy() was skipping channel migration, breaking the GlobalMigration_PreservesAllValueTypes E2E test. Channel values from legacy globalsettings.json are now preserved in ExtensionData so 'aspire config get channel' continues to work after migration. Co-authored-by: Copilot <[email protected]>
AddCommand was reading the channel from the legacy AspireJsonConfiguration (.aspire/settings.json) while InitCommand correctly used the new IConfigurationService. This caused AddCommand to ignore channels set via 'aspire config set channel <name> -g', falling back to the embedded 'stable' channel instead of the configured PR hive channel. Now AddCommand reads the channel from IConfigurationService, consistent with InitCommand (line 742) and other commands that use the new config. Co-authored-by: Copilot <[email protected]>
Summary
Two related changes to improve CLI distribution channel handling:
1.
.aspire-update.jsonself-update opt-out mechanism (#15932)Plumbs the
.aspire-update.jsonfile into the WinGet and Homebrew distribution pipelines so that package-manager-installed CLIs correctly suppress self-update notifications and show the right update instructions.2. Embed distribution channel in CLI binary (#15947)
Replaces the mutable
"channel"property inaspire.config.jsonwith a compile-timeCliChannelassembly metadata attribute baked into the CLI binary. Stable-channel binaries inherently know they are stable without relying on a mutable config file.Changes
.aspire-update.json plumbing
tools/CreateLayout/Program.cs: Added--update-instructionsoption andWriteAspireUpdateJson()methodeng/Bundle.proj: ForwardUpdateInstructionsproperty to CreateLayouteng/clipack/Common.projitems: AddedCliUpdateInstructionsper-RID and_WriteAspireUpdateJsontargeteng/homebrew/aspire.rb.template: Addedpostflightblock to write.aspire-update.jsoneng/scripts/get-aspire-cli.sh/get-aspire-cli.ps1: Delete.aspire-update.jsonafter extractionCliChannel embedding
src/Aspire.Cli/Aspire.Cli.csproj: AddedCliChannelMSBuild property +AssemblyMetadatasrc/Aspire.Cli/Packaging/PackagingService.cs: AddedGetEmbeddedChannel()to read channel at runtimesrc/Aspire.Cli/Commands/UpdateCommand.cs: Uses embedded channel as self-update defaultsrc/Aspire.Cli/Configuration/AspireConfigFile.cs: RemovedChannelproperty; addedJsonExtensionDatafor backward compatCommon.projitemsdefaultsCliChannel=stable,Bundle.projforwards it, localhive scripts useCliChannel=prChannel resolution priority (highest to lowest)
--channelCLI flag.aspire/settings.jsonchannel (polyglot backward compat)aspire.config.jsonchannel (backward compat via ExtensionData)CliChannelassembly metadataTests
ChannelpropertyBackward compatibility
aspire.config.jsonfiles with"channel"are preserved viaJsonExtensionDataon round-trip.aspire/settings.jsonchannel is still read for polyglot projectsFixes #15932
Fixes #15947