@ -10,7 +10,8 @@
// TOOLS
///////////////////////////////////////////////////////////////////////////////
#tool "nuget:?package=xunit.runner.console&version=2.3.0-beta5-build3769"
#tool "nuget:?package=xunit.runner.console&version=2.3.1"
#tool "nuget:?package=JetBrains.dotMemoryUnit&version=3.0.20171219.105559"
///////////////////////////////////////////////////////////////////////////////
// USINGS
@ -34,20 +35,31 @@ using NuGet;
// PARAMETERS
//////////////////////////////////////////////////////////////////////
Parameters parameters = new Parameters(Context);
Packages packages = new Packages(Context, parameters);
class AvaloniaBuildData
{
public AvaloniaBuildData(Parameters parameters, Packages packages)
{
Parameters = parameters;
Packages = packages;
}
public Parameters Parameters { get; }
public Packages Packages { get; }
}
///////////////////////////////////////////////////////////////////////////////
// SETUP
///////////////////////////////////////////////////////////////////////////////
Setup(context =>
Setup<AvaloniaBuildData> (context =>
{
Information("Building version {0} of Avalonia ({1}, {2}, {3}) using version {4} of Cake.",
var parameters = new Parameters(context);
var buildContext = new AvaloniaBuildData(parameters, new Packages(context, parameters));
Information("Building version {0} of Avalonia ({1}, {2}) using version {3} of Cake.",
parameters.Version,
parameters.Platform,
parameters.Configuration,
parameters.Target,
typeof(ICakeContext).Assembly.GetName().Version.ToString());
if (parameters.IsRunningOnAppVeyor)
@ -55,8 +67,7 @@ Setup(context =>
Information("Repository Name: " + BuildSystem.AppVeyor.Environment.Repository.Name);
Information("Repository Branch: " + BuildSystem.AppVeyor.Environment.Repository.Branch);
}
Information("Target: " + parameters.Target);
Information("Target:" + context.TargetTask.Name);
Information("Platform: " + parameters.Platform);
Information("Configuration: " + parameters.Configuration);
Information("IsLocalBuild: " + parameters.IsLocalBuild);
@ -70,13 +81,15 @@ Setup(context =>
Information("IsReleasable: " + parameters.IsReleasable);
Information("IsMyGetRelease: " + parameters.IsMyGetRelease);
Information("IsNuGetRelease: " + parameters.IsNuGetRelease);
return buildContext;
});
///////////////////////////////////////////////////////////////////////////////
// TEARDOWN
///////////////////////////////////////////////////////////////////////////////
Teardown(context =>
Teardown<AvaloniaBuildData>( (context, buildContext) =>
{
Information("Finished running tasks.");
});
@ -86,19 +99,19 @@ Teardown(context =>
///////////////////////////////////////////////////////////////////////////////
Task("Clean")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
CleanDirectories(p arameters.BuildDirs);
CleanDirectory(p arameters.ArtifactsDir);
CleanDirectory(p arameters.NugetRoot);
CleanDirectory(p arameters.ZipRoot);
CleanDirectory(p arameters.BinRoot);
CleanDirectories(data.P arameters.BuildDirs);
CleanDirectory(data.P arameters.ArtifactsDir);
CleanDirectory(data.P arameters.NugetRoot);
CleanDirectory(data.P arameters.ZipRoot);
CleanDirectory(data.P arameters.BinRoot);
});
Task("Restore-NuGet-Packages")
.IsDependentOn("Clean")
.WithCriteria(p arameters.IsRunningOnWindows)
.Does(() =>
.WithCriteria<AvaloniaBuildData>((context, data) => data.P arameters.IsRunningOnWindows)
.Does<AvaloniaBuildData>(data =>
{
var maxRetryCount = 5;
var toolTimeout = 2d;
@ -115,13 +128,13 @@ Task("Restore-NuGet-Packages")
toolTimeout+=0.5;
}})
.Execute(()=> {
NuGetRestore(p arameters.MSBuildSolution, new NuGetRestoreSettings {
NuGetRestore(data.P arameters.MSBuildSolution, new NuGetRestoreSettings {
ToolTimeout = TimeSpan.FromMinutes(toolTimeout)
});
});
});
void DotNetCoreBuild()
void DotNetCoreBuild(Parameters parameters )
{
var settings = new DotNetCoreBuildSettings
{
@ -137,23 +150,24 @@ void DotNetCoreBuild()
Task("Build")
.IsDependentOn("Restore-NuGet-Packages")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
if(p arameters.IsRunningOnWindows)
if(data.P arameters.IsRunningOnWindows)
{
MSBuild(p arameters.MSBuildSolution, settings => {
settings.SetConfiguration(p arameters.Configuration);
MSBuild(data.P arameters.MSBuildSolution, settings => {
settings.SetConfiguration(data.P arameters.Configuration);
settings.SetVerbosity(Verbosity.Minimal);
settings.WithProperty("Platform", "\"" + p arameters.Platform + "\"");
settings.WithProperty("Platform", "\"" + data.P arameters.Platform + "\"");
settings.WithProperty("UseRoslynPathHack", "true");
settings.UseToolVersion(MSBuildToolVersion.VS2017);
settings.WithProperty("Windows", "True");
settings.SetNodeReuse(false);
settings.SetMaxCpuCount(0);
});
}
else
{
DotNetCoreBuild();
DotNetCoreBuild(data.Parameters );
}
});
@ -182,68 +196,94 @@ void RunCoreTest(string project, Parameters parameters, bool coreOnly = false)
Task("Run-Unit-Tests")
.IsDependentOn("Build")
.IsDependentOn("Run-Designer-Tests")
.IsDependentOn("Run-Render-Tests")
.WithCriteria(() => !parameters.SkipTests)
.Does(() => {
RunCoreTest("./tests/Avalonia.Base.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Controls.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Input.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Layout.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Markup.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Styling.UnitTests", parameters, false);
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", parameters, false);
if (parameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.Base.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Controls.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Input.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Interactivity.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Layout.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Markup.Xaml.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Styling.UnitTests", data.Parameters, false);
RunCoreTest("./tests/Avalonia.Visuals.UnitTests", data.Parameters, false);
if (data.Parameters.IsRunningOnWindows)
{
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", p arameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.UnitTests", data.Parameters, true);
}
});
Task("Run-Designer-Tests")
.IsDependentOn("Build")
.WithCriteria(() => !p arameters.SkipTests)
.Does(() => {
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", p arameters, false);
.WithCriteria<AvaloniaBuildData>((context, data) => !data.P arameters.SkipTests)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.DesignerSupport.Tests", data.P arameters, false);
});
Task("Run-Render-Tests")
.IsDependentOn("Build")
.WithCriteria(() => !parameters.SkipTests && p arameters.IsRunningOnWindows)
.Does(() => {
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", p arameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", p arameters, true);
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests && data.P arameters.IsRunningOnWindows)
.Does<AvaloniaBuildData>(data => {
RunCoreTest("./tests/Avalonia.Skia.RenderTests/Avalonia.Skia.RenderTests.csproj", data.P arameters, true);
RunCoreTest("./tests/Avalonia.Direct2D1.RenderTests/Avalonia.Direct2D1.RenderTests.csproj", data.P arameters, true);
});
Task("Copy-Files")
.IsDependentOn("Run-Unit-Tests")
Task("Run-Leak-Tests")
.WithCriteria<AvaloniaBuildData>((context, data) => !data.Parameters.SkipTests && data.Parameters.IsRunningOnWindows)
.IsDependentOn("Build")
.Does(() =>
{
var dotMemoryUnit = Context.Tools.Resolve("dotMemoryUnit.exe");
var leakTestsExitCode = StartProcess(dotMemoryUnit, new ProcessSettings
{
Arguments = new ProcessArgumentBuilder()
.Append(Context.Tools.Resolve("xunit.console.x86.exe").FullPath)
.Append("--propagate-exit-code")
.Append("--")
.Append("tests\\Avalonia.LeakTests\\bin\\Release\\net461\\Avalonia.LeakTests.dll"),
Timeout = 120000
});
if (leakTestsExitCode != 0)
{
throw new Exception("Leak Tests failed");
}
});
Task("Run-Tests")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Run-Render-Tests")
.IsDependentOn("Run-Designer-Tests")
.IsDependentOn("Run-Leak-Tests");
Task("Copy-Files")
.IsDependentOn("Run-Tests")
.Does<AvaloniaBuildData>(data =>
{
CopyFiles(packages.BinFiles, parameters.BinRoot);
CopyFiles(data.Packages.BinFiles, data.P arameters.BinRoot);
});
Task("Zip-Files")
.IsDependentOn("Copy-Files")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
Zip(parameters.BinRoot, parameters.ZipCoreArtifacts);
Zip(parameters.ZipSourceControlCatalogDesktopDirs,
parameters.ZipTargetControlCatalogDesktopDirs,
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
GetFiles(parameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
Zip(data.Parameters.BinRoot, data.P arameters.ZipCoreArtifacts);
Zip(data.P arameters.ZipSourceControlCatalogDesktopDirs,
data.P arameters.ZipTargetControlCatalogDesktopDirs,
GetFiles(data.P arameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dll") +
GetFiles(data.P arameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.config") +
GetFiles(data.P arameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.so") +
GetFiles(data.P arameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.dylib") +
GetFiles(data.P arameters.ZipSourceControlCatalogDesktopDirs.FullPath + "/*.exe"));
});
Task("Create-NuGet-Packages")
.IsDependentOn("Run-Unit-Tests")
.IsDependentOn("Run-Tests")
.IsDependentOn("Inspect")
.Does(() =>
.Does<AvaloniaBuildData>(data =>
{
foreach(var nuspec in packages.NuspecNuGetSettings)
foreach(var nuspec in data.P ackages.NuspecNuGetSettings)
{
NuGetPack(nuspec);
}
@ -251,12 +291,12 @@ Task("Create-NuGet-Packages")
Task("Publish-MyGet")
.IsDependentOn("Create-NuGet-Packages")
.WithCriteria(() => !p arameters.IsLocalBuild)
.WithCriteria(() => !p arameters.IsPullRequest)
.WithCriteria(() => p arameters.IsMainRepo)
.WithCriteria(() => p arameters.IsMasterBranch)
.WithCriteria(() => p arameters.IsMyGetRelease)
.Does(() =>
.WithCriteria<AvaloniaBuildData>((context, data) => !data.P arameters.IsLocalBuild)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.P arameters.IsPullRequest)
.WithCriteria<AvaloniaBuildData>((context, data) => data.P arameters.IsMainRepo)
.WithCriteria<AvaloniaBuildData>((context, data) => data.P arameters.IsMasterBranch)
.WithCriteria<AvaloniaBuildData>((context, data) => data.P arameters.IsMyGetRelease)
.Does<AvaloniaBuildData>(data =>
{
var apiKey = EnvironmentVariable("MYGET_API_KEY");
if(string.IsNullOrEmpty(apiKey))
@ -270,7 +310,7 @@ Task("Publish-MyGet")
throw new InvalidOperationException("Could not resolve MyGet API url.");
}
foreach(var nupkg in p ackages.NugetPackages)
foreach(var nupkg in data.P ackages.NugetPackages)
{
NuGetPush(nupkg, new NuGetPushSettings {
Source = apiUrl,
@ -285,11 +325,11 @@ Task("Publish-MyGet")
Task("Publish-NuGet")
.IsDependentOn("Create-NuGet-Packages")
.WithCriteria(() => !p arameters.IsLocalBuild)
.WithCriteria(() => !p arameters.IsPullRequest)
.WithCriteria(() => p arameters.IsMainRepo)
.WithCriteria(() => p arameters.IsNuGetRelease)
.Does(() =>
.WithCriteria<AvaloniaBuildData>((context, data) => !data.P arameters.IsLocalBuild)
.WithCriteria<AvaloniaBuildData>((context, data) => !data.P arameters.IsPullRequest)
.WithCriteria<AvaloniaBuildData>((context, data) => data.P arameters.IsMainRepo)
.WithCriteria<AvaloniaBuildData>((context, data) => data.P arameters.IsNuGetRelease)
.Does<AvaloniaBuildData>(data =>
{
var apiKey = EnvironmentVariable("NUGET_API_KEY");
if(string.IsNullOrEmpty(apiKey))
@ -303,7 +343,7 @@ Task("Publish-NuGet")
throw new InvalidOperationException("Could not resolve NuGet API url.");
}
foreach(var nupkg in p ackages.NugetPackages)
foreach(var nupkg in data.P ackages.NugetPackages)
{
NuGetPush(nupkg, new NuGetPushSettings {
ApiKey = apiKey,
@ -316,48 +356,8 @@ Task("Publish-NuGet")
Information("Publish-NuGet Task failed, but continuing with next Task...");
});
Task("Run-Leak-Tests")
.WithCriteria(parameters.IsRunningOnWindows)
.IsDependentOn("Build")
.Does(() =>
{
DotNetCoreRestore("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj");
DotNetBuild("tests\\Avalonia.LeakTests\\toolproject\\tool.csproj", settings => settings.SetConfiguration("Release"));
var report = "tests\\Avalonia.LeakTests\\bin\\Release\\report.xml";
if(System.IO.File.Exists(report))
System.IO.File.Delete(report);
var toolXunitConsoleX86 = Context.Tools.Resolve("xunit.console.x86.exe").FullPath;
var proc = System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo
{
FileName="tests\\Avalonia.LeakTests\\toolproject\\bin\\dotMemoryUnit.exe",
Arguments="-targetExecutable=\"" + toolXunitConsoleX86 + "\" -returnTargetExitCode -- tests\\Avalonia.LeakTests\\bin\\Release\\Avalonia.LeakTests.dll -xml tests\\Avalonia.LeakTests\\bin\\Release\\report.xml ",
UseShellExecute = false,
});
var st = System.Diagnostics.Stopwatch.StartNew();
while(!proc.HasExited && !System.IO.File.Exists(report))
{
if(st.Elapsed.TotalSeconds>60)
{
Error("Timed out, probably a bug in dotMemoryUnit");
proc.Kill();
throw new Exception("dotMemory issue");
}
proc.WaitForExit(100);
}
try{
proc.Kill();
}catch{}
var doc = System.Xml.Linq.XDocument.Load(report);
if(doc.Root.Descendants("assembly").Any(x=>x.Attribute("failed").Value.ToString() != "0"))
{
throw new Exception("Tests failed");
}
});
Task("Inspect")
.WithCriteria(p arameters.IsRunningOnWindows)
.WithCriteria<AvaloniaBuildData>((context, data) => data.Parameters.IsRunningOnWindows)
.IsDependentOn("Restore-NuGet-Packages")
.Does(() =>
{
@ -366,8 +366,13 @@ Task("Inspect")
"src\\markup\\avalonia.markup.xaml\\portablexaml\\portable.xaml.github"};
Information("Running code inspections");
StartProcess(Context.Tools.Resolve("inspectcode.exe"),
new ProcessSettings{ Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln" });
var exitCode = StartProcess(Context.Tools.Resolve("inspectcode.exe"),
new ProcessSettings
{
Arguments = "--output=artifacts\\inspectcode.xml --profile=Avalonia.sln.DotSettings Avalonia.sln",
RedirectStandardOutput = true
});
Information("Analyzing report");
var doc = XDocument.Parse(System.IO.File.ReadAllText("artifacts\\inspectcode.xml"));
var failBuild = false;
@ -395,23 +400,23 @@ Task("Inspect")
Task("Package")
.IsDependentOn("Create-NuGet-Packages");
Task("Default").Does(() =>
{
if(parameters.IsRunningOnWindows)
RunTarget("Package");
else
RunTarget("Run-Unit-Tests");
});
Task("AppVeyor")
.IsDependentOn("Zip-Files")
.IsDependentOn("Publish-MyGet")
.IsDependentOn("Publish-NuGet");
Task("Travis")
.IsDependentOn("Run-Unit- Tests");
.IsDependentOn("Run-Tests");
///////////////////////////////////////////////////////////////////////////////
// EXECUTE
///////////////////////////////////////////////////////////////////////////////
RunTarget(parameters.Target);
var target = Context.Argument("target", "Default");
if (target == "Default")
{
target = Context.IsRunningOnWindows() ? "Package" : "Run-Tests";
}
RunTarget(target);