Skip to content

Commit

Permalink
Build: add comments to related issues and pull requests when releasing
Browse files Browse the repository at this point in the history
  • Loading branch information
aaubry committed Apr 1, 2021
1 parent ccc272e commit 6911240
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 61 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,4 @@ YamlDotNet/Properties/AssemblyInfo.Generated.cs
BenchmarkDotNet.Artifacts

/YamlDotNet.AotTest/exitcode.txt
/tools/build/Properties/launchSettings.json
158 changes: 116 additions & 42 deletions tools/build/BuildDefinition.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Reflection;
Expand All @@ -24,39 +25,47 @@ public static class BuildDefinition
{
public static GitVersion ResolveVersion(Options options, PreviousReleases releases)
{
string versionJson;
try
GitVersion version;
if (ForcedVersion != null)
{
versionJson = Read("dotnet", $"gitversion /nofetch{(options.Verbose ? " /diag" : "")}", BasePath);
version = new GitVersion(ForcedVersion);
}
catch (NonZeroExitCodeException)
else
{
Run("dotnet", "gitversion /nofetch /diag", BasePath);
throw;
}
string versionJson;
try
{
versionJson = Read("dotnet", $"gitversion /nofetch{(options.Verbose ? " /diag" : "")}", BasePath);
}
catch (NonZeroExitCodeException)
{
Run("dotnet", "gitversion /nofetch /diag", BasePath);
throw;
}

WriteVerbose(versionJson);
WriteVerbose(versionJson);

if (options.Verbose)
{
// Remove extra output from versionJson
var lines = versionJson
.Split('\n')
.Select(l => l.TrimEnd('\r'))
.SkipWhile(l => !l.StartsWith('{'))
.TakeWhile(l => !l.StartsWith('}'))
.Append("}");

versionJson = string.Join('\n', lines);
}
if (options.Verbose)
{
// Remove extra output from versionJson
var lines = versionJson
.Split('\n')
.Select(l => l.TrimEnd('\r'))
.SkipWhile(l => !l.StartsWith('{'))
.TakeWhile(l => !l.StartsWith('}'))
.Append("}");

versionJson = string.Join('\n', lines);
}

var jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
jsonOptions.Converters.Add(new AutoNumberToStringConverter());
var jsonOptions = new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
};
jsonOptions.Converters.Add(new AutoNumberToStringConverter());

var version = JsonSerializer.Deserialize<GitVersion>(versionJson, jsonOptions);
version = JsonSerializer.Deserialize<GitVersion>(versionJson, jsonOptions);
}

if (version.CommitsSinceVersionSource > 0 && version.Equals(releases.Latest))
{
Expand Down Expand Up @@ -250,19 +259,7 @@ public static ScaffoldedRelease ScaffoldReleaseNotes(GitVersion version, Previou

public static async Task CreateGithubRelease(GitVersion version, ScaffoldedRelease release)
{
var token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? throw new InvalidOperationException("Please set the GITHUB_TOKEN environment variable.");
var repository = Environment.GetEnvironmentVariable("GITHUB_REPOSITORY") ?? "aaubry/YamlDotNet.Sandbox";

using var apiClient = new HttpClient(new LoggerHttpHandler())
{
BaseAddress = new Uri("https://api.github.com"),
};

apiClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
apiClient.DefaultRequestHeaders.Add("User-Agent", repository.Split('/')[0]);
apiClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", token);

var releaseResponse = await apiClient.PostAsJsonAsync($"/repos/{repository}/releases", new
var releaseResponse = await GitHubClient.Value.PostAsJsonAsync($"/repos/{GitHubRepository}/releases", new
{
tag_name = $"v{version.NuGetVersion}",
target_commitish = version.Sha,
Expand All @@ -278,6 +275,37 @@ public static async Task CreateGithubRelease(GitVersion version, ScaffoldedRelea
WriteImportant($"Release draft created:\n{releaseInfo.html_url}");
}

public static async Task LinkPullRequestsToReleases(GitVersion version)
{
if (version.IsPreRelease)
{
WriteWarning("Not linking to pre-releases.");
return;
}

var releaseResponse = await GitHubClient.Value.GetAsync($"/repos/{GitHubRepository}/releases/tags/v{version.NuGetVersion}");

var release = await releaseResponse.EnsureSuccessStatusCode().Content.ReadAsAsync<GitHubApiModels.Release>();

var linkedIssues = Regex.Matches(release.body, @"#(\d+)").Select(m => m.Groups[1].Value);
WriteVerbose($"Found the following issues / pull requests: {string.Join(",", linkedIssues)}");

foreach (var issueNumber in linkedIssues)
{
var prResponse = await GitHubClient.Value.GetAsync($"/repos/{GitHubRepository}/pulls/{issueNumber}");
var isIssue = prResponse.StatusCode == HttpStatusCode.NotFound;

var commentResponse = await GitHubClient.Value.PostAsJsonAsync($"/repos/{GitHubRepository}/issues/{issueNumber}/comments", new
{
body = isIssue
? $"A fix for this issue has been released in [version {version.NuGetVersion}](https://github.com/{GitHubRepository}/releases/tag/v{version.NuGetVersion})."
: $"This heature has been released in [version {version.NuGetVersion}](https://github.com/{GitHubRepository}/releases/tag/v{version.NuGetVersion})."
});

commentResponse.EnsureSuccessStatusCode();
}
}

public static PreviousReleases DiscoverPreviousReleases()
{
// Find previous release
Expand Down Expand Up @@ -410,10 +438,49 @@ public static void Document(Options options)
* [Building Custom Formatters for .Net Core (Yaml Formatters)](http://www.fiyazhasan.me/building-custom-formatters-for-net-core-yaml-formatters/) by @FiyazBinHasan
");
}

private static string GitHubRepository => Environment.GetEnvironmentVariable("GITHUB_REPOSITORY") ?? "aaubry/YamlDotNet.Sandbox";


private static readonly Lazy<HttpClient> GitHubClient = new Lazy<HttpClient>(() =>
{
var token = Environment.GetEnvironmentVariable("GITHUB_TOKEN") ?? throw new InvalidOperationException("Please set the GITHUB_TOKEN environment variable.");
var gitHubClient = new HttpClient(new LoggerHttpHandler())
{
BaseAddress = new Uri("https://api.github.com"),
};
gitHubClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/vnd.github.v3+json"));
gitHubClient.DefaultRequestHeaders.Add("User-Agent", GitHubRepository.Split('/')[0]);
gitHubClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("token", token);
return gitHubClient;
});
}

public class GitVersion : IEquatable<Version>
{
public GitVersion()
{
}

public GitVersion(string version)
{
var partsMatch = Regex.Match(version, @"^(?<major>\d+).(?<minor>\d+).(?<patch>\d+)(?:-(?<label>.*))?");
if (!partsMatch.Success)
{
throw new ArgumentException($"Invalid version name '{version}'.", nameof(version));
}

Major = int.Parse(partsMatch.Groups["major"].Value, CultureInfo.InvariantCulture);
Minor = int.Parse(partsMatch.Groups["minor"].Value, CultureInfo.InvariantCulture);
Patch = int.Parse(partsMatch.Groups["patch"].Value, CultureInfo.InvariantCulture);
PreReleaseLabel = partsMatch.Groups["label"].Value;
CommitsSinceVersionSourcePadded = "0000";
Sha = "invalid commit name";
}

public int Major { get; set; }
public int Minor { get; set; }
public int Patch { get; set; }
Expand Down Expand Up @@ -488,9 +555,16 @@ internal class LoggerHttpHandler : HttpClientHandler
{
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
var requestText = await request.Content.ReadAsStringAsync();
var requestHeaders = request.Headers.Concat(request.Content.Headers)
.Select(h => $"\n{h.Key}: {string.Join(", ", h.Value)}");
string requestText = string.Empty;
var allHeaders = request.Headers.AsEnumerable();

if (request.Content is object)
{
requestText = await request.Content.ReadAsStringAsync();
allHeaders = allHeaders.Concat(request.Content.Headers);
}

var requestHeaders = allHeaders.Select(h => $"\n{h.Key}: {string.Join(", ", h.Value)}");

WriteVerbose($"> {request.Method} {request.RequestUri}{string.Concat(requestHeaders)}\n\n{requestText}\n".Replace("\n", "\n> "));

Expand Down
5 changes: 5 additions & 0 deletions tools/build/GitHubApiModels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ internal static class GitHubApiModels
public class Release
{
public string? html_url { get; set; }
public string? body { get; set; }
}

public class Issue
{
}
}
}
27 changes: 17 additions & 10 deletions tools/build/Program.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using Bullseye;
using Bullseye.Internal;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -10,7 +8,8 @@
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Web;
using Bullseye;
using Bullseye.Internal;
using static Bullseye.Targets;
using OperatingSystem = Bullseye.Internal.OperatingSystem;

Expand All @@ -21,6 +20,7 @@ class Program
public static string BasePath { get; private set; } = default!;
private static Palette palette = default!;
public static bool NoPrerelease { get; private set; }
public static string? ForcedVersion { get; private set; }
private static bool verbose;
private static Host host;
private static readonly Dictionary<Type, object> state = new Dictionary<Type, object>();
Expand Down Expand Up @@ -117,15 +117,20 @@ static int Main(string[] args)
var filteredArguments = args
.Where(a =>
{
switch (a)
if (a == "--no-prerelease")
{
case "--no-prerelease":
NoPrerelease = true;
return false;
NoPrerelease = true;
return false;
}
default:
return true;
var match = Regex.Match(a, "^--version=(.*)");
if (match.Success)
{
ForcedVersion = match.Groups[1].Value;
return false;
}
return true;
})
.ToList();

Expand Down Expand Up @@ -159,6 +164,7 @@ static int Main(string[] args)
targets.Add(nameof(BuildDefinition.SetBuildVersion));
targets.Add(nameof(BuildDefinition.Publish));
targets.Add(nameof(BuildDefinition.TweetRelease));
targets.Add(nameof(BuildDefinition.LinkPullRequestsToReleases));
}
else
{
Expand Down Expand Up @@ -202,6 +208,7 @@ static int Main(string[] args)
Console.WriteLine();
Console.WriteLine($"{palette.Default}Additional options:");
Console.WriteLine($" {palette.Option}--no-prerelease {palette.Default}Force the current version to be considered final{palette.Reset}");
Console.WriteLine($" {palette.Option}--version=<version> {palette.Default}Force the current version to equal to the specified value{palette.Reset}");
}

return exitCode;
Expand Down
9 changes: 0 additions & 9 deletions tools/build/Properties/launchSettings.json

This file was deleted.

0 comments on commit 6911240

Please sign in to comment.