Browse Source

Update Nuke to v9 and fix ValidateApiDiff (#19529)

pull/19540/head
Julien Lebosquain 6 months ago
committed by GitHub
parent
commit
5bd5249b61
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 197
      .nuke/build.schema.json
  2. 69
      nukebuild/ApiDiffHelper.cs
  3. 50
      nukebuild/Build.cs
  4. 11
      nukebuild/BuildParameters.cs
  5. 2
      nukebuild/BuildTasksPatcher.cs
  6. 10
      nukebuild/_build.csproj

197
.nuke/build.schema.json

@ -1,48 +1,78 @@
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Build Schema",
"$ref": "#/definitions/build",
"definitions": {
"build": {
"type": "object",
"Host": {
"type": "string",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
},
"ExecutableTarget": {
"type": "string",
"enum": [
"BuildToNuGetCache",
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"DownloadApiBaselinePackages",
"GenerateCppHeaders",
"OutputApiDiff",
"OutputVersion",
"Package",
"RunCoreLibsTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"RunToolsTests",
"ValidateApiDiff",
"VerifyXamlCompilation",
"ZipFiles"
]
},
"Verbosity": {
"type": "string",
"description": "",
"enum": [
"Verbose",
"Normal",
"Minimal",
"Quiet"
]
},
"NukeBuild": {
"properties": {
"configuration": {
"type": "string"
},
"Continue": {
"type": "boolean",
"description": "Indicates to continue a previously failed build attempt"
},
"force-api-baseline": {
"type": "string"
},
"force-nuget-version": {
"type": "string"
},
"Help": {
"type": "boolean",
"description": "Shows the help text for this build assembly"
},
"Host": {
"type": "string",
"description": "Host for execution. Default is 'automatic'",
"enum": [
"AppVeyor",
"AzurePipelines",
"Bamboo",
"Bitbucket",
"Bitrise",
"GitHubActions",
"GitLab",
"Jenkins",
"Rider",
"SpaceAutomation",
"TeamCity",
"Terminal",
"TravisCI",
"VisualStudio",
"VSCode"
]
"$ref": "#/definitions/Host"
},
"NoLogo": {
"type": "boolean",
@ -71,91 +101,54 @@
"type": "array",
"description": "List of targets to be skipped. Empty list skips all dependencies",
"items": {
"type": "string",
"enum": [
"BuildToNuGetCache",
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"DownloadApiBaselinePackages",
"GenerateCppHeaders",
"OutputApiDiff",
"OutputVersion",
"Package",
"RunCoreLibsTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"RunToolsTests",
"ValidateApiDiff",
"VerifyXamlCompilation",
"ZipFiles"
]
"$ref": "#/definitions/ExecutableTarget"
}
},
"skip-previewer": {
"type": "boolean"
},
"skip-tests": {
"type": "boolean"
},
"Target": {
"type": "array",
"description": "List of targets to be invoked. Default is '{default_target}'",
"items": {
"type": "string",
"enum": [
"BuildToNuGetCache",
"CiAzureLinux",
"CiAzureOSX",
"CiAzureWindows",
"Clean",
"Compile",
"CompileHtmlPreviewer",
"CompileNative",
"CreateIntermediateNugetPackages",
"CreateNugetPackages",
"DownloadApiBaselinePackages",
"GenerateCppHeaders",
"OutputApiDiff",
"OutputVersion",
"Package",
"RunCoreLibsTests",
"RunHtmlPreviewerTests",
"RunLeakTests",
"RunRenderTests",
"RunTests",
"RunToolsTests",
"ValidateApiDiff",
"VerifyXamlCompilation",
"ZipFiles"
]
"$ref": "#/definitions/ExecutableTarget"
}
},
"update-api-suppression": {
"type": "boolean"
},
"Verbosity": {
"type": "string",
"description": "Logging verbosity during build execution. Default is 'Normal'",
"enum": [
"Minimal",
"Normal",
"Quiet",
"Verbose"
"$ref": "#/definitions/Verbosity"
}
}
}
},
"allOf": [
{
"properties": {
"configuration": {
"type": "string"
},
"force-api-baseline": {
"type": "string"
},
"force-nuget-version": {
"type": "string"
},
"skip-previewer": {
"type": "boolean"
},
"skip-tests": {
"type": "boolean"
},
"update-api-suppression": {
"type": [
"boolean",
"null"
]
},
"version-output-dir": {
"type": "string"
}
}
},
{
"$ref": "#/definitions/NukeBuild"
}
}
}
]
}

69
nukebuild/ApiDiffHelper.cs

@ -7,6 +7,7 @@ using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using NuGet.Common;
@ -26,9 +27,13 @@ public static class ApiDiffHelper
const string MainPackageName = "Avalonia";
const string FolderLib = "lib";
private static readonly Regex s_suppressionPathRegex =
new("<(Left|Right)>(.*?)</(Left|Right)>", RegexOptions.Compiled);
public static void ValidatePackage(
Tool apiCompatTool,
PackageDiffInfo packageDiff,
AbsolutePath rootAssembliesFolderPath,
AbsolutePath suppressionFilesFolderPath,
bool updateSuppressionFile)
{
@ -36,28 +41,68 @@ public static class ApiDiffHelper
Directory.CreateDirectory(suppressionFilesFolderPath);
var suppressionArgs = "";
var suppressionFile = suppressionFilesFolderPath / (packageDiff.PackageId + ".nupkg.xml");
if (suppressionFile.FileExists())
suppressionArgs += $""" --suppression-file="{suppressionFile}" --permit-unnecessary-suppressions """;
if (updateSuppressionFile)
suppressionArgs += $""" --suppression-output-file="{suppressionFile}" --generate-suppression-file --preserve-unnecessary-suppressions """;
var suppressionFilePath = suppressionFilesFolderPath / (packageDiff.PackageId + ".nupkg.xml");
var replaceDirectorySeparators = Path.DirectorySeparatorChar == '\\';
var allErrors = new List<string>();
foreach (var framework in packageDiff.Frameworks)
{
var args = $""" -l="{framework.BaselineFolderPath}" -r="{framework.CurrentFolderPath}" {suppressionArgs}""";
var relativeBaselinePath = rootAssembliesFolderPath.GetRelativePathTo(framework.BaselineFolderPath);
var relativeCurrentPath = rootAssembliesFolderPath.GetRelativePathTo(framework.CurrentFolderPath);
var args = "";
if (suppressionFilePath.FileExists())
{
args += $""" --suppression-file="{suppressionFilePath}" --permit-unnecessary-suppressions """;
if (replaceDirectorySeparators)
ReplaceDirectorySeparators(suppressionFilePath, '/', '\\');
}
if (updateSuppressionFile)
args += $""" --suppression-output-file="{suppressionFilePath}" --generate-suppression-file --preserve-unnecessary-suppressions """;
args += $""" -l="{relativeBaselinePath}" -r="{relativeCurrentPath}" """;
var localErrors = GetErrors(apiCompatTool($"{args:nq}", rootAssembliesFolderPath, exitHandler: _ => { }));
if (replaceDirectorySeparators)
ReplaceDirectorySeparators(suppressionFilePath, '\\', '/');
var localErrors = GetErrors(apiCompatTool(args));
allErrors.AddRange(localErrors);
}
ThrowOnErrors(allErrors, packageDiff.PackageId, "ValidateApiDiff");
}
/// <summary>
/// The ApiCompat tool treats paths with '/' and '\' separators as different files.
/// Before running the tool, adjust the existing separators (using a dirty regex) to match the current platform.
/// After running the tool, change all separators back to '/'.
/// </summary>
static void ReplaceDirectorySeparators(AbsolutePath suppressionFilePath, char oldSeparator, char newSeparator)
{
if (!File.Exists(suppressionFilePath))
return;
var lines = File.ReadAllLines(suppressionFilePath);
for (var i = 0; i < lines.Length; i++)
{
var original = lines[i];
var replacement = s_suppressionPathRegex.Replace(original, match =>
{
var path = match.Groups[2].Value.Replace(oldSeparator, newSeparator);
return $"<{match.Groups[1].Value}>{path}</{match.Groups[3].Value}>";
});
lines[i] = replacement;
}
File.WriteAllLines(suppressionFilePath, lines);
}
public static void GenerateMarkdownDiff(
Tool apiDiffTool,
PackageDiffInfo packageDiff,
@ -87,7 +132,7 @@ public static class ApiDiffHelper
var frameworkOutputFolderPath = packageOutputFolderPath / framework.Framework.GetShortFolderName();
var args = $""" -b="{framework.BaselineFolderPath}" -bfn="{baselineDisplay}" -a="{framework.CurrentFolderPath}" -afn="{currentDisplay}" -o="{frameworkOutputFolderPath}" -eattrs="{excludedAttributesFilePath}" """;
var localErrors = GetErrors(apiDiffTool(args));
var localErrors = GetErrors(apiDiffTool($"{args:nq}"));
if (localErrors.Length > 0)
{

50
nukebuild/Build.cs

@ -11,12 +11,8 @@ using Nuke.Common.Tooling;
using Nuke.Common.Tools.DotNet;
using Nuke.Common.Tools.Npm;
using static Nuke.Common.EnvironmentInfo;
using static Nuke.Common.IO.FileSystemTasks;
using static Nuke.Common.IO.PathConstruction;
using static Nuke.Common.Tools.MSBuild.MSBuildTasks;
using static Nuke.Common.Tools.DotNet.DotNetTasks;
using static Nuke.Common.Tools.Xunit.XunitTasks;
using static Nuke.Common.Tools.VSWhere.VSWhereTasks;
using static Serilog.Log;
using MicroCom.CodeGenerator;
using NuGet.Configuration;
@ -40,13 +36,13 @@ partial class Build : NukeBuild
ApiDiffHelper.GlobalDiffInfo? GlobalDiff { get; set; }
#nullable restore
[PackageExecutable("Microsoft.DotNet.ApiCompat.Tool", "Microsoft.DotNet.ApiCompat.Tool.dll", Framework = "net8.0")]
[NuGetPackage("Microsoft.DotNet.ApiCompat.Tool", "Microsoft.DotNet.ApiCompat.Tool.dll", Framework = "net8.0")]
Tool ApiCompatTool;
[PackageExecutable("Microsoft.DotNet.ApiDiff.Tool", "Microsoft.DotNet.ApiDiff.Tool.dll", Framework = "net8.0")]
[NuGetPackage("Microsoft.DotNet.ApiDiff.Tool", "Microsoft.DotNet.ApiDiff.Tool.dll", Framework = "net8.0")]
Tool ApiDiffTool;
[PackageExecutable("dotnet-ilrepack", "ILRepackTool.dll", Framework = "net8.0")]
[NuGetPackage("dotnet-ilrepack", "ILRepackTool.dll", Framework = "net8.0")]
Tool IlRepackTool;
protected override void OnBuildInitialized()
@ -96,7 +92,7 @@ partial class Build : NukeBuild
c.AddProperty("JavaSdkDirectory", GetVariable<string>("JAVA_HOME_11_X64"));
c.AddProperty("PackageVersion", Parameters.Version)
.SetConfiguration(Parameters.Configuration)
.SetVerbosity(DotNetVerbosity.Minimal);
.SetVerbosity(DotNetVerbosity.minimal);
if (Parameters.IsPackingToLocalCache)
c
.AddProperty("ForcePackAvaloniaNative", "True")
@ -116,12 +112,23 @@ partial class Build : NukeBuild
Target Clean => _ => _.Executes(() =>
{
Parameters.BuildDirs.ForEach(DeleteDirectory);
EnsureCleanDirectory(Parameters.ArtifactsDir);
EnsureCleanDirectory(Parameters.NugetIntermediateRoot);
EnsureCleanDirectory(Parameters.NugetRoot);
EnsureCleanDirectory(Parameters.ZipRoot);
EnsureCleanDirectory(Parameters.TestResultsRoot);
foreach (var buildDir in Parameters.BuildDirs)
{
Information("Deleting {Directory}", buildDir);
buildDir.DeleteDirectory();
}
CleanDirectory(Parameters.ArtifactsDir);
CleanDirectory(Parameters.NugetIntermediateRoot);
CleanDirectory(Parameters.NugetRoot);
CleanDirectory(Parameters.ZipRoot);
CleanDirectory(Parameters.TestResultsRoot);
void CleanDirectory(AbsolutePath path)
{
Information("Cleaning {Path}", path);
path.CreateOrCleanDirectory();
}
});
Target CompileHtmlPreviewer => _ => _
@ -133,7 +140,7 @@ partial class Build : NukeBuild
NpmTasks.NpmInstall(c => c
.SetProcessWorkingDirectory(webappDir)
.SetProcessArgumentConfigurator(a => a.Add("--silent")));
.SetProcessAdditionalArguments("--silent"));
NpmTasks.NpmRun(c => c
.SetProcessWorkingDirectory(webappDir)
.SetCommand("dist"));
@ -226,7 +233,7 @@ partial class Build : NukeBuild
.SetFramework(tfm)
.EnableNoBuild()
.EnableNoRestore()
.When(Parameters.PublishTestResults, _ => _
.When(_ => Parameters.PublishTestResults, _ => _
.SetLoggers("trx")
.SetResultsDirectory(Parameters.TestResultsRoot)));
}
@ -241,7 +248,7 @@ partial class Build : NukeBuild
NpmTasks.NpmInstall(c => c
.SetProcessWorkingDirectory(webappTestDir)
.SetProcessArgumentConfigurator(a => a.Add("--silent")));
.SetProcessAdditionalArguments("--silent"));
NpmTasks.NpmRun(c => c
.SetProcessWorkingDirectory(webappTestDir)
.SetCommand("test"));
@ -318,7 +325,7 @@ partial class Build : NukeBuild
Parameters.Version + ".nupkg",
IlRepackTool);
var config = Numerge.MergeConfiguration.LoadFile(RootDirectory / "nukebuild" / "numerge.config");
EnsureCleanDirectory(Parameters.NugetRoot);
Parameters.NugetRoot.CreateOrCleanDirectory();
if(!Numerge.NugetPackageMerger.Merge(Parameters.NugetIntermediateRoot, Parameters.NugetRoot, config,
new NumergeNukeLogger()))
throw new Exception("Package merge failed");
@ -350,6 +357,7 @@ partial class Build : NukeBuild
packageDiff => ApiDiffHelper.ValidatePackage(
ApiCompatTool,
packageDiff,
Parameters.ArtifactsDir / "api-diff" / "assemblies",
Parameters.ApiValidationSuppressionFiles,
Parameters.UpdateApiValidationSuppression));
});
@ -451,7 +459,7 @@ partial class Build : NukeBuild
var artifactsDirectory = buildTestsDirectory / "artifacts";
var nugetCacheDirectory = artifactsDirectory / "nuget-cache";
DeleteDirectory(artifactsDirectory);
artifactsDirectory.DeleteDirectory();
BuildTestsAndVerify("Debug");
BuildTestsAndVerify("Release");
@ -465,7 +473,7 @@ partial class Build : NukeBuild
.SetProperty("NuGetPackageRoot", nugetCacheDirectory)
.SetPackageDirectory(nugetCacheDirectory)
.SetProjectFile(buildTestsDirectory / "BuildTests.sln")
.SetProcessArgumentConfigurator(arguments => arguments.Add("--nodeReuse:false")));
.SetProcessAdditionalArguments("--nodeReuse:false"));
// Standard compilation - should have compiled XAML
VerifyBuildTestAssembly("bin", "BuildTests");
@ -494,7 +502,7 @@ partial class Build : NukeBuild
.SetPackageDirectory(nugetCacheDirectory)
.SetNoBuild(noBuild)
.SetProject(buildTestsDirectory / projectName / (projectName + ".csproj"))
.SetProcessArgumentConfigurator(arguments => arguments.Add("--nodeReuse:false")));
.SetProcessAdditionalArguments("--nodeReuse:false"));
void VerifyBuildTestAssembly(string folder, string projectName)
=> XamlCompilationVerifier.VerifyAssemblyCompiledXaml(

11
nukebuild/BuildParameters.cs

@ -9,7 +9,6 @@ using System.Xml.Linq;
using Nuke.Common;
using Nuke.Common.CI.AzurePipelines;
using Nuke.Common.IO;
using static Nuke.Common.IO.PathConstruction;
public partial class Build
{
@ -68,7 +67,7 @@ public partial class Build
public AbsolutePath ZipRoot { get; }
public AbsolutePath TestResultsRoot { get; }
public string DirSuffix { get; }
public List<string> BuildDirs { get; }
public List<AbsolutePath> BuildDirs { get; }
public string FileZipSuffix { get; }
public AbsolutePath ZipCoreArtifacts { get; }
public AbsolutePath ZipNuGetArtifacts { get; }
@ -147,10 +146,10 @@ public partial class Build
NugetIntermediateRoot = RootDirectory / "build-intermediate" / "nuget";
ZipRoot = ArtifactsDir / "zip";
TestResultsRoot = ArtifactsDir / "test-results";
BuildDirs = GlobDirectories(RootDirectory, "**/bin")
.Concat(GlobDirectories(RootDirectory, "**/obj"))
.Where(dir => !dir.Contains("nukebuild"))
.Concat(GlobDirectories(RootDirectory, "**/node_modules"))
BuildDirs = RootDirectory.GlobDirectories("**/bin")
.Concat(RootDirectory.GlobDirectories("**/obj"))
.Where(dir => !((string)dir).Contains("nukebuild"))
.Concat(RootDirectory.GlobDirectories("**/node_modules"))
.ToList();
DirSuffix = Configuration;
FileZipSuffix = Version + ".zip";

2
nukebuild/BuildTasksPatcher.cs

@ -85,7 +85,7 @@ public class BuildTasksPatcher
var cecilMdbAsm = GetAssemblyPath(typeof(Mono.Cecil.Mdb.MdbReaderProvider));
ilRepackTool.Invoke(
$"/internalize /out:\"{output}\" \"{temp}\" \"{cecilAsm}\" \"{cecilRocksAsm}\" \"{cecilPdbAsm}\" \"{cecilMdbAsm}\"",
$"/internalize /out:\"{output:nq}\" \"{temp:nq}\" \"{cecilAsm:nq}\" \"{cecilRocksAsm:nq}\" \"{cecilPdbAsm:nq}\" \"{cecilMdbAsm:nq}\"",
tempDir);
// 'hurr-durr assembly with the same name is already loaded' prevention

10
nukebuild/_build.csproj

@ -15,18 +15,12 @@
<Import Project="..\build\JetBrains.dotMemoryUnit.props" />
<ItemGroup>
<PackageReference Include="Nuke.Common" Version="6.2.1" />
<PackageReference Include="vswhere" Version="2.6.7" Condition=" '$(OS)' == 'Windows_NT' " />
<PackageReference Include="Nuke.Common" Version="9.0.4" />
<PackageReference Include="MicroCom.CodeGenerator" Version="0.11.0" />
<!-- Keep in sync with Avalonia.Build.Tasks -->
<PackageReference Include="Mono.Cecil" Version="0.11.5" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.3.2" PrivateAssets="All" />
<PackageReference Include="Microsoft.Build.Framework" Version="17.14.8" PrivateAssets="All" />
<PackageReference Include="NuGet.Protocol" Version="6.14.0" />
<PackageReference Include="xunit.runner.console" Version="2.4.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageDownload Include="Microsoft.DotNet.ApiCompat.Tool" Version="[10.0.100-preview.7.25380.108]" />
<PackageDownload Include="Microsoft.DotNet.ApiDiff.Tool" Version="[10.0.100-rc.1.25414.111]" />
<PackageDownload Include="dotnet-ilrepack" Version="[1.0.0]" />

Loading…
Cancel
Save