Skip to content

Commit dc1eeaa

Browse files
authored
Fix RID regression by adding a task that calculates the best matching RID for platform (#5695)
* Fix RID regression by adding a task that calculates the best matching RID for each platform. * Use out-of-proc instead of MSBuild task * Do not show the output of running the tool as 'High' importance * PR Feedback * PR Feedback * Fix package authoring
1 parent a5b3bcf commit dc1eeaa

File tree

13 files changed

+310
-10
lines changed

13 files changed

+310
-10
lines changed

Aspire.sln

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -618,6 +618,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Redis.ApiService", "playgro
618618
EndProject
619619
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Redis.AppHost", "playground\Redis\Redis.AppHost\Redis.AppHost.csproj", "{6249A193-3BF4-4FFB-AB81-6590A8318889}"
620620
EndProject
621+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.Hosting.Sdk.Tests", "tests\Aspire.Hosting.Sdk.Tests\Aspire.Hosting.Sdk.Tests.csproj", "{AEF07BC6-76D8-4A45-89D5-54FC4483863F}"
622+
EndProject
623+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Aspire.RuntimeIdentifier.Tool", "src\Aspire.Hosting.Sdk\Aspire.RuntimeIdentifier.Tool\Aspire.RuntimeIdentifier.Tool.csproj", "{FF2895FC-A613-43DC-96B8-E5DFA69125CA}"
624+
EndProject
621625
Global
622626
GlobalSection(SolutionConfigurationPlatforms) = preSolution
623627
Debug|Any CPU = Debug|Any CPU
@@ -1624,6 +1628,14 @@ Global
16241628
{6249A193-3BF4-4FFB-AB81-6590A8318889}.Debug|Any CPU.Build.0 = Debug|Any CPU
16251629
{6249A193-3BF4-4FFB-AB81-6590A8318889}.Release|Any CPU.ActiveCfg = Release|Any CPU
16261630
{6249A193-3BF4-4FFB-AB81-6590A8318889}.Release|Any CPU.Build.0 = Release|Any CPU
1631+
{AEF07BC6-76D8-4A45-89D5-54FC4483863F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1632+
{AEF07BC6-76D8-4A45-89D5-54FC4483863F}.Debug|Any CPU.Build.0 = Debug|Any CPU
1633+
{AEF07BC6-76D8-4A45-89D5-54FC4483863F}.Release|Any CPU.ActiveCfg = Release|Any CPU
1634+
{AEF07BC6-76D8-4A45-89D5-54FC4483863F}.Release|Any CPU.Build.0 = Release|Any CPU
1635+
{FF2895FC-A613-43DC-96B8-E5DFA69125CA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
1636+
{FF2895FC-A613-43DC-96B8-E5DFA69125CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
1637+
{FF2895FC-A613-43DC-96B8-E5DFA69125CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
1638+
{FF2895FC-A613-43DC-96B8-E5DFA69125CA}.Release|Any CPU.Build.0 = Release|Any CPU
16271639
EndGlobalSection
16281640
GlobalSection(SolutionProperties) = preSolution
16291641
HideSolutionNode = FALSE
@@ -1922,6 +1934,8 @@ Global
19221934
{874EA351-05EA-44F5-8B12-7A7F865ECEC5} = {D173887B-AF42-4576-B9C1-96B9E9B3D9C0}
19231935
{B4CB2D9D-D3F5-4BB1-A7C0-7A6F13316A78} = {874EA351-05EA-44F5-8B12-7A7F865ECEC5}
19241936
{6249A193-3BF4-4FFB-AB81-6590A8318889} = {874EA351-05EA-44F5-8B12-7A7F865ECEC5}
1937+
{AEF07BC6-76D8-4A45-89D5-54FC4483863F} = {4981B3A5-4AFD-4191-BF7D-8692D9783D60}
1938+
{FF2895FC-A613-43DC-96B8-E5DFA69125CA} = {F534D4F8-5E3A-42FC-BCD7-4C2D6060F9C8}
19251939
EndGlobalSection
19261940
GlobalSection(ExtensibilityGlobals) = postSolution
19271941
SolutionGuid = {6DCEDFEC-988E-4CB3-B45B-191EB5086E0C}

Directory.Packages.props

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
<PackageVersion Include="Microsoft.Extensions.Primitives" Version="$(MicrosoftExtensionsPrimitivesPackageVersion)" />
9999
<PackageVersion Include="Microsoft.Extensions.Http.Resilience" Version="$(MicrosoftExtensionsHttpResiliencePackageVersion)" />
100100
<PackageVersion Include="Microsoft.Extensions.TimeProvider.Testing" Version="$(MicrosoftExtensionsTimeProviderTestingVersion)" />
101+
<!-- NuGet dependencies -->
102+
<PackageVersion Include="NuGet.ProjectModel" Version="6.11.0" />
101103
<!-- external dependencies -->
102104
<PackageVersion Include="Confluent.Kafka" Version="2.5.3" />
103105
<PackageVersion Include="Dapper" Version="2.1.44" />

eng/dashboardpack/Common.projitems

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<PackageType />
1111
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
1212
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
13+
<EnableDefaultNoneItems>false</EnableDefaultNoneItems>
1314
<IncludeBuildOutput>false</IncludeBuildOutput>
1415
<PackageOutputPath Condition=" '$(PackageOutputPath)' == '' ">$(ArtifactsShippingPackagesDir)</PackageOutputPath>
1516
</PropertyGroup>
@@ -24,7 +25,7 @@
2425
</ItemGroup>
2526

2627
<ItemGroup>
27-
<None Include="build*/*.props;**/*.targets" Pack="true" PerformTextReplacement="true" PackagePath="%(RecursiveDir)$(AssemblyName)%(Extension)" />
28+
<None Include="build*/*.props;build*/*.targets" Pack="true" PerformTextReplacement="true" PackagePath="%(RecursiveDir)$(AssemblyName)%(Extension)" />
2829
</ItemGroup>
2930

3031
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.targets" />
@@ -56,8 +57,7 @@
5657

5758
<ItemGroup>
5859
<None Include="Sdk.props" Pack="true" PackagePath="build/$(AssemblyName).props" />
59-
<None Include="Sdk.in.targets" Pack="true" PerformTextReplacement="true"
60-
PackagePath="build/$(AssemblyName).targets" />
60+
<None Include="Sdk.targets" Pack="true" PackagePath="build/$(AssemblyName).targets" />
6161
<None Include="UnixFilePermissions.xml" Pack="true" PackagePath="data/"
6262
Condition=" '$(DashboardPlatformType)' == 'Unix' " />
6363
</ItemGroup>

eng/dashboardpack/Sdk.in.targets renamed to eng/dashboardpack/Sdk.targets

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@
22

33
<!-- *** BEGIN *** -->
44

5-
<PropertyGroup Condition="'$(NETCoreSdkRuntimeIdentifier)' == '@PlatformRuntime@'">
5+
<PropertyGroup>
66
<AspireDashboardDir Condition=" '$(AspireDashboardDir)' == '' ">$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), '..', 'tools'))</AspireDashboardDir>
77
<AspireDashboardDir>$([MSBuild]::EnsureTrailingSlash('$(AspireDashboardDir)'))</AspireDashboardDir>
88
<AspireDashboardPath Condition=" '$(AspireDashboardPath)' == '' ">$([MSBuild]::NormalizePath($(AspireDashboardDir), 'Aspire.Dashboard'))</AspireDashboardPath>
99
<AspireDashboardPath Condition=" '$(OS)' == 'Windows_NT' and !$(AspireDashboardPath.EndsWith('.exe')) ">$(AspireDashboardPath).exe</AspireDashboardPath>
1010
<AspireDashboardPath Condition="$([MSBuild]::IsOsPlatform('OSX')) and !$(AspireDashboardPath.EndsWith('.dll'))">$(AspireDashboardPath).dll</AspireDashboardPath>
1111
</PropertyGroup>
1212

13-
<ItemGroup Condition="'$(NETCoreSdkRuntimeIdentifier)' == '@PlatformRuntime@'">
13+
<ItemGroup>
1414
<ProjectCapability Include="AspireDashboard" />
1515
</ItemGroup>
1616

eng/dcppack/Aspire.Hosting.Orchestration.in.targets renamed to eng/dcppack/Aspire.Hosting.Orchestration.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<Project>
22

3-
<PropertyGroup Condition="'$(NETCoreSdkRuntimeIdentifier)' == '@PlatformRuntime@'">
3+
<PropertyGroup>
44
<DcpDir Condition=" '$(DcpDir)' == '' ">$([MSBuild]::NormalizeDirectory($(MSBuildThisFileDirectory), '..', 'tools'))</DcpDir>
55
<DcpDir>$([MSBuild]::EnsureTrailingSlash('$(DcpDir)'))</DcpDir>
66
<DcpExtensionsDir Condition=" '$(DcpExtensionsDir)' == '' ">$([MSBuild]::NormalizeDirectory($(DcpDir), 'ext'))</DcpExtensionsDir>

eng/dcppack/Common.projitems

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<SuppressDependenciesWhenPacking>true</SuppressDependenciesWhenPacking>
1212
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
1313
<IncludeBuildOutput>false</IncludeBuildOutput>
14+
<EnableDefaultNoneItems>false</EnableDefaultNoneItems>
1415
<PackageOutputPath Condition=" '$(PackageOutputPath)' == '' ">$(ArtifactsShippingPackagesDir)</PackageOutputPath>
1516
<TargetsForTfmSpecificContentInPackage>$(TargetsForTfmSpecificContentInPackage);AddPackageFiles</TargetsForTfmSpecificContentInPackage>
1617
</PropertyGroup>
@@ -30,7 +31,7 @@
3031
</ItemGroup>
3132

3233
<ItemGroup>
33-
<None Include="build*/*.props;**/*.targets" Pack="true" PerformTextReplacement="true" PackagePath="%(RecursiveDir)$(AssemblyName)%(Extension)" />
34+
<None Include="**/*.targets" Pack="true" PerformTextReplacement="true" PackagePath="%(RecursiveDir)$(AssemblyName)%(Extension)" />
3435
</ItemGroup>
3536

3637
<!-- Package downloads to DCP packages as we need to repack the binaries from them -->
@@ -75,7 +76,7 @@
7576
</Target>
7677

7778
<ItemGroup>
78-
<None Include="Aspire.Hosting.Orchestration.in.targets" PerformTextReplacement="True" pack="true" PackagePath="build/$(PackageId).targets" />
79+
<None Update="Aspire.Hosting.Orchestration.targets" PerformTextReplacement="" pack="true" PackagePath="build/$(PackageId).targets" />
7980
<None Include="UnixFilePermissions.xml" Pack="true" PackagePath="data/" Condition=" '$(DcpPlatformType)' == 'Unix' " />
8081
</ItemGroup>
8182

src/Aspire.Hosting.Sdk/Aspire.Hosting.Sdk.csproj

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,45 @@
55
<PropertyGroup>
66
<PackageTags>aspire hosting sdk</PackageTags>
77
<Description>.NET Aspire Hosting SDK. Enabled via &lt;IsAspireHost&gt;true&lt;/IsAspireHost&gt;.</Description>
8+
<TargetsForTfmSpecificContentInPackage>_PublishAndPackRIDTool;$(TargetsForTfmSpecificContentInPackage)</TargetsForTfmSpecificContentInPackage>
89
</PropertyGroup>
910

1011
<PropertyGroup>
1112
<MinCodeCoverage>100</MinCodeCoverage>
1213
</PropertyGroup>
1314

15+
<ItemGroup>
16+
<TextReplacementValue Include="DefaultTargetFramework" NewValue="$(DefaultTargetFramework)" />
17+
</ItemGroup>
18+
1419
<ItemGroup>
1520
<None Include="..\Aspire.Hosting\build\*.targets" Link="SDK\%(Filename)%(Extension)" Pack="true" PackagePath="Sdk\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
1621
<None Update="SDK\AutoImport.props;SDK\*.targets" Pack="true" PackagePath="Sdk\%(Filename)%(Extension)" CopyToOutputDirectory="PreserveNewest" />
1722
<None Update="SDK\Sdk.in.props" Pack="true" PerformTextReplacement="True" PackagePath="Sdk\Sdk.props" CopyToOutputDirectory="PreserveNewest" />
1823
<None Update="SDK\Sdk.in.targets" Pack="true" PerformTextReplacement="True" PackagePath="Sdk\Sdk.targets" />
24+
25+
<!-- Adding a project reference to the tool to avoid MSBuild having clashes when building this project before the other. -->
26+
<ProjectReference Include="Aspire.RuntimeIdentifier.Tool\Aspire.RuntimeIdentifier.Tool.csproj"
27+
ReferenceOutputAssembly="false"
28+
SkipTargetFrameworkProperties="true"
29+
ExcludeAssets="all"
30+
Private="false" />
1931
</ItemGroup>
2032

33+
<Target Name="_PublishAndPackRIDTool">
34+
<MSBuild Projects="$(MSBuildThisFileDirectory)Aspire.RuntimeIdentifier.Tool\Aspire.RuntimeIdentifier.Tool.csproj"
35+
Targets="Publish"
36+
Properties="Configuration=$(Configuration);Platform=$(Platform)" />
37+
38+
<ItemGroup>
39+
<_publishContentToPackage Include="$(DotNetOutputPath)Aspire.RuntimeIdentifier.Tool/$(Configuration)/$(DefaultTargetFramework)/publish/**/*" />
40+
</ItemGroup>
41+
42+
<ItemGroup>
43+
<TfmSpecificPackageFile Include="@(_publishContentToPackage)"
44+
PackagePath="tools/$(DefaultTargetFramework)/%(_publishContentToPackage.RecursiveDir)" />
45+
</ItemGroup>
46+
47+
</Target>
48+
2149
</Project>
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<OutputType>Exe</OutputType>
5+
<TargetFramework>$(DefaultTargetFramework)</TargetFramework>
6+
<RollForward>Major</RollForward>
7+
<UsePublicApiAnalyzers>false</UsePublicApiAnalyzers>
8+
<IsPackable>false</IsPackable>
9+
<UseAppHost>false</UseAppHost>
10+
</PropertyGroup>
11+
12+
<ItemGroup>
13+
<PackageReference Include="System.CommandLine" />
14+
<PackageReference Include="NuGet.ProjectModel" />
15+
</ItemGroup>
16+
17+
</Project>
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using NuGet.RuntimeModel;
5+
6+
namespace Aspire.Hosting.Sdk;
7+
8+
/*
9+
* These utility methods were copied from the sdk repository to mimic the behavior used when selecting the best matching RID
10+
* for a given runtime identifier. For more information, please see the original source code at:
11+
* https://github.com/dotnet/sdk/blob/e6da8ca6de3ec8f392dc87b8529415e1ef59b7ea/src/Tasks/Microsoft.NET.Build.Tasks/NuGetUtils.NuGet.cs#L76-L109
12+
*/
13+
14+
internal static class NuGetUtils
15+
{
16+
public static string? GetBestMatchingRid(RuntimeGraph runtimeGraph, string runtimeIdentifier,
17+
IEnumerable<string> availableRuntimeIdentifiers, out bool wasInGraph)
18+
{
19+
return GetBestMatchingRidWithExclusion(runtimeGraph, runtimeIdentifier,
20+
runtimeIdentifiersToExclude: null,
21+
availableRuntimeIdentifiers, out wasInGraph);
22+
}
23+
24+
public static string? GetBestMatchingRidWithExclusion(RuntimeGraph runtimeGraph, string runtimeIdentifier,
25+
IEnumerable<string>? runtimeIdentifiersToExclude,
26+
IEnumerable<string> availableRuntimeIdentifiers, out bool wasInGraph)
27+
{
28+
wasInGraph = runtimeGraph.Runtimes.ContainsKey(runtimeIdentifier);
29+
30+
string? bestMatch = null;
31+
32+
HashSet<string> availableRids = new(availableRuntimeIdentifiers, StringComparer.Ordinal);
33+
HashSet<string>? excludedRids = runtimeIdentifiersToExclude switch { null => null, _ => new HashSet<string>(runtimeIdentifiersToExclude, StringComparer.Ordinal) };
34+
foreach (var candidateRuntimeIdentifier in runtimeGraph.ExpandRuntime(runtimeIdentifier))
35+
{
36+
if (bestMatch == null && availableRids.Contains(candidateRuntimeIdentifier))
37+
{
38+
bestMatch = candidateRuntimeIdentifier;
39+
}
40+
41+
if (excludedRids != null && excludedRids.Contains(candidateRuntimeIdentifier))
42+
{
43+
// Don't treat this as a match
44+
return null;
45+
}
46+
}
47+
48+
return bestMatch;
49+
}
50+
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System.CommandLine;
5+
using System.CommandLine.Parsing;
6+
using System.Diagnostics;
7+
using System.Reflection;
8+
using Aspire.Hosting.Sdk;
9+
using NuGet.RuntimeModel;
10+
11+
namespace Aspire.RuntimeIdentifier.Tool;
12+
13+
sealed class Program
14+
{
15+
static int Main(string[] args)
16+
{
17+
CliRootCommand rootCommand = new("Aspire.RuntimeIdentifier.Tool v" + FileVersionInfo.GetVersionInfo(Assembly.GetExecutingAssembly().Location).ProductVersion)
18+
{
19+
TreatUnmatchedTokensAsErrors = true
20+
};
21+
22+
CliOption<string?> runtimeGraphPathOption = new("--runtimeGraphPath")
23+
{
24+
Description = "Path to runtime graph path to use for RID mapping.",
25+
Required = true
26+
};
27+
28+
CliOption<string?> netcoreSdkRuntimeIdentifierOption = new("--netcoreSdkRuntimeIdentifier")
29+
{
30+
Description = "RID to use for finding the best applicable RID from mapping.",
31+
Required = true
32+
};
33+
34+
CliOption<string[]> supportedRidsOption = new("--supportedRids")
35+
{
36+
Description = "List of RIDs that are supported. Comma-separated.",
37+
Required = true,
38+
Arity = ArgumentArity.OneOrMore,
39+
CustomParser = ParseSupportedRidsArgument
40+
};
41+
42+
rootCommand.Options.Add(runtimeGraphPathOption);
43+
rootCommand.Options.Add(netcoreSdkRuntimeIdentifierOption);
44+
rootCommand.Options.Add(supportedRidsOption);
45+
rootCommand.SetAction((ParseResult parseResult) =>
46+
{
47+
string rgp = parseResult.GetValue(runtimeGraphPathOption) ?? throw new InvalidOperationException("The --runtimeGraphPath argument is required.");
48+
49+
if (!File.Exists(rgp))
50+
{
51+
throw new FileNotFoundException("File {0} does not exist. Please ensure the runtime graph path exists.", rgp);
52+
}
53+
54+
RuntimeGraph graph = JsonRuntimeFormat.ReadRuntimeGraph(rgp);
55+
56+
var ridToUse = parseResult.GetValue(netcoreSdkRuntimeIdentifierOption);
57+
58+
var supportedRids = parseResult.GetValue(supportedRidsOption);
59+
60+
string? bestRidForPlatform = NuGetUtils.GetBestMatchingRid(graph, ridToUse!, supportedRids!, out bool wasInGraph);
61+
62+
if (!wasInGraph)
63+
{
64+
Console.WriteLine("Unable to find the best rid to use");
65+
return -1;
66+
}
67+
68+
Console.WriteLine(bestRidForPlatform);
69+
return 0;
70+
});
71+
72+
return rootCommand.Parse(args).Invoke();
73+
}
74+
75+
private static string[]? ParseSupportedRidsArgument(ArgumentResult result)
76+
{
77+
List<string> args = new();
78+
79+
foreach (var token in result.Tokens)
80+
{
81+
args.AddRange(token.Value.Split(','));
82+
}
83+
84+
return args.ToArray();
85+
}
86+
}

0 commit comments

Comments
 (0)