diff --git a/.cake/Artifacts-Copy.cake b/.cake/Artifacts-Copy.cake new file mode 100644 index 0000000..5a53c43 --- /dev/null +++ b/.cake/Artifacts-Copy.cake @@ -0,0 +1,58 @@ +#load "Configuration.cake" + +public static Configuration IncludeArtifactCopyTarget(this Configuration configuration, DirectoryPath sourceDirectory) +{ + var copyList = new HashSet(); + if(configuration.TaskParameters.TryGetValue("Artifacts:Copy__Items", out object value) && value is HashSet) + { + copyList = value as HashSet; + } + else + { + configuration.TaskParameters.Add("Artifacts:Copy__Items", copyList); + } + + copyList.Add(sourceDirectory); + + return configuration; +} + +public static bool HasArtifactCopyTargets(this Configuration configuration) +{ + var copyList = new HashSet(); + if(configuration.TaskParameters.TryGetValue("Artifacts:Copy__Items", out object value) && value is HashSet) + { + copyList = value as HashSet; + } + + return copyList.Any(); +} + +public static IEnumerable GetArtifactCopyTargets(this Configuration configuration) +{ + var copyList = new HashSet(); + if(configuration.TaskParameters.TryGetValue("Artifacts:Copy__Items", out object value) && value is HashSet) + { + copyList = value as HashSet; + } + return copyList; +} + +Task("Artifacts:Copy") + .WithCriteria((ctx, config) => config.HasArtifactCopyTargets()) + .IsDependentOn("Build") + .IsDependeeOf("Publish") + .Does(config => +{ + var artifacts = $"{config.Artifacts.Root}"; + EnsureDirectoryExists(artifacts); + foreach(var directory in config.GetArtifactCopyTargets()) + { + var copyFrom = directory; + var copyTo = $"{artifacts}/{directory.GetDirectoryName()}"; + Information("{0} -> {1}", copyFrom, copyTo); + EnsureDirectoryExists(copyTo); + CopyDirectory(directory, copyTo); + config.Artifacts.Add(ArtifactTypeOption.Other, directory.GetDirectoryName(), directory.FullPath); + } +}); \ No newline at end of file diff --git a/.cake/Artifacts-DotNetCore-Ef.cake b/.cake/Artifacts-DotNetCore-Ef.cake index 138495f..0d94677 100644 --- a/.cake/Artifacts-DotNetCore-Ef.cake +++ b/.cake/Artifacts-DotNetCore-Ef.cake @@ -1,5 +1,5 @@ #load "Configuration.cake" -#addin nuget:?package=Newtonsoft.Json +#addin nuget:?package=Newtonsoft.Json&version=12.0.1 using Newtonsoft.Json; public class EfMigration @@ -25,7 +25,7 @@ IEnumerable GetAllDbContexts(DirectoryPath workingDirectory, string c RedirectStandardOutput = true }; - settings.Arguments = string.Format("ef dbcontext list --configuration {0} --json", configuration); + settings.Arguments = string.Format("ef dbcontext list --configuration {0} --json --prefix-output", configuration); var list = Enumerable.Empty(); using(var process = StartAndReturnProcess("dotnet", settings)) @@ -35,7 +35,7 @@ IEnumerable GetAllDbContexts(DirectoryPath workingDirectory, string c { try { - var outputAsJson = string.Join(Environment.NewLine, process.GetStandardOutput()); + var outputAsJson = string.Join(Environment.NewLine, process.GetStandardOutput().Where(l => l.StartsWith("data:")).Select(l => l.Replace("data:", ""))); list = JsonConvert.DeserializeObject>(outputAsJson); Verbose("Found {0} Db contexts", list.Count()); } @@ -56,7 +56,7 @@ IEnumerable GetMigrationsForContext(string dbContext, DirectoryPath RedirectStandardOutput = true }; - settings.Arguments = string.Format("ef migrations list --configuration {0} --context {1} --json", configuration, dbContext); + settings.Arguments = string.Format("ef migrations list --configuration {0} --context {1} --json --prefix-output", configuration, dbContext); var list = Enumerable.Empty(); using(var process = StartAndReturnProcess("dotnet", settings)) @@ -66,7 +66,7 @@ IEnumerable GetMigrationsForContext(string dbContext, DirectoryPath { try { - var outputAsJson = string.Join(Environment.NewLine, process.GetStandardOutput()); + var outputAsJson = string.Join(Environment.NewLine, process.GetStandardOutput().Where(l => l.StartsWith("data:")).Select(l => l.Replace("data:", ""))); list = JsonConvert.DeserializeObject>(outputAsJson); } catch(Exception exception) @@ -78,12 +78,50 @@ IEnumerable GetMigrationsForContext(string dbContext, DirectoryPath return list; } +public static Configuration IncludeAsEfDbContext(this Configuration configuration, Func includeAsEFDbContext) +{ + var projects = new HashSet(); + if(configuration.TaskParameters.TryGetValue("Artifacts:DotNetCore:Ef:Migration-Script", out object value) && value is HashSet) + { + projects = value as HashSet; + } + else + { + configuration.TaskParameters.Add("Artifacts:DotNetCore:Ef:Migration-Script", projects); + } + + var projectsToInclude = configuration.Solution.Projects.Where(includeAsEFDbContext).ToList(); + + if(projectsToInclude != null && projectsToInclude.Any()) + { + projects.UnionWith(projectsToInclude); + } + + return configuration; +} + +public static bool HasCustomEfDbContextTargets(this Configuration configuration) +{ + var projectList = configuration.GetEfDbContextTargets(); + return projectList?.Any() ?? false; +} + +public static IEnumerable GetEfDbContextTargets(this Configuration configuration) +{ + var projects = new HashSet(); + if(configuration.TaskParameters.TryGetValue("Artifacts:DotNetCore:Ef:Migration-Script", out object value) && value is HashSet) + { + projects = value as HashSet; + } + return projects; +} + Task("Artifacts:DotNetCore:Ef:Migration-Script") .IsDependentOn("Build") .IsDependeeOf("Publish") .Does(config => { - var efProjects = config.Solution.Projects.ToList(); + var efProjects = (config.HasCustomEfDbContextTargets() ? config.GetEfDbContextTargets() : config.Solution.Projects).ToList(); Information("Generating scripts for {0} projects", efProjects.Count()); foreach(var project in efProjects) { @@ -91,32 +129,35 @@ Task("Artifacts:DotNetCore:Ef:Migration-Script") var workingDirectory = project.ProjectFilePath.GetDirectory(); var availableDbContexts = GetAllDbContexts(workingDirectory, config.Solution.BuildConfiguration).ToList(); - Information("Generating scripts for {0} containing {1} contexts", assemblyName, availableDbContexts.Count); - foreach(var dbContext in availableDbContexts) + if(availableDbContexts.Any()) { - Information("Generating Sql Script for {0}", dbContext.SafeName); - var migrations = GetMigrationsForContext(dbContext.SafeName, workingDirectory, config.Solution.BuildConfiguration); - - var sqlScript = MakeAbsolute(File($"{config.Artifacts.Root}/sql/{dbContext.SafeName}.sql")); - if(FileExists(sqlScript)) { - DeleteFile(sqlScript); - } + Information("Generating scripts for {0} containing {1} contexts", assemblyName, availableDbContexts.Count); + foreach(var dbContext in availableDbContexts) + { + Information("Generating Sql Script for {0}", dbContext.SafeName); + var migrations = GetMigrationsForContext(dbContext.SafeName, workingDirectory, config.Solution.BuildConfiguration); + + var sqlScript = MakeAbsolute(File($"{config.Artifacts.Root}/sql/{dbContext.SafeName}.sql")); + if(FileExists(sqlScript)) { + DeleteFile(sqlScript); + } - var settings = new ProcessSettings() - { - WorkingDirectory = workingDirectory - }; + var settings = new ProcessSettings() + { + WorkingDirectory = workingDirectory + }; - settings.Arguments = string.Format("ef migrations script -i -o {0} --configuration {1} --context {2}", sqlScript, config.Solution.BuildConfiguration, dbContext.SafeName); + settings.Arguments = string.Format("ef migrations script -i -o {0} --configuration {1} --context {2}", sqlScript, config.Solution.BuildConfiguration, dbContext.SafeName); - using(var process = StartAndReturnProcess("dotnet", settings)) - { - process.WaitForExit(); - Verbose("Exit code: {0}", process.GetExitCode()); - } + using(var process = StartAndReturnProcess("dotnet", settings)) + { + process.WaitForExit(); + Verbose("Exit code: {0}", process.GetExitCode()); + } - config.Artifacts.Add(ArtifactTypeOption.Other, sqlScript.GetFilename().ToString(), sqlScript); + config.Artifacts.Add(ArtifactTypeOption.Other, sqlScript.GetFilename().ToString(), sqlScript); + } } } -}); \ No newline at end of file +}); diff --git a/.cake/Build-MsBuild.cake b/.cake/Build-MsBuild.cake index acad65a..c9bd84a 100644 --- a/.cake/Build-MsBuild.cake +++ b/.cake/Build-MsBuild.cake @@ -8,7 +8,6 @@ Task("Build:MsBuild") MSBuild(config.Solution.Path.ToString(), c => c .SetConfiguration(config.Solution.BuildConfiguration) .SetVerbosity(Verbosity.Minimal) - .UseToolVersion(MSBuildToolVersion.VS2017) .WithWarningsAsError() .WithTarget("Build") ); diff --git a/.cake/CI-VSTS.cake b/.cake/CI-Azure-DevOps.cake similarity index 89% rename from .cake/CI-VSTS.cake rename to .cake/CI-Azure-DevOps.cake index 6257e90..28bcc59 100644 --- a/.cake/CI-VSTS.cake +++ b/.cake/CI-Azure-DevOps.cake @@ -1,18 +1,18 @@ #load "Configuration.cake" Task("CI:VSTS:UploadArtifacts") - .WithCriteria((ctx, config) => BuildSystem.IsRunningOnVSTS || TFBuild.IsRunningOnTFS) + .WithCriteria((ctx, config) => BuildSystem.IsRunningOnAzurePipelinesHosted || TFBuild.IsRunningOnAzurePipelines) .IsDependentOn("Publish") .IsDependeeOf("CI:UploadArtifacts") .Does(config => { Information("Uploading artifacts from {0}", config.Artifacts.Root); - TFBuild.Commands.UploadArtifact("artifacts", config.Artifacts.Root.ToString(), "artifacts"); + TFBuild.Commands.UploadArtifact("artifacts", config.Artifacts.Root.ToString(), "artifacts"); }); Task("CI:VSTS:UpdateBuildNumber") .IsDependeeOf("CI:UpdateBuildNumber") - .WithCriteria((ctx, config) => BuildSystem.IsRunningOnVSTS || TFBuild.IsRunningOnTFS) + .WithCriteria((ctx, config) => BuildSystem.IsRunningOnAzurePipelinesHosted || TFBuild.IsRunningOnAzurePipelines) .Does(config => { Information( diff --git a/.cake/CI.cake b/.cake/CI.cake index c3eab93..b037189 100644 --- a/.cake/CI.cake +++ b/.cake/CI.cake @@ -1,4 +1,4 @@ -#load "CI-VSTS.cake" +#load "CI-Azure-DevOps.cake" #load "CI-AppVeyor.cake" Task("CI") diff --git a/.cake/Configuration-Version.cake b/.cake/Configuration-Version.cake index ff2f559..f99ad1e 100644 --- a/.cake/Configuration-Version.cake +++ b/.cake/Configuration-Version.cake @@ -1,4 +1,4 @@ -#tool "nuget:?package=GitVersion.CommandLine&prerelease" +#tool "nuget:?package=GitVersion.CommandLine&version=4.0.0&prerelease" public class BuildVersion { public FilePath VersionAssemblyInfo { get; private set; } @@ -97,4 +97,4 @@ public class BuildVersion { throw new Exception("Version information has not been determined, build failed!"); } } -} \ No newline at end of file +} diff --git a/.cake/Configuration.cake b/.cake/Configuration.cake index a4d2c48..92e8916 100644 --- a/.cake/Configuration.cake +++ b/.cake/Configuration.cake @@ -1,4 +1,4 @@ -#addin "Cake.Incubator&version=3.1.0" +#addin "Cake.Incubator&version=5.0.1" #load "Configuration-Version.cake" const string _solutionFilePathPattern = "*.sln"; @@ -56,6 +56,8 @@ public partial class Configuration { return config; } + public Dictionary TaskParameters { get; } = new Dictionary(); + public BuildVersion Version { get; } public SolutionParameters Solution { get; } @@ -81,6 +83,8 @@ public partial class Configuration { Artifacts = new ArtifactsParameters(context, artifactsRootPath ?? context.Directory("artifacts")); } + public ICakeLog Logger => context.Log; + public void Log(ICakeLog logger) { Solution.Log(logger); @@ -110,7 +114,7 @@ public struct Artifact { } public override string ToString() { - return $"{Name} ({Type}/{Category}) - {Path}"; + return $"{Name} ({Type}/{Category}) - {Path.FullPath}"; } } @@ -133,7 +137,7 @@ public class ArtifactsParameters : List { } public void Add(ArtifactTypeOption type, string name, FilePath path) { - Add(new Artifact(type, name, path)); + Add(new Artifact(type, name, context.MakeAbsolute(path))); } } @@ -158,11 +162,12 @@ public class SolutionParameters { } private ISet> WebProjectResolvers { get; } = new HashSet>() { - p => p.IsWebApplication() + p => p.IsWebApplication(), + p => p.HasPackage("Microsoft.NET.Sdk.Functions") }; private ISet> TestProjectResolvers { get; } = new HashSet>() { - p => p.IsDotNetCliTestProject() + p => p.IsTestProject() }; private ISet> NuGetProjectResolvers { get; } = new HashSet>() { diff --git a/.cake/Npm-RunScript.cake b/.cake/Npm-RunScript.cake index 919abeb..ba89f8b 100644 --- a/.cake/Npm-RunScript.cake +++ b/.cake/Npm-RunScript.cake @@ -27,7 +27,6 @@ public class NpmConfiguration public bool CanExecuteNpm { get { - cakeContext.Information($"{WorkingDirectory.TrimEnd('/')}/package.json"); return cakeContext.FileExists($"{WorkingDirectory.TrimEnd('/')}/package.json"); } } diff --git a/.cake/Publish-Pack-DotNetCore.cake b/.cake/Publish-Pack-DotNetCore.cake index 7df8d3d..de49969 100644 --- a/.cake/Publish-Pack-DotNetCore.cake +++ b/.cake/Publish-Pack-DotNetCore.cake @@ -12,8 +12,7 @@ Task("Publish:Pack:DotNetCore") NoRestore = true, IncludeSymbols = true, Configuration = config.Solution.BuildConfiguration, - OutputDirectory = projectArtifactDirectory, - Verbosity = DotNetCoreVerbosity.Minimal + OutputDirectory = projectArtifactDirectory }; settings.MSBuildSettings = new DotNetCoreMSBuildSettings(); settings.MSBuildSettings diff --git a/.cake/Publish-Pack-NuGet.cake b/.cake/Publish-Pack-NuGet.cake index 8ff72fc..a7a875a 100644 --- a/.cake/Publish-Pack-NuGet.cake +++ b/.cake/Publish-Pack-NuGet.cake @@ -8,9 +8,11 @@ Task("Publish:Pack:NuGet") var projectArtifactDirectory = config.Artifacts.GetRootFor(ArtifactTypeOption.NuGet); foreach(var nugetProject in config.Solution.NuGetProjects) { + var properties = new Dictionary{ { "Configuration", "Release"} }; var nuGetPackSettings = new NuGetPackSettings { Version = $"{config.Version.SemVersion}", - OutputDirectory = $"{projectArtifactDirectory}/" + OutputDirectory = $"{projectArtifactDirectory}/", + Properties = properties }; NuGetPack(nugetProject.ProjectFilePath.ToString(), nuGetPackSettings); diff --git a/.cake/Publish-Zip-DotNetCore.cake b/.cake/Publish-Zip-DotNetCore.cake index 87a6eb9..a700749 100644 --- a/.cake/Publish-Zip-DotNetCore.cake +++ b/.cake/Publish-Zip-DotNetCore.cake @@ -18,8 +18,7 @@ Task("Publish:Zip:DotNetCore") { NoRestore = true, Configuration = config.Solution.BuildConfiguration, - OutputDirectory = publishDirectory, - Verbosity = DotNetCoreVerbosity.Minimal, + OutputDirectory = publishDirectory }; settings.MSBuildSettings = new DotNetCoreMSBuildSettings(); diff --git a/.cake/Test-DotNetCore.cake b/.cake/Test-DotNetCore.cake index 034ab1d..fe7cab2 100644 --- a/.cake/Test-DotNetCore.cake +++ b/.cake/Test-DotNetCore.cake @@ -3,41 +3,50 @@ Task("Test:DotNetCore") .IsDependentOn("Build") .IsDependeeOf("Test") - .WithCriteria((ctx, config) => config.Solution.TestProjects.Any()) + .WithCriteria((ctx, config) => config.Solution.TestProjects.Any(p => p.IsDotNetCliTestProject())) .Does(config => -{ - foreach(var testProject in config.Solution.TestProjects) { +{ + CreateDirectory($"{config.Artifacts.Root}/test-results"); + var testResultsRoot = $"{config.Artifacts.Root}/test-results"; + + var shouldFail = false; + foreach(var testProject in config.Solution.TestProjects.Where(p => p.IsDotNetCliTestProject())) { var assemblyName = config.Solution.GetProjectName(testProject); - var settings = new DotNetCoreTestSettings() { - Configuration = config.Solution.BuildConfiguration, - Logger = $"trx;LogFileName={config.Artifacts.Root}/test-results/{assemblyName}.xml", - NoBuild = true, - NoRestore = true - }; + var testResultsXml = $"{testResultsRoot}/{assemblyName}.xml"; + try + { + var settings = new DotNetCoreTestSettings() { + Configuration = config.Solution.BuildConfiguration, + Logger = $"trx;LogFileName={testResultsXml}", + NoBuild = true, + NoRestore = true + }; - DotNetCoreTest(testProject.ProjectFilePath.ToString(), settings); + DotNetCoreTest(testProject.ProjectFilePath.ToString(), settings); + } + catch + { + shouldFail = true; + } } -}); -Task("CI:VSTS:VSTest:PublishTestResults") - .WithCriteria((ctx, config) => BuildSystem.IsRunningOnVSTS || TFBuild.IsRunningOnTFS) - .IsDependentOn("Test") - .IsDependeeOf("Publish") - .Does(config => -{ - Information("Publishing Test results from {0}", config.Artifacts.Root); - var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").Select(file => MakeAbsolute(file)).ToArray(); + Information("Publishing Test results from {0}", testResultsRoot); + var testResults = GetFiles($"{testResultsRoot}/**/*.xml").ToArray(); if(testResults.Any()) { - TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { - Configuration = config.Solution.BuildConfiguration, - MergeTestResults = true, - TestResultsFiles = testResults, - TestRunner = TFTestRunnerType.VSTest - }); + if(BuildSystem.IsRunningOnAzurePipelinesHosted || TFBuild.IsRunningOnAzurePipelines) + { + TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { + Configuration = config.Solution.BuildConfiguration, + MergeTestResults = true, + TestResultsFiles = testResults, + TestRunner = TFTestRunnerType.VSTest + }); + } } - else + + if(shouldFail) { - Warning("No test results to publish"); + throw new Exception("Tests have failed"); } }); diff --git a/.cake/Test-NUnit2.cake b/.cake/Test-NUnit2.cake index ba17954..5ac2e98 100644 --- a/.cake/Test-NUnit2.cake +++ b/.cake/Test-NUnit2.cake @@ -4,42 +4,51 @@ Task("Test:NUnit") .IsDependentOn("Build") .IsDependeeOf("Test") - .WithCriteria((ctx, config) => config.Solution.TestProjects.Any()) + .WithCriteria((ctx, config) => config.Solution.TestProjects.Any(p => p.IsNUnitTestProject())) .Does(config => { CreateDirectory($"{config.Artifacts.Root}/test-results"); - foreach(var testProject in config.Solution.TestProjects) { + var shouldFail = false; + foreach(var testProject in config.Solution.TestProjects.Where(p => p.IsNUnitTestProject())) { var assemblyName = config.Solution.GetProjectName(testProject); - var testAssembly = $"{testProject.OutputPaths.First()}/{assemblyName}.dll"; - var settings = new NUnitSettings() { - NoLogo = true, - ResultsFile = $"{config.Artifacts.Root}/test-results/{assemblyName}.xml", - OutputFile = $"{config.Artifacts.Root}/test-results/{assemblyName}.log", - }; + var testResultsRoot = $"{config.Artifacts.Root}/test-results"; + var testResultsXml = $"{testResultsRoot}/{assemblyName}.xml"; + var testAssembly = $"{testProject.OutputPaths.FirstOrDefault().ToString()}/{assemblyName}.dll"; + + try + { + var settings = new NUnitSettings() { + NoLogo = true, + ResultsFile = testResultsXml, + OutputFile = $"{testResultsRoot}/{assemblyName}.log", + }; - NUnit(testAssembly, settings); + NUnit(testAssembly, settings); + } + catch + { + shouldFail = true; + } } -}); -Task("CI:VSTS:NUnit:PublishTestResults") - .WithCriteria((ctx, config) => BuildSystem.IsRunningOnVSTS || TFBuild.IsRunningOnTFS) - .IsDependentOn("Test") - .IsDependeeOf("Publish") - .Does(config => -{ Information("Publishing Test results from {0}", config.Artifacts.Root); - var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").Select(file => MakeAbsolute(file).ToString()).ToArray(); - TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { - Configuration = config.Solution.BuildConfiguration, - MergeTestResults = true, - TestResultsFiles = testResults, - TestRunner = TFTestRunnerType.NUnit - }); + var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").ToArray(); + if(testResults.Any()) + { + if(BuildSystem.IsRunningOnAzurePipelinesHosted || TFBuild.IsRunningOnAzurePipelines) + { + TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { + Configuration = config.Solution.BuildConfiguration, + MergeTestResults = true, + TestResultsFiles = testResults, + TestRunner = TFTestRunnerType.VSTest + }); + } + } - var testLogs = GetFiles($"{config.Artifacts.Root}/test-results/**/*.log").Select(file => MakeAbsolute(file).ToString()); - foreach(var log in testLogs) + if(shouldFail) { - TFBuild.Commands.UploadTaskLogFile(log); - } + throw new Exception("Tests have failed"); + } }); diff --git a/.cake/Test-NUnit3.cake b/.cake/Test-NUnit3.cake index 9b9bd74..57e54c4 100644 --- a/.cake/Test-NUnit3.cake +++ b/.cake/Test-NUnit3.cake @@ -1,49 +1,58 @@ -#tool "nuget:?package=NUnit.ConsoleRunner" +#tool "nuget:?package=NUnit.ConsoleRunner&version=3.10.0" #load "Configuration.cake" Task("Test:NUnit") .IsDependentOn("Build") .IsDependeeOf("Test") - .WithCriteria((ctx, config) => config.Solution.TestProjects.Any()) + .WithCriteria((ctx, config) => config.Solution.TestProjects.Any(p => p.IsNUnitTestProject())) .Does(config => { CreateDirectory($"{config.Artifacts.Root}/test-results"); - foreach(var testProject in config.Solution.TestProjects) { + var shouldFail = false; + foreach(var testProject in config.Solution.TestProjects.Where(p => p.IsNUnitTestProject())) { var assemblyName = config.Solution.GetProjectName(testProject); - var testAssembly = $"{testProject.OutputPaths.First()}/{assemblyName}.dll"; - var settings = new NUnit3Settings() { - NoHeader = true, - Configuration = config.Solution.BuildConfiguration, - Results = new[] { - new NUnit3Result { FileName = $"{config.Artifacts.Root}/test-results/{assemblyName}.xml" } - }, - OutputFile = $"{config.Artifacts.Root}/test-results/{assemblyName}.log", - }; + var testResultsRoot = $"{config.Artifacts.Root}/test-results"; + var testResultsXml = $"{testResultsRoot}/{assemblyName}.xml"; + var testAssembly = $"{testProject.OutputPaths.FirstOrDefault().ToString()}/{assemblyName}.dll"; - NUnit3(testAssembly, settings); + try + { + var settings = new NUnit3Settings() { + NoHeader = true, + Configuration = config.Solution.BuildConfiguration, + Results = new[] { + new NUnit3Result { FileName = testResultsXml } + }, + OutputFile = $"{testResultsRoot}/{assemblyName}.log", + }; + + NUnit3(testAssembly, settings); + } + catch + { + shouldFail = true; + } } -}); -Task("CI:VSTS:NUnit:PublishTestResults") - .WithCriteria((ctx, config) => BuildSystem.IsRunningOnVSTS || TFBuild.IsRunningOnTFS) - .IsDependentOn("Test") - .IsDependeeOf("Publish") - .Does(config => -{ Information("Publishing Test results from {0}", config.Artifacts.Root); - var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").Select(file => MakeAbsolute(file).ToString()).ToArray(); - TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { - Configuration = config.Solution.BuildConfiguration, - MergeTestResults = true, - TestResultsFiles = testResults, - TestRunner = TFTestRunnerType.NUnit - }); + var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").ToArray(); + if(testResults.Any()) + { + if(BuildSystem.IsRunningOnAzurePipelinesHosted || TFBuild.IsRunningOnAzurePipelines) + { + TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { + Configuration = config.Solution.BuildConfiguration, + MergeTestResults = true, + TestResultsFiles = testResults, + TestRunner = TFTestRunnerType.VSTest + }); + } + } - var testLogs = GetFiles($"{config.Artifacts.Root}/test-results/**/*.log").Select(file => MakeAbsolute(file).ToString()); - foreach(var log in testLogs) + if(shouldFail) { - TFBuild.Commands.UploadTaskLogFile(log); + throw new Exception("Tests have failed"); } -}); \ No newline at end of file +}); diff --git a/.cake/Test-XUnit2.cake b/.cake/Test-XUnit2.cake index c515627..5d6def4 100644 --- a/.cake/Test-XUnit2.cake +++ b/.cake/Test-XUnit2.cake @@ -1,46 +1,54 @@ -#tool "xunit.runner.console" +#tool "xunit.runner.console&version=2.4.1" #load "Configuration.cake" Task("Test:XUnit2") .IsDependentOn("Build") .IsDependeeOf("Test") - .WithCriteria((ctx, config) => config.Solution.TestProjects.Any()) + .WithCriteria((ctx, config) => config.Solution.TestProjects.Any(p => p.IsXUnitTestProject())) .Does(config => { CreateDirectory($"{config.Artifacts.Root}/test-results"); - foreach(var testProject in config.Solution.TestProjects) { + var shouldFail = false; + foreach(var testProject in config.Solution.TestProjects.Where(p => p.IsXUnitTestProject())) { var assemblyName = config.Solution.GetProjectName(testProject); - var testAssembly = $"{testProject.OutputPaths.First()}/{assemblyName}.dll"; - var settings = new XUnit2Settings { - XmlReport = true, - ReportName = assemblyName, - OutputDirectory = $"{config.Artifacts.Root}/test-results", - }; - - XUnit2(testAssembly, settings); + var testResultsRoot = $"{config.Artifacts.Root}/test-results"; + var testResultsXml = $"{testResultsRoot}/{assemblyName}.xml"; + var testAssembly = $"{testProject.OutputPaths.FirstOrDefault().ToString()}/{assemblyName}.dll"; + + try + { + var settings = new XUnit2Settings { + XmlReport = true, + ReportName = assemblyName, + OutputDirectory = $"{testResultsRoot}", + }; + + XUnit2(testAssembly, settings); + } + catch + { + shouldFail = true; + } } -}); -Task("CI:VSTS:XUnit:PublishTestResults") - .WithCriteria((ctx, config) => BuildSystem.IsRunningOnVSTS || TFBuild.IsRunningOnTFS) - .IsDependentOn("Test") - .IsDependeeOf("Publish") - .Does(config => -{ Information("Publishing Test results from {0}", config.Artifacts.Root); - var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").Select(file => MakeAbsolute(file)).ToList(); + var testResults = GetFiles($"{config.Artifacts.Root}/test-results/**/*.xml").ToArray(); if(testResults.Any()) { - TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { - Configuration = config.Solution.BuildConfiguration, - MergeTestResults = true, - TestResultsFiles = testResults, - TestRunner = TFTestRunnerType.XUnit - }); + if(BuildSystem.IsRunningOnAzurePipelinesHosted || TFBuild.IsRunningOnAzurePipelines) + { + TFBuild.Commands.PublishTestResults(new TFBuildPublishTestResultsData() { + Configuration = config.Solution.BuildConfiguration, + MergeTestResults = true, + TestResultsFiles = testResults, + TestRunner = TFTestRunnerType.VSTest + }); + } } - else + + if(shouldFail) { - Warning("No test results to publish"); + throw new Exception("Tests have failed"); } }); diff --git a/build.cake b/build.cake index 4a81978..f04d84f 100644 --- a/build.cake +++ b/build.cake @@ -1,16 +1,10 @@ #load ".cake/Configuration.cake" -/**********************************************************/ Setup(Configuration.Create); -/**********************************************************/ #load ".cake/CI.cake" - -// -- DotNetCore -#load ".cake/Restore-DotNetCore.cake" -#load ".cake/Build-DotNetCore.cake" -#load ".cake/Test-DotNetCore.cake" -#load ".cake/Publish-Pack-DotNetCore.cake" -// ------------- +#load ".cake/Restore-NuGet.cake" +#load ".cake/Build-MsBuild.cake" +#load ".cake/Publish-Pack-NuGet.cake" RunTarget(Argument("target", Argument("Target", "Default"))); \ No newline at end of file diff --git a/src/Storm.Umbraco.Smtp/Storm.Umbraco.Smtp.csproj b/src/Storm.Umbraco.Smtp/Storm.Umbraco.Smtp.csproj index 5c13457..0af61c2 100644 --- a/src/Storm.Umbraco.Smtp/Storm.Umbraco.Smtp.csproj +++ b/src/Storm.Umbraco.Smtp/Storm.Umbraco.Smtp.csproj @@ -6,6 +6,7 @@ false Uses configuration builders to generate an smtp section in the web config based on app settings. Owen Roberts + false diff --git a/tools/packages.config b/tools/packages.config index f27ab48..ec87d00 100644 --- a/tools/packages.config +++ b/tools/packages.config @@ -1,4 +1,4 @@ - +