Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit ed4c375
Merge: e676955 20d00e1
Author: Ankit Jain <radical@gmail.com>
Date:   Tue Aug 13 00:50:09 2024 -0400

    Merge remote-tracking branch 'origin/main' into re-enable-playground-tests

commit 20d00e1
Author: Ankit Jain <radical@gmail.com>
Date:   Tue Aug 13 00:49:21 2024 -0400

    [tests] Try to fix random failures on playground tests build (dotnet#5271)

    * [tests] Try to fix random failures on playground tests build

    `Aspire.Playground.Tests` build failed sometimes with errors like:

    `Could not copy "D:\a\_work\1\s\artifacts\obj\CatalogModel\Release\net8.0\CatalogModel.dll" to "D:\a\_work\1\s\artifacts\bin\CatalogModel\Release\net8.0\CatalogModel.dll". Beginning retry 1 in 1000ms. The process cannot access the file 'D:\a\_work\1\s\artifacts\bin\CatalogModel\Release\net8.0\CatalogModel.dll' because it is being used by another process. The file is locked by: "Pdb2Pdb (1628)"`

    The errors are not limited to this file, but can be one from any of the
    playground projects.

    Given:

    1. `Aspire.Playgroud.Tests` references various playground AppHost projects
       directly with `AdditionalProperties="SkipDashboardProjectReference=true"`.
    2. `Aspire.sln` also references these playground projects.

    My thinking is that msbuild ends up treating these projects like
    `TestShop/CatalogModel/CatalogModel.csproj` as two different project
    instances:

    1. One with `SkipDashboardProjectReference=true` (from
       `Aspire.Playground.Tests`)
    2. One without that property, when building the reference directly from
       `Aspire.sln`.

    This patch avoids that entirely by defaulting to
    `SkipDashboardProjectReference=true` on CI, and on helix.

    * Skip dashboard references

    * fix build

commit e676955
Author: Ankit Jain <radical@gmail.com>
Date:   Mon Aug 12 23:33:26 2024 -0400

    [tests] Re-enable playground tests

    .. and don't set `SkipDashboardProjectReference=true` (see
    dotnet#5271).

commit e0e23d3
Author: Ankit Jain <radical@gmail.com>
Date:   Tue Aug 13 00:21:37 2024 -0400

    [ci] Avoid duplicating trx file on helix, and copy it for playground tests also (dotnet#5253)

commit c3fbc5b
Author: Ankit Jain <radical@gmail.com>
Date:   Mon Aug 12 23:31:22 2024 -0400

    Squashed commit of the following:

    commit b24e087
    Merge: ee90475 4f1a352
    Author: Ankit Jain <radical@gmail.com>
    Date:   Mon Aug 12 23:11:22 2024 -0400

        Merge remote-tracking branch 'origin/main' into fix-playground-tests-build

        # Conflicts:
        #	tests/Aspire.Playground.Tests/Aspire.Playground.Tests.csproj

    commit ee90475
    Author: Ankit Jain <radical@gmail.com>
    Date:   Mon Aug 12 18:02:05 2024 -0400

        fix build

    commit e10b215
    Author: Ankit Jain <radical@gmail.com>
    Date:   Mon Aug 12 17:45:36 2024 -0400

        Skip dashboard references

    commit cf31acc
    Author: Ankit Jain <radical@gmail.com>
    Date:   Mon Aug 12 17:02:56 2024 -0400

        [tests] Try to fix random failures on playground tests build

        `Aspire.Playground.Tests` build failed sometimes with errors like:

        `Could not copy "D:\a\_work\1\s\artifacts\obj\CatalogModel\Release\net8.0\CatalogModel.dll" to "D:\a\_work\1\s\artifacts\bin\CatalogModel\Release\net8.0\CatalogModel.dll". Beginning retry 1 in 1000ms. The process cannot access the file 'D:\a\_work\1\s\artifacts\bin\CatalogModel\Release\net8.0\CatalogModel.dll' because it is being used by another process. The file is locked by: "Pdb2Pdb (1628)"`

        The errors are not limited to this file, but can be one from any of the
        playground projects.

        Given:

        1. `Aspire.Playgroud.Tests` references various playground AppHost projects
           directly with `AdditionalProperties="SkipDashboardProjectReference=true"`.
        2. `Aspire.sln` also references these playground projects.

        My thinking is that msbuild ends up treating these projects like
        `TestShop/CatalogModel/CatalogModel.csproj` as two different project
        instances:

        1. One with `SkipDashboardProjectReference=true` (from
           `Aspire.Playground.Tests`)
        2. One without that property, when building the reference directly from
           `Aspire.sln`.

        This patch avoids that entirely by defaulting to
        `SkipDashboardProjectReference=true` on CI, and on helix.

commit 42cc82d
Author: Sébastien Ros <sebastienros@gmail.com>
Date:   Mon Aug 12 20:24:22 2024 -0700

    Improve reliability of `AppHostTests.TestEndpointsReturnOk` (dotnet#5251)

    Use `WaitForText` since some services are really slow to start (CosmosDB emulator takes 45s locally).
    Use predicates in LoggerNotificationService since some texts are more complex than just `Contains`. For instance CosmonDBEmulator uses `Started` as the log when it's ready, but it also uses it many other times in the middle of some lines. Another example us MySql which starts the server twice (temp server).

    Disabling mongo tests - dotnet#5274

    * Improve reliability of `AppHostTests.TestEndpointsReturnOk`

    * Fix up usings

    * fix Aspire.Playground.Tests build

    * Format TestEndpoints

    * Remove unnecessary line

    * fix build

    * Improve mysql test reliability

    * Increase host startup timeout

    * Disable mongo app in playground tests - dotnet#5274

    ---------

    Co-authored-by: Eric Erhardt <eric.erhardt@microsoft.com>
    Co-authored-by: Ankit Jain <radical@gmail.com>

commit 990d6d0
Author: Ankit Jain <radical@gmail.com>
Date:   Mon Aug 12 23:12:54 2024 -0400

    playground.BrowserTelemetry: avoid using npm on ci/windows (dotnet#5269)

commit 4f1a352
Author: Ankit Jain <radical@gmail.com>
Date:   Mon Aug 12 22:38:17 2024 -0400

    [ci] Disable failing Aspire.Playground.Tests (dotnet#5273)

    * [ci] Disable failing Aspire.Playground.Tests

    There are two failures hitting CI right now:

    1. `Could not copy "D:\a\_work\1\s\artifacts\obj\CatalogModel\Release\net8.0\CatalogModel.dll" to "D:\a\_work\1\s\artifacts\bin\CatalogModel\Release\net8.0\CatalogModel.dll". Beginning retry 1 in 1000ms. The process cannot access the file 'D:\a\_work\1\s\artifacts\bin\CatalogModel\Release\net8.0\CatalogModel.dll' because it is being used by another process. The file is locked by: "Pdb2Pdb (1628)"`

        - Exceptions like this when building playground apps.
        - Waiting on dotnet#5271 which might
          be a fix.

    2. Individual playground tests failing
        - Waiting on dotnet#5251

    This PR disable the tests completely to get the CI in a better state,
    and can be re-enabled once the aforementioned issues are fixed.

# Conflicts:
#	tests/Aspire.Playground.Tests/Aspire.Playground.Tests.csproj
  • Loading branch information
radical committed Aug 13, 2024
1 parent a16cced commit 015ec3e
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 79 deletions.
9 changes: 6 additions & 3 deletions playground/AzureSearchEndToEnd/AzureSearch.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
.WithExternalHttpEndpoints()
.WithReference(azureSearch);

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

builder.Build().Run();
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,14 @@
builder.AddProject<Projects.BrowserTelemetry_Web>("web")
.WithExternalHttpEndpoints();

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

builder.Build().Run();
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<!-- Issue: https://github.com/dotnet/dnceng/issues/3091 -->
<NpmUnavailable Condition="'$(ContinuousIntegrationBuild)' == 'true' and '$(OS)' == 'Windows_NT'">true</NpmUnavailable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\Playground.ServiceDefaults\Playground.ServiceDefaults.csproj" />
</ItemGroup>

<Target Name="NpmInstall" Inputs="package.json" Outputs="node_modules/.install-stamp">
<Target Name="NpmInstall" Inputs="package.json" Outputs="node_modules/.install-stamp" Condition="'$(NpmUnavailable)' != 'true'">
<!--
Use npm install or npm ci depending on RestorePackagesWithLockFile value.
Uncomment the following lines if you want to use this feature:
Expand All @@ -30,7 +32,7 @@
2. Run npm run build before building the .NET project.
MSBuild runs NpmInstall before this task because of the DependsOnTargets attribute.
-->
<Target Name="NpmRunBuild" DependsOnTargets="NpmInstall" BeforeTargets="BeforeBuild" Condition="'$(Configuration)' == 'Debug' ">
<Target Name="NpmRunBuild" DependsOnTargets="NpmInstall" BeforeTargets="BeforeBuild" Condition="'$(Configuration)' == 'Debug' and '$(NpmUnavailable)' != 'true' ">
<Exec Command="npm run build" />
</Target>

Expand Down
6 changes: 6 additions & 0 deletions playground/Directory.Build.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
<Project>
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.targets', '$(MSBuildThisFileDirectory)../'))" />

<PropertyGroup>
<!-- Skip dashboard when building outside the repo, like on helix. Or when
building on CI -->
<SkipDashboardProjectReference Condition="'$(SkipDashboardProjectReference)' == '' and ('$(RepoRoot)' == '' or '$(ContinuousIntegrationBuild)' == 'true')">true</SkipDashboardProjectReference>
</PropertyGroup>

<ItemGroup Condition="'$(IsAspireHost)' == 'true' and '$(SkipDashboardProjectReference)' != 'true'">
<ProjectReference Include="$(RepoRoot)src\Aspire.Dashboard\Aspire.Dashboard.csproj" />
</ItemGroup>
Expand Down
9 changes: 6 additions & 3 deletions playground/OpenAIEndToEnd/OpenAIEndToEnd.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,14 @@
.WithReference(openai)
.WithEnvironment("OpenAI__DeploymentName", deploymentAndModelName);

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

builder.Build().Run();
9 changes: 6 additions & 3 deletions playground/OracleEndToEnd/OracleEndToEnd.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,14 @@
builder.AddProject<Projects.OracleEndToEnd_ApiService>("api")
.WithReference(pdb);

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

builder.Build().Run();
9 changes: 6 additions & 3 deletions playground/bicep/BicepSample.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,14 @@
.WithEnvironment("bicepValue0", bicep1.GetOutput("val0"))
.WithEnvironment("bicepValue1", bicep1.GetOutput("val1"));

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

builder.Build().Run();
9 changes: 6 additions & 3 deletions playground/cdk/CdkSample.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,14 @@
.WithReference(search)
.WithReference(appInsights);

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

builder.Build().Run();
9 changes: 6 additions & 3 deletions playground/dapr/Dapr.AppHost/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@
.WithDaprSidecar()
.WithReference(pubSub);

#if !SKIP_DASHBOARD_REFERENCE
// This project is only added in playground projects to support development/debugging
// of the dashboard. It is not required in end developer code. Comment out this code
// to test end developer dashboard launch experience. Refer to Directory.Build.props
// for the path to the dashboard binary (defaults to the Aspire.Dashboard bin output
// in the artifacts dir).
// or build with `/p:SkipDashboardReference=true`, to test end developer
// dashboard launch experience, Refer to Directory.Build.props for the path to
// the dashboard binary (defaults to the Aspire.Dashboard bin output in the
// artifacts dir).
builder.AddProject<Projects.Aspire_Dashboard>(KnownResourceNames.AspireDashboard);
#endif

using var app = builder.Build();

Expand Down
14 changes: 14 additions & 0 deletions tests/Aspire.Hosting.MySql.Tests/MySqlFunctionalTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Data;
using Aspire.Components.Common.Tests;
using Aspire.Hosting.Tests.Utils;
using Aspire.Hosting.Utils;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
Expand All @@ -19,6 +20,8 @@ namespace Aspire.Hosting.MySql.Tests;

public class MySqlFunctionalTests(ITestOutputHelper testOutputHelper)
{
private static readonly Predicate<string> s_mySqlReadyText = log => log.Contains("ready for connections") && log.Contains("port: 3306");

[Fact]
[RequiresDocker]
public async Task VerifyMySqlResource()
Expand All @@ -39,6 +42,8 @@ public async Task VerifyMySqlResource()

await app.StartAsync();

await app.WaitForTextAsync(s_mySqlReadyText).WaitAsync(TimeSpan.FromMinutes(2));

var hb = Host.CreateApplicationBuilder();

hb.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
Expand Down Expand Up @@ -108,6 +113,8 @@ public async Task WithDataShouldPersistStateBetweenUsages(bool useVolume)
{
await app.StartAsync();

await app.WaitForTextAsync(s_mySqlReadyText).WaitAsync(TimeSpan.FromMinutes(2));

try
{
var hb = Host.CreateApplicationBuilder();
Expand Down Expand Up @@ -175,6 +182,9 @@ await pipeline.ExecuteAsync(async token =>
using (var app = builder2.Build())
{
await app.StartAsync();

await app.WaitForTextAsync(s_mySqlReadyText).WaitAsync(TimeSpan.FromMinutes(2));

try
{
var hb = Host.CreateApplicationBuilder();
Expand Down Expand Up @@ -281,6 +291,8 @@ public async Task VerifyWithInitBindMount()

await app.StartAsync();

await app.WaitForTextAsync(s_mySqlReadyText).WaitAsync(TimeSpan.FromMinutes(2));

var hb = Host.CreateApplicationBuilder();

hb.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
Expand Down Expand Up @@ -349,6 +361,8 @@ public async Task VerifyEfMySql()

await app.StartAsync();

await app.WaitForTextAsync(s_mySqlReadyText).WaitAsync(TimeSpan.FromMinutes(2));

var hb = Host.CreateApplicationBuilder();

hb.Configuration.AddInMemoryCollection(new Dictionary<string, string?>
Expand Down
42 changes: 29 additions & 13 deletions tests/Aspire.Hosting.Tests/Utils/LoggerNotificationExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

#pragma warning disable IDE0005 // Using directive is unnecessary. This using is required when building this file in Aspire.Playground.Tests.csproj.
using Aspire.Hosting.ApplicationModel;
#pragma warning restore IDE0005 // Using directive is unnecessary.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
Expand All @@ -22,7 +25,7 @@ public static Task WaitForTextAsync(this DistributedApplication app, string logT
ArgumentNullException.ThrowIfNull(app);
ArgumentException.ThrowIfNullOrEmpty(logText);

return WaitForTextAsync(app, [logText], resourceName, cancellationToken);
return WaitForTextAsync(app, (log) => log.Contains(logText), resourceName, cancellationToken);
}

/// <summary>
Expand All @@ -38,18 +41,34 @@ public static Task WaitForTextAsync(this DistributedApplication app, IEnumerable
ArgumentNullException.ThrowIfNull(app);
ArgumentNullException.ThrowIfNull(logTexts);

return app.WaitForTextAsync((log) => logTexts.Any(x => log.Contains(x)), resourceName, cancellationToken);
}

/// <summary>
/// Waits for the specified text to be logged.
/// </summary>
/// <param name="app">The <see cref="DistributedApplication" /> instance to watch.</param>
/// <param name="predicate">A predicate checking the text to wait for.</param>
/// <param name="resourceName">An optional resource name to filter the logs for.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns></returns>
public static Task WaitForTextAsync(this DistributedApplication app, Predicate<string> predicate, string? resourceName = null, CancellationToken cancellationToken = default)
{
ArgumentNullException.ThrowIfNull(app);
ArgumentNullException.ThrowIfNull(predicate);

var hostApplicationLifetime = app.Services.GetRequiredService<IHostApplicationLifetime>();

var watchCts = CancellationTokenSource.CreateLinkedTokenSource(hostApplicationLifetime.ApplicationStopping, cancellationToken);

var tcs = new TaskCompletionSource();

_ = Task.Run(() => WatchNotifications(app, resourceName, logTexts, tcs, watchCts), watchCts.Token);
_ = Task.Run(() => WatchNotifications(app, resourceName, predicate, tcs, watchCts), watchCts.Token);

return tcs.Task;
}

private static async Task WatchNotifications(DistributedApplication app, string? resourceName, IEnumerable<string> logTexts, TaskCompletionSource tcs, CancellationTokenSource cancellationTokenSource)
private static async Task WatchNotifications(DistributedApplication app, string? resourceName, Predicate<string> predicate, TaskCompletionSource tcs, CancellationTokenSource cancellationTokenSource)
{
var resourceNotificationService = app.Services.GetRequiredService<ResourceNotificationService>();
var resourceLoggerService = app.Services.GetRequiredService<ResourceLoggerService>();
Expand All @@ -62,7 +81,7 @@ private static async Task WatchNotifications(DistributedApplication app, string?
{
await foreach (var resourceEvent in resourceNotificationService.WatchAsync(cancellationTokenSource.Token).ConfigureAwait(false))
{
if (resourceName != null && !string.Equals(resourceEvent.Resource.Name, resourceName, StringComparisons.ResourceName))
if (resourceName != null && !string.Equals(resourceEvent.Resource.Name, resourceName, StringComparison.OrdinalIgnoreCase))
{
continue;
}
Expand All @@ -72,7 +91,7 @@ private static async Task WatchNotifications(DistributedApplication app, string?
if (loggingResourceIds.Add(resourceId))
{
// Start watching the logs for this resource ID
logWatchTasks.Add(WatchResourceLogs(tcs, resourceId, logTexts, resourceLoggerService, cancellationTokenSource));
logWatchTasks.Add(WatchResourceLogs(tcs, resourceId, predicate, resourceLoggerService, cancellationTokenSource));
}
}
}
Expand All @@ -86,20 +105,17 @@ private static async Task WatchNotifications(DistributedApplication app, string?
}
}

private static async Task WatchResourceLogs(TaskCompletionSource tcs, string resourceId, IEnumerable<string> logTexts, ResourceLoggerService resourceLoggerService, CancellationTokenSource cancellationTokenSource)
private static async Task WatchResourceLogs(TaskCompletionSource tcs, string resourceId, Predicate<string> predicate, ResourceLoggerService resourceLoggerService, CancellationTokenSource cancellationTokenSource)
{
await foreach (var logEvent in resourceLoggerService.WatchAsync(resourceId).WithCancellation(cancellationTokenSource.Token).ConfigureAwait(false))
{
foreach (var line in logEvent)
{
foreach (var log in logTexts)
if (predicate(line.Content))
{
if (line.Content.Contains(log))
{
tcs.SetResult();
cancellationTokenSource.Cancel();
return;
}
tcs.SetResult();
cancellationTokenSource.Cancel();
return;
}
}
}
Expand Down
Loading

0 comments on commit 015ec3e

Please sign in to comment.