зеркало из
1
0
Форкнуть 0

Use dev00001 build of common NUnit cake recipe

This commit is contained in:
Charlie Poole 2024-07-14 18:17:14 -07:00
Родитель 43310d4216
Коммит 3a021451be
31 изменённых файлов: 5 добавлений и 3086 удалений

Просмотреть файл

@ -19,3 +19,4 @@ environment:
secure: aDsu1U+umVYFVybjkBVtVQsatSj3QKbD7VkGQci9mNF3493g9Giao/GABISIaHjT
GITHUB_ACCESS_TOKEN:
secure: xmGXWrw5Nj3CI3fPxhw/DWIU5YL/1mM06pSmjpkd9LpKs3t3EYXbECbEQs62lU/O
IGNORE_NORMALISATION_GIT_HEAD_MOVE: 1

Просмотреть файл

@ -1,14 +1,11 @@
#tool NuGet.CommandLine&version=6.9.1
#tool nuget:?package=GitVersion.CommandLine&version=5.6.3
#tool nuget:?package=GitReleaseManager&version=0.17.0
#tool nuget:?package=NUnit.ConsoleRunner&version=3.17.0
#tool nuget:?package=NUnit.ConsoleRunner&version=3.15.5
#tool nuget:?package=NUnit.ConsoleRUnner&version=3.17.0
#tool nuget:?package=NUnit.ConsoleRunner&version=3.18.0-dev00037
#tool nuget:?package=NUnit.ConsoleRunner.NetCore&version=3.18.0-dev00037
// Load scripts
#load recipe/*.cake
#load nuget:?package=NUnit.Cake.Recipe&version=1.0.0-dev00001
//#load ../NUnit.Cake.Recipe/recipe/*.cake
// Initialize BuildSettings
BuildSettings.Initialize(
@ -16,12 +13,8 @@ BuildSettings.Initialize(
"NUnit Project Loader",
"nunit-project-loader",
solutionFile: "nunit-project-loader.sln",
//unitTestRunner: new NUnitLiteRunner(),
//unitTests: "**/*.Tests.exe");
unitTestRunner: new NUnitConsoleRunner("3.17.0"),
unitTests: "**/*.Tests.dll");
//unitTestRunner: new NUnitNetCoreConsoleRunner("3.18.0-dev00037"),
//unitTests: "**/*.Tests.dll");
unitTestRunner: new NUnitLiteRunner(),
unitTests: "**/*.Tests.exe");
//////////////////////////////////////////////////////////////////////
// PACKAGE TESTS
@ -100,11 +93,6 @@ BuildSettings.Packages.Add(
HasDirectory("tools/net6.0").WithFiles("nunit-project-loader.dll", "nunit.engine.api.dll") },
tests: PackageTests,
testRunnerSource: new TestRunnerSource(new NUnitConsoleRunner("3.17.0"), new NUnitConsoleRunner("3.15.5"), new NUnitConsoleRunner("3.18.0-dev00037"))
//testRunner: new NUnitConsoleRunner("3.17.0")
//testRunner: new NUnitConsoleRunner("3.15.5")
//testRunner: new NUnitConsoleRunner("3.18.0-dev00037")
//testRunner: new NUnitNetCoreConsoleRunner("3.18.0-dev00037")
//testRunner: new EngineExtensionTestRunner()
));
//////////////////////////////////////////////////////////////////////
@ -121,10 +109,6 @@ BuildSettings.Packages.Add(
HasDirectory("tools/net6.0").WithFiles("nunit-project-loader.dll", "nunit.engine.api.dll") },
tests: PackageTests,
testRunnerSource: new TestRunnerSource(new NUnitConsoleRunner("3.17.0"), new NUnitConsoleRunner("3.15.5"), new NUnitConsoleRunner("3.18.0-dev00037"))
//testRunner: new NUnitConsoleRunner("3.17.0")
//testRunner: new NUnitConsoleRunner("3.15.5")
//testRunner: new NUnitConsoleRunner("3.18.0-dev00037")
//testRunner: new NUnitNetCoreConsoleRunner("3.18.0-dev00037")
));
//////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -29,38 +29,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test-lib-1", "src\test-lib-
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test-lib-2", "src\test-lib-2\test-lib-2.csproj", "{7808DEA9-FB13-47FC-823F-DC78C1057061}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "recipe", "recipe", "{7EE5FBD2-CD4B-4FB0-9F36-29665955E8BE}"
ProjectSection(SolutionItems) = preProject
recipe\banner.cake = recipe\banner.cake
recipe\build-settings.cake = recipe\build-settings.cake
recipe\builder.cake = recipe\builder.cake
recipe\chocolatey-package.cake = recipe\chocolatey-package.cake
recipe\command-line-options.cake = recipe\command-line-options.cake
recipe\constants.cake = recipe\constants.cake
recipe\dotnet.cake = recipe\dotnet.cake
recipe\extending.cake = recipe\extending.cake
recipe\headers.cake = recipe\headers.cake
recipe\help-messages.cake = recipe\help-messages.cake
recipe\known-extensions.cake = recipe\known-extensions.cake
recipe\nuget-package.cake = recipe\nuget-package.cake
recipe\package-checks.cake = recipe\package-checks.cake
recipe\package-reference.cake = recipe\package-reference.cake
recipe\package-definition.cake = recipe\package-definition.cake
recipe\package-test.cake = recipe\package-test.cake
recipe\publishing.cake = recipe\publishing.cake
recipe\setup.cake = recipe\setup.cake
recipe\task-builders.cake = recipe\task-builders.cake
recipe\task-definitions.cake = recipe\task-definitions.cake
recipe\test-reports.cake = recipe\test-reports.cake
recipe\test-results.cake = recipe\test-results.cake
recipe\test-runners.cake = recipe\test-runners.cake
recipe\tools.cake = recipe\tools.cake
recipe\unit-testing.cake = recipe\unit-testing.cake
recipe\utilities.cake = recipe\utilities.cake
recipe\versioning.cake = recipe\versioning.cake
recipe\zip-package.cake = recipe\zip-package.cake
EndProjectSection
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "nuget", "nuget", "{6C381491-0062-4276-B884-86A6A175FFF5}"
ProjectSection(SolutionItems) = preProject
nuget\nunit-project-loader.legacy.addins = nuget\nunit-project-loader.legacy.addins
@ -101,7 +69,6 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{7EE5FBD2-CD4B-4FB0-9F36-29665955E8BE} = {3B28CF0C-D613-4971-9D8F-00C960C656E2}
{6C381491-0062-4276-B884-86A6A175FFF5} = {3B28CF0C-D613-4971-9D8F-00C960C656E2}
{2DA8DF86-18D3-4832-970C-A0B26498B93D} = {3B28CF0C-D613-4971-9D8F-00C960C656E2}
EndGlobalSection

Просмотреть файл

@ -1,23 +0,0 @@
// Banner class displays banners similar to those created by Cake
// We use this to display intermediate steps within a task
public static class Banner
{
public static void Display(string message, char barChar='-', int length=0)
{
if (length == 0) length = MaxLineLength(message);
var bar = new string(barChar, length);
Console.WriteLine();
Console.WriteLine(bar);
Console.WriteLine(message);
Console.WriteLine(bar);
int MaxLineLength(string message)
{
int length = 0;
foreach (string line in message.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries))
length = Math.Max(length, line.Length);
return length;
}
}
}

Просмотреть файл

@ -1,342 +0,0 @@
public static class BuildSettings
{
private static BuildSystem _buildSystem;
public static void Initialize(
// Required parameters
ICakeContext context,
string title,
string githubRepository,
// Optional Parameters
bool suppressHeaderCheck = false,
string[] standardHeader = null,
string[] exemptFiles = null,
string solutionFile = null,
string[] validConfigurations = null,
string githubOwner = "NUnit",
bool msbuildAllowPreviewVersion = false,
Verbosity msbuildVerbosity = Verbosity.Minimal,
string unitTests = null, // Defaults to "**/*.tests.dll|**/*.tests.exe" (case insensitive)
IUnitTestRunner unitTestRunner = null, // If not set, NUnitLite is used
string unitTestArguments = null
)
{
// Required arguments
Context = context ?? throw new ArgumentNullException(nameof(context));
Title = title ?? throw new ArgumentNullException(nameof(title));
GitHubRepository = githubRepository ?? throw new ArgumentNullException(nameof(githubRepository));
// NOTE: Order of initialization can be sensitive. Obviously,
// we have to set any properties in this method before we
// make use of them. Less obviously, some of the classes we
// construct here have dependencies on certain properties
// being set before the constructor is called. I have
// tried to annotate such dependencies below.
_buildSystem = context.BuildSystem();
SolutionFile = solutionFile ?? DeduceSolutionFile();
ValidConfigurations = validConfigurations ?? DEFAULT_VALID_CONFIGS;
UnitTests = unitTests;
// NUnitLiteRunner depends indirectly on ValidConfigurations
UnitTestRunner = unitTestRunner ?? new NUnitLiteRunner();
UnitTestArguments = unitTestArguments;
BuildVersion = new BuildVersion(context);
GitHubOwner = githubOwner;
// File Header Checks
SuppressHeaderCheck = suppressHeaderCheck && !CommandLineOptions.NoBuild;
StandardHeader = standardHeader ?? DEFAULT_STANDARD_HEADER;
ExemptFiles = exemptFiles ?? new string[0];
//if (defaultTarget != null)
// BuildTasks.DefaultTask.IsDependentOn(defaultTarget);
// Skip remaining initialization if help was requested
if (CommandLineOptions.Usage)
return;
ValidateSettings();
context.Information($"{Title} {Configuration} version {PackageVersion}");
// Output like this should go after the run title display
if (solutionFile == null && SolutionFile != null)
Context.Warning($" SolutionFile: '{SolutionFile}'");
Context.Information($" PackageTestLevel: {PackageTestLevel}");
// Keep this last
if (IsRunningOnAppVeyor)
{
var buildNumber = _buildSystem.AppVeyor.Environment.Build.Number;
_buildSystem.AppVeyor.UpdateBuildVersion($"{PackageVersion}-{buildNumber}");
}
}
// If solution file was not provided, uses TITLE.sln if it exists or
// the solution found in the root directory provided there is only one.
private static string DeduceSolutionFile()
{
if (SIO.File.Exists(Title + ".sln"))
return Title + ".sln";
var files = SIO.Directory.GetFiles(ProjectDirectory, "*.sln");
if (files.Length == 1 && SIO.File.Exists(files[0]))
return files[0];
return null;
}
private static int CalcPackageTestLevel()
{
if (!BuildVersion.IsPreRelease)
return 3;
// TODO: The prerelease label is no longer being set to pr by GitVersion
// for some reason. This check in AppVeyor is a workaround.
if (IsRunningOnAppVeyor && _buildSystem.AppVeyor.Environment.PullRequest.IsPullRequest)
return 2;
switch (BuildVersion.PreReleaseLabel)
{
case "pre":
case "rc":
case "alpha":
case "beta":
return 3;
case "dev":
case "pr":
return 2;
case "ci":
default:
return 1;
}
}
// Cake Context
public static ICakeContext Context { get; private set; }
// NOTE: These are set in setup.cake
public static string Target { get; set; }
public static IEnumerable<string> TasksToExecute { get; set; }
// Arguments
public static string Configuration
{
get
{
// Correct casing on user-provided config if necessary
foreach (string config in ValidConfigurations)
if (string.Equals(config, CommandLineOptions.Configuration.Value, StringComparison.OrdinalIgnoreCase))
return config;
// Return the (invalid) user-provided config
return CommandLineOptions.Configuration.Value;
}
}
// Build Environment
public static bool IsLocalBuild => _buildSystem.IsLocalBuild;
public static bool IsRunningOnUnix => Context.IsRunningOnUnix();
public static bool IsRunningOnWindows => Context.IsRunningOnWindows();
public static bool IsRunningOnAppVeyor => _buildSystem.AppVeyor.IsRunningOnAppVeyor;
// Versioning
public static BuildVersion BuildVersion { get; private set;}
public static string BranchName => BuildVersion.BranchName;
public static bool IsReleaseBranch => BuildVersion.IsReleaseBranch;
public static string PackageVersion => BuildVersion.PackageVersion;
public static string AssemblyVersion => BuildVersion.AssemblyVersion;
public static string AssemblyFileVersion => BuildVersion.AssemblyFileVersion;
public static string AssemblyInformationalVersion => BuildVersion.AssemblyInformationalVersion;
public static bool IsDevelopmentRelease => PackageVersion.Contains("-dev");
// Standard Directory Structure - not changeable by user
public static string ProjectDirectory => Context.Environment.WorkingDirectory.FullPath + "/";
public static string SourceDirectory => ProjectDirectory + SRC_DIR;
public static string OutputDirectory => ProjectDirectory + BIN_DIR + Configuration + "/";
public static string NuGetDirectory => ProjectDirectory + NUGET_DIR;
public static string ChocolateyDirectory => ProjectDirectory + CHOCO_DIR;
public static string ZipDirectory => ProjectDirectory + ZIP_DIR;
public static string PackageDirectory => ProjectDirectory + PACKAGE_DIR;
public static string PackageTestDirectory => ProjectDirectory + PKG_TEST_DIR;
public static string NuGetTestDirectory => ProjectDirectory + NUGET_TEST_DIR;
public static string ChocolateyTestDirectory => ProjectDirectory + CHOCO_TEST_DIR;
public static string ZipTestDirectory => ProjectDirectory + ZIP_TEST_DIR;
public static string PackageResultDirectory => ProjectDirectory + PKG_RSLT_DIR;
public static string NuGetResultDirectory => ProjectDirectory + NUGET_RSLT_DIR;
public static string ChocolateyResultDirectory => ProjectDirectory + CHOCO_RSLT_DIR;
public static string ZipResultDirectory => ProjectDirectory + ZIP_RSLT_DIR;
public static string ImageDirectory => ProjectDirectory + IMAGE_DIR;
public static string ZipImageDirectory => ProjectDirectory + ZIP_IMG_DIR;
public static string ExtensionsDirectory => ProjectDirectory + "bundled-extensions/";
public static string ToolsDirectory => ProjectDirectory + "tools/";
// Files
public static string SolutionFile { get; set; }
// Building
public static string[] ValidConfigurations { get; set; }
public static bool MSBuildAllowPreviewVersion { get; set; }
public static Verbosity MSBuildVerbosity { get; set; }
public static MSBuildSettings MSBuildSettings => new MSBuildSettings {
Verbosity = MSBuildVerbosity,
Configuration = Configuration,
PlatformTarget = PlatformTarget.MSIL,
AllowPreviewVersion = MSBuildAllowPreviewVersion
};
// File Header Checks
public static bool SuppressHeaderCheck { get; private set; }
public static string[] StandardHeader { get; private set; }
public static string[] ExemptFiles { get; private set; }
//Testing
public static string UnitTests { get; set; }
public static IUnitTestRunner UnitTestRunner { get; private set; }
public static string UnitTestArguments { get; private set; }
// Packaging
public static string Title { get; private set; }
public static List<PackageDefinition> Packages { get; } = new List<PackageDefinition>();
// Package Testing
public static int PackageTestLevel =>
CommandLineOptions.TestLevel.Value > 0
? CommandLineOptions.TestLevel.Value
: CalcPackageTestLevel();
// Publishing - MyGet
public static string MyGetPushUrl => MYGET_PUSH_URL;
public static string MyGetApiKey => Context.EnvironmentVariable(MYGET_API_KEY);
// Publishing - NuGet
public static string NuGetPushUrl => NUGET_PUSH_URL;
public static string NuGetApiKey => Context.EnvironmentVariable(NUGET_API_KEY);
// Publishing - Chocolatey
public static string ChocolateyPushUrl => CHOCO_PUSH_URL;
public static string ChocolateyApiKey => Context.EnvironmentVariable(CHOCO_API_KEY);
// Publishing - GitHub
public static string GitHubOwner { get; set; }
public static string GitHubRepository { get; set; }
public static string GitHubAccessToken => Context.EnvironmentVariable(GITHUB_ACCESS_TOKEN);
public static bool IsPreRelease => BuildVersion.IsPreRelease;
public static bool ShouldPublishToMyGet =>
!IsPreRelease || LABELS_WE_PUBLISH_ON_MYGET.Contains(BuildVersion.PreReleaseLabel);
public static bool ShouldPublishToNuGet =>
!IsPreRelease || LABELS_WE_PUBLISH_ON_NUGET.Contains(BuildVersion.PreReleaseLabel);
public static bool ShouldPublishToChocolatey =>
!IsPreRelease || LABELS_WE_PUBLISH_ON_CHOCOLATEY.Contains(BuildVersion.PreReleaseLabel);
public static bool IsProductionRelease =>
!IsPreRelease || LABELS_WE_RELEASE_ON_GITHUB.Contains(BuildVersion.PreReleaseLabel);
private static void ValidateSettings()
{
var validationErrors = new List<string>();
if (!ValidConfigurations.Contains(Configuration))
validationErrors.Add($"Invalid configuration: {Configuration}");
if (validationErrors.Count > 0)
{
DumpSettings();
var msg = new StringBuilder("Parameter validation failed! See settings above.\n\nErrors found:\n");
foreach (var error in validationErrors)
msg.AppendLine(" " + error);
throw new InvalidOperationException(msg.ToString());
}
}
public static void DumpSettings()
{
Console.WriteLine("\nTASKS");
Console.WriteLine("Target: " + Target);
Console.WriteLine("TasksToExecute: " + string.Join(", ", TasksToExecute));
Console.WriteLine("\nENVIRONMENT");
Console.WriteLine("IsLocalBuild: " + IsLocalBuild);
Console.WriteLine("IsRunningOnWindows: " + IsRunningOnWindows);
Console.WriteLine("IsRunningOnUnix: " + IsRunningOnUnix);
Console.WriteLine("IsRunningOnAppVeyor: " + IsRunningOnAppVeyor);
Console.WriteLine("\nVERSIONING");
Console.WriteLine("PackageVersion: " + PackageVersion);
Console.WriteLine("AssemblyVersion: " + AssemblyVersion);
Console.WriteLine("AssemblyFileVersion: " + AssemblyFileVersion);
Console.WriteLine("AssemblyInformationalVersion: " + AssemblyInformationalVersion);
Console.WriteLine("SemVer: " + BuildVersion.SemVer);
Console.WriteLine("IsPreRelease: " + BuildVersion.IsPreRelease);
Console.WriteLine("PreReleaseLabel: " + BuildVersion.PreReleaseLabel);
Console.WriteLine("PreReleaseSuffix: " + BuildVersion.PreReleaseSuffix);
Console.WriteLine("\nDIRECTORIES");
Console.WriteLine("Project: " + ProjectDirectory);
Console.WriteLine("Output: " + OutputDirectory);
Console.WriteLine("Source: " + SourceDirectory);
Console.WriteLine("NuGet: " + NuGetDirectory);
Console.WriteLine("Chocolatey: " + ChocolateyDirectory);
Console.WriteLine("Package: " + PackageDirectory);
Console.WriteLine("PackageTest: " + PackageTestDirectory);
Console.WriteLine("NuGetTest: " + NuGetTestDirectory);
Console.WriteLine("ChocoTest: " + ChocolateyTestDirectory);
Console.WriteLine("ZipTest: " + ZipTestDirectory);
Console.WriteLine("PackageResult: " + PackageResultDirectory);
Console.WriteLine("NuGetResult: " + NuGetResultDirectory);
Console.WriteLine("ChocoResult: " + ChocolateyResultDirectory);
Console.WriteLine("ZipResult: " + ZipResultDirectory);
Console.WriteLine("Image: " + ImageDirectory);
Console.WriteLine("ZipImage: " + ZipImageDirectory);
Console.WriteLine("\nBUILD");
Console.WriteLine("Configuration: " + Configuration);
Console.WriteLine("\nUNIT TESTS");
Console.WriteLine("UnitTests: " + UnitTests);
Console.WriteLine("UnitTestRunner: " + UnitTestRunner?.GetType().Name ?? "<NUnitLiteRunner>");
Console.WriteLine("\nPACKAGING");
Console.WriteLine("PackageTestLevel: " + PackageTestLevel);
Console.WriteLine("MyGetPushUrl: " + MyGetPushUrl);
Console.WriteLine("NuGetPushUrl: " + NuGetPushUrl);
Console.WriteLine("ChocolateyPushUrl: " + ChocolateyPushUrl);
Console.WriteLine("MyGetApiKey: " + (!string.IsNullOrEmpty(MyGetApiKey) ? "AVAILABLE" : "NOT AVAILABLE"));
Console.WriteLine("NuGetApiKey: " + (!string.IsNullOrEmpty(NuGetApiKey) ? "AVAILABLE" : "NOT AVAILABLE"));
Console.WriteLine("ChocolateyApiKey: " + (!string.IsNullOrEmpty(ChocolateyApiKey) ? "AVAILABLE" : "NOT AVAILABLE"));
Console.WriteLine("GitHubAccessToken: " + (!string.IsNullOrEmpty(GitHubAccessToken) ? "AVAILABLE" : "NOT AVAILABLE"));
Console.WriteLine("\nPACKAGES");
foreach (var package in Packages)
{
Console.WriteLine(package.PackageId);
Console.WriteLine(" PackageType: " + package.PackageType);
Console.WriteLine(" PackageFileName: " + package.PackageFileName);
Console.WriteLine(" PackageInstallDirectory: " + package.PackageInstallDirectory);
Console.WriteLine(" PackageTestDirectory: " + package.PackageTestDirectory);
}
Console.WriteLine("\nPUBLISHING");
Console.WriteLine("ShouldPublishToMyGet: " + ShouldPublishToMyGet);
Console.WriteLine("ShouldPublishToNuGet: " + ShouldPublishToNuGet);
Console.WriteLine("ShouldPublishToChocolatey: " + ShouldPublishToChocolatey);
Console.WriteLine("\nRELEASING");
Console.WriteLine("BranchName: " + BranchName);
Console.WriteLine("IsReleaseBranch: " + IsReleaseBranch);
Console.WriteLine("IsProductionRelease: " + IsProductionRelease);
}
}

Просмотреть файл

@ -1,22 +0,0 @@
//////////////////////////////////////////////////////////////////////
// EXECUTION
//////////////////////////////////////////////////////////////////////
public Builder Build => CommandLineOptions.Usage
? new Builder(() => Information(HelpMessages.Usage))
: new Builder(() => RunTarget(CommandLineOptions.Target.Value));
public class Builder
{
private Action _action;
public Builder(Action action)
{
_action = action;
}
public void Run()
{
_action();
}
}

Просмотреть файл

@ -1,44 +0,0 @@
public class ChocolateyPackage : PackageDefinition
{
public ChocolateyPackage(
string id,
string source,
IPackageTestRunner testRunner = null,
TestRunnerSource testRunnerSource = null,
PackageCheck[] checks = null,
IEnumerable<PackageTest> tests = null)
: base(
PackageType.Chocolatey,
id,
source,
testRunner: testRunner,
testRunnerSource: testRunnerSource,
checks: checks,
tests: tests)
{
if (!source.EndsWith(".nuspec"))
throw new ArgumentException("Source must be a nuspec file", nameof(source));
}
// The file name of this package, including extension
public override string PackageFileName => $"{PackageId}.{PackageVersion}.nupkg";
// The file name of any symbol package, including extension
public override string SymbolPackageName => SIO.Path.ChangeExtension(PackageFileName, ".snupkg");
// The directory into which this package is installed
public override string PackageInstallDirectory => BuildSettings.ChocolateyTestDirectory;
// The directory used to contain results of package tests for this package
public override string PackageResultDirectory => BuildSettings.ChocolateyResultDirectory + PackageId + "/";
// The directory into which extensions to the test runner are installed
public override string ExtensionInstallDirectory => BuildSettings.PackageTestDirectory;
public override void BuildPackage()
{
_context.ChocolateyPack(PackageSource,
new ChocolateyPackSettings()
{
Version = PackageVersion,
OutputDirectory = BuildSettings.PackageDirectory,
ArgumentCustomization = args => args.Append($"BIN_DIR={BuildSettings.OutputDirectory}")
});
}
}

Просмотреть файл

@ -1,118 +0,0 @@
// ***********************************************************************
// Copyright (c) Charlie Poole and TestCentric GUI contributors.
// Licensed under the MIT License. See LICENSE.txt in root directory.
// ***********************************************************************
CommandLineOptions.Initialize(Context);
public static class CommandLineOptions
{
static private ICakeContext _context;
static public ValueOption<string> Target;
static public ValueOption<string> Configuration;
static public ValueOption<string> PackageVersion;
static public ValueOption<string> PackageSelector;
static public ValueOption<int> TestLevel;
static public ValueOption<string> TraceLevel;
static public SimpleOption NoBuild;
static public SimpleOption NoPush;
static public SimpleOption Usage;
public static void Initialize(ICakeContext context)
{
_context = context;
// The name of the TARGET task to be run, e.g. Test.
Target = new ValueOption<string>("target", "Default", 1);
Configuration = new ValueOption<String>("configuration", DEFAULT_CONFIGURATION, 1);
PackageVersion = new ValueOption<string>("packageVersion", null, 4);
PackageSelector = new ValueOption<string>("where", null, 1);
TestLevel = new ValueOption<int>("level", 0, 3);
TraceLevel = new ValueOption<string>("trace", "Off", 2);
NoBuild = new SimpleOption("nobuild", 3);
NoPush = new SimpleOption("nopush", 3);
Usage = new SimpleOption("usage", 2);
}
// Nested classes to represent individual options
// AbstractOption has a name and can tell us if it exists.
public abstract class AbstractOption
{
public string Name { get; }
public int MinimumAbbreviation { get; internal set; }
public bool Exists
{
get
{
for (int len = Name.Length; len >= MinimumAbbreviation; len--)
if (_context.HasArgument(Name.Substring(0,len)))
return true;
return false;
}
}
public string Description { get; }
public AbstractOption(string name, int minimumAbbreviation = 0, string description = null)
{
Name = name;
MinimumAbbreviation = minimumAbbreviation > 0 && minimumAbbreviation <= name.Length
? minimumAbbreviation
: name.Length;
Description = description;
}
}
// Simple Option adds an implicit boolean conversion operator.
// It throws an exception if you gave it a value on the command-line.
public class SimpleOption : AbstractOption
{
static public implicit operator bool(SimpleOption o) => o.Exists;
public SimpleOption(string name, int minimumAbbreviation = 0, string description = null)
: base(name, minimumAbbreviation, description)
{
if (_context.Argument(name, (string)null) != null)
throw new Exception($"Option --{name} does not take a value.");
}
}
// Generic ValueOption adds Value as well as a default value
public class ValueOption<T> : AbstractOption
{
public T DefaultValue { get; }
public ValueOption(string name, T defaultValue, int minimumAbbreviation = 0, string description = null)
: base(name, minimumAbbreviation, description)
{
DefaultValue = defaultValue;
}
public T Value
{
get
{
for (int len = Name.Length; len >= MinimumAbbreviation; len--)
{
string abbrev = Name.Substring(0,len);
if (_context.HasArgument(abbrev))
return _context.Argument<T>(abbrev);
}
return DefaultValue;
}
}
}
}

Просмотреть файл

@ -1,53 +0,0 @@
// This file contains both real constants and static readonly variables used
// as constants. All values are initialized before any instance variables.
// Alias used throughout the recipe
using SIO = System.IO;
// GitHub owner is the NUnit organization
const string GITHUB_OWNER = "nunit";
// Defaults
const string DEFAULT_CONFIGURATION = "Release";
private static readonly string[] DEFAULT_VALID_CONFIGS = { "Release", "Debug" };
static readonly string[] DEFAULT_STANDARD_HEADER = new[] {
"// Copyright (c) Charlie Poole, Rob Prouse and Contributors. MIT License - see LICENSE.txt" };
const string DEFAULT_TEST_RESULT_FILE = "TestResult.xml";
// Standardized project directory structure - not changeable by user
const string SRC_DIR = "src/";
const string BIN_DIR = "bin/";
const string NUGET_DIR = "nuget/";
const string CHOCO_DIR = "choco/";
const string ZIP_DIR = "zip/";
const string PACKAGE_DIR = "package/";
const string PKG_TEST_DIR = "package/tests/";
const string NUGET_TEST_DIR = "package/tests/nuget/";
//const string NUGET_RUNNER_DIR = "package/tests/nuget/runners/";
const string CHOCO_TEST_DIR = "package/tests/choco/";
//const string CHOCO_RUNNER_DIR = "package/tests/choco/runners/";
const string ZIP_TEST_DIR = "package/tests/zip/";
const string PKG_RSLT_DIR = "package/results/";
const string NUGET_RSLT_DIR = "package/results/nuget/";
const string CHOCO_RSLT_DIR = "package/results/choco/";
const string ZIP_RSLT_DIR = "package/results/zip/";
const string IMAGE_DIR = "package/images";
const string ZIP_IMG_DIR = "package/images/zip/";
const string TOOLS_DIR = "tools/";
// URLs for uploading packages
private const string MYGET_PUSH_URL = "https://www.myget.org/F/nunit/api/v2";
private const string NUGET_PUSH_URL = "https://api.nuget.org/v3/index.json";
private const string CHOCO_PUSH_URL = "https://push.chocolatey.org/";
// Environment Variable names holding API keys
private const string MYGET_API_KEY = "MYGET_API_KEY";
private const string NUGET_API_KEY = "NUGET_API_KEY";
private const string CHOCO_API_KEY = "CHOCO_API_KEY";
private const string GITHUB_ACCESS_TOKEN = "GITHUB_ACCESS_TOKEN";
// Pre-release labels that we publish
private static readonly string[] LABELS_WE_PUBLISH_ON_MYGET = { "dev" };
private static readonly string[] LABELS_WE_PUBLISH_ON_NUGET = { "alpha", "beta", "rc" };
private static readonly string[] LABELS_WE_PUBLISH_ON_CHOCOLATEY = { "alpha", "beta", "rc" };
private static readonly string[] LABELS_WE_RELEASE_ON_GITHUB = { "alpha", "beta", "rc" };

Просмотреть файл

@ -1,88 +0,0 @@
public class DotnetInfo
{
// Experimenting with finding dotnet installs for X64 vs x86
// This code will end up moved into the engine as well.
private ICakeContext _context;
private bool _onWindows;
public DotnetInfo(ICakeContext context)
{
_context = context;
_onWindows = context.IsRunningOnWindows();
InstallPath = GetDotnetInstallDirectory(false);
X86InstallPath = GetDotnetInstallDirectory(true);
}
// NOTES:
// * We don't need an IsInstalled property because our scripts all run under dotnet.
public bool IsX86Installed => SIO.Directory.Exists(X86InstallPath) && SIO.File.Exists(X86Executable);
public string InstallPath { get; }
public string Executable => InstallPath + "dotnet.exe";
public List<string> Runtimes { get; }
public string X86InstallPath { get; }
public string X86Executable => X86InstallPath + "dotnet.exe";
public List<string> X86Runtimes { get; }
public void Display()
{
_context.Information($"Install Path: {InstallPath}");
_context.Information($"Executable: {Executable}");
_context.Information("Runtimes:");
foreach (string dir in SIO.Directory.GetDirectories(SIO.Path.Combine(InstallPath, "shared")))
{
string runtime = SIO.Path.GetFileName(dir);
foreach (string dir2 in SIO.Directory.GetDirectories(dir))
{
string version = SIO.Path.GetFileName(dir2);
_context.Information($" {runtime} {version}");
}
}
if (IsX86Installed)
{
_context.Information($"\nX86 Install Path: {X86InstallPath}");
_context.Information($"X86 Executable: {X86Executable}");
_context.Information("Runtimes:");
foreach (var dir in SIO.Directory.GetDirectories(SIO.Path.Combine(X86InstallPath, "shared")))
{
string runtime = SIO.Path.GetFileName(dir);
foreach (string dir2 in SIO.Directory.GetDirectories(dir))
{
string version = SIO.Path.GetFileName(dir2);
_context.Information($" {runtime} {version}");
}
}
}
else
_context.Information("\nDotnet X86 is not installed");
}
private string GetDotnetInstallDirectory(bool forX86 = false)
{
if (_onWindows)
{
if (forX86)
{
Microsoft.Win32.RegistryKey key =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\WOW6432Node\dotnet\SetUp\InstalledVersions\x86\");
return (string)key?.GetValue("InstallLocation");
}
else
{
Microsoft.Win32.RegistryKey key =
Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dotnet\SetUp\InstalledVersions\x64\sharedHost\");
return (string)key?.GetValue("Path");
}
}
else // Assuming linux for now
return "/usr/shared/dotnet/";
}
}
// Use this task to verify that the script understands the dotnet environment
Task("DotnetInfo").Does(() => { new DotnetInfo(Context).Display(); });

Просмотреть файл

@ -1,57 +0,0 @@
// This file provides information on how to change the pre-defined tasks in
// the NUnit Cake Recipe for a particular project, without changing the
// recipe files themselves. Those files should not be changed unless you
// are trying to make changes for all projects, which use the recipe.
//
// In addition, this file defines a few static methods intended to make it
// easier to override task definitions for a project.
//
// Code given in the following examples should be added to your file after
// the recipe itself has been loaded.
//
// SIMPLE EXAMPLES:
//
// Adding a new dependency after those already present
// BuildTasks.SomeTask.IsDependentOn("SomeOtherTask");
//
// Adding a new action, which will be performed after the existing action.
// BuildTasks.SomeTask.Does(() => {
// // Code here to do something
// });
//
// MORE COMPLEX EXAMPLES:
//
// Replacing the existing dependencies, criteria or actions is a bit harder.
// You must first clear the relevant items and then re-add them in the desired
// order along with any new items. The following static methods allow you to do
// so a bit more simply than would otherwise be possible.
public static void ClearCriteria(CakeTaskBuilder builder) => ((CakeTask)builder.Task).Criterias.Clear();
public static void ClearDependencies(CakeTaskBuilder builder) => ((CakeTask)builder.Task).Dependencies.Clear();
public static void ClearActions(CakeTaskBuilder builder) => ((CakeTask)builder.Task).Actions.Clear();
// Redefining the action of the build task. Note that dependencies will still run, since we haven't changed them.
// ClearActions(BuildTasks.Build);
// BuildTasks.Build.Does(() => Information("I'm not building today!"));
//
// In some cases, you may wish to completely redefine what a task does. The following static method
// supports a fluent syntax for doing just that
public static CakeTaskBuilder Redefine(CakeTaskBuilder builder)
{
ClearCriteria(builder);
ClearDependencies(builder);
ClearActions(builder);
return builder;
}
// Redefine the build task completely. Note that in this case, dependencies are not run.
// Redefine(BuildTasks.BuildTask)
// .Does(() => {
// Information("Not Building today!");
// });
//
// Modify the Default task for a project to run "Test" rather than "Build".
// Redefine(BuildTasks.DefaultTask)
// .IsDependentOn("Test");

Просмотреть файл

@ -1,115 +0,0 @@
//////////////////////////////////////////////////////////////////////
// CHECK FOR MISSING AND NON-STANDARD FILE HEADERS
//////////////////////////////////////////////////////////////////////
public static class Headers
{
private static ICakeContext _context;
static Headers()
{
_context = BuildSettings.Context;
}
public static void Check()
{
var NoHeader = new List<FilePath>();
var NonStandard = new List<FilePath>();
var Exempted = new List<FilePath>();
int examined = 0;
var sourceFiles = _context.GetFiles(BuildSettings.SourceDirectory + "**/*.cs");
var exemptFiles = BuildSettings.ExemptFiles;
foreach (var file in sourceFiles)
{
var path = file.ToString();
// Ignore autogenerated files in an obj directory
if (path.Contains("/obj/"))
continue;
// Ignore designer files
if (path.EndsWith(".Designer.cs"))
continue;
// Ignore AssemblyInfo files
if (SIO.Path.GetFileName(path) == "AssemblyInfo.cs")
continue;
examined++;
var header = GetHeader(file);
if (exemptFiles.Contains(file.GetFilename().ToString()))
Exempted.Add(file);
else if (header.Count == 0)
NoHeader.Add(file);
else if (!header.SequenceEqual(BuildSettings.StandardHeader))
NonStandard.Add(file);
}
_context.Information("\nSTANDARD HEADER\n");
foreach (string line in BuildSettings.StandardHeader)
_context.Information(line);
_context.Information("");
if (NoHeader.Count > 0)
{
_context.Information("\nFILES WITH NO HEADER\n");
foreach (var file in NoHeader)
_context.Information(RelPathTo(file));
}
if (NonStandard.Count > 0)
{
_context.Information("\nFILES WITH A NON-STANDARD HEADER\n");
foreach (var file in NonStandard)
{
_context.Information(RelPathTo(file));
_context.Information("");
foreach (string line in GetHeader(file))
_context.Information(line);
_context.Information("");
}
}
if (Exempted.Count > 0)
{
_context.Information("\nEXEMPTED FILES (NO CHECK MADE)\n");
foreach (var file in Exempted)
_context.Information(RelPathTo(file));
}
_context.Information($"\nFiles Examined: {examined}");
_context.Information($"Missing Headers: {NoHeader.Count}");
_context.Information($"Non-Standard Headers: {NonStandard.Count}");
_context.Information($"Exempted Files: {Exempted.Count}");
if (NoHeader.Count > 0 || NonStandard.Count > 0)
throw new Exception("Missing or invalid file headers found");
if (examined == 0)
_context.Warning("\nWARNING: There were no '*.cs' files in the source directory. Use of the 'CheckHeaders' task may not make sense for this project.");
List<string> GetHeader(FilePath file)
{
var header = new List<string>();
var lines = SIO.File.ReadLines(file.ToString());
foreach (string line in lines)
{
if (!line.StartsWith("//"))
break;
header.Add(line);
}
return header;
}
string RelPathTo(FilePath file)
{
int CD_LENGTH = Environment.CurrentDirectory.Length + 1;
return file.ToString().Substring(CD_LENGTH);
}
}
}

Просмотреть файл

@ -1,77 +0,0 @@
static public class HelpMessages
{
static public string Usage => $"""
BUILD.CAKE
This script builds the {BuildSettings.Title} project. It makes use of
NUnit.Cake.Recipe, which provides a number of built-in options and
tasks. You may define additional options and tasks in build.cake or
in additional cake files you load from build.cake. Recipe options may
be specified in abbreviated form, down to the minimum length shown in
square braces. Single character abbreviations use a single dash.
Usage: build [options]
Options:
--target=TARGET [-t]
The TARGET task to be run, e.g. Test. Default is Build.
--configuration=CONFIG [-c]
The name of the configuration to build. Default is Release.
--packageVersion [--pack]
Specifies the full package version, including any pre-release
suffix. If provided, this version is used directly in place of
the default version calculated by the script.
--where=SELECTION [-w]
Specifies a selction expression used to choose which packages
to build and test, for use in debugging. Consists of one or
more specifications, separated by '|' and '&'. Each specification
is of the form "prop=value", where prop may be either id or type.
Examples:
--where type=nuget
--where id=NUnit.Engine.Api
--where "type=nuget|type=choco"
--level=LEVEL [--lev]
Specifies the level of package testing, 1, 2 or 3. Defaults are
1 = for normal CI tests run every time you build a package
2 = for PRs and Dev builds uploaded to MyGet
3 = prior to publishing a release
--trace=LEVEL [--tr]
Specifies the default trace level for this run. Values are Off,
Error, Warning, Info or Debug. Default is value of environment
variable NUNIT_INTERNAL_TRACE_LEVEL if set. If not,
tracing is turned Off.
--nobuild [--nob]
Indicates that the Build task should not be run even if other
tasks depend on it. The existing build is used instead.
--nopush [--nop]
Indicates that no publishing or releasing should be done. If
publish or release targets are run, a message is displayed.
--usage [--us]
Displays this help message. No targets are run.
Selected Cake Options:
--version
Displays the cake version in use.
--description
Displays a list of the available tasks (targets).
--tree
Displays the task dependency tree
--help
Displays help information for cake itself.
NOTE: The above Cake options bypass execution of the script.
""";
}

Просмотреть файл

@ -1,48 +0,0 @@
// Static class holding information about known extensions.
public static class KnownExtensions
{
// Static Variables representing well-known Extensions with the latest tested version
public static ExtensionSpecifier NUnitV2Driver = new ExtensionSpecifier(
"NUnit.Extension.NUnitV2Driver", "nunit-extension-nunit-v2-driver", "3.9.0");
public static ExtensionSpecifier NUnitProjectLoader = new ExtensionSpecifier(
"NUnit.Extension.NUnitProjectLoader", "nunit-extension-nunit-project-loader", "3.7.1");
}
// Representation of an extension, for use by PackageTests. Because our
// extensions usually exist as both nuget and chocolatey packages, each
// extension may have a nuget id, a chocolatey id or both. A default version
// is used unless the user overrides it using SetVersion.
public class ExtensionSpecifier
{
public ExtensionSpecifier(string nugetId, string chocoId, string version)
{
NuGetId = nugetId;
ChocoId = chocoId;
Version = version;
}
public string NuGetId { get; }
public string ChocoId { get; }
public string Version { get; }
public PackageReference NuGetPackage => new PackageReference(NuGetId, Version);
public PackageReference ChocoPackage => new PackageReference(ChocoId, Version);
public PackageReference LatestChocolateyRelease => ChocoPackage.LatestRelease;
// Return an extension specifier using the same package ids as this
// one but specifying a particular version to be used.
public ExtensionSpecifier SetVersion(string version)
{
return new ExtensionSpecifier(NuGetId, ChocoId, version);
}
// Install this extension for a package
public void InstallExtension(PackageDefinition targetPackage)
{
PackageReference extensionPackage = targetPackage.PackageType == PackageType.Chocolatey
? ChocoPackage
: NuGetPackage;
extensionPackage.Install(targetPackage.ExtensionInstallDirectory);
}
}

Просмотреть файл

@ -1,58 +0,0 @@
public class NuGetPackage : PackageDefinition
{
public NuGetPackage(
string id,
string source,
IPackageTestRunner testRunner = null,
TestRunnerSource testRunnerSource = null,
PackageCheck[] checks = null,
PackageCheck[] symbols = null,
IEnumerable<PackageTest> tests = null)
: base(
PackageType.NuGet,
id,
source,
testRunner: testRunner,
testRunnerSource: testRunnerSource,
checks: checks,
symbols: symbols,
tests: tests)
{
if (!source.EndsWith(".nuspec"))
throw new ArgumentException("Source must be a nuspec file", nameof(source));
if (symbols != null)
{
HasSymbols = true;
SymbolChecks = symbols;
}
}
// The file name of this package, including extension
public override string PackageFileName => $"{PackageId}.{PackageVersion}.nupkg";
// The file name of any symbol package, including extension
public override string SymbolPackageName => SIO.Path.ChangeExtension(PackageFileName, ".snupkg");
// The directory into which this package is installed
public override string PackageInstallDirectory => BuildSettings.NuGetTestDirectory;
// The directory used to contain results of package tests for this package
public override string PackageResultDirectory => BuildSettings.NuGetResultDirectory + PackageId + "/";
// The directory into which extensions to the test runner are installed
public override string ExtensionInstallDirectory => BuildSettings.PackageTestDirectory;
public override void BuildPackage()
{
var nugetPackSettings = new NuGetPackSettings()
{
Version = PackageVersion,
BasePath = BuildSettings.OutputDirectory,
OutputDirectory = BuildSettings.PackageDirectory,
NoPackageAnalysis = true,
Symbols = HasSymbols
};
if (HasSymbols)
nugetPackSettings.SymbolPackageFormat = "snupkg";
_context.NuGetPack(PackageSource, nugetPackSettings);
}
}

Просмотреть файл

@ -1,148 +0,0 @@
//////////////////////////////////////////////////////////////////////
// SYNTAX FOR EXPRESSING CHECKS
//////////////////////////////////////////////////////////////////////
public static class Check
{
public static void That(DirectoryPath testDirPath, IList<PackageCheck> checks)
{
if (checks == null)
throw new ArgumentNullException(nameof(checks));
bool allOK = true;
foreach (var check in checks)
allOK &= check.ApplyTo(testDirPath);
if (!allOK) throw new Exception("Verification failed!");
}
}
private static FileCheck HasFile(FilePath file) => HasFiles(new[] { file });
private static FileCheck HasFiles(params FilePath[] files) => new FileCheck(files);
private static DirectoryCheck HasDirectory(string dir) => new DirectoryCheck(dir);
//////////////////////////////////////////////////////////////////////
// PACKAGECHECK CLASS
//////////////////////////////////////////////////////////////////////
public abstract class PackageCheck
{
protected ICakeContext _context;
public PackageCheck()
{
_context = BuildSettings.Context;
}
public abstract bool ApplyTo(DirectoryPath testDirPath);
protected bool CheckDirectoryExists(DirectoryPath dirPath)
{
if (!_context.DirectoryExists(dirPath))
{
DisplayError($"Directory {dirPath} was not found.");
return false;
}
return true;
}
protected bool CheckFileExists(FilePath filePath)
{
if (!_context.FileExists(filePath))
{
DisplayError($"File {filePath} was not found.");
return false;
}
return true;
}
protected bool CheckFilesExist(IEnumerable<FilePath> filePaths)
{
bool isOK = true;
foreach (var filePath in filePaths)
isOK &= CheckFileExists(filePath);
return isOK;
}
protected bool DisplayError(string msg)
{
_context.Error(" ERROR: " + msg);
// The return value may be ignored or used as a shortcut
// for an immediate return from ApplyTo as in
// return DisplayError(...)
return false;
}
}
//////////////////////////////////////////////////////////////////////
// FILECHECK CLASS
//////////////////////////////////////////////////////////////////////
public class FileCheck : PackageCheck
{
FilePath[] _files;
public FileCheck(FilePath[] files)
{
_files = files;
}
public override bool ApplyTo(DirectoryPath testDirPath)
{
return CheckFilesExist(_files.Select(file => testDirPath.CombineWithFilePath(file)));
}
}
//////////////////////////////////////////////////////////////////////
// DIRECTORYCHECK CLASS
//////////////////////////////////////////////////////////////////////
public class DirectoryCheck : PackageCheck
{
private DirectoryPath _relDirPath;
private List<FilePath> _files = new List<FilePath>();
public DirectoryCheck(DirectoryPath relDirPath)
{
_relDirPath = relDirPath;
}
public DirectoryCheck WithFiles(params FilePath[] files)
{
_files.AddRange(files);
return this;
}
public DirectoryCheck AndFiles(params FilePath[] files)
{
return WithFiles(files);
}
public DirectoryCheck WithFile(FilePath file)
{
_files.Add(file);
return this;
}
public DirectoryCheck AndFile(FilePath file)
{
return AndFiles(file);
}
public override bool ApplyTo(DirectoryPath testDirPath)
{
DirectoryPath absDirPath = testDirPath.Combine(_relDirPath);
if (!CheckDirectoryExists(absDirPath))
return false;
return CheckFilesExist(_files.Select(file => absDirPath.CombineWithFilePath(file)));
}
}

Просмотреть файл

@ -1,313 +0,0 @@
public enum PackageType
{
NuGet,
Chocolatey,
Zip
}
public abstract class PackageDefinition
{
protected ICakeContext _context;
/// <summary>
/// Constructor
/// </summary>
/// <param name="packageType">A PackageType value specifying one of the four known package types</param>
/// <param name="id">A string containing the package ID, used as the root of the PackageName</param>
/// <param name="source">A string representing the source used to create the package, e.g. a nuspec file</param>
/// <param name="testRunner">A TestRunner instance used to run package tests.</param>
/// <param name="checks">An array of PackageChecks be made on the content of the package. Optional.</param>
/// <param name="symbols">An array of PackageChecks to be made on the symbol package, if one is created. Optional. Only supported for nuget packages.</param>
/// <param name="tests">An array of PackageTests to be run against the package. Optional.</param>
protected PackageDefinition(
PackageType packageType,
string id,
string source,
IPackageTestRunner testRunner = null,
TestRunnerSource testRunnerSource = null,
string extraTestArguments = null,
PackageCheck[] checks = null,
PackageCheck[] symbols = null,
IEnumerable<PackageTest> tests = null)
{
if (testRunner == null && testRunnerSource == null && tests != null)
throw new System.InvalidOperationException($"Unable to create {packageType} package {id}: TestRunner or TestRunnerSource must be provided if there are tests.");
if (testRunner != null && testRunnerSource != null)
throw new System.InvalidOperationException($"Unable to create {packageType} package {id}: Either TestRunner or TestRunnerSource must be provided, but not both.");
_context = BuildSettings.Context;
PackageType = packageType;
PackageId = id;
PackageVersion = BuildSettings.PackageVersion;
PackageSource = source;
BasePath = BuildSettings.OutputDirectory;
TestRunner = testRunner;
TestRunnerSource = testRunnerSource;
ExtraTestArguments = extraTestArguments;
PackageChecks = checks;
SymbolChecks = symbols;
PackageTests = tests;
}
public PackageType PackageType { get; }
public string PackageId { get; }
public string PackageVersion { get; protected set; }
public string PackageSource { get; }
public string BasePath { get; }
public IPackageTestRunner TestRunner { get; }
public TestRunnerSource TestRunnerSource { get; }
public string ExtraTestArguments { get; }
public PackageCheck[] PackageChecks { get; }
public PackageCheck[] SymbolChecks { get; protected set; }
public IEnumerable<PackageTest> PackageTests { get; }
public bool HasSymbols { get; protected set; } = false;
public virtual string SymbolPackageName => throw new System.NotImplementedException($"Symbols are not available for {PackageType} packages.");
// The file name of this package, including extension
public abstract string PackageFileName { get; }
// The directory into which this package is installed
public abstract string PackageInstallDirectory { get; }
// The directory used to contain results of package tests for this package
public abstract string PackageResultDirectory { get; }
// The directory into which extensions to the test runner are installed
public abstract string ExtensionInstallDirectory { get; }
public string PackageFilePath => BuildSettings.PackageDirectory + PackageFileName;
public string PackageTestDirectory => $"{PackageInstallDirectory}{PackageId}.{PackageVersion}/";
public bool IsSelectedBy(string selectionExpression)
{
return IsSelectedByAny(selectionExpression.Split("|", StringSplitOptions.RemoveEmptyEntries));
bool IsSelectedByAny(string[] terms)
{
foreach (var term in terms)
if (IsSelectedByAll(term.Split("&", StringSplitOptions.RemoveEmptyEntries)))
return true;
return false;
}
bool IsSelectedByAll(string[] factors)
{
foreach (string factor in factors)
{
int index = factor.IndexOf("=");
if (index <= 0)
throw new ArgumentException("Selection expression does not contain =", "where");
string prop = factor.Substring(0, index).Trim();
string val = factor.Substring(index+1).Trim();
switch(prop.ToUpper())
{
case "ID":
return PackageId.ToLower() == val.ToLower();
case "TYPE":
return PackageType.ToString().ToLower() == val.ToLower();
default:
throw new Exception($"Not a valid selection property: {prop}");
}
}
return false;
}
}
public void BuildVerifyAndTest()
{
_context.EnsureDirectoryExists(BuildSettings.PackageDirectory);
Banner.Display($"Building {PackageFileName}");
BuildPackage();
Banner.Display($"Installing {PackageFileName}");
InstallPackage();
if (PackageChecks != null)
{
Banner.Display($"Verifying {PackageFileName}");
VerifyPackage();
}
if (SymbolChecks != null)
{
// TODO: Override this in NuGetPackage
VerifySymbolPackage();
}
if (PackageTests != null)
{
Banner.Display($"Testing {PackageFileName}");
RunPackageTests();
}
}
protected void FetchBundledExtensions(PackageReference[] extensions)
{
foreach (var extension in extensions)
if (!extension.IsInstalled(BuildSettings.ExtensionsDirectory))
extension.Install(BuildSettings.ExtensionsDirectory);
}
public abstract void BuildPackage();
// Base implementation is used for installing both NuGet and
// Chocolatey packages. Other package types should override.
public virtual void InstallPackage()
{
var installSettings = new NuGetInstallSettings
{
Source = new [] {
// Package will be found here
BuildSettings.PackageDirectory,
// Dependencies may be in any of these
"https://www.myget.org/F/nunit/api/v3/index.json",
"https://api.nuget.org/v3/index.json" },
Version = PackageVersion,
OutputDirectory = PackageInstallDirectory,
//ExcludeVersion = true,
Prerelease = true,
NoCache = true
};
_context.NuGetInstall(PackageId, installSettings);
}
public void VerifyPackage()
{
bool allOK = true;
if (PackageChecks != null)
foreach (var check in PackageChecks)
allOK &= check.ApplyTo(PackageTestDirectory);
if (allOK)
Console.WriteLine("All checks passed!");
else
throw new Exception("Verification failed!");
}
public void RunPackageTests()
{
_context.Information($"Package tests will run at level {BuildSettings.PackageTestLevel}");
var reporter = new ResultReporter(PackageFileName);
_context.CleanDirectory(PackageResultDirectory);
// Ensure we start out each package with no extensions installed.
// If any package test installs an extension, it remains available
// for subsequent tests of the same package only.
//foreach (DirectoryPath dirPath in _context.GetDirectories(ExtensionInstallDirectory + "*"))
//{
// _context.DeleteDirectory(dirPath, new DeleteDirectorySettings() { Recursive = true });
// _context.Information("Deleted directory " + dirPath.GetDirectoryName());
//}
// Package was defined with either a TestRunnerSource or a single TestRunner. In either
// case, these will all be package test runners and may or may not require installation.
var defaultRunners = TestRunnerSource ?? new TestRunnerSource((TestRunner)TestRunner);
// Preinstall all runners requiring installation
InstallRunners(defaultRunners.PackageTestRunners);
foreach (var packageTest in PackageTests)
{
if (packageTest.Level > BuildSettings.PackageTestLevel)
continue;
InstallExtensions(packageTest.ExtensionsNeeded);
InstallRunners(packageTest.TestRunners);
// Use runners from the test if provided, otherwise the default runners
var runners = packageTest.TestRunners.Length > 0 ? packageTest.TestRunners : defaultRunners.PackageTestRunners;
foreach (var runner in runners)
{
Console.WriteLine(runner.Version);
var testResultDir = $"{PackageResultDirectory}/{packageTest.Name}/";
var resultFile = testResultDir + "TestResult.xml";
Banner.Display(packageTest.Description);
_context.CreateDirectory(testResultDir);
string arguments = $"{packageTest.Arguments} {ExtraTestArguments} --work={testResultDir}";
if (CommandLineOptions.TraceLevel.Value != "Off")
arguments += $" --trace:{CommandLineOptions.TraceLevel.Value}";
int rc = runner.RunPackageTest(arguments);
try
{
var result = new ActualResult(resultFile);
var report = new PackageTestReport(packageTest, result, runner);
reporter.AddReport(report);
Console.WriteLine(report.Errors.Count == 0
? "\nSUCCESS: Test Result matches expected result!"
: "\nERROR: Test Result not as expected!");
}
catch (Exception ex)
{
reporter.AddReport(new PackageTestReport(packageTest, ex));
Console.WriteLine("\nERROR: No result found!");
}
}
}
// Create report as a string
var sw = new StringWriter();
bool hadErrors = reporter.ReportResults(sw);
string reportText = sw.ToString();
//Display it on the console
Console.WriteLine(reportText);
// Save it to the result directory as well
using (var reportFile = new StreamWriter($"{PackageResultDirectory}/PackageTestSummary.txt"))
reportFile.Write(reportText);
if (hadErrors)
throw new Exception("One or more package tests had errors!");
}
private void InstallExtensions(ExtensionSpecifier[] extensionsNeeded)
{
foreach (ExtensionSpecifier extension in extensionsNeeded)
extension.InstallExtension(this);
}
private void InstallRunners(IEnumerable<IPackageTestRunner> runners)
{
// Install any runners needing installation
foreach (var runner in runners)
if (runner is InstallableTestRunner)
InstallRunner((InstallableTestRunner)runner);
}
private void InstallRunner(InstallableTestRunner runner)
{
runner.Install(PackageInstallDirectory);
// We are using nuget packages for the runner, so it won't normally recognize
// chocolatey extensions. We add an extra addins file for that purpose.
if (PackageType == PackageType.Chocolatey)
{
var filePath = runner.ExecutablePath.GetDirectory().CombineWithFilePath("choco.engine.addins").ToString();
Console.WriteLine($"Creating {filePath}");
using (var writer = new StreamWriter(filePath))
{
writer.WriteLine("../../nunit-extension-*/tools/");
writer.WriteLine("../../nunit-extension-*/tools/*/");
writer.WriteLine("../../../nunit-extension-*/tools/");
writer.WriteLine("../../../nunit-extension-*/tools/*/");
}
}
}
public virtual void VerifySymbolPackage() { } // Does nothing. Overridden for NuGet packages.
}

Просмотреть файл

@ -1,90 +0,0 @@
// Representation of a package reference, containing everything needed to install it
public class PackageReference
{
private ICakeContext _context;
public string Id { get; }
public string Version { get; }
public PackageReference(string id, string version)
{
_context = BuildSettings.Context;
Id = id;
Version = version;
}
public PackageReference LatestDevBuild => GetLatestDevBuild();
public PackageReference LatestRelease => GetLatestRelease();
private PackageReference GetLatestDevBuild()
{
var packageList = _context.NuGetList(Id, new NuGetListSettings()
{
Prerelease = true,
Source = new [] { "https://www.myget.org/F/nunit/api/v3/index.json" }
} );
foreach (var package in packageList)
return new PackageReference(package.Name, package.Version);
return this;
}
private PackageReference GetLatestRelease()
{
var packageList = _context.NuGetList(Id, new NuGetListSettings()
{
Prerelease = true,
Source = new [] {
"https://www.nuget.org/api/v2/",
"https://community.chocolatey.org/api/v2/" }
} );
// TODO: There seems to be an error in NuGet or in Cake, causing the list to
// contain ALL NuGet packages, so we check the Id in this loop.
foreach (var package in packageList)
if (package.Name == Id)
return new PackageReference(Id, package.Version);
return this;
}
public bool IsInstalled(string installDirectory)
{
return _context.GetDirectories($"{installDirectory}{Id}.*").Count > 0;
}
public void InstallExtension(PackageDefinition targetPackage)
{
Install(targetPackage.ExtensionInstallDirectory);
}
public void Install(string installDirectory)
{
if (!IsInstalled(installDirectory))
{
Banner.Display($"Installing {Id} version {Version}");
var packageSources = new []
{
"https://www.myget.org/F/nunit/api/v3/index.json",
"https://api.nuget.org/v3/index.json",
"https://community.chocolatey.org/api/v2/"
};
Console.WriteLine("Package Sources:");
foreach(var source in packageSources)
Console.WriteLine($" {source}");
Console.WriteLine();
_context.NuGetInstall(Id,
new NuGetInstallSettings()
{
OutputDirectory = installDirectory,
Version = Version,
Source = packageSources
});
}
}
}

Просмотреть файл

@ -1,76 +0,0 @@
// Representation of a single test to be run against a pre-built package.
// Each test has a Level, with the following values defined...
// 0 Do not run - used for temporarily disabling a test
// 1 Run for all CI tests - that is every time we test packages
// 2 Run only on PRs, dev builds and when publishing
// 3 Run only when publishing
public struct PackageTest
{
public int Level;
public string Name;
public string Description;
public string Arguments;
public ExpectedResult ExpectedResult;
public IPackageTestRunner[] TestRunners;
public ExtensionSpecifier[] ExtensionsNeeded;
public PackageTest(int level, string name, string description, string arguments, ExpectedResult expectedResult )
{
if (name == null)
throw new ArgumentNullException(nameof(name));
if (description == null)
throw new ArgumentNullException(nameof(description));
if (arguments == null)
throw new ArgumentNullException(nameof(arguments));
if (expectedResult == null)
throw new ArgumentNullException(nameof(expectedResult));
Level = level;
Name = name;
Description = description;
Arguments = arguments;
ExpectedResult = expectedResult;
ExtensionsNeeded = new ExtensionSpecifier[0];
TestRunners = new IPackageTestRunner[0];
}
public PackageTest(int level, string name, string description, string arguments, ExpectedResult expectedResult, params ExtensionSpecifier[] extensionsNeeded )
{
if (name == null)
throw new ArgumentNullException(nameof(name));
if (description == null)
throw new ArgumentNullException(nameof(description));
if (arguments == null)
throw new ArgumentNullException(nameof(arguments));
if (expectedResult == null)
throw new ArgumentNullException(nameof(expectedResult));
Level = level;
Name = name;
Description = description;
Arguments = arguments;
ExpectedResult = expectedResult;
ExtensionsNeeded = extensionsNeeded;
TestRunners = new IPackageTestRunner[0];
}
public PackageTest(int level, string name, string description, string arguments, ExpectedResult expectedResult, params IPackageTestRunner[] testRunners )
{
if (name == null)
throw new ArgumentNullException(nameof(name));
if (description == null)
throw new ArgumentNullException(nameof(description));
if (arguments == null)
throw new ArgumentNullException(nameof(arguments));
if (expectedResult == null)
throw new ArgumentNullException(nameof(expectedResult));
Level = level;
Name = name;
Description = description;
Arguments = arguments;
ExpectedResult = expectedResult;
TestRunners = testRunners;
ExtensionsNeeded = new ExtensionSpecifier[0];
}
}

Просмотреть файл

@ -1,244 +0,0 @@
public static class PackageReleaseManager
{
private static ICakeContext _context;
static PackageReleaseManager()
{
_context = BuildSettings.Context;
}
private static bool _hadErrors = false;
public static void Publish()
{
_hadErrors = false;
PublishToMyGet();
PublishToNuGet();
PublishToChocolatey();
if (_hadErrors)
throw new Exception("One of the publishing steps failed.");
}
public static void PublishToMyGet()
{
if (!BuildSettings.ShouldPublishToMyGet)
_context.Information("Nothing to publish to MyGet from this run.");
else if (CommandLineOptions.NoPush)
_context.Information("NoPush option suppressing publication to MyGet");
else
foreach (var package in BuildSettings.Packages)
{
var packageName = $"{package.PackageId}.{BuildSettings.PackageVersion}.nupkg";
var packagePath = BuildSettings.PackageDirectory + packageName;
try
{
if (package.PackageType == PackageType.NuGet)
PushNuGetPackage(packagePath, BuildSettings.MyGetApiKey, BuildSettings.MyGetPushUrl);
else if (package.PackageType == PackageType.Chocolatey)
PushChocolateyPackage(packagePath, BuildSettings.MyGetApiKey, BuildSettings.MyGetPushUrl);
}
catch (Exception ex)
{
_context.Error(ex.Message);
_hadErrors = true;
}
}
}
public static void PublishToNuGet()
{
if (!BuildSettings.ShouldPublishToNuGet)
_context.Information("Nothing to publish to NuGet from this run.");
else if (CommandLineOptions.NoPush)
_context.Information("NoPush option suppressing publication to NuGet");
else
foreach (var package in BuildSettings.Packages)
{
var packageName = $"{package.PackageId}.{BuildSettings.PackageVersion}.nupkg";
var packagePath = BuildSettings.PackageDirectory + packageName;
try
{
if (package.PackageType == PackageType.NuGet)
PushNuGetPackage(packagePath, BuildSettings.NuGetApiKey, BuildSettings.NuGetPushUrl);
}
catch (Exception ex)
{
_context.Error(ex.Message);
_hadErrors = true;
}
}
}
public static void PublishToChocolatey()
{
if (!BuildSettings.ShouldPublishToChocolatey)
_context.Information("Nothing to publish to Chocolatey from this run.");
else if (CommandLineOptions.NoPush)
_context.Information("NoPush option suppressing publication to Chocolatey");
else
foreach (var package in BuildSettings.Packages)
{
var packageName = $"{package.PackageId}.{BuildSettings.PackageVersion}.nupkg";
var packagePath = BuildSettings.PackageDirectory + packageName;
try
{
if (package.PackageType == PackageType.Chocolatey)
PushChocolateyPackage(packagePath, BuildSettings.ChocolateyApiKey, BuildSettings.ChocolateyPushUrl);
}
catch (Exception ex)
{
_context.Error(ex.Message);
_hadErrors = true;
}
}
}
private static void PushNuGetPackage(FilePath package, string apiKey, string url)
{
CheckPackageExists(package);
_context.NuGetPush(package, new NuGetPushSettings() { ApiKey = apiKey, Source = url });
}
private static void PushChocolateyPackage(FilePath package, string apiKey, string url)
{
CheckPackageExists(package);
_context.ChocolateyPush(package, new ChocolateyPushSettings() { ApiKey = apiKey, Source = url });
}
private static void CheckPackageExists(FilePath package)
{
if (!_context.FileExists(package))
throw new InvalidOperationException(
$"Package not found: {package.GetFilename()}.\nCode may have changed since package was last built.");
}
private const string DRAFT_RELEASE_ERROR =
"A direct call to CreateDraftRelease is permitted only:\r\n" +
" * On a release branch (release-x.x.x)\r\n" +
" * On the main branch tagged for a production release\r\n" +
" * Using option --packageVersion to specify a release version";
public static void CreateDraftRelease()
{
string releaseVersion =
CommandLineOptions.PackageVersion.Exists ? CommandLineOptions.PackageVersion.Value :
BuildSettings.IsReleaseBranch ? BuildSettings.BuildVersion.BranchName.Substring(8) :
BuildSettings.IsProductionRelease ? BuildSettings.PackageVersion : null;
if (releaseVersion != null)
{
if (CommandLineOptions.NoPush)
_context.Information($"NoPush option skipping creation of draft release for version {releaseVersion}");
else
{
string releaseName = $"{BuildSettings.Title} {releaseVersion}";
_context.Information($"Creating draft release for {releaseName}");
try
{
_context.GitReleaseManagerCreate(BuildSettings.GitHubAccessToken, BuildSettings.GitHubOwner, BuildSettings.GitHubRepository, new GitReleaseManagerCreateSettings()
{
Name = releaseName,
Milestone = releaseVersion
});
}
catch
{
_context.Error($"Unable to create draft release for {releaseName}.");
_context.Error($"Check that there is a {releaseVersion} milestone with at least one closed issue.");
_context.Error("");
throw;
}
}
}
else
{
bool calledDirectly = CommandLineOptions.Target.Value == "CreateDraftRelease";
if (calledDirectly)
throw new InvalidOperationException(DRAFT_RELEASE_ERROR);
else
_context.Information("Skipping creation of draft release because this is not a release branch");
}
}
private const string UPDATE_RELEASE_ERROR =
"A direct call to UpdateReleaseNotes is permitted only:\r\n" +
" * On the main branch tagged for a production release\r\n" +
" * Using option --packageVersion to specify a release version";
public static void UpdateReleaseNotes()
{
string releaseVersion =
CommandLineOptions.PackageVersion.Exists ? CommandLineOptions.PackageVersion.Value :
BuildSettings.IsProductionRelease ? BuildSettings.PackageVersion : null;
if (releaseVersion == null)
throw new InvalidOperationException(UPDATE_RELEASE_ERROR);
if (CommandLineOptions.NoPush)
_context.Information($"NoPush option skipping update of release notes for version {releaseVersion}");
else
{
string releaseName = $"{BuildSettings.Title} {releaseVersion}";
_context.Information($"Updating release notes for {releaseName}");
try
{
_context.GitReleaseManagerCreate(BuildSettings.GitHubAccessToken, BuildSettings.GitHubOwner, BuildSettings.GitHubRepository, new GitReleaseManagerCreateSettings()
{
Name = releaseName,
Milestone = releaseVersion
});
}
catch
{
_context.Error($"Unable to update release notes for {releaseName}.");
_context.Error($"Check that there is a {releaseVersion} milestone with a matching release.");
_context.Error("");
throw;
}
}
}
public static void DownloadDraftRelease()
{
if (!BuildSettings.IsReleaseBranch)
throw new Exception("DownloadDraftRelease requires a release branch!");
string milestone = BuildSettings.BranchName.Substring(8);
_context.GitReleaseManagerExport(BuildSettings.GitHubAccessToken, BuildSettings.GitHubOwner, BuildSettings.GitHubRepository, "DraftRelease.md",
new GitReleaseManagerExportSettings() { TagName = milestone });
}
public static void CreateProductionRelease()
{
if (!BuildSettings.IsProductionRelease)
{
_context.Information("Skipping CreateProductionRelease because this is not a production release");
}
else if (CommandLineOptions.NoPush)
_context.Information($"NoPush option skipping creation of production release for version {BuildSettings.PackageVersion}");
else
{
string token = BuildSettings.GitHubAccessToken;
string owner = BuildSettings.GitHubOwner;
string repository = BuildSettings.GitHubRepository;
string tagName = BuildSettings.PackageVersion;
string assets = string.Join<string>(',', BuildSettings.Packages.Select(p => p.PackageFilePath));
//IsRunningOnWindows()
// ? $"\"{BuildSettings.NuGetPackage},{BuildSettings.ChocolateyPackage}\""
// : $"\"{BuildSettings.NuGetPackage}\"";
_context.Information($"Publishing release {tagName} to GitHub");
_context.Information($" Assets: {assets}");
_context.GitReleaseManagerAddAssets(token, owner, repository, tagName, assets);
_context.GitReleaseManagerClose(token, owner, repository, tagName);
}
}
}

Просмотреть файл

@ -1,51 +0,0 @@
Setup((context) =>
{
var target = context.TargetTask.Name;
var tasksToExecute = context.TasksToExecute.Select(t => t.Name);
// Ensure that BuildSettings have been initialized
if (BuildSettings.Context == null)
throw new Exception("BuildSettings have not been initialized. Call BuildSettings.Initialize() from your build.cake script.");
// Ensure Api Keys and tokens are available if needed for tasks to be executed
// MyGet Api Key
bool needMyGetApiKey = tasksToExecute.Contains("PublishToMyGet") && BuildSettings.ShouldPublishToMyGet && !CommandLineOptions.NoPush;
if (needMyGetApiKey && string.IsNullOrEmpty(BuildSettings.MyGetApiKey))
DisplayErrorAndThrow("MyGet ApiKey is required but was not set.");
// NuGet Api Key
bool needNuGetApiKey = tasksToExecute.Contains("PublishToNuGet") && BuildSettings.ShouldPublishToNuGet && !CommandLineOptions.NoPush;
if (needNuGetApiKey && string.IsNullOrEmpty(BuildSettings.NuGetApiKey))
DisplayErrorAndThrow("NuGet ApiKey is required but was not set.");
// Chocolatey Api Key
bool needChocolateyApiKey = tasksToExecute.Contains("PublishToChocolatey") && BuildSettings.ShouldPublishToChocolatey && !CommandLineOptions.NoPush;
if (needChocolateyApiKey && string.IsNullOrEmpty(BuildSettings.ChocolateyApiKey))
DisplayErrorAndThrow("Chocolatey ApiKey is required but was not set.");
// GitHub Access Token, Owner and Repository
if (!CommandLineOptions.NoPush)
if (tasksToExecute.Contains("CreateDraftRelease") && BuildSettings.IsReleaseBranch ||
tasksToExecute.Contains("CreateProductionRelease") && BuildSettings.IsProductionRelease)
{
if (string.IsNullOrEmpty(BuildSettings.GitHubAccessToken))
DisplayErrorAndThrow("GitHub Access Token is required but was not set.");
if (string.IsNullOrEmpty(BuildSettings.GitHubOwner))
DisplayErrorAndThrow("GitHub Owner is required but was not set.");
if (string.IsNullOrEmpty(BuildSettings.GitHubRepository))
DisplayErrorAndThrow("GitHub Repository is required but was not set.");
}
// Add settings to BuildSettings
BuildSettings.Target = target;
BuildSettings.TasksToExecute = tasksToExecute;
void DisplayErrorAndThrow(string message)
{
message += $"\r\n Tasks: {string.Join(", ", tasksToExecute)}";
context.Error(message);
throw new Exception(message);
}
});

Просмотреть файл

@ -1,48 +0,0 @@
// All tasks incorporated in the recipe are defined using CakeTaskBuilders.
// The actual specification of criteria, dependencies and actions for each
// task is done separately in task-definitions.cake.
//
// This approach provides a level of indirection, permitting the user to
// modify or completely redefine what a task does in their build.cake file,
// without changing the definitions in the recipe.
public static class BuildTasks
{
// General
public static CakeTaskBuilder DumpSettingsTask { get; set; }
public static CakeTaskBuilder DefaultTask {get; set; }
// Building
public static CakeTaskBuilder BuildTask { get; set; }
public static CakeTaskBuilder CheckHeadersTask { get; set; }
public static CakeTaskBuilder CleanTask { get; set; }
public static CakeTaskBuilder CleanAllTask { get; set; }
public static CakeTaskBuilder RestoreTask { get; set; }
// Unit Testing
public static CakeTaskBuilder UnitTestTask { get; set; }
// Packaging
public static CakeTaskBuilder PackageTask { get; set; }
public static CakeTaskBuilder BuildTestAndPackageTask { get; set; }
//public static CakeTaskBuilder PackageBuildTask { get; set; }
//public static CakeTaskBuilder PackageInstallTask { get; set; }
//public static CakeTaskBuilder PackageVerifyTask { get; set; }
//public static CakeTaskBuilder PackageTestTask { get; set; }
// Publishing
public static CakeTaskBuilder PublishTask { get; set; }
public static CakeTaskBuilder PublishToMyGetTask { get; set; }
public static CakeTaskBuilder PublishToNuGetTask { get; set; }
public static CakeTaskBuilder PublishToChocolateyTask { get; set; }
// Releasing
public static CakeTaskBuilder CreateDraftReleaseTask { get; set; }
//public static CakeTaskBuilder DownloadDraftReleaseTask { get; set; }
//public static CakeTaskBuilder UpdateReleaseNotesTask { get; set; }
public static CakeTaskBuilder CreateProductionReleaseTask { get; set; }
// Continuous Integration
public static CakeTaskBuilder ContinuousIntegrationTask { get; set; }
public static CakeTaskBuilder AppveyorTask { get; set; }
}

Просмотреть файл

@ -1,134 +0,0 @@
// This file defines what each of the tasks in the recipe actually does.
// You should not change these definitions unless you intend to change
// the behavior of a task for all projects that use the recipe.
//
// To make a change for a single project, you should add code to your build.cake
// or another project-specific cake file. See extending.cake for examples.
BuildTasks.DefaultTask = Task("Default")
.Description("Default task if none specified by user")
.IsDependentOn("Build");
BuildTasks.DumpSettingsTask = Task("DumpSettings")
.Description("Display BuildSettings properties")
.Does(() => BuildSettings.DumpSettings());
BuildTasks.CheckHeadersTask = Task("CheckHeaders")
.Description("Check source files for valid copyright headers")
.WithCriteria(() => !CommandLineOptions.NoBuild)
.WithCriteria(() => !BuildSettings.SuppressHeaderCheck)
.Does(() => Headers.Check());
BuildTasks.CleanTask = Task("Clean")
.Description("Clean output and package directories")
.WithCriteria(() => !CommandLineOptions.NoBuild)
.Does(() =>
{
foreach (var binDir in GetDirectories($"**/bin/{BuildSettings.Configuration}/"))
CleanDirectory(binDir);
CleanDirectory(BuildSettings.PackageDirectory);
CleanDirectory(BuildSettings.ImageDirectory);
CleanDirectory(BuildSettings.ExtensionsDirectory);
DeleteFiles(BuildSettings.ProjectDirectory + "*.log");
});
BuildTasks.CleanAllTask = Task("CleanAll")
.Description("Clean everything!")
.Does(() =>
{
foreach (var binDir in GetDirectories("**/bin/"))
CleanDirectory(binDir);
CleanDirectory(BuildSettings.PackageDirectory);
CleanDirectory(BuildSettings.ImageDirectory);
CleanDirectory(BuildSettings.ExtensionsDirectory);
DeleteFiles(BuildSettings.ProjectDirectory + "*.log");
foreach (var dir in GetDirectories("src/**/obj/"))
DeleteDirectory(dir, new DeleteDirectorySettings() { Recursive = true });
});
BuildTasks.RestoreTask = Task("Restore")
.Description("Restore referenced packages")
.WithCriteria(() => BuildSettings.SolutionFile != null)
.WithCriteria(() => !CommandLineOptions.NoBuild)
.Does(() => {
NuGetRestore(BuildSettings.SolutionFile, new NuGetRestoreSettings() {
Source = new string[] {
"https://www.nuget.org/api/v2",
"https://www.myget.org/F/nunit/api/v2" }
});
});
BuildTasks.BuildTask = Task("Build")
.WithCriteria(() => BuildSettings.SolutionFile != null)
.WithCriteria(() => !CommandLineOptions.NoBuild)
.IsDependentOn("Clean")
.IsDependentOn("Restore")
.IsDependentOn("CheckHeaders")
.Description("Build the solution")
.Does(() => {
MSBuild(BuildSettings.SolutionFile, BuildSettings.MSBuildSettings.WithProperty("Version", BuildSettings.PackageVersion));
});
BuildTasks.UnitTestTask = Task("Test")
.Description("Run unit tests")
.IsDependentOn("Build")
.Does(() => UnitTesting.RunAllTests());
BuildTasks.PackageTask = Task("Package")
.IsDependentOn("Build")
.Description("Build, Install, Verify and Test all packages")
.Does(() => {
var selector = CommandLineOptions.PackageSelector;
foreach(var package in BuildSettings.Packages)
if (!selector.Exists || package.IsSelectedBy(selector.Value))
package.BuildVerifyAndTest();
});
BuildTasks.BuildTestAndPackageTask = Task("BuildTestAndPackage")
.Description("Do Build, Test and Package all in one run")
.IsDependentOn("Build")
.IsDependentOn("Test")
.IsDependentOn("Package");
BuildTasks.PublishTask = Task("Publish")
.Description("Publish all packages for current branch")
.IsDependentOn("Package")
.Does(() => PackageReleaseManager.Publish());
BuildTasks.PublishToMyGetTask = Task("PublishToMyGet")
.Description("Publish packages to MyGet")
.Does(() => PackageReleaseManager.PublishToMyGet() );
BuildTasks.PublishToNuGetTask = Task("PublishToNuGet")
.Description("Publish packages to NuGet")
.Does(() => PackageReleaseManager.PublishToNuGet() );
BuildTasks.PublishToChocolateyTask = Task("PublishToChocolatey")
.Description("Publish packages to Chocolatey")
.Does(() => PackageReleaseManager.PublishToChocolatey() );
BuildTasks.CreateDraftReleaseTask = Task("CreateDraftRelease")
.Description("Create a draft release on GitHub")
.Does(() => PackageReleaseManager.CreateDraftRelease() );
BuildTasks.CreateProductionReleaseTask = Task("CreateProductionRelease")
.Description("Create a production GitHub Release")
.Does(() => PackageReleaseManager.CreateProductionRelease() );
BuildTasks.ContinuousIntegrationTask = Task("ContinuousIntegration")
.Description("Perform continuous integration run")
.IsDependentOn("Build")
.IsDependentOn("Test")
.IsDependentOn("Package")
.IsDependentOn("Publish")
.IsDependentOn("CreateDraftRelease")
.IsDependentOn("CreateProductionRelease");
BuildTasks.AppveyorTask = Task("Appveyor")
.Description("Target for running on AppVeyor")
.IsDependentOn("ContinuousIntegration");

Просмотреть файл

@ -1,171 +0,0 @@
public class PackageTestReport
{
public PackageTest Test;
public ActualResult Result;
public ITestRunner Runner;
public List<string> Errors;
public List<string> Warnings;
public PackageTestReport(PackageTest test, ActualResult actualResult, ITestRunner runner = null)
{
Test = test;
Result = actualResult;
Runner = runner;
Errors = new List<string>();
Warnings = new List<string>();
var expectedResult = test.ExpectedResult;
ReportMissingFiles();
if (actualResult.OverallResult == null)
Errors.Add(" The test-run element has no result attribute.");
else if (expectedResult.OverallResult != actualResult.OverallResult)
Errors.Add($" Expected: Overall Result = {expectedResult.OverallResult} But was: {actualResult.OverallResult}");
CheckCounter("Test Count", expectedResult.Total, actualResult.Total);
CheckCounter("Passed", expectedResult.Passed, actualResult.Passed);
CheckCounter("Failed", expectedResult.Failed, actualResult.Failed);
CheckCounter("Warnings", expectedResult.Warnings, actualResult.Warnings);
CheckCounter("Inconclusive", expectedResult.Inconclusive, actualResult.Inconclusive);
CheckCounter("Skipped", expectedResult.Skipped, actualResult.Skipped);
var expectedAssemblies = expectedResult.Assemblies;
var actualAssemblies = actualResult.Assemblies;
for (int i = 0; i < expectedAssemblies.Length && i < actualAssemblies.Length; i++)
{
var expected = expectedAssemblies[i];
var actual = actualAssemblies[i];
if (expected.AssemblyName != actual.AssemblyName)
Errors.Add($" Expected: {expected.AssemblyName} But was: { actual.AssemblyName}");
else if (runner == null || runner.PackageId == "NUnit.ConsoleRunner.NetCore")
{
if (actual.Runtime == null)
Warnings.Add($"Unable to determine actual runtime used for {expected.AssemblyName}");
else if (expected.Runtime != actual.Runtime)
Errors.Add($" Assembly {actual.AssemblyName} Expected: {expected.Runtime} But was: {actual.Runtime}");
}
}
for (int i = actualAssemblies.Length; i < expectedAssemblies.Length; i++)
Errors.Add($" Assembly {expectedAssemblies[i].AssemblyName} was not found");
for (int i = expectedAssemblies.Length; i < actualAssemblies.Length; i++)
Errors.Add($" Found unexpected assembly {actualAssemblies[i].AssemblyName}");
}
public PackageTestReport(PackageTest test, Exception ex, ITestRunner runner = null)
{
Test = test;
Result = null;
Errors = new List<string>();
Errors.Add($" {ex.Message}");
Runner = runner;
}
public void Display(int index, TextWriter writer)
{
writer.WriteLine();
writer.WriteLine($"{index}. {Test.Description}");
if (Runner != null)
writer.WriteLine($" Runner: {Runner.PackageId} {Runner.Version}");
writer.WriteLine($" Args: {Test.Arguments}");
writer.WriteLine();
foreach (var error in Errors)
writer.WriteLine(error);
if (Errors.Count == 0)
{
writer.WriteLine(" SUCCESS: Test Result matches expected result!");
}
else
{
writer.WriteLine();
writer.WriteLine(" ERROR: Test Result not as expected!");
}
foreach (var warning in Warnings)
writer.WriteLine(" WARNING: " + warning);
}
// File level errors, like missing or mal-formatted files, need to be highlighted
// because otherwise it's hard to detect the cause of the problem without debugging.
// This method finds and reports that type of error.
private void ReportMissingFiles()
{
// Start with all the top-level test suites. Note that files that
// cannot be found show up as Unknown as do unsupported file types.
var suites = Result.Xml.SelectNodes(
"//test-suite[@type='Unknown'] | //test-suite[@type='Project'] | //test-suite[@type='Assembly']");
// If there is no top-level suite, it generally means the file format could not be interpreted
if (suites.Count == 0)
Errors.Add(" No top-level suites! Possible empty command-line or misformed project.");
foreach (XmlNode suite in suites)
{
// Narrow down to the specific failures we want
string runState = GetAttribute(suite, "runstate");
string suiteResult = GetAttribute(suite, "result");
string label = GetAttribute(suite, "label");
string site = suite.Attributes["site"]?.Value ?? "Test";
if (runState == "NotRunnable" || suiteResult == "Failed" && site == "Test" && (label == "Invalid" || label == "Error"))
{
string message = suite.SelectSingleNode("reason/message")?.InnerText;
Errors.Add($" {message}");
}
}
}
private void CheckCounter(string label, int expected, int actual)
{
// If expected value of counter is negative, it means no check is needed
if (expected >= 0 && expected != actual)
Errors.Add($" Expected: {label} = {expected} But was: {actual}");
}
private string GetAttribute(XmlNode node, string name)
{
return node.Attributes[name]?.Value;
}
}
public class ResultReporter
{
private string _packageName;
private List<PackageTestReport> _reports = new List<PackageTestReport>();
public ResultReporter(string packageName)
{
_packageName = packageName;
}
public void AddReport(PackageTestReport report)
{
_reports.Add(report);
}
public bool ReportResults(TextWriter writer)
{
writer.WriteLine("\n=================================================="); ;
writer.WriteLine($"Test Results for {_packageName}");
writer.WriteLine("=================================================="); ;
writer.WriteLine("\nTest Environment");
writer.WriteLine($" OS Version: {Environment.OSVersion.VersionString}");
writer.WriteLine($" CLR Version: {Environment.Version}\n");
int index = 0;
bool hasErrors = false;
foreach (var report in _reports)
{
hasErrors |= report.Errors.Count > 0;
report.Display(++index, writer);
}
return hasErrors;
}
}

Просмотреть файл

@ -1,168 +0,0 @@
// This file contains classes used to interpret the result XML that is
// produced by test runs of the GUI.
using System.Xml;
public abstract class ResultSummary
{
public string OverallResult { get; set; }
public int Total { get; set; }
public int Passed { get; set; }
public int Failed { get; set; }
public int Warnings { get; set; }
public int Inconclusive { get; set; }
public int Skipped { get; set; }
}
public class ExpectedResult : ResultSummary
{
public ExpectedResult(string overallResult)
{
if (string.IsNullOrEmpty(overallResult))
throw new ArgumentNullException(nameof(overallResult));
OverallResult = overallResult;
// Initialize counters to -1, indicating no expected value.
// Set properties of those items to be checked.
Total = Passed = Failed = Warnings = Inconclusive = Skipped = -1;
}
public ExpectedAssemblyResult[] Assemblies { get; set; } = new ExpectedAssemblyResult[0];
}
public class ExpectedAssemblyResult
{
public ExpectedAssemblyResult(string name, string expectedRuntime = null)
{
AssemblyName = name;
Runtime = expectedRuntime;
}
public string AssemblyName { get; }
public string Runtime { get; }
}
public class ActualResult : ResultSummary
{
public ActualResult(string resultFile)
{
var doc = new XmlDocument();
doc.Load(resultFile);
Xml = doc.DocumentElement;
if (Xml.Name != "test-run")
throw new Exception("The test-run element was not found.");
OverallResult = GetAttribute(Xml, "result");
Total = IntAttribute(Xml, "total");
Passed = IntAttribute(Xml, "passed");
Failed = IntAttribute(Xml, "failed");
Warnings = IntAttribute(Xml, "warnings");
Inconclusive = IntAttribute(Xml, "inconclusive");
Skipped = IntAttribute(Xml, "skipped");
var assemblies = new List<ActualAssemblyResult>();
//var engineVersion = new Version(GetAttribute(Xml, "engine-version"));
foreach (XmlNode node in Xml.SelectNodes("//test-suite[@type='Assembly']"))
assemblies.Add(new ActualAssemblyResult(node));
//foreach (XmlNode node in Xml.SelectNodes("//test-suite[@type='Assembly']"))
// assemblies.Add(new ActualAssemblyResult(node, engineVersion));
Assemblies = assemblies.ToArray();
}
public XmlNode Xml { get; }
public ActualAssemblyResult[] Assemblies { get; }
private string GetAttribute(XmlNode node, string name)
{
return node.Attributes[name]?.Value;
}
private int IntAttribute(XmlNode node, string name)
{
string s = GetAttribute(node, name);
// TODO: We should replace 0 with -1, representing a missing counter
// attribute, after issue #707 is fixed.
return s == null ? 0 : int.Parse(s);
}
}
public class ActualAssemblyResult
{
public ActualAssemblyResult(XmlNode xml)
{
AssemblyName = xml.Attributes["name"]?.Value;
//var env = xml.SelectSingleNode("environment");
var settings = xml.SelectSingleNode("settings");
// If TargetRuntimeFramework setting is not present, the Runner will probably crash
var runtimeSetting = settings?.SelectSingleNode("setting[@name='TargetRuntimeFramework']");
Runtime = runtimeSetting?.Attributes["value"]?.Value;
var agentSetting = settings?.SelectSingleNode("setting[@name='SelectedAgentName']");
AgentName = agentSetting?.Attributes["value"]?.Value;
}
public string AssemblyName { get; }
public string AgentName { get; }
public string Runtime { get; }
}
#if false
public class ActualAssemblyResult
{
public ActualAssemblyResult(XmlNode xml, Version engineVersion)
{
Name = xml.Attributes["name"]?.Value;
var env = xml.SelectSingleNode("environment");
var settings = xml.SelectSingleNode("settings");
// If TargetRuntimeFramework setting is not present, the GUI will have crashed anyway
var runtimeSetting = settings.SelectSingleNode("setting[@name='ImageTargetFrameworkName']");
TargetRuntime = runtimeSetting?.Attributes["value"]?.Value;
// Engine 3.10 and earlier doesn't provide enough info
if (engineVersion >= new Version(3,11,0,0))
Runtime = DeduceActualRuntime(xml);
}
public string Name { get; }
public string Runtime { get; }
public string TargetRuntime { get; }
// Code to determine the runtime actually used is adhoc
// and doesn't work for all assemblies because the needed
// information may not be present in the result file.
// TODO: Modify result file schema so this can be cleaner
private static string DeduceActualRuntime(XmlNode assembly)
{
var env = assembly.SelectSingleNode("environment");
// The TargetRuntimeFramework setting is only present
// under the 3.12 and later versions of the engine.
var runtimeSetting = assembly.SelectSingleNode("settings/setting[@name='TargetRuntimeFramework']");
var targetRuntime = runtimeSetting?.Attributes["value"]?.Value;
if (targetRuntime != null)
return targetRuntime;
var clrVersion = env.Attributes["clr-version"]?.Value;
if (clrVersion == null)
return null;
if (clrVersion.StartsWith("2.0"))
return "net-2.0";
if (clrVersion.StartsWith("4.0"))
return "net-4";
return null;
}
}
#endif

Просмотреть файл

@ -1,224 +0,0 @@
/////////////////////////////////////////////////////////////////////////////
// TEST RUNNER INTERFACES
/////////////////////////////////////////////////////////////////////////////
/// <Summary>
/// Common interface for all test runners
/// </Summary>
public interface ITestRunner
{
string PackageId { get; }
string Version { get; }
}
/// <Summary>
/// A runner capable of running unit tests
/// </Summary>
public interface IUnitTestRunner : ITestRunner
{
int RunUnitTest(FilePath testPath);
}
/// <Summary>
/// A runner capable of running package tests
/// </Summary>
public interface IPackageTestRunner : ITestRunner
{
int RunPackageTest(string arguments);
}
/////////////////////////////////////////////////////////////////////////////
// ABSTRACT TEST RUNNER
/////////////////////////////////////////////////////////////////////////////
/// <summary>
/// The TestRunner class is the abstract base for all TestRunners used to run unit-
/// or package-tests. A TestRunner knows how to run a test assembly and provide a result.
/// All base functionality is implemented in this class. Derived classes make that
/// functionality available selectively by implementing specific interfaces.
/// </summary>
public abstract class TestRunner : ITestRunner
{
protected ICakeContext Context => BuildSettings.Context;
public string PackageId { get; protected set; }
public string Version { get; protected set; }
protected int RunTest(FilePath executablePath, string arguments = null)
{
return RunTest(executablePath, new ProcessSettings { Arguments = arguments });
}
protected int RunTest(FilePath executablePath, ProcessSettings processSettings=null)
{
if (executablePath == null)
throw new ArgumentNullException(nameof(executablePath));
if (processSettings == null)
processSettings = new ProcessSettings();
// Add default values to settings if not present
if (processSettings.WorkingDirectory == null)
processSettings.WorkingDirectory = BuildSettings.OutputDirectory;
if (executablePath.GetExtension() == ".dll")
return Context.StartProcess("dotnet", processSettings);
else
return Context.StartProcess(executablePath, processSettings);
}
}
/// <Summary>
/// A TestRunner requiring some sort of installation before use.
/// </Summary>
public abstract class InstallableTestRunner : TestRunner
{
protected InstallableTestRunner(string packageId, string version)
{
PackageId = packageId;
Version = version;
}
protected abstract FilePath ExecutableRelativePath { get; }
// Path under tools directory where package would be installed by Cake #tool directive.
// NOTE: When used to run unit tests, a #tool directive is required. If derived package
// is only used for package tests, it is optional.
protected DirectoryPath ToolInstallDirectory => BuildSettings.ToolsDirectory + $"{PackageId}.{Version}";
protected bool IsInstalledAsTool =>
ToolInstallDirectory != null && Context.DirectoryExists(ToolInstallDirectory);
protected DirectoryPath InstallDirectory;
public FilePath ExecutablePath => InstallDirectory.CombineWithFilePath(ExecutableRelativePath);
public void Install(DirectoryPath installDirectory)
{
InstallDirectory = installDirectory.Combine($"{PackageId}.{Version}");
// If the runner package is already installed as a cake tool, we just copy it
if (IsInstalledAsTool)
Context.CopyDirectory(ToolInstallDirectory, InstallDirectory);
// Otherwise, we install it to the requested location
else
Context.NuGetInstall(
PackageId,
new NuGetInstallSettings() { OutputDirectory = installDirectory, Version = Version });
}
}
/////////////////////////////////////////////////////////////////////////////
// TEST RUNNER SOURCE
/////////////////////////////////////////////////////////////////////////////
/// <Summary>
/// TestRunnerSource is a provider of TestRunners. It is used when the tests
/// are to be run under multiple TestRunners rather than just one.
/// </Summary>
public class TestRunnerSource
{
public TestRunnerSource(TestRunner runner1, params TestRunner[] moreRunners)
{
AllRunners.Add(runner1);
AllRunners.AddRange(moreRunners);
}
public List<TestRunner> AllRunners { get; } = new List<TestRunner>();
public IEnumerable<IUnitTestRunner> UnitTestRunners
{
get { foreach(var runner in AllRunners.Where(r => r is IUnitTestRunner)) yield return (IUnitTestRunner)runner; }
}
public IEnumerable<IPackageTestRunner> PackageTestRunners
{
get { foreach(var runner in AllRunners.Where(r => r is IPackageTestRunner)) yield return (IPackageTestRunner)runner; }
}
}
/////////////////////////////////////////////////////////////////////////////
// NUNITLITE RUNNER
/////////////////////////////////////////////////////////////////////////////
// For NUnitLite tests, the test is run directly
public class NUnitLiteRunner : TestRunner, IUnitTestRunner
{
public int RunUnitTest(FilePath testPath) =>
RunTest(testPath, BuildSettings.UnitTestArguments);
}
/////////////////////////////////////////////////////////////////////////////
// NUNIT CONSOLE RUNNERS
/////////////////////////////////////////////////////////////////////////////
// NUnitConsoleRunner is used for both unit and package tests. It must be pre-installed
// in the tools directory by use of a #tools directive.
public class NUnitConsoleRunner : InstallableTestRunner, IUnitTestRunner, IPackageTestRunner
{
protected override FilePath ExecutableRelativePath => "tools/nunit3-console.exe";
public NUnitConsoleRunner(string version) : base("NUnit.ConsoleRunner", version) { }
// Run a unit test
public int RunUnitTest(FilePath testPath) => RunTest(ToolInstallDirectory.CombineWithFilePath(ExecutableRelativePath), $"\"{testPath}\" {BuildSettings.UnitTestArguments}");
// Run a package test
public int RunPackageTest(string arguments) => RunTest(ExecutablePath, arguments);
}
public class NUnitNetCoreConsoleRunner : InstallableTestRunner, IUnitTestRunner, IPackageTestRunner
{
protected override FilePath ExecutableRelativePath => "tools/net6.0/nunit3-console.exe";
public NUnitNetCoreConsoleRunner(string version) : base("NUnit.ConsoleRunner.NetCore", version) { }
// Run a unit test
public int RunUnitTest(FilePath testPath) => RunTest(ExecutablePath, $"\"{testPath}\" {BuildSettings.UnitTestArguments}");
// Run a package test
public int RunPackageTest(string arguments) => RunTest(ExecutablePath, arguments);
}
public class EngineExtensionTestRunner : TestRunner, IPackageTestRunner
{
private IPackageTestRunner[] _runners = new IPackageTestRunner[] {
new NUnitConsoleRunner("3.17.0"),
new NUnitConsoleRunner("3.15.5")
};
public int RunPackageTest(string arguments)
{
return _runners[0].RunPackageTest(arguments);
}
}
/////////////////////////////////////////////////////////////////////////////
// AGENT RUNNER
/////////////////////////////////////////////////////////////////////////////
/// <summary>
/// Class that knows how to run an agent directly. (For future use)
/// </summary>
public class AgentRunner : TestRunner, IPackageTestRunner
{
private string _stdExecutable;
private string _x86Executable;
private FilePath _executablePath;
public AgentRunner(string stdExecutable, string x86Executable = null)
{
_stdExecutable = stdExecutable;
_x86Executable = x86Executable;
}
public int RunPackageTest(string arguments)
{
_executablePath = arguments.Contains("--x86")
? _x86Executable
: _stdExecutable;
return base.RunTest(_executablePath, arguments.Replace("--x86", string.Empty));
}
}

Просмотреть файл

@ -1,27 +0,0 @@
// Load all tools used by the recipe
#tool NuGet.CommandLine&version=6.9.1
#tool dotnet:?package=GitVersion.Tool&version=5.12.0
#tool dotnet:?package=GitReleaseManager.Tool&version=0.17.0
public static class Tools
{
public static DirectoryPath FindInstalledTool(string packageId)
{
if (SIO.Directory.Exists(BuildSettings.ToolsDirectory + packageId))
return BuildSettings.ToolsDirectory + packageId;
foreach(var dir in BuildSettings.Context.GetDirectories(BuildSettings.ToolsDirectory + $"{packageId}.*"))
return dir; // Use first one found
return null;
}
public static DirectoryPath FindInstalledTool(string packageId, string version)
{
if (version == null)
throw new ArgumentNullException(nameof(version));
var toolPath = BuildSettings.ToolsDirectory + $"{packageId}.{version}";
return BuildSettings.ToolsDirectory + $"{packageId}.{version}";
}
}

Просмотреть файл

@ -1,95 +0,0 @@
//////////////////////////////////////////////////////////////////////
// UNIT TEST RUNNER
//////////////////////////////////////////////////////////////////////
public static class UnitTesting
{
static ICakeContext _context;
static UnitTesting()
{
_context = BuildSettings.Context;
}
public static void RunAllTests()
{
var unitTests = FindUnitTestFiles(BuildSettings.UnitTests);
_context.Information($"Located {unitTests.Count} unit test assemblies.");
var errors = new List<string>();
var runner = BuildSettings.UnitTestRunner ?? new NUnitLiteRunner();
foreach (var testPath in unitTests)
{
var testFile = testPath.GetFilename();
var containingDir = testPath.GetDirectory().GetDirectoryName();
var runtime = IsValidRuntime(containingDir) ? containingDir : null;
Banner.Display(runtime != null
? $"Running {testFile} under {runtime}"
: $"Running {testFile}");
int rc = runner.RunUnitTest(testPath);
var name = runtime != null
? $"{testFile}({runtime})"
: testFile;
if (rc > 0)
errors.Add($"{name}: {rc} tests failed");
else if (rc < 0)
errors.Add($"{name} returned rc = {rc}");
}
if (unitTests.Count == 0)
_context.Warning("No unit tests were found");
else if (errors.Count > 0)
throw new Exception(
"One or more unit tests failed, breaking the build.\r\n"
+ errors.Aggregate((x, y) => x + "\r\n" + y) );
static bool IsValidRuntime(string text)
{
string[] VALID_RUNTIMES = {
"net20", "net30", "net35", "net40", "net45", "net451", "net451",
"net46", "net461", "net462", "net47", "net471", "net472", "net48", "net481",
"netcoreapp1.1", "netcoreapp2.1", "netcoreapp3.1",
"net5.0", "net6.0", "net7.0", "net8.0"
};
return VALID_RUNTIMES.Contains(text);
}
}
private static List<FilePath> FindUnitTestFiles(string patternSet)
{
var result = new List<FilePath>();
if (!string.IsNullOrEmpty(patternSet))
{
// User supplied a set of patterns for the unit tests
foreach (string filePattern in patternSet.Split('|'))
foreach (var testPath in _context.GetFiles(BuildSettings.OutputDirectory + filePattern))
result.Add(testPath);
}
else
{
// Use default patterns to find unit tests - case insensitive because
// we don't know how the user may have named test assemblies.
var defaultPatterns = new [] { "**/*.tests.dll", "**/*.tests.exe" };
var globberSettings = new GlobberSettings { IsCaseSensitive = false };
foreach (string filePattern in defaultPatterns)
foreach (var testPath in _context.GetFiles(BuildSettings.OutputDirectory + filePattern, globberSettings))
result.Add(testPath);
}
result.Sort(ComparePathsByFileName);
return result;
static int ComparePathsByFileName(FilePath x, FilePath y)
{
return x.GetFilename().ToString().CompareTo(y.GetFilename().ToString());
}
}
}

Просмотреть файл

@ -1,10 +0,0 @@
//////////////////////////////////////////////////////////////////////
// HELPER METHODS - PACKAGING
//////////////////////////////////////////////////////////////////////
public void CopyPackageContents(DirectoryPath packageDir, DirectoryPath outDir)
{
var files = GetFiles(packageDir + "/tools/*").Concat(GetFiles(packageDir + "/tools/net462/*"));
CopyFiles(files.Where(f => f.GetExtension() != ".addins"), outDir);
}

Просмотреть файл

@ -1,115 +0,0 @@
using System.Text.RegularExpressions;
public class BuildVersion
{
private ICakeContext _context;
private GitVersion _gitVersion;
// NOTE: This is complicated because (1) the user may have specified
// the package version on the command-line and (2) GitVersion may
// or may not be available. We'll work on solving (2) by getting
// GitVersion to run for us on Linux, but (1) will alwas remain.
//
// We simplify things a by figuring out the full package version and
// then parsing it to provide information that is used in the build.
public BuildVersion(ICakeContext context)
{
if (context==null)
throw new ArgumentNullException(nameof(context));
_context = context;
_gitVersion = context.GitVersion();
BranchName = _gitVersion.BranchName;
IsReleaseBranch = BranchName.StartsWith("release-");
string packageVersion = CommandLineOptions.PackageVersion.Value ?? CalculatePackageVersion();
int dash = packageVersion.IndexOf('-');
IsPreRelease = dash > 0;
string versionPart = packageVersion;
string suffix = "";
string label = "";
if (IsPreRelease)
{
versionPart = packageVersion.Substring(0, dash);
suffix = packageVersion.Substring(dash + 1);
foreach (char c in suffix)
{
if (!char.IsLetter(c))
break;
label += c;
}
}
Version version = new Version(versionPart);
SemVer = version.ToString(3);
PreReleaseLabel = label;
PreReleaseSuffix = suffix;
PackageVersion = packageVersion;
AssemblyVersion = SemVer + ".0";
AssemblyFileVersion = SemVer;
AssemblyInformationalVersion = packageVersion;
}
public string BranchName { get; }
public bool IsReleaseBranch { get; }
public string PackageVersion { get; }
public string AssemblyVersion { get; }
public string AssemblyFileVersion { get; }
public string AssemblyInformationalVersion { get; }
public string SemVer { get; }
public bool IsPreRelease { get; }
public string PreReleaseLabel { get; }
public string PreReleaseSuffix { get; }
private string CalculatePackageVersion()
{
string label = _gitVersion.PreReleaseLabel;
// Non pre-release is easy
if (string.IsNullOrEmpty(label))
return _gitVersion.MajorMinorPatch;
string branchName = _gitVersion.BranchName;
// We don't currently use this pattern, but check in case we do later.
if (branchName.StartsWith("feature/"))
branchName = branchName.Substring(8);
// Arbitrary branch names are ci builds
if (label == branchName)
label = "ci";
string suffix = "-" + label + _gitVersion.CommitsSinceVersionSourcePadded;
switch (label)
{
case "ci":
branchName = Regex.Replace(branchName, "[^0-9A-Za-z-]+", "-");
suffix += "-" + branchName;
// Nuget limits "special version part" to 20 chars. Add one for the hyphen.
if (suffix.Length > 21)
suffix = suffix.Substring(0, 21);
return _gitVersion.MajorMinorPatch + suffix;
case "dev":
case "pre":
return _gitVersion.MajorMinorPatch + suffix;
case "pr":
return _gitVersion.LegacySemVerPadded;
case "rc":
case "alpha":
case "beta":
default:
return _gitVersion.LegacySemVer;
}
}
}

Просмотреть файл

@ -1,74 +0,0 @@
public class ZipPackage : PackageDefinition
{
public ZipPackage(
string id,
string source,
IPackageTestRunner testRunner = null,
TestRunnerSource testRunnerSource = null,
PackageCheck[] checks = null,
IEnumerable<PackageTest> tests = null,
PackageReference[] bundledExtensions = null )
: base(
PackageType.Zip,
id,
source,
testRunner: testRunner,
testRunnerSource: testRunnerSource,
checks: checks,
tests: tests)
{
BundledExtensions = bundledExtensions;
}
// ZIP package supports bundling of extensions
public PackageReference[] BundledExtensions { get; }
// The file name of this package, including extension
public override string PackageFileName => $"{PackageId}-{PackageVersion}.zip";
// The directory into which this package is installed
public override string PackageInstallDirectory => BuildSettings.ZipTestDirectory;
// The directory used to contain results of package tests for this package
public override string PackageResultDirectory => $"{BuildSettings.ZipResultDirectory}{PackageId}/";
// The directory into which extensions to the test runner are installed
public override string ExtensionInstallDirectory => $"{BuildSettings.ZipTestDirectory}{PackageId}.{PackageVersion}/bin/addins/";
public override void BuildPackage()
{
FetchBundledExtensions(BundledExtensions);
CreateZipImage();
_context.Zip(BuildSettings.ZipImageDirectory, $"{BuildSettings.PackageDirectory}{PackageFileName}");
}
public override void InstallPackage()
{
_context.Unzip($"{BuildSettings.PackageDirectory}{PackageFileName}", $"{PackageInstallDirectory}{PackageId}.{PackageVersion}");
}
private void CreateZipImage()
{
_context.CleanDirectory(BuildSettings.ZipImageDirectory);
_context.CopyFiles(
new FilePath[] { "LICENSE.txt", "NOTICES.txt", "CHANGES.txt", "nunit.ico" },
BuildSettings.ZipImageDirectory);
_context.CopyDirectory(
BuildSettings.OutputDirectory,
BuildSettings.ZipImageDirectory + "bin/" );
_context.CopyFileToDirectory(
BuildSettings.ZipDirectory + "nunit.bundle.addins",
BuildSettings.ZipImageDirectory);
var addinsDir = BuildSettings.ZipImageDirectory + "bin/net462/addins/";
_context.CreateDirectory(addinsDir);
foreach (var packageDir in SIO.Directory.GetDirectories(BuildSettings.ExtensionsDirectory))
{
var files = _context.GetFiles(packageDir + "/tools/*").Concat(_context.GetFiles(packageDir + "/tools/net462/*"));
_context.CopyFiles(files.Where(f => f.GetExtension() != ".addins"), addinsDir);
}
}
}