e7718b7163
- Add the new version number to the commit and PR message. - Check if anything has been updated and no-op if there wasn't anything updated. - Add support to CC indviduals on the PR.
162 lines
6.2 KiB
C#
162 lines
6.2 KiB
C#
// 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.
|
|
|
|
using System;
|
|
using System.Linq;
|
|
using Microsoft.DotNet.Cli.Build.Framework;
|
|
using Octokit;
|
|
|
|
using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers;
|
|
|
|
namespace Microsoft.DotNet.Scripts
|
|
{
|
|
/// <summary>
|
|
/// Creates a GitHub Pull Request for the current changes in the repo.
|
|
/// </summary>
|
|
public static class PushPRTargets
|
|
{
|
|
private static readonly Config s_config = Config.Instance;
|
|
|
|
[Target(nameof(CommitChanges), nameof(CreatePR))]
|
|
public static BuildTargetResult PushPR(BuildTargetContext c) => c.Success();
|
|
|
|
/// <summary>
|
|
/// Commits all the current changes in the repo and pushes the commit to a remote
|
|
/// so a PR can be created for it.
|
|
/// </summary>
|
|
[Target]
|
|
public static BuildTargetResult CommitChanges(BuildTargetContext c)
|
|
{
|
|
CommandResult statusResult = Cmd("git", "status", "--porcelain")
|
|
.CaptureStdOut()
|
|
.Execute();
|
|
statusResult.EnsureSuccessful();
|
|
|
|
bool hasModifiedFiles = !string.IsNullOrWhiteSpace(statusResult.StdOut);
|
|
bool hasUpdatedDependencies = c.GetDependencyInfos().Where(d => d.IsUpdated).Any();
|
|
|
|
if (hasModifiedFiles != hasUpdatedDependencies)
|
|
{
|
|
return c.Failed($"'git status' does not match DependencyInfo information. Git has modified files: {hasModifiedFiles}. DependencyInfo is updated: {hasUpdatedDependencies}.");
|
|
}
|
|
|
|
if (!hasUpdatedDependencies)
|
|
{
|
|
c.Warn("Dependencies are currently up to date");
|
|
return c.Success();
|
|
}
|
|
|
|
string userName = s_config.UserName;
|
|
string email = s_config.Email;
|
|
|
|
string commitMessage = GetCommitMessage(c);
|
|
|
|
Cmd("git", "commit", "-a", "-m", commitMessage, "--author", $"{userName} <{email}>")
|
|
.EnvironmentVariable("GIT_COMMITTER_NAME", userName)
|
|
.EnvironmentVariable("GIT_COMMITTER_EMAIL", email)
|
|
.Execute()
|
|
.EnsureSuccessful();
|
|
|
|
string remoteUrl = $"github.com/{s_config.GitHubOriginOwner}/{s_config.GitHubProject}.git";
|
|
string remoteBranchName = $"UpdateDependencies{DateTime.UtcNow.ToString("yyyyMMddhhmmss")}";
|
|
string refSpec = $"HEAD:refs/heads/{remoteBranchName}";
|
|
|
|
string logMessage = $"git push https://{remoteUrl} {refSpec}";
|
|
BuildReporter.BeginSection("EXEC", logMessage);
|
|
|
|
CommandResult pushResult =
|
|
Cmd("git", "push", $"https://{userName}:{s_config.Password}@{remoteUrl}", refSpec)
|
|
.QuietBuildReporter() // we don't want secrets showing up in our logs
|
|
.CaptureStdErr() // git push will write to StdErr upon success, disable that
|
|
.CaptureStdOut()
|
|
.Execute();
|
|
|
|
var message = logMessage + $" exited with {pushResult.ExitCode}";
|
|
if (pushResult.ExitCode == 0)
|
|
{
|
|
BuildReporter.EndSection("EXEC", message.Green(), success: true);
|
|
}
|
|
else
|
|
{
|
|
BuildReporter.EndSection("EXEC", message.Red().Bold(), success: false);
|
|
}
|
|
|
|
pushResult.EnsureSuccessful(suppressOutput: true);
|
|
|
|
c.SetRemoteBranchName(remoteBranchName);
|
|
|
|
return c.Success();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a GitHub PR for the remote branch created above.
|
|
/// </summary>
|
|
[Target]
|
|
public static BuildTargetResult CreatePR(BuildTargetContext c)
|
|
{
|
|
string remoteBranchName = c.GetRemoteBranchName();
|
|
string commitMessage = c.GetCommitMessage();
|
|
|
|
NewPullRequest prInfo = new NewPullRequest(
|
|
commitMessage,
|
|
s_config.GitHubOriginOwner + ":" + remoteBranchName,
|
|
s_config.GitHubUpstreamBranch);
|
|
|
|
string[] prNotifications = s_config.GitHubPullRequestNotifications;
|
|
if (prNotifications.Length > 0)
|
|
{
|
|
prInfo.Body = $"/cc @{string.Join(" @", prNotifications)}";
|
|
}
|
|
|
|
GitHubClient gitHub = new GitHubClient(new ProductHeaderValue("dotnetDependencyUpdater"));
|
|
|
|
gitHub.Credentials = new Credentials(s_config.Password);
|
|
|
|
PullRequest createdPR = gitHub.PullRequest.Create(s_config.GitHubUpstreamOwner, s_config.GitHubProject, prInfo).Result;
|
|
c.Info($"Created Pull Request: {createdPR.HtmlUrl}");
|
|
|
|
return c.Success();
|
|
}
|
|
|
|
private static string GetRemoteBranchName(this BuildTargetContext c)
|
|
{
|
|
return (string)c.BuildContext["RemoteBranchName"];
|
|
}
|
|
|
|
private static void SetRemoteBranchName(this BuildTargetContext c, string value)
|
|
{
|
|
c.BuildContext["RemoteBranchName"] = value;
|
|
}
|
|
|
|
private static string GetCommitMessage(this BuildTargetContext c)
|
|
{
|
|
const string commitMessagePropertyName = "CommitMessage";
|
|
|
|
string message;
|
|
object messageObject;
|
|
if (c.BuildContext.Properties.TryGetValue(commitMessagePropertyName, out messageObject))
|
|
{
|
|
message = (string)messageObject;
|
|
}
|
|
else
|
|
{
|
|
DependencyInfo[] updatedDependencies = c.GetDependencyInfos()
|
|
.Where(d => d.IsUpdated)
|
|
.ToArray();
|
|
|
|
string updatedDependencyNames = string.Join(", ", updatedDependencies.Select(d => d.Name));
|
|
string updatedDependencyVersions = string.Join(", ", updatedDependencies.Select(d => d.NewReleaseVersion));
|
|
|
|
message = $"Updating {updatedDependencyNames} to {updatedDependencyVersions}";
|
|
if (updatedDependencies.Count() > 1)
|
|
{
|
|
message += " respectively";
|
|
}
|
|
|
|
c.BuildContext[commitMessagePropertyName] = message;
|
|
}
|
|
|
|
return message;
|
|
}
|
|
}
|
|
}
|