Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
43 changes: 35 additions & 8 deletions src/Aspire.Cli/Commands/AddCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,30 @@ protected override async Task<int> ExecuteAsync(ParseResult parseResult, Cancell
var packages = new List<(NuGetPackage Package, PackageChannel Channel)>();
var packagesLock = new object();

await Parallel.ForEachAsync(channels, cancellationToken, async (channel, ct) =>
// Use a configurable timeout so one slow NuGet feed can't block the entire search.
// Default is 120 seconds; override via ASPIRE_SEARCH_TIMEOUT_SECONDS environment variable.
var searchTimeout = GetSearchTimeout();
using var searchCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
searchCts.CancelAfter(searchTimeout);

try
{
var integrationPackages = await channel.GetIntegrationPackagesAsync(
workingDirectory: effectiveAppHostProjectFile.Directory!,
cancellationToken: ct);
lock (packagesLock)
await Parallel.ForEachAsync(channels, searchCts.Token, async (channel, ct) =>
{
packages.AddRange(integrationPackages.Select(p => (p, channel)));
}
});
var integrationPackages = await channel.GetIntegrationPackagesAsync(
workingDirectory: effectiveAppHostProjectFile.Directory!,
cancellationToken: ct);
lock (packagesLock)
{
packages.AddRange(integrationPackages.Select(p => (p, channel)));
}
});
}
catch (OperationCanceledException) when (searchCts.IsCancellationRequested && !cancellationToken.IsCancellationRequested)
{
// The search timed out but the user didn't cancel. Use whatever partial results
// we collected so far. This prevents one slow NuGet feed from blocking the entire search.
}

return packages;

Expand Down Expand Up @@ -330,6 +344,19 @@ internal static (string FriendlyName, NuGetPackage Package, PackageChannel Chann

return (friendlyName, packageWithChannel.Package, packageWithChannel.Channel);
}

private static TimeSpan GetSearchTimeout()
{
const int defaultTimeoutSeconds = 120;

var envValue = Environment.GetEnvironmentVariable("ASPIRE_SEARCH_TIMEOUT_SECONDS");
if (!string.IsNullOrEmpty(envValue) && int.TryParse(envValue, CultureInfo.InvariantCulture, out var seconds) && seconds > 0)
{
return TimeSpan.FromSeconds(seconds);
}

return TimeSpan.FromSeconds(defaultTimeoutSeconds);
}
}

internal interface IAddCommandPrompter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ private async Task DeployWithCompactNamingFixesStorageCollisionCore(Cancellation
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ private async Task UpgradeFromGaToDevDoesNotDuplicateStorageAccountsCore(Cancell
output.WriteLine("Step 6: Adding Azure Container Apps package (GA)...");
sequenceBuilder.Type("aspire add Aspire.Hosting.Azure.AppContainers")
.Enter()
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter()
.WaitForSuccessPrompt(counter, TimeSpan.FromSeconds(180));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ private async Task DeployStarterTemplateWithCustomRegistryCore(CancellationToken
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand All @@ -169,7 +169,7 @@ private async Task DeployStarterTemplateWithCustomRegistryCore(CancellationToken
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ private async Task DeployStarterTemplateWithExistingRegistryCore(CancellationTok
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand All @@ -193,7 +193,7 @@ private async Task DeployStarterTemplateWithExistingRegistryCore(CancellationTok
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ private async Task DeployStarterTemplateToAzureContainerAppsCore(CancellationTok
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // select first version (PR build)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ private async Task DeployStarterTemplateToAksCore(CancellationToken cancellation
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // select first version (PR build)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ private async Task DeployStarterTemplateWithRedisToAksCore(CancellationToken can
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // select first version (PR build)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private async Task DeployPythonFastApiTemplateToAzureAppServiceCore(Cancellation
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // select first version (PR build)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ private async Task DeployReactTemplateToAzureAppServiceCore(CancellationToken ca
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // select first version (PR build)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ private async Task DeployAzureAppConfigResourceCore(CancellationToken cancellati
{
// First, handle integration selection prompt
sequenceBuilder
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter() // Select first integration (azure-appcontainers)
// Then, handle version selection prompt
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version (PR build)
}

Expand All @@ -144,7 +144,7 @@ private async Task DeployAzureAppConfigResourceCore(CancellationToken cancellati
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private async Task DeployAzureContainerRegistryResourceCore(CancellationToken ca
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ private async Task DeployAzureEventHubsResourceCore(CancellationToken cancellati
{
// First, handle integration selection prompt
sequenceBuilder
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter() // Select first integration (azure-appcontainers)
// Then, handle version selection prompt
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version (PR build)
}

Expand All @@ -144,7 +144,7 @@ private async Task DeployAzureEventHubsResourceCore(CancellationToken cancellati
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ private async Task DeployAzureKeyVaultResourceCore(CancellationToken cancellatio
{
// First, handle integration selection prompt
sequenceBuilder
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter() // Select first integration (azure-appcontainers)
// Then, handle version selection prompt
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version (PR build)
}

Expand All @@ -144,7 +144,7 @@ private async Task DeployAzureKeyVaultResourceCore(CancellationToken cancellatio
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private async Task DeployAzureLogAnalyticsResourceCore(CancellationToken cancell
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ private async Task DeployAzureServiceBusResourceCore(CancellationToken cancellat
{
// First, handle integration selection prompt
sequenceBuilder
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter() // Select first integration (azure-appcontainers)
// Then, handle version selection prompt
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version (PR build)
}

Expand All @@ -144,7 +144,7 @@ private async Task DeployAzureServiceBusResourceCore(CancellationToken cancellat
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,10 @@ private async Task DeployAzureStorageResourceCore(CancellationToken cancellation
{
// First, handle integration selection prompt
sequenceBuilder
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForIntegrationSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter() // Select first integration (azure-appcontainers)
// Then, handle version selection prompt
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version (PR build)
}

Expand All @@ -144,7 +144,7 @@ private async Task DeployAzureStorageResourceCore(CancellationToken cancellation
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // Select first version
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ private async Task DeployPythonFastApiTemplateToAzureContainerAppsCore(Cancellat
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter(); // select first version (PR build)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ private async Task DeployStarterTemplateWithKeyVaultPrivateEndpointCore(Cancella
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand All @@ -157,7 +157,7 @@ private async Task DeployStarterTemplateWithKeyVaultPrivateEndpointCore(Cancella
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand All @@ -171,7 +171,7 @@ private async Task DeployStarterTemplateWithKeyVaultPrivateEndpointCore(Cancella
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForAddVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ private async Task DeployVnetKeyVaultInfrastructureCore(CancellationToken cancel
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand All @@ -122,7 +122,7 @@ private async Task DeployVnetKeyVaultInfrastructureCore(CancellationToken cancel
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand All @@ -136,7 +136,7 @@ private async Task DeployVnetKeyVaultInfrastructureCore(CancellationToken cancel
if (DeploymentE2ETestHelpers.IsRunningInCI)
{
sequenceBuilder
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(60))
.WaitUntil(s => waitingForVersionSelectionPrompt.Search(s).Count > 0, TimeSpan.FromSeconds(180))
.Enter();
}

Expand Down
Loading
Loading