Skip to content

Instantly share code, notes, and snippets.

@GeorgDangl
Last active July 27, 2022 01:21
Show Gist options
  • Save GeorgDangl/ad40b2b8b5871f6f7b432946e6907f9c to your computer and use it in GitHub Desktop.
Save GeorgDangl/ad40b2b8b5871f6f7b432946e6907f9c to your computer and use it in GitHub Desktop.

Revisions

  1. GeorgDangl revised this gist Mar 15, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion .build.csproj
    Original file line number Diff line number Diff line change
    @@ -9,7 +9,7 @@
    <NoWarn>CS0649;CS0169</NoWarn>

    <!-- NUKE CONFIGURATION -->
    <NukeVersion>0.2.0</NukeVersion>
    <NukeVersion>0.2.26</NukeVersion>
    </PropertyGroup>

    <ItemGroup>
  2. GeorgDangl revised this gist Mar 15, 2018. 2 changed files with 53 additions and 55 deletions.
    102 changes: 47 additions & 55 deletions Build.cs
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,10 @@
    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;
    @@ -20,10 +22,13 @@
    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;
    @@ -34,27 +39,30 @@ class Build : NukeBuild
    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.

    // Parameters, passed via script invokation in the form of
    // -MyGetSource "https://myget.org/f/my-feed"
    [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);
    });

    @@ -93,14 +101,16 @@ class Build : NukeBuild
    foreach (var testProject in testProjects)
    {
    var projectDirectory = Path.GetDirectoryName(testProject);
    var dotnetXunitSettings = new DotNetSettings()
    // Need to set it here, otherwise it takes the one from NUKEs .tmp directory
    .SetToolPath(ToolPathResolver.GetPathExecutable("dotnet"))
    .SetWorkingDirectory(projectDirectory)
    .SetArgumentConfigurator(c => c.Add("xunit")
    .Add("-nobuild")
    .Add("-xml {value}", "\"" + OutputDirectory / $"test_{testRun++}.testresults" + "\""));
    ProcessTasks.StartProcess(dotnetXunitSettings)
    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();
    }

    @@ -112,58 +122,41 @@ class Build : NukeBuild
    .Executes(() =>
    {
    var testProjects = GlobFiles(SolutionDirectory / "test", "*.csproj").ToList();
    var dotnetPath = ToolPathResolver.GetPathExecutable("dotnet");
    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;
    var toolSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("cover")
    .Add($"/TargetExecutable=\"{dotnetPath}\"")
    .Add($"/TargetWorkingDir=\"{projectDirectory}\"")
    .Add($"/TargetArguments=\"xunit -nobuild -xml \"\"{OutputDirectory / $"test_{snapshotIndex:00}.testresults"}\"\"\"")
    .Add("/Filters=\"+:CoberturaConverter.Core\"")
    .Add("/AttributeFilters=\"System.CodeDom.Compiler.GeneratedCodeAttribute\"")
    .Add($"/Output=\"{OutputDirectory / $"coverage{snapshotIndex:00}.snapshot"}\""));
    ProcessTasks.StartProcess(toolSettings)
    .AssertZeroExitCode();

    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);

    var mergeSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("merge")
    .Add($"/Source=\"{snapshots}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.snapshot"}\""));
    ProcessTasks.StartProcess(mergeSettings)
    .AssertZeroExitCode();

    var reportSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("report")
    .Add($"/Source=\"{OutputDirectory / "coverage.snapshot"}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.xml"}\"")
    .Add("/ReportType=\"DetailedXML\""));
    ProcessTasks.StartProcess(reportSettings)
    .AssertZeroExitCode();
    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
    var reportGeneratorSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("ReportGenerator", "tools/ReportGenerator.exe"))
    .SetArgumentConfigurator(a => a
    .Add($"-reports:\"{OutputDirectory / "coverage.xml"}\"")
    .Add($"-targetdir:\"{OutputDirectory / "CoverageReport"}\""));
    ProcessTasks.StartProcess(reportGeneratorSettings)
    .AssertZeroExitCode();
    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
    @@ -198,12 +191,11 @@ class Build : NukeBuild
    .DependsOn(Restore)
    .Executes(() =>
    {
    if (IsLocalBuild)
    {
    SetVariable("VSINSTALLDIR", @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional");
    SetVariable("VisualStudioVersion", "15.0");
    }

    // 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));
    });

    6 changes: 6 additions & 0 deletions NuGet.config
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,6 @@
    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
    <packageSources>
    <add key="NukeMyGet" value="https://www.myget.org/F/nukebuild/api/v3/index.json" protocolVersion="3" />
    </packageSources>
    </configuration>
  3. GeorgDangl revised this gist Mar 12, 2018. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions Build.cs
    Original file line number Diff line number Diff line change
    @@ -128,7 +128,7 @@ class Build : NukeBuild
    .Add($"/TargetArguments=\"xunit -nobuild -xml \"\"{OutputDirectory / $"test_{snapshotIndex:00}.testresults"}\"\"\"")
    .Add("/Filters=\"+:CoberturaConverter.Core\"")
    .Add("/AttributeFilters=\"System.CodeDom.Compiler.GeneratedCodeAttribute\"")
    .Add($"/Output={(OutputDirectory / $"coverage{snapshotIndex:00}.snapshot").DoubleQuote()}"));
    .Add($"/Output=\"{OutputDirectory / $"coverage{snapshotIndex:00}.snapshot"}\""));
    ProcessTasks.StartProcess(toolSettings)
    .AssertZeroExitCode();
    }
    @@ -142,16 +142,16 @@ class Build : NukeBuild
    .SetArgumentConfigurator(a => a
    .Add("merge")
    .Add($"/Source=\"{snapshots}\"")
    .Add($"/Output={(OutputDirectory / "coverage.snapshot").DoubleQuote()}"));
    .Add($"/Output=\"{OutputDirectory / "coverage.snapshot"}\""));
    ProcessTasks.StartProcess(mergeSettings)
    .AssertZeroExitCode();

    var reportSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("report")
    .Add($"/Source={(OutputDirectory / "coverage.snapshot").DoubleQuote()}")
    .Add($"/Output={(OutputDirectory / "coverage.xml").DoubleQuote()}")
    .Add($"/Source=\"{OutputDirectory / "coverage.snapshot"}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.xml"}\"")
    .Add("/ReportType=\"DetailedXML\""));
    ProcessTasks.StartProcess(reportSettings)
    .AssertZeroExitCode();
    @@ -160,8 +160,8 @@ class Build : NukeBuild
    var reportGeneratorSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("ReportGenerator", "tools/ReportGenerator.exe"))
    .SetArgumentConfigurator(a => a
    .Add($"-reports:{(OutputDirectory / "coverage.xml").DoubleQuote()}")
    .Add($"-targetdir:{(OutputDirectory / "CoverageReport").DoubleQuote()}"));
    .Add($"-reports:\"{OutputDirectory / "coverage.xml"}\"")
    .Add($"-targetdir:\"{OutputDirectory / "CoverageReport"}\""));
    ProcessTasks.StartProcess(reportGeneratorSettings)
    .AssertZeroExitCode();

  4. GeorgDangl revised this gist Mar 12, 2018. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions JenkinsDeployConfig.ps1
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    ./build.ps1 UploadDocumentation+PublishGitHubRelease `
    -MyGetSource $env:MyGetPushSource `
    -MyGetSource $env:MyGetSource `
    -MyGetApiKey $env:MyGetApiKey `
    -DocuApiKey $env:DocsApiKey `
    -DocuApiEndpoint $env:DocsApi `
    -DocuApiKey $env:DocuApiKey `
    -DocuApiEndpoint $env:DocuApiEndpoint `
    -GitHubAuthenticationToken $env:GitHubAuthenticationToken
  5. GeorgDangl revised this gist Mar 6, 2018. No changes.
  6. GeorgDangl revised this gist Mar 6, 2018. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions Build.cs
    Original file line number Diff line number Diff line change
    @@ -128,7 +128,7 @@ class Build : NukeBuild
    .Add($"/TargetArguments=\"xunit -nobuild -xml \"\"{OutputDirectory / $"test_{snapshotIndex:00}.testresults"}\"\"\"")
    .Add("/Filters=\"+:CoberturaConverter.Core\"")
    .Add("/AttributeFilters=\"System.CodeDom.Compiler.GeneratedCodeAttribute\"")
    .Add($"/Output=\"{OutputDirectory / $"coverage{snapshotIndex:00}.snapshot"}\""));
    .Add($"/Output={(OutputDirectory / $"coverage{snapshotIndex:00}.snapshot").DoubleQuote()}"));
    ProcessTasks.StartProcess(toolSettings)
    .AssertZeroExitCode();
    }
    @@ -142,16 +142,16 @@ class Build : NukeBuild
    .SetArgumentConfigurator(a => a
    .Add("merge")
    .Add($"/Source=\"{snapshots}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.snapshot"}\""));
    .Add($"/Output={(OutputDirectory / "coverage.snapshot").DoubleQuote()}"));
    ProcessTasks.StartProcess(mergeSettings)
    .AssertZeroExitCode();

    var reportSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("report")
    .Add($"/Source=\"{OutputDirectory / "coverage.snapshot"}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.xml"}\"")
    .Add($"/Source={(OutputDirectory / "coverage.snapshot").DoubleQuote()}")
    .Add($"/Output={(OutputDirectory / "coverage.xml").DoubleQuote()}")
    .Add("/ReportType=\"DetailedXML\""));
    ProcessTasks.StartProcess(reportSettings)
    .AssertZeroExitCode();
    @@ -160,8 +160,8 @@ class Build : NukeBuild
    var reportGeneratorSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("ReportGenerator", "tools/ReportGenerator.exe"))
    .SetArgumentConfigurator(a => a
    .Add($"-reports:\"{OutputDirectory / "coverage.xml"}\"")
    .Add($"-targetdir:\"{OutputDirectory / "CoverageReport"}\""));
    .Add($"-reports:{(OutputDirectory / "coverage.xml").DoubleQuote()}")
    .Add($"-targetdir:{(OutputDirectory / "CoverageReport").DoubleQuote()}"));
    ProcessTasks.StartProcess(reportGeneratorSettings)
    .AssertZeroExitCode();

  7. GeorgDangl revised this gist Mar 4, 2018. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions JenkinsDeployConfig.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,6 @@
    ./build.ps1 UploadDocumentation+PublishGitHubRelease `
    -MyGetSource $env:MyGetPushSource `
    -MyGetApiKey $env:MyGetApiKey `
    -DocuApiKey $env:DocsApiKey `
    -DocuApiEndpoint $env:DocsApi `
    -GitHubAuthenticationToken $env:GitHubAuthenticationToken
  8. GeorgDangl revised this gist Mar 4, 2018. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions GitVersion.yml
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    assembly-versioning-scheme: MajorMinorPatch
    assembly-file-versioning-scheme: MajorMinorPatch

    branches:
    master:
    regex: (origin/)?master
    develop:
    increment: Patch
    tag: beta
    regex: (origin/)?dev(elop)?(ment)?$
  9. GeorgDangl revised this gist Mar 4, 2018. 1 changed file with 6 additions and 0 deletions.
    6 changes: 6 additions & 0 deletions NukeBuildConfiguration.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,6 @@
    /// <summary>
    /// Configuration to build. Default is <em>Debug</em> (local) or <em>Release</em> (server).
    /// </summary>
    [Parameter("Configuration to build. Default is 'Debug' (local) or 'Release' (server).")]
    public string Configuration { get; } = EnvironmentInfo.IsLocalBuild ? "Debug" : "Release";

  10. GeorgDangl revised this gist Mar 4, 2018. 1 changed file with 37 additions and 0 deletions.
    37 changes: 37 additions & 0 deletions .build.csproj
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,37 @@
    <Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <RootNamespace></RootNamespace>
    <IsPackable>False</IsPackable>
    <NoWarn>CS0649;CS0169</NoWarn>

    <!-- NUKE CONFIGURATION -->
    <NukeVersion>0.2.0</NukeVersion>
    </PropertyGroup>

    <ItemGroup>
    <PackageReference Include="Nuke.Common" Version="$(NukeVersion)" />
    <PackageReference Include="Nuke.CodeGeneration" Version="$(NukeVersion)" />
    <PackageReference Include="GitVersion.CommandLine" Version="4.0.0-beta0012" />
    <PackageReference Include="Nuke.WebDocu" Version="1.0.2" />
    <PackageReference Include="Nuke.GitHub" Version="1.0.2" />
    <PackageReference Include="JetBrains.dotCover.CommandLineTools" Version="2018.1.0-eap01" />
    <PackageReference Include="ReportGenerator" Version="3.1.2" />
    <PackageReference Include="docfx.console" Version="2.31.0">
    <ExcludeAssets>build</ExcludeAssets>
    </PackageReference>
    </ItemGroup>

    <ItemGroup>
    <NukeMetadata Include="**/*.json" Exclude="bin/**;obj/**" />
    <None Remove="*.csproj.DotSettings;*.ref.*.txt" />
    </ItemGroup>

    <ItemGroup>
    <ProjectReference Include="..\src\Nuke.CoberturaConverter\Nuke.CoberturaConverter.csproj" />
    </ItemGroup>

    </Project>
  11. GeorgDangl revised this gist Mar 4, 2018. 1 changed file with 10 additions and 0 deletions.
    10 changes: 10 additions & 0 deletions CHANGELOG.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    # Changelog

    All notable changes to **CoberturaConverter** are documented here.

    ## v1.0.1
    - Support nested types when converting from dotCover
    - Exclude types without lines when converting from dotCover to Cobertura

    ## v1.0.0
    - Initial Release
  12. GeorgDangl revised this gist Mar 4, 2018. 1 changed file with 3 additions and 0 deletions.
    3 changes: 3 additions & 0 deletions NUKE_init.ps1
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,3 @@
    # PowerShell
    powershell -Command iwr https://nuke.build/powershell -OutFile setup.ps1
    powershell -ExecutionPolicy ByPass -File ./setup.ps1
  13. GeorgDangl created this gist Mar 4, 2018.
    316 changes: 316 additions & 0 deletions Build.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,316 @@
    using Nuke.CoberturaConverter;
    using Nuke.Common.Git;
    using Nuke.Common.Tools.DocFx;
    using Nuke.Common.Tools.DotNet;
    using Nuke.Common.Tools.GitVersion;
    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.DotNet.DotNetTasks;
    using static Nuke.Core.EnvironmentInfo;
    using static Nuke.Core.IO.FileSystemTasks;
    using static Nuke.Core.IO.PathConstruction;
    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.

    // Parameters, passed via script invokation in the form of
    // -MyGetSource "https://myget.org/f/my-feed"
    [Parameter] string MyGetSource;
    [Parameter] string MyGetApiKey;
    [Parameter] string DocuApiKey;
    [Parameter] string DocuApiEndpoint;
    [Parameter] string GitHubAuthenticationToken;

    string DocFxFile => SolutionDirectory / "docfx.json";
    string ChangeLogFile => RootDirectory / "CHANGELOG.md";

    Target Clean => _ => _
    .Executes(() =>
    {
    DeleteDirectories(GlobDirectories(SourceDirectory, "**/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);
    var dotnetXunitSettings = new DotNetSettings()
    // Need to set it here, otherwise it takes the one from NUKEs .tmp directory
    .SetToolPath(ToolPathResolver.GetPathExecutable("dotnet"))
    .SetWorkingDirectory(projectDirectory)
    .SetArgumentConfigurator(c => c.Add("xunit")
    .Add("-nobuild")
    .Add("-xml {value}", "\"" + OutputDirectory / $"test_{testRun++}.testresults" + "\""));
    ProcessTasks.StartProcess(dotnetXunitSettings)
    .AssertWaitForExit();
    }

    PrependFrameworkToTestresults();
    });

    Target Coverage => _ => _
    .DependsOn(Compile)
    .Executes(() =>
    {
    var testProjects = GlobFiles(SolutionDirectory / "test", "*.csproj").ToList();
    var dotnetPath = ToolPathResolver.GetPathExecutable("dotnet");
    for (var i = 0; i < testProjects.Count; i++)
    {
    var testProject = testProjects[i];

    var projectDirectory = Path.GetDirectoryName(testProject);
    var snapshotIndex = i;
    var toolSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("cover")
    .Add($"/TargetExecutable=\"{dotnetPath}\"")
    .Add($"/TargetWorkingDir=\"{projectDirectory}\"")
    .Add($"/TargetArguments=\"xunit -nobuild -xml \"\"{OutputDirectory / $"test_{snapshotIndex:00}.testresults"}\"\"\"")
    .Add("/Filters=\"+:CoberturaConverter.Core\"")
    .Add("/AttributeFilters=\"System.CodeDom.Compiler.GeneratedCodeAttribute\"")
    .Add($"/Output=\"{OutputDirectory / $"coverage{snapshotIndex:00}.snapshot"}\""));
    ProcessTasks.StartProcess(toolSettings)
    .AssertZeroExitCode();
    }

    var snapshots = testProjects.Select((t, i) => OutputDirectory / $"coverage{i:00}.snapshot")
    .Select(p => p.ToString())
    .Aggregate((c, n) => c + ";" + n);

    var mergeSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("merge")
    .Add($"/Source=\"{snapshots}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.snapshot"}\""));
    ProcessTasks.StartProcess(mergeSettings)
    .AssertZeroExitCode();

    var reportSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("JetBrains.dotCover.CommandLineTools", "tools/dotCover.exe"))
    .SetArgumentConfigurator(a => a
    .Add("report")
    .Add($"/Source=\"{OutputDirectory / "coverage.snapshot"}\"")
    .Add($"/Output=\"{OutputDirectory / "coverage.xml"}\"")
    .Add("/ReportType=\"DetailedXML\""));
    ProcessTasks.StartProcess(reportSettings)
    .AssertZeroExitCode();

    // This is the report that's pretty and visualized in Jenkins
    var reportGeneratorSettings = new ToolSettings()
    .SetToolPath(ToolPathResolver.GetPackageExecutable("ReportGenerator", "tools/ReportGenerator.exe"))
    .SetArgumentConfigurator(a => a
    .Add($"-reports:\"{OutputDirectory / "coverage.xml"}\"")
    .Add($"-targetdir:\"{OutputDirectory / "CoverageReport"}\""));
    ProcessTasks.StartProcess(reportGeneratorSettings)
    .AssertZeroExitCode();

    // 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(() =>
    {
    if (IsLocalBuild)
    {
    SetVariable("VSINSTALLDIR", @"C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional");
    SetVariable("VisualStudioVersion", "15.0");
    }

    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;
    }
    }