Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<UsePublicApiAnalyzers>true</UsePublicApiAnalyzers>
<EnableAspireHostingAnalyzers>true</EnableAspireHostingAnalyzers>
<!-- Redirect test logs into a subfolder -->
<TestResultsLogDir>$([MSBuild]::NormalizeDirectory('$(ArtifactsLogDir)', 'TestLogs'))</TestResultsLogDir>
<!-- We don't want to use the workload for AppHost projects in this repo -->
Expand Down
2 changes: 1 addition & 1 deletion playground/Directory.Build.targets
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<ProjectReference Include="$(RepoRoot)src\Aspire.Dashboard\Aspire.Dashboard.csproj" />
</ItemGroup>

<ItemGroup Condition="'$(IsAspireHost)' == 'true' and '$(RepoRoot)' != '' and '$(SkipAspireHostingAnalyzersReference)' != 'true'">
<ItemGroup Condition="'$(IsAspireHost)' == 'true' and '$(RepoRoot)' != '' and '$(EnableAspireHostingAnalyzers)' == 'true' and '$(SkipAspireHostingAnalyzersReference)' != 'true'">
<ProjectReference Include="$(MSBuildThisFileDirectory)..\src\Aspire.Hosting.Analyzers\Aspire.Hosting.Analyzers.csproj" IsAspireProjectResource="false"
PrivateAssets="all"
ReferenceOutputAssembly="false"
Expand Down
2 changes: 1 addition & 1 deletion src/Aspire.Hosting.AppHost/Aspire.Hosting.AppHost.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
<Error Condition="'$(AspireHostingAnalyzerFile)' == ''" Text="Could not find Aspire.Hosting.Analyzers.dll." />

<ItemGroup>
<None Include="$(AspireHostingAnalyzerFile)" Pack="True" PackagePath="analyzers/dotnet/cs" />
<None Include="$(AspireHostingAnalyzerFile)" Pack="True" PackagePath="build\" />
</ItemGroup>
</Target>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
<PropertyGroup>
<!-- Similar to ASP.NET Core and Worker apps, set the default CWD of orchestrator projects to be the project directory. -->
<RunWorkingDirectory Condition=" '$(RunWorkingDirectory)' == '' and '$(EnableDefaultRunWorkingDirectory)' != 'false' ">$(MSBuildProjectDirectory)</RunWorkingDirectory>
<EnableAspireHostingAnalyzers Condition="'$(EnableAspireHostingAnalyzers)' == ''">false</EnableAspireHostingAnalyzers>
Comment thread
eerhardt marked this conversation as resolved.
Outdated
<AspireGeneratedClassesVisibility Condition="'$(AspireGeneratedClassesVisibility)' == ''">public</AspireGeneratedClassesVisibility>
<_AspireIntermediatePath>$(IntermediateOutputPath)Aspire\</_AspireIntermediatePath>
<_GeneratedClassNameFixupRegex>(((?&lt;=\.)|^)(?=\d)|\W)</_GeneratedClassNameFixupRegex>
Expand All @@ -11,6 +12,7 @@
<_AspireTasksTfm Condition="'$(MSBuildRuntimeType)' == 'Core'">net8.0</_AspireTasksTfm>
<_AspireTasksTfm Condition="'$(MSBuildRuntimeType)' != 'Core'">net472</_AspireTasksTfm>
<_AspireTasksAssembly Condition="'$(_AspireTasksAssembly)' == ''">$(MSBuildThisFileDirectory)..\tools\$(_AspireTasksTfm)\Aspire.Hosting.Tasks.dll</_AspireTasksAssembly>
<_AspireHostingAnalyzerAssembly Condition="'$(_AspireHostingAnalyzerAssembly)' == ''">$(MSBuildThisFileDirectory)Aspire.Hosting.Analyzers.dll</_AspireHostingAnalyzerAssembly>
</PropertyGroup>

<!-- Use TaskHostFactory when running in the repo so the Aspire.Hosting.Tasks.dll assembly is not locked. -->
Expand All @@ -22,6 +24,10 @@
<ProjectCapability Include="Aspire_@VERSION@" Condition=" '$(IsAspireHost)' == 'true' " />
</ItemGroup>

<ItemGroup Condition="'$(IsAspireHost)' == 'true' and '$(EnableAspireHostingAnalyzers)' == 'true'">
<Analyzer Include="$(_AspireHostingAnalyzerAssembly)" Condition="Exists('$(_AspireHostingAnalyzerAssembly)')" />
</ItemGroup>

<ItemGroup>
<JsonSchemaSegment Include="$(MSBuildThisFileDirectory)..\AspireAppHostConfiguration.json"
FilePathPattern="appsettings\..*json" />
Expand Down
207 changes: 206 additions & 1 deletion tests/Aspire.Hosting.Tests/MSBuildTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,12 @@ await Verify(new
});
}

private static void CreateDirectoryBuildFiles(string basePath, string repoRoot)
private static void CreateDirectoryBuildFiles(
string basePath,
string repoRoot,
bool enableAspireHostingAnalyzers = false,
bool useAnalyzerProjectReference = false,
string? analyzerAssemblyPath = null)
{
#if DEBUG
var config = "Debug";
Expand All @@ -151,7 +156,9 @@ private static void CreateDirectoryBuildFiles(string basePath, string repoRoot)
$"""
<Project>
<PropertyGroup>
<RepoRoot>{repoRoot}\</RepoRoot>
<SkipAspireWorkloadManifest>true</SkipAspireWorkloadManifest>
<EnableAspireHostingAnalyzers>{enableAspireHostingAnalyzers.ToString().ToLowerInvariant()}</EnableAspireHostingAnalyzers>
</PropertyGroup>

<Import Project="{repoRoot}\src\Aspire.Hosting.AppHost\build\Aspire.Hosting.AppHost.props" />
Expand All @@ -162,8 +169,18 @@ private static void CreateDirectoryBuildFiles(string basePath, string repoRoot)
<Project>
<PropertyGroup>
<_AspireTasksAssembly>{repoRoot}\artifacts\bin\Aspire.Hosting.Tasks\{config}\net8.0\Aspire.Hosting.Tasks.dll</_AspireTasksAssembly>
<_AspireHostingAnalyzerAssembly Condition="'$(EnableAspireHostingAnalyzers)' == 'true' and '{analyzerAssemblyPath}' != ''">{analyzerAssemblyPath}</_AspireHostingAnalyzerAssembly>
</PropertyGroup>

<ItemGroup Condition="'$(EnableAspireHostingAnalyzers)' == 'true' and '{useAnalyzerProjectReference.ToString().ToLowerInvariant()}' == 'true'">
<ProjectReference Include="{repoRoot}\src\Aspire.Hosting.Analyzers\Aspire.Hosting.Analyzers.csproj"
IsAspireProjectResource="false"
PrivateAssets="all"
ReferenceOutputAssembly="false"
OutputItemType="Analyzer"
SetTargetFramework="TargetFramework=netstandard2.0" />
</ItemGroup>

<Import Project="{repoRoot}\src\Aspire.Hosting.AppHost\build\Aspire.Hosting.AppHost.in.targets" />
<Import Project="{repoRoot}\src\Aspire.AppHost.Sdk\SDK\Sdk.in.targets" />
</Project>
Expand Down Expand Up @@ -372,6 +389,194 @@ the Aspire.AppHost.SDK targets that will automatically add these references to p
Assert.Contains("warning ASPIRE004", output);
}

[Fact]
public void AspireHostingAnalyzersAreDisabledByDefault()

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Is this enough or do we want a true nuget-based test?

{
var repoRoot = MSBuildUtils.GetRepoRoot();
using var tempDirectory = new TestTempDirectory();

var appHostDirectory = Path.Combine(tempDirectory.Path, "AppHost");
Directory.CreateDirectory(appHostDirectory);

File.WriteAllText(Path.Combine(appHostDirectory, "AppHost.csproj"),
$"""
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>

<!--
Test applications have their own way of referencing Aspire.Hosting.AppHost, as well as DCP and Dashboard, so we disable
the Aspire.AppHost.SDK targets that will automatically add these references to projects.
-->
<SkipAddAspireDefaultReferences Condition="'$(TestsRunningOutsideOfRepo)' != 'true'">true</SkipAddAspireDefaultReferences>
<AspireHostingSDKVersion>9.0.0</AspireHostingSDKVersion>
<_AspireUseTaskHostFactory>true</_AspireUseTaskHostFactory>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="{repoRoot}\src\Aspire.Hosting.AppHost\Aspire.Hosting.AppHost.csproj" IsAspireProjectResource="false" />
</ItemGroup>

</Project>
""");

File.WriteAllText(Path.Combine(appHostDirectory, "AppHost.cs"),
"""
using Aspire.Hosting;

var builder = DistributedApplication.CreateBuilder(args);
builder.AddCustomResource();
builder.Build().Run();

public static class CustomResourceExtensions
{
public static IDistributedApplicationBuilder AddCustomResource(this IDistributedApplicationBuilder builder)
{
return builder;
}
}
""");

CreateDirectoryBuildFiles(appHostDirectory, repoRoot);

var output = BuildProject(appHostDirectory);

Assert.DoesNotContain("warning ASPIRE014", output);
}

[Fact]
public void AspireHostingAnalyzersCanBeEnabledWithMsBuildProperty()
{
var repoRoot = MSBuildUtils.GetRepoRoot();
using var tempDirectory = new TestTempDirectory();

var appHostDirectory = Path.Combine(tempDirectory.Path, "AppHost");
Directory.CreateDirectory(appHostDirectory);

File.WriteAllText(Path.Combine(appHostDirectory, "AppHost.csproj"),
$"""
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>

<!--
Test applications have their own way of referencing Aspire.Hosting.AppHost, as well as DCP and Dashboard, so we disable
the Aspire.AppHost.SDK targets that will automatically add these references to projects.
-->
<SkipAddAspireDefaultReferences Condition="'$(TestsRunningOutsideOfRepo)' != 'true'">true</SkipAddAspireDefaultReferences>
<AspireHostingSDKVersion>9.0.0</AspireHostingSDKVersion>
<_AspireUseTaskHostFactory>true</_AspireUseTaskHostFactory>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="{repoRoot}\src\Aspire.Hosting.AppHost\Aspire.Hosting.AppHost.csproj" IsAspireProjectResource="false" />
</ItemGroup>

</Project>
""");

File.WriteAllText(Path.Combine(appHostDirectory, "AppHost.cs"),
"""
using Aspire.Hosting;

var builder = DistributedApplication.CreateBuilder(args);
builder.AddCustomResource();
builder.Build().Run();

public static class CustomResourceExtensions
{
public static IDistributedApplicationBuilder AddCustomResource(this IDistributedApplicationBuilder builder)
{
return builder;
}
}
""");

CreateDirectoryBuildFiles(appHostDirectory, repoRoot, enableAspireHostingAnalyzers: true, useAnalyzerProjectReference: true);

var output = BuildProject(appHostDirectory);

Assert.Contains("warning ASPIRE014", output);
}

[Fact]
public void AspireHostingAnalyzersCanBeEnabledWhenRepoRootIsSet()
{
var repoRoot = MSBuildUtils.GetRepoRoot();
using var tempDirectory = new TestTempDirectory();

#if DEBUG
var config = "Debug";
#else
var config = "Release";
#endif

var appHostDirectory = Path.Combine(tempDirectory.Path, "AppHost");
Directory.CreateDirectory(appHostDirectory);

File.WriteAllText(Path.Combine(appHostDirectory, "AppHost.csproj"),
$"""
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsAspireHost>true</IsAspireHost>

<!--
Test applications have their own way of referencing Aspire.Hosting.AppHost, as well as DCP and Dashboard, so we disable
the Aspire.AppHost.SDK targets that will automatically add these references to projects.
-->
<SkipAddAspireDefaultReferences Condition="'$(TestsRunningOutsideOfRepo)' != 'true'">true</SkipAddAspireDefaultReferences>
<AspireHostingSDKVersion>9.0.0</AspireHostingSDKVersion>
<_AspireUseTaskHostFactory>true</_AspireUseTaskHostFactory>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="{repoRoot}\src\Aspire.Hosting.AppHost\Aspire.Hosting.AppHost.csproj" IsAspireProjectResource="false" />
</ItemGroup>

</Project>
""");

File.WriteAllText(Path.Combine(appHostDirectory, "AppHost.cs"),
"""
using Aspire.Hosting;

var builder = DistributedApplication.CreateBuilder(args);
builder.AddCustomResource();
builder.Build().Run();

public static class CustomResourceExtensions
{
public static IDistributedApplicationBuilder AddCustomResource(this IDistributedApplicationBuilder builder)
{
return builder;
}
}
""");

var analyzerAssemblyPath = Path.Combine(repoRoot, "artifacts", "bin", "Aspire.Hosting.Analyzers", config, "netstandard2.0", "Aspire.Hosting.Analyzers.dll");

CreateDirectoryBuildFiles(appHostDirectory, repoRoot, enableAspireHostingAnalyzers: true, analyzerAssemblyPath: analyzerAssemblyPath);

var output = BuildProject(appHostDirectory);

Assert.Contains("warning ASPIRE014", output);
}

/// <summary>
/// Tests that when GenerateAssemblyInfo is set to false, a build error is emitted.
/// </summary>
Expand Down