From d75a6b4b4080e3dcacfba521181c7d60ea245dca Mon Sep 17 00:00:00 2001 From: Glenn Watson <5834289+glennawatson@users.noreply.github.com> Date: Sat, 16 Feb 2019 03:53:31 +0000 Subject: [PATCH] housekeeping: Make ReactiveUI use the new ReactiveUI.Cake.Recipe (#1953) * housekeeping: change ReactiveUI to use the common rxui cake recipe * Update azure-pipelines.yml --- azure-pipelines.yml | 64 +++++--- build.cake | 387 ++++++++------------------------------------ 2 files changed, 109 insertions(+), 342 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 950c6d5a4b..043fe9e264 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -12,11 +12,12 @@ jobs: - job: Windows pool: vmImage: vs2017-win2016 + steps: - task: DotNetCoreInstaller@0 displayName: Install Dot Net Core v2.2.1 inputs: - version: '2.2.103' + version: '2.2.103' - task: BatchScript@1 inputs: @@ -28,34 +29,61 @@ jobs: - powershell: .\build.ps1 displayName: Build env: - SIGNCLIENT_SECRET: $(SignClientSecret) - SIGNCLIENT_USER: $(SignClientUser) - ArtifactDirectory: $(System.DefaultWorkingDirectory)\artifacts + SIGNCLIENT_SECRET: $(SignClientSecret) + SIGNCLIENT_USER: $(SignClientUser) + CODECOV_TOKEN: $(CODECOV_TOKEN) + ArtifactDirectory: $(System.DefaultWorkingDirectory)\Artifacts + + - task: PublishTestResults@2 + displayName: Publish Test Results + inputs: + testResultsFormat: 'VSTest' + testResultsFiles: '**\testresults.trx' + searchFolder: '$(System.DefaultWorkingDirectory)\artifacts\tests' + + - task: PublishCodeCoverageResults@1 + displayName: Publish Coverage Results + inputs: + codeCoverageTool: 'cobertura' + summaryFileLocation: 'artifacts\tests\Report\Cobertura.xml' + reportDirectory: 'artifacts\tests\Report' - task: CopyFiles@2 inputs: - Contents: 'artifacts/packages/*.nupkg' - TargetFolder: '$(build.artifactstagingdirectory)\packages' - flattenFolders: true + Contents: 'artifacts/packages/*.nupkg' + TargetFolder: '$(build.artifactstagingdirectory)\packages' + flattenFolders: true - task: PublishBuildArtifacts@1 - displayName: Publish Package Artifacts + displayName: Publish Package Build Artifacts inputs: - pathToPublish: '$(build.artifactstagingdirectory)\packages' - artifactType: container - artifactName: Packages + pathToPublish: '$(build.artifactstagingdirectory)\packages' + artifactType: container + artifactName: Packages - task: CopyFiles@2 inputs: - Contents: 'artifacts/binaries/**/*' - TargetFolder: '$(build.artifactstagingdirectory)\binaries' + Contents: 'artifacts/binaries/**/*' + TargetFolder: '$(build.artifactstagingdirectory)\binaries' - task: PublishBuildArtifacts@1 - displayName: Publish Binaries + displayName: Publish Binaries Build Artifacts inputs: - pathToPublish: '$(build.artifactstagingdirectory)\binaries' - artifactType: container - artifactName: Binaries + pathToPublish: '$(build.artifactstagingdirectory)\binaries' + artifactType: container + artifactName: Binaries + + - task: CopyFiles@2 + inputs: + Contents: 'artifacts/tests/**/*' + TargetFolder: '$(build.artifactstagingdirectory)\tests' + + - task: PublishBuildArtifacts@1 + displayName: Publish Test Results Build Artifacts + inputs: + pathToPublish: '$(build.artifactstagingdirectory)\tests' + artifactType: container + artifactName: Tests - task: CopyFiles@2 inputs: @@ -74,7 +102,7 @@ jobs: vmImage: 'macOS-10.13' steps: - task: DotNetCoreInstaller@0 - displayName: Install Dot Net Core v2.2.1 + displayName: Install Dot Net Core v2.2.103 inputs: version: '2.2.103' diff --git a/build.cake b/build.cake index 4b1196f18c..b95a954022 100644 --- a/build.cake +++ b/build.cake @@ -2,221 +2,91 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -////////////////////////////////////////////////////////////////////// -// ADDINS -////////////////////////////////////////////////////////////////////// - -#addin "nuget:?package=Cake.FileHelpers&version=3.1.0" -#addin "nuget:?package=Cake.Codecov&version=0.5.0" -#addin "nuget:?package=Cake.Coverlet&version=2.2.1" - -////////////////////////////////////////////////////////////////////// -// MODULES -////////////////////////////////////////////////////////////////////// - -#module "nuget:?package=Cake.DotNetTool.Module&version=0.1.0" - -////////////////////////////////////////////////////////////////////// -// TOOLS -////////////////////////////////////////////////////////////////////// - -#tool "nuget:?package=vswhere&version=2.5.9" -#tool "nuget:?package=xunit.runner.console&version=2.4.1" -#tool "nuget:?package=Codecov&version=1.1.0" -#tool "nuget:?package=ReportGenerator&version=4.0.9" - -////////////////////////////////////////////////////////////////////// -// DOTNET TOOLS -////////////////////////////////////////////////////////////////////// +#load nuget:https://www.myget.org/F/reactiveui/api/v2?package=ReactiveUI.Cake.Recipe&prerelease -#tool "dotnet:?package=SignClient&version=1.0.82" -#tool "dotnet:?package=coverlet.console&version=1.4.1" -#tool "dotnet:?package=nbgv&version=2.3.38" +const string project = "ReactiveUI"; ////////////////////////////////////////////////////////////////////// -// CONSTANTS +// PROJECTS ////////////////////////////////////////////////////////////////////// -const string project = "ReactiveUI"; - // Whitelisted Packages -var packageWhitelist = new List +var packageWhitelist = new List { - "ReactiveUI", - "ReactiveUI.Testing", - "ReactiveUI.Events", - "ReactiveUI.Events.XamEssentials", - "ReactiveUI.Events.XamForms", - "ReactiveUI.Fody", - "ReactiveUI.Fody.Helpers", - "ReactiveUI.AndroidSupport", - "ReactiveUI.XamForms", + MakeAbsolute(File("./src/ReactiveUI/ReactiveUI.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Testing/ReactiveUI.Testing.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Events/ReactiveUI.Events.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Events.XamEssentials/ReactiveUI.Events.XamEssentials.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Events.XamForms/ReactiveUI.Events.XamForms.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Fody/ReactiveUI.Fody.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Fody.Helpers/ReactiveUI.Fody.Helpers.csproj")), + MakeAbsolute(File("./src/ReactiveUI.AndroidSupport/ReactiveUI.AndroidSupport.csproj")), + MakeAbsolute(File("./src/ReactiveUI.XamForms/ReactiveUI.XamForms.csproj")), }; if (IsRunningOnWindows()) { packageWhitelist.AddRange(new [] { - "ReactiveUI.Blend", - "ReactiveUI.WPF", - "ReactiveUI.Winforms", - "ReactiveUI.Events.WPF", - "ReactiveUI.Events.Winforms", + MakeAbsolute(File("./src/ReactiveUI.Blend/ReactiveUI.Blend.csproj")), + MakeAbsolute(File("./src/ReactiveUI.WPF/ReactiveUI.WPF.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Winforms/ReactiveUI.Winforms.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Events.WPF/ReactiveUI.Events.WPF.csproj")), + MakeAbsolute(File("./src/ReactiveUI.Events.Winforms/ReactiveUI.Events.Winforms.csproj")), // TODO: seems the leak tests never worked as part of the CI, fix. For the moment just make sure it compiles. - "ReactiveUI.LeakTests" + MakeAbsolute(File("./src/ReactiveUI.LeakTests/ReactiveUI.LeakTests.csproj")) }); } -var packageTestWhitelist = new List +var packageTestWhitelist = new List { - "ReactiveUI.Tests", + MakeAbsolute(File("./src/ReactiveUI.Tests/ReactiveUI.Tests.csproj")), }; if (IsRunningOnWindows()) { packageTestWhitelist.AddRange(new[] { - "ReactiveUI.Fody.Tests" + MakeAbsolute(File("./src/ReactiveUI.Fody.Tests/ReactiveUI.Fody.Tests.csproj")) }); } -var coverageTestFrameworks = new List -{ - "netcoreapp2.0" -}; - -if (IsRunningOnWindows()) -{ - coverageTestFrameworks.Add("net461"); -} - -var eventGenerators = new List<(string targetName, string destination)> +var eventGenerators = new List<(string targetName, DirectoryPath destination)> { - ("android", "src/ReactiveUI.Events/"), - ("ios", "src/ReactiveUI.Events/"), - ("mac", "src/ReactiveUI.Events/"), - ("tizen4", "src/ReactiveUI.Events/"), - ("essentials", "src/ReactiveUI.Events.XamEssentials/"), - ("tvos", "src/ReactiveUI.Events/"), - ("xamforms", "src/ReactiveUI.Events.XamForms/"), + ("android", MakeAbsolute(Directory("src/ReactiveUI.Events/"))), + ("ios", MakeAbsolute(Directory("src/ReactiveUI.Events/"))), + ("mac", MakeAbsolute(Directory("src/ReactiveUI.Events/"))), + ("tizen4", MakeAbsolute(Directory("src/ReactiveUI.Events/"))), + ("essentials", MakeAbsolute(Directory("src/ReactiveUI.Events.XamEssentials/"))), + ("tvos", MakeAbsolute(Directory("src/ReactiveUI.Events/"))), + ("xamforms", MakeAbsolute(Directory("src/ReactiveUI.Events.XamForms/"))), }; if (IsRunningOnWindows()) { eventGenerators.AddRange(new [] { - ("wpf", "src/ReactiveUI.Events.WPF/"), - ("uwp", "src/ReactiveUI.Events/"), - ("winforms", "src/ReactiveUI.Events.Winforms/"), + ("wpf", MakeAbsolute(Directory("src/ReactiveUI.Events.WPF/"))), + ("uwp", MakeAbsolute(Directory("src/ReactiveUI.Events/"))), + ("winforms", MakeAbsolute(Directory("src/ReactiveUI.Events.Winforms/"))), }); } ////////////////////////////////////////////////////////////////////// -// ARGUMENTS -////////////////////////////////////////////////////////////////////// - -var target = Argument("target", "Default"); -if (string.IsNullOrWhiteSpace(target)) -{ - target = "Default"; -} - -var configuration = Argument("configuration", "Release"); -if (string.IsNullOrWhiteSpace(configuration)) -{ - configuration = "Release"; -} - -var includePrerelease = Argument("includePrerelease", false); -var vsLocationString = Argument("vsLocation", string.Empty); -var msBuildPathString = Argument("msBuildPath", string.Empty); - -////////////////////////////////////////////////////////////////////// -// PREPARATION +// SETUP ////////////////////////////////////////////////////////////////////// -// Should MSBuild treat any errors as warnings? -var treatWarningsAsErrors = false; +Environment.SetVariableNames(); -// Build configuration -var local = BuildSystem.IsLocalBuild; -var isPullRequest = !string.IsNullOrWhiteSpace(Environment.GetEnvironmentVariable("SYSTEM_PULLREQUEST_PULLREQUESTNUMBER")); -var isRepository = StringComparer.OrdinalIgnoreCase.Equals($"reactiveui/{project}", TFBuild.Environment.Repository.RepoName); +BuildParameters.SetParameters(context: Context, + buildSystem: BuildSystem, + title: project, + whitelistPackages: packageWhitelist, + whitelistTestPackages: packageTestWhitelist, + artifactsDirectory: "./artifacts", + sourceDirectory: "./src"); -FilePath msBuildPath = null; -DirectoryPath referenceAssembliesPath = null; -if (IsRunningOnWindows()) -{ - var vsWhereSettings = new VSWhereLatestSettings() { IncludePrerelease = includePrerelease }; - var vsLocation = string.IsNullOrWhiteSpace(vsLocationString) ? VSWhereLatest(vsWhereSettings) : new DirectoryPath(vsLocationString); - msBuildPath = string.IsNullOrWhiteSpace(msBuildPathString) ? vsLocation.CombineWithFilePath("./MSBuild/15.0/Bin/MSBuild.exe") : new FilePath(msBuildPathString); - referenceAssembliesPath = vsLocation.Combine("./Common7/IDE/ReferenceAssemblies/Microsoft/Framework"); -} -else -{ - referenceAssembliesPath = Directory("⁨/Library⁩/Frameworks⁩/Libraries/⁨mono⁩"); -} - -////////////////////////////////////////////////////////////////////// -// FOLDERS -////////////////////////////////////////////////////////////////////// - -// Artifacts -var artifactDirectory = "./artifacts/"; -var testsArtifactDirectory = artifactDirectory + "tests/"; -var binariesArtifactDirectory = artifactDirectory + "binaries/"; -var packagesArtifactDirectory = artifactDirectory + "packages/"; -var eventsArtifactDirectory = artifactDirectory + "Events/"; - -/////////////////////////////////////////////////////////////////////////////// -// SETUP / TEARDOWN -/////////////////////////////////////////////////////////////////////////////// -Setup(context => -{ - StartProcess(Context.Tools.Resolve("nbgv*").ToString(), "cloud"); - - CleanDirectories(artifactDirectory); - CreateDirectory(testsArtifactDirectory); - CreateDirectory(binariesArtifactDirectory); - CreateDirectory(packagesArtifactDirectory); - CreateDirectory(eventsArtifactDirectory); -}); - -Teardown(context => -{ - // Executed AFTER the last task. -}); - -////////////////////////////////////////////////////////////////////// -// HELPER METHODS -////////////////////////////////////////////////////////////////////// -Action Build = (solution, packageOutputPath, doNotOptimise) => -{ - Information("Building {0} using {1}", solution, msBuildPath); - - var msBuildSettings = new MSBuildSettings() { - ToolPath = msBuildPath, - ArgumentCustomization = args => args.Append("/m /NoWarn:VSX1000"), - NodeReuse = false, - Restore = true - } - .WithProperty("TreatWarningsAsErrors", treatWarningsAsErrors.ToString()) - .SetConfiguration(configuration) - .WithTarget("build;pack") - .SetVerbosity(Verbosity.Minimal); - - if (!string.IsNullOrWhiteSpace(packageOutputPath)) - { - msBuildSettings = msBuildSettings.WithProperty("PackageOutputPath", MakeAbsolute(Directory(packageOutputPath)).ToString().Quote()); - } - - if (doNotOptimise) - { - msBuildSettings = msBuildSettings.WithProperty("Optimize", "False"); - } - - MSBuild(solution, msBuildSettings); -}; +ToolSettings.SetToolSettings(context: Context); ////////////////////////////////////////////////////////////////////// // TASKS @@ -225,15 +95,28 @@ Action Build = (solution, packageOutputPath, doNotOptimise Task("BuildEventBuilder") .Does(() => { - Build("./src/EventBuilder.sln", artifactDirectory + "eventbuilder", false); + BuildProject("./src/EventBuilder.sln", false); }); Task("GenerateEvents") .IsDependentOn("BuildEventBuilder") .Does (() => { + var eventsArtifactDirectory = BuildParameters.ArtifactsDirectory.Combine("Events"); + EnsureDirectoryExists(eventsArtifactDirectory); + var workingDirectory = MakeAbsolute(Directory("./src/EventBuilder/bin/Release/netcoreapp2.1")); - var eventBuilder = workingDirectory + "/EventBuilder.dll"; + var eventBuilder = workingDirectory.CombineWithFilePath("EventBuilder.dll"); + + DirectoryPath referenceAssembliesPath = null; + if (IsRunningOnWindows()) + { + referenceAssembliesPath = ToolSettings.VsLocation.Combine("./Common7/IDE/ReferenceAssemblies/Microsoft/Framework"); + } + else + { + referenceAssembliesPath = Directory("⁨/Library⁩/Frameworks⁩/Libraries/⁨mono⁩"); + } foreach (var eventGenerator in eventGenerators) { @@ -245,7 +128,7 @@ Task("GenerateEvents") }; var filename = String.Format("Events_{0}.cs", platform); - var output = MakeAbsolute(File(System.IO.Path.Combine(directory, filename))).ToString().Quote(); + var output = directory.CombineWithFilePath(filename); Information("Generating events for '{0}'", platform); DotNetCoreExecute( @@ -253,163 +136,19 @@ Task("GenerateEvents") new ProcessArgumentBuilder() .AppendSwitch("--platform","=", platform) .AppendSwitchQuoted("--reference","=", referenceAssembliesPath.ToString()) - .AppendSwitchQuoted("--output-path", "=", output), + .AppendSwitchQuoted("--output-path", "=", output.ToString()), settings); Information("The events have been written to '{0}'", output); } - CopyFiles(GetFiles("./src/ReactiveUI.**/Events_*.cs"), Directory(eventsArtifactDirectory)); -}); - -Task("Build") - .IsDependentOn("GenerateEvents") - .Does (() => -{ - - // Clean the directories since we'll need to re-generate the debug type. - CleanDirectories($"./src/**/obj/{configuration}"); - CleanDirectories($"./src/**/bin/{configuration}"); - - foreach(var packageName in packageWhitelist) - { - Build($"./src/{packageName}/{packageName}.csproj", packagesArtifactDirectory, false); - } - - CopyFiles(GetFiles($"./src/**/bin/{configuration}/**/*"), Directory(binariesArtifactDirectory), true); + CopyFiles(GetFiles("./src/ReactiveUI.**/Events_*.cs"), eventsArtifactDirectory); }); -Task("RunUnitTests") - .Does(() => -{ - foreach (var packageName in packageTestWhitelist) - { - var projectName = $"./src/{packageName}/{packageName}.csproj"; - Build(projectName, null, true); - - foreach (var testFramework in coverageTestFrameworks) - { - Information($"Performing coverage tests on {packageName} on framework {testFramework}"); - - var testFile = $"./src/{packageName}/bin/{configuration}/{testFramework}/{packageName}.dll"; - - StartProcess(Context.Tools.Resolve("coverlet*").ToString(), new ProcessSettings { - RedirectStandardOutput = true, - RedirectStandardError = true, - Arguments = new ProcessArgumentBuilder() - .AppendQuoted(testFile) - .AppendSwitch("--include", $"[{project}*]*") - .AppendSwitch("--exclude", "[*.Tests*]*") - .AppendSwitch("--exclude", "[*]*Legacy*") - .AppendSwitch("--exclude", "[*]*ThisAssembly*") - .AppendSwitch("--exclude-by-file", "*ApprovalTests*") - .AppendSwitchQuoted("--output", testsArtifactDirectory + $"testcoverage-{packageName}-{testFramework}.xml") - .AppendSwitch("--format", "cobertura") - .AppendSwitch("--target", "dotnet") - .AppendSwitchQuoted("--targetargs", $"test {projectName} --no-build -c {configuration} --logger:trx;LogFileName=testresults-{packageName}-{testFramework}.trx -r {MakeAbsolute(Directory(testsArtifactDirectory))}") - }); - - Information($"Finished coverage testing {packageName}"); - } - } - - // Generate both a summary and a combined summary. - ReportGenerator( - GetFiles($"{testsArtifactDirectory}**/testcoverage-*.xml"), - testsArtifactDirectory + "report/", - new ReportGeneratorSettings - { - ReportTypes = new[] { ReportGeneratorReportType.Cobertura, ReportGeneratorReportType.Html }, - }); -}) -.ReportError(exception => -{ - var apiApprovals = GetFiles("./**/ApiApprovalTests.*"); - CopyFiles(apiApprovals, artifactDirectory); -}); - -Task("UploadTestCoverage") - .WithCriteria(() => !local) - .WithCriteria(() => isRepository) - .IsDependentOn("RunUnitTests") - .Does(() => -{ - // Resolve the API key. - var token = EnvironmentVariable("CODECOV_TOKEN"); - - if(EnvironmentVariable("CODECOV_TOKEN") == null) - { - throw new Exception("Codecov token not found, not sending code coverage data."); - } - - if (!string.IsNullOrEmpty(token)) - { - var testCoverageOutputFile = MakeAbsolute(File(testsArtifactDirectory + "Report/Cobertura.xml")); - - Information("Upload {0} to Codecov server", testCoverageOutputFile); - - // Upload a coverage report. - Codecov(testCoverageOutputFile.ToString(), token); - } -}); - -Task("SignPackages") - .IsDependentOn("Build") - .WithCriteria(() => !local) - .WithCriteria(() => !isPullRequest) - .Does(() => -{ - if(EnvironmentVariable("SIGNCLIENT_SECRET") == null) - { - throw new Exception("Client Secret not found, not signing packages."); - } - - var nupkgs = GetFiles(packagesArtifactDirectory + "*.nupkg"); - foreach(FilePath nupkg in nupkgs) - { - var packageName = nupkg.GetFilenameWithoutExtension(); - Information($"Submitting {packageName} for signing"); - - StartProcess(Context.Tools.Resolve("SignClient*").ToString(), new ProcessSettings { - RedirectStandardOutput = true, - RedirectStandardError = true, - Arguments = new ProcessArgumentBuilder() - .Append("sign") - .AppendSwitch("-c", "./SignPackages.json") - .AppendSwitch("-i", nupkg.FullPath) - .AppendSwitch("-r", EnvironmentVariable("SIGNCLIENT_USER")) - .AppendSwitch("-s", EnvironmentVariable("SIGNCLIENT_SECRET")) - .AppendSwitch("-n", "ReactiveUI") - .AppendSwitch("-d", "ReactiveUI") - .AppendSwitch("-u", "https://reactiveui.net") - }); - - Information($"Finished signing {packageName}"); - } - - Information("Sign-package complete"); -}); - -Task("Package") - .IsDependentOn("Build") - .IsDependentOn("SignPackages") - .Does (() => -{ -}); - -////////////////////////////////////////////////////////////////////// -// TASK TARGETS -////////////////////////////////////////////////////////////////////// - -Task("Default") - .IsDependentOn("Package") - .IsDependentOn("RunUnitTests") - .Does (() => -{ -}); +BuildParameters.Tasks.BuildTask.IsDependentOn("GenerateEvents"); ////////////////////////////////////////////////////////////////////// // EXECUTION ////////////////////////////////////////////////////////////////////// -RunTarget(target); \ No newline at end of file +Build.Run(); \ No newline at end of file