|  | using Nuke.CoberturaConverter; | 
        
          |  | using Nuke.Common.Git; | 
        
          |  | using Nuke.Common.Tools.DocFx; | 
        
          |  | using Nuke.Common.Tools.DotCover; | 
        
          |  | using Nuke.Common.Tools.DotNet; | 
        
          |  | using Nuke.Common.Tools.GitVersion; | 
        
          |  | using Nuke.Common.Tools.ReportGenerator; | 
        
          |  | using Nuke.Core; | 
        
          |  | using Nuke.Core.Tooling; | 
        
          |  | using Nuke.Core.Utilities; | 
        
          |  | using Nuke.Core.Utilities.Collections; | 
        
          |  | using Nuke.GitHub; | 
        
          |  | using Nuke.WebDocu; | 
        
          |  | using System; | 
        
          |  | using System.Collections; | 
        
          |  | using System.IO; | 
        
          |  | using System.Linq; | 
        
          |  | using System.Threading.Tasks; | 
        
          |  | using System.Xml.Linq; | 
        
          |  | using System.Xml.XPath; | 
        
          |  | using static Nuke.CoberturaConverter.CoberturaConverterTasks; | 
        
          |  | using static Nuke.CodeGeneration.CodeGenerator; | 
        
          |  | using static Nuke.Common.ChangeLog.ChangelogTasks; | 
        
          |  | using static Nuke.Common.Tools.DocFx.DocFxTasks; | 
        
          |  | using static Nuke.Common.Tools.DotCover.DotCoverTasks; | 
        
          |  | using static Nuke.Common.Tools.DotNet.DotNetTasks; | 
        
          |  | using static Nuke.Common.Tools.ReportGenerator.ReportGeneratorTasks; | 
        
          |  | using static Nuke.Core.EnvironmentInfo; | 
        
          |  | using static Nuke.Core.IO.FileSystemTasks; | 
        
          |  | using static Nuke.Core.IO.PathConstruction; | 
        
          |  | using static Nuke.Core.Tooling.ProcessTasks; | 
        
          |  | using static Nuke.GitHub.ChangeLogExtensions; | 
        
          |  | using static Nuke.GitHub.GitHubTasks; | 
        
          |  | using static Nuke.WebDocu.WebDocuTasks; | 
        
          |  |  | 
        
          |  | class Build : NukeBuild | 
        
          |  | { | 
        
          |  | // Console application entry. Also defines the default target. | 
        
          |  | public static int Main() => Execute<Build>(x => x.Compile); | 
        
          |  |  | 
        
          |  | // Auto-injection fields: | 
        
          |  |  | 
        
          |  | [GitVersion] readonly GitVersion GitVersion; | 
        
          |  | // Semantic versioning. Must have 'GitVersion.CommandLine' referenced. | 
        
          |  |  | 
        
          |  | [GitRepository] readonly GitRepository GitRepository; | 
        
          |  | // Parses origin, branch name and head from git config. | 
        
          |  |  | 
        
          |  | [Parameter] string MyGetSource; | 
        
          |  | [Parameter] string MyGetApiKey; | 
        
          |  | [Parameter] string DocuApiKey; | 
        
          |  | [Parameter] string DocuApiEndpoint; | 
        
          |  | [Parameter] string GitHubAuthenticationToken; | 
        
          |  |  | 
        
          |  | string DocFxFile => SolutionDirectory / "docfx.json"; | 
        
          |  |  | 
        
          |  | // This is used to to infer which dotnet sdk version to use when generating DocFX metadata | 
        
          |  | string DocFxDotNetSdkVersion = "2.1.4"; | 
        
          |  | string ChangeLogFile => RootDirectory / "CHANGELOG.md"; | 
        
          |  |  | 
        
          |  | Target Clean => _ => _ | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | DeleteDirectories(GlobDirectories(SourceDirectory, "**/bin", "**/obj")); | 
        
          |  | DeleteDirectories(GlobDirectories(RootDirectory / "test", "**/bin", "**/obj")); | 
        
          |  | EnsureCleanDirectory(OutputDirectory); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Restore => _ => _ | 
        
          |  | .DependsOn(Clean) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | DotNetRestore(s => DefaultDotNetRestore); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Compile => _ => _ | 
        
          |  | .DependsOn(Restore) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | DotNetBuild(s => DefaultDotNetBuild | 
        
          |  | .SetFileVersion(GitVersion.GetNormalizedFileVersion()) | 
        
          |  | .SetAssemblyVersion(GitVersion.AssemblySemVer)); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Pack => _ => _ | 
        
          |  | .DependsOn(Compile) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | var changeLog = GetCompleteChangeLog(ChangeLogFile) | 
        
          |  | .EscapeStringPropertyForMsBuild(); | 
        
          |  | DotNetPack(s => DefaultDotNetPack | 
        
          |  | .SetPackageReleaseNotes(changeLog)); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Test => _ => _ | 
        
          |  | .DependsOn(Compile) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | var testProjects = GlobFiles(SolutionDirectory / "test", "*.csproj"); | 
        
          |  | var testRun = 1; | 
        
          |  | foreach (var testProject in testProjects) | 
        
          |  | { | 
        
          |  | var projectDirectory = Path.GetDirectoryName(testProject); | 
        
          |  | string testFile = OutputDirectory / $"test_{testRun++}.testresults"; | 
        
          |  | // This is so that the global dotnet is used instead of the one that comes with NUKE | 
        
          |  | var dotnetPath = ToolPathResolver.GetPathExecutable("dotnet"); | 
        
          |  |  | 
        
          |  | StartProcess(dotnetPath, "xunit " + | 
        
          |  | "-nobuild " + | 
        
          |  | $"-xml {testFile.DoubleQuoteIfNeeded()}", | 
        
          |  | workingDirectory: projectDirectory) | 
        
          |  | // AssertWairForExit() instead of AssertZeroExitCode() | 
        
          |  | // because we want to continue all tests even if some fail | 
        
          |  | .AssertWaitForExit(); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | PrependFrameworkToTestresults(); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Coverage => _ => _ | 
        
          |  | .DependsOn(Compile) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | var testProjects = GlobFiles(SolutionDirectory / "test", "*.csproj").ToList(); | 
        
          |  | for (var i = 0; i < testProjects.Count; i++) | 
        
          |  | { | 
        
          |  | var testProject = testProjects[i]; | 
        
          |  | var projectDirectory = Path.GetDirectoryName(testProject); | 
        
          |  | // This is so that the global dotnet is used instead of the one that comes with NUKE | 
        
          |  | var dotnetPath = ToolPathResolver.GetPathExecutable("dotnet"); | 
        
          |  | var snapshotIndex = i; | 
        
          |  |  | 
        
          |  | string xUnitOutputDirectory = OutputDirectory / $"test_{snapshotIndex:00}.testresults"; | 
        
          |  | DotCoverCover(c => c | 
        
          |  | .SetTargetExecutable(dotnetPath) | 
        
          |  | .SetTargetWorkingDirectory(projectDirectory) | 
        
          |  | .SetTargetArguments($"xunit -nobuild -xml {xUnitOutputDirectory.DoubleQuoteIfNeeded()}") | 
        
          |  | .SetFilters("+:CoberturaConverter.Core") | 
        
          |  | .SetAttributeFilters("System.CodeDom.Compiler.GeneratedCodeAttribute") | 
        
          |  | .SetOutputFile(OutputDirectory / $"coverage{snapshotIndex:00}.snapshot")); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | var snapshots = testProjects.Select((t, i) => OutputDirectory / $"coverage{i:00}.snapshot") | 
        
          |  | .Select(p => p.ToString()) | 
        
          |  | .Aggregate((c, n) => c + ";" + n); | 
        
          |  |  | 
        
          |  | DotCoverMerge(c => c | 
        
          |  | .SetSource(snapshots) | 
        
          |  | .SetOutputFile(OutputDirectory / "coverage.snapshot")); | 
        
          |  |  | 
        
          |  | DotCoverReport(c => c | 
        
          |  | .SetSource(OutputDirectory / "coverage.snapshot") | 
        
          |  | .SetOutputFile(OutputDirectory / "coverage.xml") | 
        
          |  | .SetReportType(DotCoverReportType.DetailedXml)); | 
        
          |  |  | 
        
          |  | // This is the report that's pretty and visualized in Jenkins | 
        
          |  | ReportGenerator(c => c | 
        
          |  | .SetReports(OutputDirectory / "coverage.xml") | 
        
          |  | .SetTargetDirectory(OutputDirectory / "CoverageReport")); | 
        
          |  |  | 
        
          |  | // This is the report in Cobertura format that integrates so nice in Jenkins | 
        
          |  | // dashboard and allows to extract more metrics and set build health based | 
        
          |  | // on coverage readings | 
        
          |  | DotCoverToCobertura(s => s | 
        
          |  | .SetInputFile(OutputDirectory / "coverage.xml") | 
        
          |  | .SetOutputFile(OutputDirectory / "cobertura_coverage.xml")) | 
        
          |  | .ConfigureAwait(false) | 
        
          |  | .GetAwaiter() | 
        
          |  | .GetResult(); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Push => _ => _ | 
        
          |  | .DependsOn(Pack) | 
        
          |  | .Requires(() => MyGetSource) | 
        
          |  | .Requires(() => MyGetApiKey) | 
        
          |  | .Requires(() => Configuration.EqualsOrdinalIgnoreCase("Release")) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | GlobFiles(OutputDirectory, "*.nupkg").NotEmpty() | 
        
          |  | .Where(x => !x.EndsWith("symbols.nupkg")) | 
        
          |  | .ForEach(x => | 
        
          |  | { | 
        
          |  | DotNetNuGetPush(s => s | 
        
          |  | .SetTargetPath(x) | 
        
          |  | .SetSource(MyGetSource) | 
        
          |  | .SetApiKey(MyGetApiKey)); | 
        
          |  | }); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target BuildDocFxMetadata => _ => _ | 
        
          |  | .DependsOn(Restore) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | // So it uses a fixed, known version of MsBuild to generate the metadata. Otherwise, | 
        
          |  | // updates of dotnet or Visual Studio could introduce incompatibilities and generation failures | 
        
          |  | var dotnetPath = Path.GetDirectoryName(ToolPathResolver.GetPathExecutable("dotnet.exe")); | 
        
          |  | var msBuildPath = Path.Combine(dotnetPath, "sdk", DocFxDotNetSdkVersion, "MSBuild.dll"); | 
        
          |  | SetVariable("MSBUILD_EXE_PATH", msBuildPath); | 
        
          |  | DocFxMetadata(DocFxFile, s => s.SetLogLevel(DocFxLogLevel.Verbose)); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target BuildDocumentation => _ => _ | 
        
          |  | .DependsOn(Clean) | 
        
          |  | .DependsOn(BuildDocFxMetadata) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | // Using README.md as index.md | 
        
          |  | if (File.Exists(SolutionDirectory / "index.md")) | 
        
          |  | { | 
        
          |  | File.Delete(SolutionDirectory / "index.md"); | 
        
          |  | } | 
        
          |  |  | 
        
          |  | File.Copy(SolutionDirectory / "README.md", SolutionDirectory / "index.md"); | 
        
          |  |  | 
        
          |  | DocFxBuild(DocFxFile, s => s | 
        
          |  | .ClearXRefMaps() | 
        
          |  | .SetLogLevel(DocFxLogLevel.Verbose)); | 
        
          |  |  | 
        
          |  | File.Delete(SolutionDirectory / "index.md"); | 
        
          |  | Directory.Delete(SolutionDirectory / "core", true); | 
        
          |  | Directory.Delete(SolutionDirectory / "cli", true); | 
        
          |  | Directory.Delete(SolutionDirectory / "nuke", true); | 
        
          |  | Directory.Delete(SolutionDirectory / "obj", true); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target UploadDocumentation => _ => _ | 
        
          |  | .DependsOn(Push) // To have a relation between pushed package version and published docs version | 
        
          |  | .DependsOn(BuildDocumentation) | 
        
          |  | .Requires(() => DocuApiKey) | 
        
          |  | .Requires(() => DocuApiEndpoint) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | WebDocu(s => s | 
        
          |  | .SetDocuApiEndpoint(DocuApiEndpoint) | 
        
          |  | .SetDocuApiKey(DocuApiKey) | 
        
          |  | .SetSourceDirectory(OutputDirectory) | 
        
          |  | .SetVersion(GitVersion.NuGetVersion) | 
        
          |  | ); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target PublishGitHubRelease => _ => _ | 
        
          |  | .DependsOn(Pack) | 
        
          |  | .Requires(() => GitHubAuthenticationToken) | 
        
          |  | .OnlyWhen(() => GitVersion.BranchName.Equals("master") || GitVersion.BranchName.Equals("origin/master")) | 
        
          |  | .Executes<Task>(async () => | 
        
          |  | { | 
        
          |  | var releaseTag = $"v{GitVersion.MajorMinorPatch}"; | 
        
          |  |  | 
        
          |  | var changeLogSectionEntries = ExtractChangelogSectionNotes(ChangeLogFile); | 
        
          |  | var latestChangeLog = changeLogSectionEntries | 
        
          |  | .Aggregate((c, n) => c + Environment.NewLine + n); | 
        
          |  | var completeChangeLog = $"## {releaseTag}" + Environment.NewLine + latestChangeLog; | 
        
          |  |  | 
        
          |  | var repositoryInfo = GetGitHubRepositoryInfo(GitRepository); | 
        
          |  | var nuGetPackages = GlobFiles(OutputDirectory, "*.nupkg").NotEmpty().ToArray(); | 
        
          |  |  | 
        
          |  | await PublishRelease(new GitHubReleaseSettings() | 
        
          |  | .SetArtifactPaths(nuGetPackages) | 
        
          |  | .SetCommitSha(GitVersion.Sha) | 
        
          |  | .SetReleaseNotes(completeChangeLog) | 
        
          |  | .SetRepositoryName(repositoryInfo.repositoryName) | 
        
          |  | .SetRepositoryOwner(repositoryInfo.gitHubOwner) | 
        
          |  | .SetTag(releaseTag) | 
        
          |  | .SetToken(GitHubAuthenticationToken)); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | Target Generate => _ => _ | 
        
          |  | .DependsOn(Restore) | 
        
          |  | .Executes(() => | 
        
          |  | { | 
        
          |  | GenerateCode( | 
        
          |  | metadataDirectory: RootDirectory / "src" / "Nuke.CoberturaConverter", | 
        
          |  | generationBaseDirectory: RootDirectory / "src" / "Nuke.CoberturaConverter", | 
        
          |  | baseNamespace: "Nuke.CoberturaConverter" | 
        
          |  | ); | 
        
          |  | }); | 
        
          |  |  | 
        
          |  | void PrependFrameworkToTestresults() | 
        
          |  | { | 
        
          |  | var testResults = GlobFiles(OutputDirectory, "*.testresults"); | 
        
          |  | foreach (var testResultFile in testResults) | 
        
          |  | { | 
        
          |  | var frameworkName = GetFrameworkNameFromFilename(testResultFile); | 
        
          |  | var xDoc = XDocument.Load(testResultFile); | 
        
          |  |  | 
        
          |  | foreach (var testType in ((IEnumerable) xDoc.XPathEvaluate("//test/@type")).OfType<XAttribute>()) | 
        
          |  | { | 
        
          |  | testType.Value = frameworkName + "+" + testType.Value; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | foreach (var testName in ((IEnumerable) xDoc.XPathEvaluate("//test/@name")).OfType<XAttribute>()) | 
        
          |  | { | 
        
          |  | testName.Value = frameworkName + "+" + testName.Value; | 
        
          |  | } | 
        
          |  |  | 
        
          |  | xDoc.Save(testResultFile); | 
        
          |  | } | 
        
          |  | } | 
        
          |  |  | 
        
          |  | string GetFrameworkNameFromFilename(string filename) | 
        
          |  | { | 
        
          |  | var name = Path.GetFileName(filename); | 
        
          |  | name = name.Substring(0, name.Length - ".testresults".Length); | 
        
          |  | var startIndex = name.LastIndexOf('-'); | 
        
          |  | name = name.Substring(startIndex + 1); | 
        
          |  | return name; | 
        
          |  | } | 
        
          |  | } |