Skip to content
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
cf82ee0
fix(cli): honor source for guest language package restore
radical May 16, 2026
a49d604
chore(cli): remove source restore diff noise
radical May 16, 2026
7ef60d4
fix(cli): constrain source override restore behavior
radical May 16, 2026
32d4b3d
Merge origin/main into source restore fix
radical May 18, 2026
0381a4e
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 18, 2026
845de43
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 18, 2026
d60807b
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 18, 2026
9b6d705
fix(cli): keep --source override exclusive for Aspire packages
radical May 19, 2026
c3b0183
fix(cli): warn that aspire-empty --source is one-shot at scaffold
radical May 19, 2026
7518348
fix(cli): include --source/channel context in scaffold restore failures
radical May 19, 2026
e68732a
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 19, 2026
b59e2a0
fix(cli): honor --source override for guest-language starter templates
radical May 19, 2026
1f0c606
chore(cli): rename EmptySourceOverrideNotPersistedWarning resource
radical May 19, 2026
7e76ca4
fix(cli): align --source argument list with temp NuGet.config in Preb…
radical May 19, 2026
6e8bc74
fix(cli): redact credentials from --source in restore-failure output
radical May 19, 2026
f55e41f
fix(cli): auto-discover local Aspire source from requested channel
radical May 19, 2026
7295d17
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 19, 2026
5e069d7
fix(cli): close 5 findings from PR #17166 post-merge review
radical May 19, 2026
057abfa
fix(cli): degrade restore on channel-lookup failure + cover gaps from…
radical May 19, 2026
2b54a5c
Merge origin/main into source restore fix
radical May 19, 2026
968df31
fix(cli): address source-restore review feedback
radical May 19, 2026
d1564d2
fix(cli): persist aspire new source overrides
radical May 19, 2026
ad0f434
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 19, 2026
0bd9fce
fix(cli): reject credentialed new sources before persistence
radical May 19, 2026
94512f5
Merge remote-tracking branch 'origin/main' into radical/issue-17159-a…
radical May 19, 2026
9e82f97
fix(cli): update PR-hive NuGet config snapshots
radical May 19, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion src/Aspire.Cli/NuGet/BundleNuGetService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,14 @@ public async Task<string> RestorePackagesAsync(

_logger.LogDebug("Restoring {Count} packages", packageList.Count);
_logger.LogDebug("aspire-managed path: {ManagedPath}", managedPath);
_logger.LogDebug("NuGet restore args: {Args}", string.Join(" ", restoreArgs));
if (_logger.IsEnabled(LogLevel.Debug))
{
// Build a redacted copy of the args specifically for the log line so user-supplied
// credentialed feeds (e.g., `https://user:pat@host/v3/index.json`, SAS-token URLs) do
// not flow to the debug log alongside the rest of the restore invocation. The
// original `restoreArgs` list is still passed verbatim to the process below.
_logger.LogDebug("NuGet restore args: {Args}", string.Join(" ", BuildRedactedArgsForLog(restoreArgs)));
}

var environmentVariables = new Dictionary<string, string>();
NuGetSignatureVerificationEnabler.Apply(environmentVariables, _features, _executionContext);
Expand Down Expand Up @@ -253,6 +260,25 @@ private static bool TryValidatePackageManifest(string manifestPath, ILogger logg
}
}

// Returns a redacted copy of the restore args suitable for debug logging. Replaces the value
// immediately following each `--source` token with the credential-safe form from
// PackageSourceRedactor. Built defensively to handle repeated `--source` flags and a missing
// trailing value at the end of the args list.
private static IReadOnlyList<string> BuildRedactedArgsForLog(IReadOnlyList<string> args)
{
var redacted = new List<string>(args.Count);
for (var i = 0; i < args.Count; i++)
{
redacted.Add(args[i]);
if (string.Equals(args[i], "--source", StringComparison.Ordinal) && i + 1 < args.Count)
{
redacted.Add(PackageSourceRedactor.RedactForDisplay(args[++i]));
}
}

return redacted;
}

internal static string ComputePackageHash(
List<(string Id, string Version)> packages,
string tfm,
Expand Down
22 changes: 19 additions & 3 deletions src/Aspire.Cli/Projects/DotNetBasedAppHostServerProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,8 @@ private XDocument CreateProjectFile(IEnumerable<IntegrationReference> integratio
/// </summary>
public async Task<(string ProjectPath, string? ChannelName)> CreateProjectFilesAsync(
IEnumerable<IntegrationReference> integrations,
CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default,
string? packageSourceOverride = null)
{
// Clean obj folder to ensure fresh NuGet restore
var objPath = Path.Combine(_projectModelPath, "obj");
Expand Down Expand Up @@ -351,6 +352,20 @@ private XDocument CreateProjectFile(IEnumerable<IntegrationReference> integratio
}
}

// Thread an explicit `--source` override into the restore sources so the dogfood
// `aspire new --source <pr-hive>` flow is honored in dev mode (in-repo). Prepending
// makes the override the first source NuGet evaluates, which matters when the same
// Aspire package version exists in both the hive and a channel feed. Note: unlike
// PrebuiltAppHostServer this path does not emit Package Source Mappings, so NuGet
// may still consult other sources if the override does not satisfy a request — the
// override is best-effort here, sufficient for the in-repo developer scenario where
// most Aspire.* dependencies come from ProjectReference, not PackageReference.
if (!string.IsNullOrWhiteSpace(packageSourceOverride) &&
!channelSources.Contains(packageSourceOverride, StringComparer.OrdinalIgnoreCase))
{
channelSources.Insert(0, packageSourceOverride);
}

// Create the project file
var doc = CreateProjectFile(integrations);

Expand Down Expand Up @@ -422,9 +437,10 @@ private XDocument CreateProjectFile(IEnumerable<IntegrationReference> integratio
public async Task<AppHostServerPrepareResult> PrepareAsync(
string sdkVersion,
IEnumerable<IntegrationReference> integrations,
CancellationToken cancellationToken = default)
CancellationToken cancellationToken = default,
Comment thread
radical marked this conversation as resolved.
Outdated
string? packageSourceOverride = null)
{
var (_, channelName) = await CreateProjectFilesAsync(integrations, cancellationToken);
var (_, channelName) = await CreateProjectFilesAsync(integrations, cancellationToken, packageSourceOverride);
var (buildSuccess, buildOutput) = await BuildAsync(cancellationToken);

if (!buildSuccess)
Expand Down
13 changes: 7 additions & 6 deletions src/Aspire.Cli/Projects/GuestAppHostProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -224,17 +224,18 @@ private string GetPrepareSdkVersion(AspireConfigFile config)
IAppHostServerProject appHostServerProject,
string sdkVersion,
List<IntegrationReference> integrations,
CancellationToken cancellationToken)
CancellationToken cancellationToken,
string? packageSourceOverride = null)
{
var result = await appHostServerProject.PrepareAsync(sdkVersion, integrations, cancellationToken);
var result = await appHostServerProject.PrepareAsync(sdkVersion, integrations, cancellationToken, packageSourceOverride: packageSourceOverride);
return (result.Success, result.Output, result.ChannelName, result.NeedsCodeGeneration);
}

/// <summary>
/// Builds the AppHost server project and generates SDK code.
/// </summary>
/// <returns><see langword="true"/> if the code was generated successfully; otherwise, <see langword="false"/>.</returns>
internal async Task<bool> BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken)
internal async Task<bool> BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken, string? packageSourceOverride = null)
{
var appHostServerProject = await _appHostServerProjectFactory.CreateAsync(directory.FullName, cancellationToken);

Expand All @@ -243,7 +244,7 @@ internal async Task<bool> BuildAndGenerateSdkAsync(DirectoryInfo directory, Canc
var integrations = await GetIntegrationReferencesAsync(config, directory, cancellationToken);
var sdkVersion = GetPrepareSdkVersion(config);

var (buildSuccess, buildOutput, _, _) = await PrepareAppHostServerAsync(appHostServerProject, sdkVersion, integrations, cancellationToken);
var (buildSuccess, buildOutput, _, _) = await PrepareAppHostServerAsync(appHostServerProject, sdkVersion, integrations, cancellationToken, packageSourceOverride);
if (!buildSuccess)
{
if (buildOutput is not null)
Expand Down Expand Up @@ -280,9 +281,9 @@ await GenerateCodeViaRpcAsync(
return true;
}

Task<bool> IGuestAppHostSdkGenerator.BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken)
Task<bool> IGuestAppHostSdkGenerator.BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken, string? packageSourceOverride)
{
return BuildAndGenerateSdkAsync(directory, cancellationToken);
return BuildAndGenerateSdkAsync(directory, cancellationToken, packageSourceOverride);
}

// ═══════════════════════════════════════════════════════════════
Expand Down
4 changes: 3 additions & 1 deletion src/Aspire.Cli/Projects/IAppHostServerProject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ internal interface IAppHostServerProject
/// <param name="sdkVersion">The Aspire SDK version to use.</param>
/// <param name="integrations">The integration references (NuGet packages and/or project references) required by the app host.</param>
/// <param name="cancellationToken">Cancellation token.</param>
/// <param name="packageSourceOverride">Optional package source to prefer for Aspire package restore.</param>
/// <returns>The preparation result indicating success/failure and any output.</returns>
Task<AppHostServerPrepareResult> PrepareAsync(
string sdkVersion,
IEnumerable<IntegrationReference> integrations,
CancellationToken cancellationToken = default);
CancellationToken cancellationToken = default,
Comment thread
radical marked this conversation as resolved.
Outdated
string? packageSourceOverride = null);

/// <summary>
/// Runs the AppHost server process.
Expand Down
3 changes: 2 additions & 1 deletion src/Aspire.Cli/Projects/IGuestAppHostSdkGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ internal interface IGuestAppHostSdkGenerator
/// </summary>
/// <param name="directory">The AppHost project directory.</param>
/// <param name="cancellationToken">A cancellation token.</param>
/// <param name="packageSourceOverride">Optional package source to prefer for Aspire package restore during the build.</param>
/// <returns><see langword="true"/> if SDK generation succeeded; otherwise, <see langword="false"/>.</returns>
Task<bool> BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken);
Task<bool> BuildAndGenerateSdkAsync(DirectoryInfo directory, CancellationToken cancellationToken, string? packageSourceOverride = null);
}
Loading
Loading