You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
471 lines
18 KiB
471 lines
18 KiB
#addin nuget:?package=Cake.FileHelpers&version=5.0.0
|
|
#addin nuget:?package=Cake.Git&version=2.0.0
|
|
#addin nuget:?package=Cake.Incubator&version=7.0.0
|
|
#tool dotnet:?package=GitVersion.Tool&version=5.10.3
|
|
#tool nuget:?package=JunitXml.TestLogger&version=3.0.114
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text.RegularExpressions;
|
|
using Cake.Common.Tools.DotNet.DotNetVerbosity;
|
|
using Architecture = System.Runtime.InteropServices.Architecture;
|
|
using Path = Cake.Core.IO.Path;
|
|
|
|
const string defaultTarget = "Default";
|
|
var target = Argument("target", defaultTarget);
|
|
var configuration = Argument("configuration", "Release");
|
|
|
|
var gitVersion = GitVersion();
|
|
|
|
var solutionDirectory = MakeAbsolute(Directory("./"));
|
|
var artifactsDirectory = solutionDirectory.Combine("artifacts");
|
|
var artifactsBinDirectory = artifactsDirectory.Combine("bin");
|
|
var artifactsPackagesDirectory = artifactsDirectory.Combine("packages");
|
|
var srcDirectory = solutionDirectory.Combine("src");
|
|
var testsDirectory = solutionDirectory.Combine("tests");
|
|
var outputDirectory = solutionDirectory.Combine("build");
|
|
var toolsDirectory = solutionDirectory.Combine("tools");
|
|
var toolsHugoDirectory = toolsDirectory.Combine("Hugo");
|
|
var mongoDbDriverPackageName = "MongoDB.Driver";
|
|
|
|
var solutionFile = solutionDirectory.CombineWithFilePath("CSharpDriver.sln");
|
|
var solutionFullPath = solutionFile.FullPath;
|
|
var srcProjectNames = new[]
|
|
{
|
|
"MongoDB.Bson",
|
|
"MongoDB.Driver"
|
|
};
|
|
|
|
Task("Default")
|
|
.IsDependentOn("Test");
|
|
|
|
Task("Release")
|
|
.IsDependentOn("Build")
|
|
.IsDependentOn("Package");
|
|
|
|
Task("Restore")
|
|
.Does(() =>
|
|
{
|
|
// disable parallel restore to work around apparent bugs in restore
|
|
var restoreSettings = new DotNetRestoreSettings
|
|
{
|
|
DisableParallel = true
|
|
};
|
|
DotNetRestore(solutionFullPath, restoreSettings);
|
|
});
|
|
|
|
Task("Build")
|
|
.IsDependentOn("Restore")
|
|
.Does<BuildConfig>((buildConfig) =>
|
|
{
|
|
var settings = new DotNetBuildSettings
|
|
{
|
|
NoRestore = true,
|
|
Configuration = configuration,
|
|
EnvironmentVariables = new Dictionary<string, string>
|
|
{
|
|
{ "Version", gitVersion.LegacySemVer },
|
|
{ "SourceRevisionId", gitVersion.Sha }
|
|
}
|
|
};
|
|
|
|
if (buildConfig.IsReleaseMode)
|
|
{
|
|
Console.WriteLine("Build continuousIntegration is enabled");
|
|
settings.MSBuildSettings = new DotNetMSBuildSettings();
|
|
// configure deterministic build for better compatibility with debug symbols (used in Package/Build tasks). Affects: *.nupkg
|
|
settings.MSBuildSettings.SetContinuousIntegrationBuild(continuousIntegrationBuild: true);
|
|
}
|
|
DotNetBuild(solutionFullPath, settings);
|
|
});
|
|
|
|
Task("BuildArtifacts")
|
|
.IsDependentOn("Build")
|
|
.Does(() =>
|
|
{
|
|
foreach (var targetFramework in new[] { "net472", "netstandard2.0", "netstandard2.1" })
|
|
{
|
|
var toDirectory = artifactsBinDirectory.Combine(targetFramework);
|
|
CleanDirectory(toDirectory);
|
|
|
|
var projects = new[] { "MongoDB.Bson", "MongoDB.Driver" };
|
|
foreach (var project in projects)
|
|
{
|
|
var fromDirectory = srcDirectory.Combine(project).Combine("bin").Combine(configuration).Combine(targetFramework);
|
|
|
|
var fileNames = new List<string>();
|
|
foreach (var extension in new[] { "dll", "pdb", "xml" })
|
|
{
|
|
var fileName = $"{project}.{extension}";
|
|
fileNames.Add(fileName);
|
|
}
|
|
|
|
foreach (var fileName in fileNames)
|
|
{
|
|
var fromFile = fromDirectory.CombineWithFilePath(fileName);
|
|
var toFile = toDirectory.CombineWithFilePath(fileName);
|
|
CopyFile(fromFile, toFile);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
|
|
Task("Test")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/*.Tests.csproj").Where(name => !name.ToString().Contains("Atlas")),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
{
|
|
if (Environment.GetEnvironmentVariable("MONGODB_API_VERSION") != null &&
|
|
testProject.ToString().Contains("Legacy"))
|
|
{
|
|
return; // Legacy tests are exempt from Version API testing
|
|
}
|
|
|
|
var mongoX509ClientCertificatePath = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PATH");
|
|
if (mongoX509ClientCertificatePath != null)
|
|
{
|
|
Console.WriteLine($"MONGO_X509_CLIENT_CERTIFICATE_PATH={mongoX509ClientCertificatePath}");
|
|
}
|
|
var mongoX509ClientCertificatePassword = Environment.GetEnvironmentVariable("MONGO_X509_CLIENT_CERTIFICATE_PASSWORD");
|
|
if (mongoX509ClientCertificatePassword != null)
|
|
{
|
|
Console.WriteLine($"MONGO_X509_CLIENT_CERTIFICATE_PASSWORD={mongoX509ClientCertificatePassword}");
|
|
}
|
|
|
|
RunTests(buildConfig, testProject);
|
|
})
|
|
.DeferOnError();
|
|
|
|
Task("TestNet472").IsDependentOn("Test");
|
|
Task("TestNetStandard21").IsDependentOn("Test");
|
|
Task("TestNet60").IsDependentOn("Test");
|
|
|
|
Task("TestAwsAuthentication")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"AwsMechanism\""));
|
|
|
|
Task("TestPlainAuthentication")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"PlainMechanism\""));
|
|
|
|
Task("TestAtlasConnectivity")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/AtlasConnectivity.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) => RunTests(buildConfig, testProject));
|
|
|
|
Task("TestAtlasDataLake")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"AtlasDataLake\""));
|
|
|
|
Task("TestAtlasSearch")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"AtlasSearch\""));
|
|
|
|
Task("TestAtlasSearchIndexHelpers")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"AtlasSearchIndexHelpers\""));
|
|
|
|
Task("TestOcsp")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"OCSP\""));
|
|
|
|
Task("TestGssapi")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"GssapiMechanism\""));
|
|
|
|
Task("TestGssapiNet472").IsDependentOn("TestGssapi");
|
|
Task("TestGssapiNetStandard21").IsDependentOn("TestGssapi");
|
|
Task("TestGssapiNet60").IsDependentOn("TestGssapi");
|
|
|
|
Task("TestMongoDbOidc")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"MongoDbOidc\""));
|
|
|
|
Task("TestServerless")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"Serverless\""));
|
|
|
|
Task("TestServerlessNet472").IsDependentOn("TestServerless");
|
|
Task("TestServerlessNetStandard21").IsDependentOn("TestServerless");
|
|
Task("TestServerlessNet60").IsDependentOn("TestServerless");
|
|
|
|
Task("TestLibMongoCrypt")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/MongoDB.Driver.Encryption.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) => RunTests(buildConfig, testProject));
|
|
|
|
Task("TestLoadBalanced")
|
|
.IsDependentOn("Build")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/*.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"SupportLoadBalancing\""));
|
|
|
|
Task("TestLoadBalancedNetStandard21").IsDependentOn("TestLoadBalanced");
|
|
Task("TestLoadBalancedNet60").IsDependentOn("TestLoadBalanced");
|
|
|
|
Task("TestCsfleWithMockedKms")
|
|
.IsDependentOn("TestLibMongoCrypt")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/*.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"CSFLE\""));
|
|
|
|
Task("TestCsfleWithMockedKmsNet472").IsDependentOn("TestCsfleWithMockedKms");
|
|
Task("TestCsfleWithMockedKmsNetStandard21").IsDependentOn("TestCsfleWithMockedKms");
|
|
Task("TestCsfleWithMockedKmsNet60").IsDependentOn("TestCsfleWithMockedKms");
|
|
|
|
Task("TestCsfleWithMongocryptd")
|
|
.IsDependentOn("TestLibMongoCrypt")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/*.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"CSFLE\""));
|
|
|
|
Task("TestCsfleWithMongocryptdNet472").IsDependentOn("TestCsfleWithMongocryptd");
|
|
Task("TestCsfleWithMongocryptdNetStandard21").IsDependentOn("TestCsfleWithMongocryptd");
|
|
Task("TestCsfleWithMongocryptdNet60").IsDependentOn("TestCsfleWithMongocryptd");
|
|
|
|
Task("TestCsfleWithAzureKms")
|
|
.IsDependentOn("TestLibMongoCrypt")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/*.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"CsfleAZUREKMS\""));
|
|
|
|
Task("TestCsfleWithGcpKms")
|
|
.IsDependentOn("TestLibMongoCrypt")
|
|
.DoesForEach(
|
|
items: GetFiles("./**/*.Tests.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
RunTests(buildConfig, testProject, filter: "Category=\"CsfleGCPKMS\""));
|
|
|
|
Task("Package")
|
|
.IsDependentOn("PackageNugetPackages");
|
|
|
|
Task("PackageNugetPackages")
|
|
.IsDependentOn("Build")
|
|
.Does<BuildConfig>((buildConfig) =>
|
|
{
|
|
EnsureDirectoryExists(artifactsPackagesDirectory);
|
|
CleanDirectory(artifactsPackagesDirectory);
|
|
|
|
var projects = new[]
|
|
{
|
|
"MongoDB.Bson",
|
|
"MongoDB.Driver",
|
|
"MongoDB.Driver.Encryption"
|
|
};
|
|
|
|
foreach (var project in projects)
|
|
{
|
|
var projectPath = $"{srcDirectory}\\{project}\\{project}.csproj";
|
|
var settings = new DotNetPackSettings
|
|
{
|
|
Configuration = configuration,
|
|
OutputDirectory = artifactsPackagesDirectory,
|
|
NoBuild = true, // SetContinuousIntegrationBuild is enabled for nupkg on the Build step
|
|
IncludeSymbols = true,
|
|
MSBuildSettings = new DotNetMSBuildSettings()
|
|
// configure deterministic build for better compatibility with debug symbols (used in Package/Build tasks). Affects: *.snupkg
|
|
.SetContinuousIntegrationBuild(continuousIntegrationBuild: true)
|
|
.WithProperty("PackageVersion", buildConfig.PackageVersion)
|
|
};
|
|
DotNetPack(projectPath, settings);
|
|
}
|
|
});
|
|
|
|
Task("PushToNuGet")
|
|
.Does(() =>
|
|
{
|
|
var nugetApiKey = EnvironmentVariable("NUGETAPIKEY");
|
|
if (nugetApiKey == null)
|
|
{
|
|
throw new Exception("NUGETAPIKEY environment variable missing");
|
|
}
|
|
|
|
var packageFiles = new List<FilePath>();
|
|
|
|
var projects = new[]
|
|
{
|
|
"MongoDB.Bson",
|
|
"MongoDB.Driver"
|
|
};
|
|
|
|
foreach (var project in projects)
|
|
{
|
|
var packageFileName = $"{project}.{gitVersion.LegacySemVer}.nupkg";
|
|
var packageFile = artifactsPackagesDirectory.CombineWithFilePath(packageFileName);
|
|
packageFiles.Add(packageFile);
|
|
}
|
|
|
|
NuGetPush(packageFiles, new NuGetPushSettings
|
|
{
|
|
ApiKey = nugetApiKey,
|
|
Source = "https://api.nuget.org/v3/index.json"
|
|
});
|
|
});
|
|
|
|
Task("DumpGitVersion")
|
|
.Does(() =>
|
|
{
|
|
Information(gitVersion.Dump());
|
|
});
|
|
|
|
Task("SmokeTests")
|
|
.DoesForEach(
|
|
GetFiles("./**/SmokeTests/**/*.SmokeTests*.csproj"),
|
|
action: (BuildConfig buildConfig, Path testProject) =>
|
|
{
|
|
var environmentVariables = new Dictionary<string, string>
|
|
{
|
|
{ "SmokeTestsPackageSha", gitVersion.Sha }
|
|
};
|
|
|
|
var toolSettings = new DotNetToolSettings { EnvironmentVariables = environmentVariables };
|
|
|
|
Information($"Updating MongoDB package: {buildConfig.PackageVersion} sha: {gitVersion.Sha}");
|
|
|
|
DotNetTool(
|
|
testProject.FullPath,
|
|
"add package MongoDB.Driver",
|
|
$"--no-restore --version [{buildConfig.PackageVersion}]",
|
|
toolSettings);
|
|
|
|
DotNetTool(
|
|
testProject.FullPath,
|
|
"add package MongoDB.Driver.Encryption",
|
|
$"--no-restore --version [{buildConfig.PackageVersion}]",
|
|
toolSettings);
|
|
|
|
RunTests(
|
|
buildConfig,
|
|
testProject,
|
|
settings =>
|
|
{
|
|
settings.NoBuild = false;
|
|
settings.NoRestore = false;
|
|
settings.EnvironmentVariables = environmentVariables;
|
|
});
|
|
});
|
|
|
|
Task("SmokeTestsNet472").IsDependentOn("SmokeTests");
|
|
Task("SmokeTestsNetCoreApp31").IsDependentOn("SmokeTests");
|
|
Task("SmokeTestsNet50").IsDependentOn("SmokeTests");
|
|
Task("SmokeTestsNet60").IsDependentOn("SmokeTests");
|
|
Task("SmokeTestsNet80").IsDependentOn("SmokeTests");
|
|
|
|
Setup<BuildConfig>(
|
|
setupContext =>
|
|
{
|
|
var targetPlatform = RuntimeInformation.OSArchitecture switch
|
|
{
|
|
Architecture.Arm64 => "arm64",
|
|
Architecture.X64 => "x64",
|
|
var unknownArchitecture => throw new Exception($"Unknown CPU architecture: {unknownArchitecture}.")
|
|
};
|
|
|
|
var lowerTarget = target.ToLowerInvariant();
|
|
// Apple M1 (arm64) must run on .NET 6 as the hosting process is arm64 and cannot load the previous netcoreapp2.1/3.1 runtimes.
|
|
// While Rosetta 2 can cross-compile x64->arm64 to run x64 code, it requires a completely separate install of the .NET runtimes
|
|
// in a different directory with a x64 dotnet host process. This would further complicate our testing for little additional gain.
|
|
var framework = targetPlatform == "arm64" ? "net6.0" : lowerTarget switch
|
|
{
|
|
string s when s.EndsWith("netstandard21") || s.EndsWith("netcoreapp31") => "netcoreapp3.1",
|
|
string s when s.EndsWith("net472") => "net472",
|
|
string s when s.EndsWith("net50") => "net5.0",
|
|
string s when s.EndsWith("net60") => "net6.0",
|
|
string s when s.EndsWith("net80") => "net8.0",
|
|
_ => null
|
|
};
|
|
|
|
var isReleaseMode = lowerTarget.StartsWith("package") || lowerTarget == "release";
|
|
var packageVersion = lowerTarget.StartsWith("smoketests") ? Environment.GetEnvironmentVariable("PACKAGE_VERSION") : gitVersion.LegacySemVer;
|
|
|
|
Console.WriteLine($"Framework: {framework ?? "null (not set)"}, TargetPlatform: {targetPlatform}, IsReleaseMode: {isReleaseMode}, PackageVersion: {packageVersion}");
|
|
|
|
return new BuildConfig(isReleaseMode, framework, targetPlatform, packageVersion);
|
|
});
|
|
|
|
RunTarget(target);
|
|
|
|
public class BuildConfig
|
|
{
|
|
public bool IsReleaseMode { get; }
|
|
public string Framework { get; }
|
|
public string PackageVersion { get; }
|
|
public string TargetPlatform { get; }
|
|
|
|
public BuildConfig(bool isReleaseMode, string framework, string targetPlatform, string packageVersion)
|
|
{
|
|
IsReleaseMode = isReleaseMode;
|
|
Framework = framework;
|
|
TargetPlatform = targetPlatform;
|
|
PackageVersion = packageVersion;
|
|
}
|
|
}
|
|
|
|
string[] CreateLoggers(string projectName)
|
|
{
|
|
var testResultsFile = outputDirectory.Combine("test-results").Combine($"TEST-{projectName}-{target.ToLowerInvariant()}-{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}.xml");
|
|
|
|
// Evergreen CI server requires JUnit output format to display test results
|
|
var junitLogger = $"junit;LogFilePath={testResultsFile};FailureBodyFormat=Verbose";
|
|
var consoleLogger = "console;verbosity=detailed";
|
|
return new[] { junitLogger, consoleLogger };
|
|
}
|
|
|
|
void RunTests(BuildConfig buildConfig, Path path, string filter = null)
|
|
{
|
|
RunTests(buildConfig, path, settings => settings.Filter = filter);
|
|
}
|
|
|
|
void RunTests(BuildConfig buildConfig, Path path, Action<DotNetTestSettings> settingsAction)
|
|
{
|
|
var projectName = System.IO.Path.GetFileNameWithoutExtension(path.FullPath);
|
|
|
|
var settings = new DotNetTestSettings
|
|
{
|
|
NoBuild = true,
|
|
NoRestore = true,
|
|
Configuration = configuration,
|
|
Loggers = CreateLoggers(projectName),
|
|
ArgumentCustomization = args => args.Append($"-- RunConfiguration.TargetPlatform={buildConfig.TargetPlatform}"),
|
|
Framework = buildConfig.Framework
|
|
};
|
|
|
|
settingsAction?.Invoke(settings);
|
|
|
|
DotNetTest(path.FullPath, settings);
|
|
}
|