Skip to content

Fix non-interactive self-update channel selection#17512

Open
alirezafzali wants to merge 2 commits into
microsoft:mainfrom
alirezafzali:fix/update-self-non-interactive-channel
Open

Fix non-interactive self-update channel selection#17512
alirezafzali wants to merge 2 commits into
microsoft:mainfrom
alirezafzali:fix/update-self-non-interactive-channel

Conversation

@alirezafzali
Copy link
Copy Markdown
Contributor

@alirezafzali alirezafzali commented May 26, 2026

Description

Fixes #15253

aspire update --self --non-interactive fails with an interactive prompt error when --channel is not provided.

This updates ExecuteSelfUpdateAsync so that in non-interactive mode:

  • If the CLI's identity channel maps to a known update channel (stable, daily, or staging), that channel is used (with canonical casing from the channel list).
  • If identity is local, the command defaults to stable.
  • If identity does not map to a known channel (e.g. stale pr-*), the command requires --channel instead of guessing.

Interactive mode still prompts for channel selection as before.

Added tests for:

  • Using a known CLI identity channel (daily/stable, including case-insensitive identity) without prompting in non-interactive mode
  • Defaulting to stable for local identity in non-interactive mode
  • Requiring --channel for stale/unmatched PR identity (pr-99999) in non-interactive mode
  • Explicit --channel overriding the identity channel in non-interactive mode

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
      • If yes, did you have an API Review for it?
        • Yes
        • No
      • Did you add <remarks /> and <code /> elements on your triple slash comments?
        • Yes
        • No
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
      • If yes, have you done a threat model and had a security review?
        • Yes
        • No
    • No

Copilot AI review requested due to automatic review settings May 26, 2026 22:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds non-interactive self-update behavior to avoid channel prompts by inferring the update channel from the CLI’s identity channel (or defaulting to stable), with accompanying tests to validate the selection/override rules.

Changes:

  • Update self-update flow to skip channel prompting in --non-interactive mode and select a channel deterministically.
  • Prefer ExecutionContext.IdentityChannel when it matches a known update channel; otherwise default to stable.
  • Add unit tests covering identity-channel matching, local/stale identity channels defaulting, and explicit --channel override.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
tests/Aspire.Cli.Tests/Commands/UpdateCommandTests.cs Adds tests validating non-interactive self-update channel selection and override behavior.
src/Aspire.Cli/Commands/UpdateCommand.cs Changes non-interactive self-update to bypass prompting and pick a channel based on identity/default logic.

Comment on lines +489 to +494
if (!string.IsNullOrWhiteSpace(identityChannel)
&& !string.Equals(identityChannel, PackageChannelNames.Local, StringComparisons.ChannelName)
&& channels.Any(c => string.Equals(c, identityChannel, StringComparisons.ChannelName)))
{
channel = identityChannel;
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Updated ExecuteSelfUpdateAsync to use channels.FirstOrDefault(...) and assign matchedChannel so the channel string is normalized, consistent with the project-update identity path. Added [InlineData("DAILY", "daily")] to the non-interactive self-update tests.

Comment on lines +2554 to +2557
await result.InvokeAsync().DefaultTimeout();

Assert.False(promptForSelectionInvoked, "Identity-channel match should bypass the channel prompt.");
Assert.Equal(identityChannel, capturedChannel);
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don’t assert exit code Success on these self-update tests because we only fake the download with invalid archive bytes; extraction always fails afterward, so the process exits with an error even when channel selection worked. We assert the channel passed to the downloader (and MissingRequiredArgument when channel is required), same as TracksChannelParameter.

Comment on lines +2568 to +2591
var services = CliTestHelper.CreateServiceCollection(workspace, outputHelper, options =>
{
options.CliExecutionContextFactory = _ => workspace.CreateExecutionContext(identityChannel: PackageChannelNames.Local);

options.InteractionServiceFactory = _ => new TestInteractionService()
{
PromptForSelectionCallback = (prompt, choices, formatter, ct) =>
{
promptForSelectionInvoked = true;
return PackageChannelNames.Stable;
}
};

options.CliDownloaderFactory = _ => new TestCliDownloader(workspace.WorkspaceRoot)
{
DownloadLatestCliAsyncCallback = (channel, ct) =>
{
capturedChannel = channel;
var archivePath = Path.Combine(workspace.WorkspaceRoot.FullName, "test-cli.tar.gz");
File.WriteAllText(archivePath, "fake archive");
return Task.FromResult(archivePath);
}
};
});
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Matches existing self-update tests (TracksChannelParameter, etc.). I can add RunSelfUpdateAndCaptureChannelAsync in a follow-up, or in this PR if maintainers want that refactor here.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 26, 2026

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 17512

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 17512"

@JamesNK
Copy link
Copy Markdown
Member

JamesNK commented May 26, 2026

@davidfowl @mitchdenny I'm not a channel expert. Does it make sense or is it possible to default the channel?

@davidfowl
Copy link
Copy Markdown
Collaborator

Yep this makes sense

@JamesNK
Copy link
Copy Markdown
Member

JamesNK commented May 27, 2026

@alirezafzali The one scenario I'm not sure about is this one:

Falling back to stable for stale PR identity (pr-99999) in non-interactive mode

I think there is also an argument to switching to nightly from a PR. Since there isn't an obvious choice, I think in this case the channel should be required.

…ution.

Require --channel when identity does not map to a known update channel (e.g. stale pr-*), keep local defaulting to stable, and assign canonical channel names from the channels list for case-insensitive identity matches.
@alirezafzali
Copy link
Copy Markdown
Contributor Author

@alirezafzali The one scenario I'm not sure about is this one:

Falling back to stable for stale PR identity (pr-99999) in non-interactive mode

I think there is also an argument to switching to nightly from a PR. Since there isn't an obvious choice, I think in this case the channel should be required.

Makes sense. I’ve changed this so stale/unmatched identities (e.g. pr-99999) require --channel in non-interactive mode instead of defaulting to stable. Known channels still auto-resolve from identity; local still falls back to stable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

aspire update --self --non-interactive fails without --channel

4 participants