#tool nuget:?package=GitVersion.CommandLine #tool nuget:?package=vswhere #addin nuget:?package=Cake.Figlet #addin nuget:?package=Cake.Incubator&version=1.7.1 #addin nuget:?package=Cake.Git&version=0.16.1 #addin nuget:?package=Polly using Polly; var sln = new FilePath("./MvvmCross.sln"); var outputDir = new DirectoryPath("./artifacts"); var nuspecDir = new DirectoryPath("./nuspec"); var target = Argument("target", "Default"); var configuration = Argument("configuration", "Release"); var verbosityArg = Argument("verbosity", "Minimal"); var verbosity = Verbosity.Minimal; var isRunningOnAppVeyor = AppVeyor.IsRunningOnAppVeyor; GitVersion versionInfo = null; Setup(context => { versionInfo = context.GitVersion(new GitVersionSettings { UpdateAssemblyInfo = true, OutputType = GitVersionOutput.Json }); if (isRunningOnAppVeyor) { var buildNumber = AppVeyor.Environment.Build.Number; AppVeyor.UpdateBuildVersion(versionInfo.InformationalVersion + "-" + buildNumber); } var cakeVersion = typeof(ICakeContext).Assembly.GetName().Version.ToString(); Information(Figlet("MvvmCross")); Information("Building version {0}, ({1}, {2}) using version {3} of Cake.", versionInfo.SemVer, configuration, target, cakeVersion); Debug("Will push NuGet packages {0}", ShouldPushNugetPackages(versionInfo.BranchName)); verbosity = (Verbosity) Enum.Parse(typeof(Verbosity), verbosityArg, true); }); Task("Clean").Does(() => { CleanDirectories("./**/bin"); CleanDirectories("./**/obj"); CleanDirectories(outputDir.FullPath); EnsureDirectoryExists(outputDir); }); FilePath msBuildPath; Task("ResolveBuildTools") .WithCriteria(() => IsRunningOnWindows()) .Does(() => { var vsLatest = VSWhereLatest(); msBuildPath = (vsLatest == null) ? null : vsLatest.CombineWithFilePath("./MSBuild/15.0/Bin/MSBuild.exe"); }); Task("Restore") .IsDependentOn("ResolveBuildTools") .Does(() => { var settings = GetDefaultBuildSettings() .WithTarget("Restore"); MSBuild(sln, settings); }); Task("PatchBuildProps") .Does(() => { var buildProp = new FilePath("./Directory.build.props"); XmlPoke(buildProp, "//Project/PropertyGroup/Version", versionInfo.SemVer); }); Task("Build") .IsDependentOn("ResolveBuildTools") .IsDependentOn("Clean") .IsDependentOn("PatchBuildProps") .IsDependentOn("Restore") .Does(() => { var settings = GetDefaultBuildSettings() .WithProperty("DebugSymbols", "True") .WithProperty("DebugType", "Embedded") .WithProperty("Version", versionInfo.SemVer) .WithProperty("PackageVersion", versionInfo.SemVer) .WithProperty("InformationalVersion", versionInfo.InformationalVersion) .WithProperty("NoPackageAnalysis", "True"); MSBuild(sln, settings); }); Task("UnitTest") .IsDependentOn("Build") .Does(() => { EnsureDirectoryExists(outputDir + "/Tests/"); var testPaths = GetFiles("./UnitTests/*.UnitTest/*.UnitTest.csproj"); var testsFailed = false; foreach(var project in testPaths) { var projectName = project.GetFilenameWithoutExtension(); var testXml = new FilePath(outputDir + "/Tests/" + projectName + ".xml").MakeAbsolute(Context.Environment); try { DotNetCoreTool(project, "xunit", "-fxversion 2.0.0 --no-build -parallel none -configuration " + configuration + " -xml \"" + testXml.FullPath + "\""); } catch { testsFailed = true; } } if (isRunningOnAppVeyor) { foreach(var testResult in GetFiles(outputDir + "/Tests/*.xml")) AppVeyor.UploadTestResults(testResult, AppVeyorTestResultsType.XUnit); } if (testsFailed) throw new Exception("Tests failed :("); }); Task("PublishPackages") .WithCriteria(() => !BuildSystem.IsLocalBuild) .WithCriteria(() => IsRepository("mvvmcross/mvvmcross")) .WithCriteria(() => ShouldPushNugetPackages(versionInfo.BranchName)) .Does (() => { // Resolve the API key. var nugetKeySource = GetNugetKeyAndSource(); var apiKey = nugetKeySource.Item1; var source = nugetKeySource.Item2; var nugetFiles = GetFiles("MvvmCross*/**/bin/" + configuration + "/**/*.nupkg"); var policy = Policy .Handle() .WaitAndRetry(5, retryAttempt => TimeSpan.FromSeconds(Math.Pow(1.5, retryAttempt))); foreach(var nugetFile in nugetFiles) { policy.Execute(() => NuGetPush(nugetFile, new NuGetPushSettings { Source = source, ApiKey = apiKey }) ); } }); Task("UploadAppVeyorArtifact") .WithCriteria(() => isRunningOnAppVeyor) .Does(() => { Information("Artifacts Dir: {0}", outputDir.FullPath); var uploadSettings = new AppVeyorUploadArtifactsSettings(); var artifacts = GetFiles("MvvmCross*/**/bin/" + configuration + "/**/*.nupkg") + GetFiles(outputDir.FullPath + "/**/*"); foreach(var file in artifacts) { Information("Uploading {0}", file.FullPath); if (file.GetExtension().Contains("nupkg")) uploadSettings.ArtifactType = AppVeyorUploadArtifactType.NuGetPackage; else uploadSettings.ArtifactType = AppVeyorUploadArtifactType.Auto; AppVeyor.UploadArtifact(file.FullPath, uploadSettings); } }); Task("Default") .IsDependentOn("Build") .IsDependentOn("UnitTest") .IsDependentOn("PublishPackages") .IsDependentOn("UploadAppVeyorArtifact") .Does(() => { }); RunTarget(target); MSBuildSettings GetDefaultBuildSettings() { var settings = new MSBuildSettings { Configuration = configuration, ToolPath = msBuildPath, Verbosity = verbosity, ArgumentCustomization = args => args.Append("/m") }; return settings; } bool ShouldPushNugetPackages(string branchName) { if (StringComparer.OrdinalIgnoreCase.Equals(branchName, "develop")) return true; return IsMasterOrReleases(branchName) && IsTagged().Item1; } bool IsMasterOrReleases(string branchName) { if (StringComparer.OrdinalIgnoreCase.Equals(branchName, "master")) return true; if (branchName.StartsWith("release/", StringComparison.OrdinalIgnoreCase) || branchName.StartsWith("releases/", StringComparison.OrdinalIgnoreCase)) return true; return false; } bool IsRepository(string repoName) { if (isRunningOnAppVeyor) { var buildEnvRepoName = AppVeyor.Environment.Repository.Name; Information("Checking repo name: {0} against build repo name: {1}", repoName, buildEnvRepoName); return StringComparer.OrdinalIgnoreCase.Equals(repoName, buildEnvRepoName); } else { try { var path = MakeAbsolute(sln).GetDirectory().FullPath; using (var repo = new LibGit2Sharp.Repository(path)) { var origin = repo.Network.Remotes.FirstOrDefault( r => r.Name.ToLowerInvariant() == "origin"); return origin.Url.ToLowerInvariant() == "https://github.com/" + repoName.ToLowerInvariant(); } } catch(Exception ex) { Information("Failed to lookup repository: {0}", ex); return false; } } } Tuple IsTagged() { var path = MakeAbsolute(sln).GetDirectory().FullPath; using (var repo = new LibGit2Sharp.Repository(path)) { var head = repo.Head; var headSha = head.Tip.Sha; var tag = repo.Tags.FirstOrDefault(t => t.Target.Sha == headSha); if (tag == null) { Debug("HEAD is not tagged"); return Tuple.Create(false, null); } Debug("HEAD is tagged: {0}", tag.FriendlyName); return Tuple.Create(true, tag.FriendlyName); } } Tuple GetNugetKeyAndSource() { var apiKeyKey = string.Empty; var sourceKey = string.Empty; if (isRunningOnAppVeyor) { apiKeyKey = "NUGET_APIKEY"; sourceKey = "NUGET_SOURCE"; } else { if (StringComparer.OrdinalIgnoreCase.Equals(versionInfo.BranchName, "develop")) { apiKeyKey = "NUGET_APIKEY_DEVELOP"; sourceKey = "NUGET_SOURCE_DEVELOP"; } else if (IsMasterOrReleases(versionInfo.BranchName)) { apiKeyKey = "NUGET_APIKEY_MASTER"; sourceKey = "NUGET_SOURCE_MASTER"; } } var apiKey = EnvironmentVariable(apiKeyKey); if (string.IsNullOrEmpty(apiKey)) throw new Exception(string.Format("The {0} environment variable is not defined.", apiKeyKey)); var source = EnvironmentVariable(sourceKey); if (string.IsNullOrEmpty(source)) throw new Exception(string.Format("The {0} environment variable is not defined.", sourceKey)); return Tuple.Create(apiKey, source); }