diff --git a/Ocelot.sln b/Ocelot.sln index c1f647af..3bc1f60a 100644 --- a/Ocelot.sln +++ b/Ocelot.sln @@ -19,6 +19,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Ocelot.nuspec = Ocelot.nuspec push-to-nuget.bat = push-to-nuget.bat README.md = README.md + release.cake = release.cake + release.ps1 = release.ps1 run-acceptance-tests.bat = run-acceptance-tests.bat run-benchmarks.bat = run-benchmarks.bat run-tests.bat = run-tests.bat diff --git a/build.cake b/build.cake index 513f99dd..73dbae18 100644 --- a/build.cake +++ b/build.cake @@ -3,6 +3,7 @@ #tool "nuget:?package=ReportGenerator" #tool "nuget:?package=GitReleaseNotes" #addin nuget:?package=Cake.DoInDirectory +#addin "Cake.Json" var target = Argument("target", "Default"); var artifactsDir = Directory("artifacts"); @@ -25,20 +26,32 @@ var unitTestAssemblies = @"./test/Ocelot.UnitTests"; var artifactsForAcceptanceTestsDir = artifactsDir + Directory("AcceptanceTests"); var acceptanceTestAssemblies = @"./test/Ocelot.AcceptanceTests"; -//benchmark testing +// benchmark testing var artifactsForBenchmarkTestsDir = artifactsDir + Directory("BenchmarkTests"); var benchmarkTestAssemblies = @"./test/Ocelot.Benchmarks"; // packaging -var packagesDir = artifactsDir + Directory("Packages"); var projectJson = "./src/Ocelot/project.json"; - -// release notes +var packagesDir = artifactsDir + Directory("Packages"); var releaseNotesFile = packagesDir + File("releasenotes.md"); +var artifactsFile = packagesDir + File("artifacts.txt"); + +//unstable releases +var publishUnstableBuilds = true; +var nugetFeedUnstableKey = EnvironmentVariable("nuget-apikey-unstable"); +var nugetFeedUnstableUploadUrl = "https://www.myget.org/F/ocelot-unstable/api/v2/package"; +var nugetFeedUnstableSymbolsUploadUrl = "https://www.myget.org/F/ocelot-unstable/symbols/api/v2/package"; + +//stable releases +var releaseTag = ""; +var nugetFeedStableKey = EnvironmentVariable("nuget-apikey-stable"); +var nugetFeedStableUploadUrl = "https://www.myget.org/F/ocelot-stable/api/v2/package"; +var nugetFeedStableSymbolsUploadUrl = "https://www.myget.org/F/ocelot-stable/symbols/api/v2/package"; Task("Default") .IsDependentOn("RunTests") - .IsDependentOn("Package") + .IsDependentOn("CreatePackages") + .IsDependentOn("ReleasePackagesToUnstableFeed") .Does(() => { }); @@ -56,7 +69,7 @@ Task("Clean") Task("Version") .Does(() => { - var nugetVersion = GetVersion(); + var nugetVersion = GetNuGetVersionForCommit(); Information("SemVer version number: " + nugetVersion); if (AppVeyor.IsRunningOnAppVeyor) @@ -135,7 +148,7 @@ Task("RunTests") { }); -Task("Package") +Task("CreatePackages") .Does(() => { EnsureDirectoryExists(packagesDir); @@ -150,7 +163,7 @@ Task("Package") DotNetCorePack(projectJson, settings); - System.IO.File.WriteAllLines(packagesDir + File("artifacts"), new[]{ + System.IO.File.WriteAllLines(artifactsFile, new[]{ "nuget:Ocelot." + buildVersion + ".nupkg", "nugetSymbols:Ocelot." + buildVersion + ".symbols.nupkg", "releaseNotes:releasenotes.md" @@ -167,9 +180,71 @@ Task("Package") } }); +Task("ReleasePackagesToUnstableFeed") + .IsDependentOn("CreatePackages") + .Does(() => + { + PublishPackages(nugetFeedUnstableKey, nugetFeedUnstableUploadUrl, nugetFeedUnstableSymbolsUploadUrl); + }); + +Task("EnsureStableReleaseRequirements") + .Does(() => + { + if (!AppVeyor.IsRunningOnAppVeyor) + { + throw new Exception("Stable release should happen via appveyor"); + } + + var isTag = + AppVeyor.Environment.Repository.Tag.IsTag && + !string.IsNullOrWhiteSpace(AppVeyor.Environment.Repository.Tag.Name); + + if (!isTag) + { + throw new Exception("Stable release should happen from a published GitHub release"); + } + }); + +Task("UpdateVersionInfo") + .IsDependentOn("EnsureStableReleaseRequirements") + .Does(() => + { + releaseTag = AppVeyor.Environment.Repository.Tag.Name; + AppVeyor.UpdateBuildVersion(releaseTag); + }); + +Task("DownloadGitHubReleaseArtifacts") + .IsDependentOn("UpdateVersionInfo") + .Does(() => + { + EnsureDirectoryExists(packagesDir); + + var assets_url = ParseJson(GetResource("https://api.github.com/repos/binarymash/pipelinetesting/releases/tags/" + releaseTag)) + .GetValue("assets_url") + .Value(); + + foreach(var asset in DeserializeJson(GetResource(assets_url))) + { + var file = packagesDir + File(asset.Value("name")); + Information("Downloading " + file); + DownloadFile(asset.Value("browser_download_url"), file); + } + }); + +Task("ReleasePackagesToStableFeed") + .IsDependentOn("DownloadGitHubReleaseArtifacts") + .Does(() => + { + PublishPackages(nugetFeedStableKey, nugetFeedStableUploadUrl, nugetFeedStableSymbolsUploadUrl); + }); + +Task("Release") + .IsDependentOn("ReleasePackagesToStableFeed"); + RunTarget(target); -private string GetVersion() +/// Gets nuique nuget version for this commit +private string GetNuGetVersionForCommit() { GitVersion(new GitVersionSettings{ UpdateAssemblyInfo = false, @@ -180,9 +255,11 @@ private string GetVersion() return versionInfo.NuGetVersion; } +/// Updates project version in all of our projects private void PersistVersion(string version) { Information(string.Format("We'll search all project.json files for {0} and replace with {1}...", committedVersion, version)); + var projectJsonFiles = GetFiles("./**/project.json"); foreach(var projectJsonFile in projectJsonFiles) @@ -198,6 +275,7 @@ private void PersistVersion(string version) } } +/// generates release notes based on issues closed in GitHub since the last release private void GenerateReleaseNotes() { Information("Generating release notes at " + releaseNotesFile); @@ -215,4 +293,49 @@ private void GenerateReleaseNotes() { throw new Exception("Failed to generate release notes"); } +} + +/// Publishes code and symbols packages to nuget feed, based on contents of artifacts file +private void PublishPackages(string feedApiKey, string codeFeedUrl, string symbolFeedUrl) +{ + var artifacts = System.IO.File + .ReadAllLines(artifactsFile) + .Select(l => l.Split(':')) + .ToDictionary(v => v[0], v => v[1]); + + var codePackage = packagesDir + File(artifacts["nuget"]); + var symbolsPackage = packagesDir + File(artifacts["nugetSymbols"]); + + NuGetPush( + codePackage, + new NuGetPushSettings { + ApiKey = feedApiKey, + Source = codeFeedUrl + }); + + NuGetPush( + symbolsPackage, + new NuGetPushSettings { + ApiKey = feedApiKey, + Source = symbolFeedUrl + }); + +} + +/// gets the resource from the specified url +private string GetResource(string url) +{ + Information("Getting resource from " + url); + + var assetsRequest = System.Net.WebRequest.CreateHttp(url); + assetsRequest.Method = "GET"; + assetsRequest.Accept = "application/vnd.github.v3+json"; + assetsRequest.UserAgent = "BuildScript"; + + using (var assetsResponse = assetsRequest.GetResponse()) + { + var assetsStream = assetsResponse.GetResponseStream(); + var assetsReader = new StreamReader(assetsStream); + return assetsReader.ReadToEnd(); + } } \ No newline at end of file diff --git a/release.ps1 b/release.ps1 new file mode 100644 index 00000000..6cf4c66b --- /dev/null +++ b/release.ps1 @@ -0,0 +1 @@ +./build.ps1 -target Release \ No newline at end of file