diff --git a/build/Microsoft.DotNet.Cli.tasks b/build/Microsoft.DotNet.Cli.tasks index 58227dce8..67085b6fc 100644 --- a/build/Microsoft.DotNet.Cli.tasks +++ b/build/Microsoft.DotNet.Cli.tasks @@ -31,7 +31,7 @@ - + diff --git a/build/publish/FinishBuild.targets b/build/publish/FinishBuild.targets index fd439bab0..49efcf115 100644 --- a/build/publish/FinishBuild.targets +++ b/build/publish/FinishBuild.targets @@ -32,10 +32,14 @@ Channel="$(Channel)" CommitHash="$(CommitHash)" Coherent="$(Coherent)" /> - - + + + diff --git a/build_projects/dotnet-cli-build/UpdateVersionsRepo.cs b/build_projects/dotnet-cli-build/UpdateVersionsRepo.cs deleted file mode 100644 index 7baae1795..000000000 --- a/build_projects/dotnet-cli-build/UpdateVersionsRepo.cs +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) .NET Foundation and contributors. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -#if !SOURCE_BUILD -using Microsoft.Build.Framework; -using Microsoft.Build.Utilities; -using Microsoft.DotNet.VersionTools.Automation; -using System.IO; - - -namespace Microsoft.DotNet.Cli.Build -{ - public class UpdateVersionsRepo : Task - { - [Required] - public string BranchName { get; set; } - - [Required] - public string PackagesDirectory { get; set; } - - [Required] - public string GitHubPassword { get; set; } - - public override bool Execute() - { - string versionsRepoPath = $"build-info/dotnet/core-sdk/{BranchName}"; - - GitHubAuth auth = new GitHubAuth(GitHubPassword); - GitHubVersionsRepoUpdater repoUpdater = new GitHubVersionsRepoUpdater(auth); - repoUpdater.UpdateBuildInfoAsync( - Directory.GetFiles(PackagesDirectory, "*.nupkg"), - versionsRepoPath).Wait(); - - return true; - } - } -} -#endif diff --git a/build_projects/dotnet-cli-build/WriteVersionToVersionsRepo.cs b/build_projects/dotnet-cli-build/WriteVersionToVersionsRepo.cs new file mode 100644 index 000000000..6f2c99d9f --- /dev/null +++ b/build_projects/dotnet-cli-build/WriteVersionToVersionsRepo.cs @@ -0,0 +1,171 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +#if !SOURCE_BUILD +using Microsoft.Build.Framework; +using MSBuildUtilities = Microsoft.Build.Utilities; +using Microsoft.DotNet.VersionTools.Automation; +using Microsoft.DotNet.VersionTools.Automation.GitHubApi; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Net.Http; +using ThreadingTasks= System.Threading.Tasks; + +namespace Microsoft.DotNet.Cli.Build +{ + public class WriteVersionToVersionsRepo : MSBuildUtilities.Task + { + [Required] + public string BranchName { get; set; } + + [Required] + public string Name { get; set; } + + [Required] + public string Version { get; set; } + + [Required] + public string GitHubPassword { get; set; } + + public string VersionsRepoPath { get; set; } + + public override bool Execute() + { + string versionsRepoPath = VersionsRepoPath ?? $"build-info/dotnet/core-sdk/{BranchName}"; + + GitHubAuth auth = new GitHubAuth(GitHubPassword); + + GitHubWriteVersionUpdater repoUpdater = new GitHubWriteVersionUpdater(auth); + repoUpdater.UpdateBuildInfoAsync( + Name, + Version, + versionsRepoPath).Wait(); + + return true; + } + } + + // This code is a slightly modified port of GitHubVersionsRepoUpdater from + // https://raw.githubusercontent.com/dotnet/buildtools/master/src/Microsoft.DotNet.VersionTools/Automation/GitHubVersionsRepoUpdater.cs + internal class GitHubWriteVersionUpdater: VersionsRepoUpdater + { + private const int MaxTries = 10; + private const int RetryMillisecondsDelay = 5000; + + private GitHubAuth _gitHubAuth; + private GitHubProject _project; + + public GitHubWriteVersionUpdater( + GitHubAuth gitHubAuth, + string versionsRepoOwner = null, + string versionsRepo = null) + : this( + gitHubAuth, + new GitHubProject(versionsRepo ?? "versions", versionsRepoOwner)) + { + } + + public GitHubWriteVersionUpdater(GitHubAuth gitHubAuth, GitHubProject project) + { + if (gitHubAuth == null) + { + throw new ArgumentNullException(nameof(gitHubAuth)); + } + _gitHubAuth = gitHubAuth; + + if (project == null) + { + throw new ArgumentNullException(nameof(project)); + } + _project = project; + } + /// If true, updates Latest.txt with a prerelease moniker. If there isn't one, makes the file empty. + /// If true, updates Latest_Packages.txt. + public async ThreadingTasks.Task UpdateBuildInfoAsync( + string versionIdentifier, + string version, + string versionsRepoPath, + bool updateLatestPackageList = true, + bool updateLatestVersion = true) + { + if (versionIdentifier == null) + { + throw new ArgumentNullException(nameof(versionIdentifier)); + } + if (version == null) + { + throw new ArgumentNullException(nameof(version)); + } + if (versionsRepoPath == null) + { + throw new ArgumentNullException(nameof(versionsRepoPath)); + } + + using (GitHubClient client = new GitHubClient(_gitHubAuth)) + { + for (int i = 0; i < MaxTries; i++) + { + try + { + // Master commit to use as new commit's parent. + string masterRef = "heads/master"; + GitReference currentMaster = await client.GetReferenceAsync(_project, masterRef); + string masterSha = currentMaster.Object.Sha; + + List objects = new List(); + + if (updateLatestVersion) + { + objects.Add(new GitObject + { + Path = $"{versionsRepoPath}/Latest.txt", + Type = GitObject.TypeBlob, + Mode = GitObject.ModeFile, + Content = version + }); + } + if (updateLatestPackageList) + { + objects.Add(new GitObject + { + Path = $"{versionsRepoPath}/Latest_Packages.txt", + Type = GitObject.TypeBlob, + Mode = GitObject.ModeFile, + Content = $"{versionIdentifier} {version}{Environment.NewLine}" + }); + } + string message = $"Updating {versionsRepoPath}"; + + GitTree tree = await client.PostTreeAsync(_project, masterSha, objects.ToArray()); + GitCommit commit = await client.PostCommitAsync(_project, message, tree.Sha, new[] { masterSha }); + + // Only fast-forward. Don't overwrite other changes: throw exception instead. + await client.PatchReferenceAsync(_project, masterRef, commit.Sha, force: false); + + Trace.TraceInformation($"Committed build-info update on attempt {i + 1}."); + break; + } + catch (HttpRequestException ex) + { + int nextTry = i + 1; + if (nextTry < MaxTries) + { + Trace.TraceInformation($"Encountered exception committing build-info update: {ex.Message}"); + Trace.TraceInformation($"Trying again in {RetryMillisecondsDelay}ms. {MaxTries - nextTry} tries left."); + await ThreadingTasks.Task.Delay(RetryMillisecondsDelay); + } + else + { + Trace.TraceInformation("Encountered exception committing build-info update."); + throw; + } + } + } + } + } + } +} +#endif