Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhancements to Pull Request Creation/Update in CreateBaselineUpdatePR Tool #41160

Merged
merged 5 commits into from
Jun 13, 2024
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -280,72 +280,120 @@ private async Task<TreeResponse> CreateParentTreeAsync(TreeResponse testResultsT

private async Task CreateOrUpdatePullRequestAsync(TreeResponse parentTreeResponse, int buildId, string title, string targetBranch)
{
// Look for a pre-existing pull request
var request = new PullRequestRequest
{
Base = targetBranch
};
var existingPullRequest = await _client.PullRequest.GetAllForRepository(_repoOwner, _repoName, request);
var matchingPullRequest = existingPullRequest.FirstOrDefault(pr => pr.Title == title);
var existingPullRequest = await GetExistingPullRequestAsync(title, targetBranch);

// Create the branch name and get the head reference
string newBranchName = string.Empty;
Reference? headReference = null;
if (matchingPullRequest == null)
string headSha = await GetHeadShaAsync(targetBranch);
if (existingPullRequest == null)
{
string utcTime = DateTime.UtcNow.ToString("yyyyMMddHHmmss");
newBranchName = $"pr-baseline-{utcTime}";
headReference = await _client.Git.Reference.Get(_repoOwner, _repoName, "heads/" + targetBranch);
}
else
{
newBranchName = matchingPullRequest.Head.Ref;
headReference = await _client.Git.Reference.Get(_repoOwner, _repoName, "heads/" + matchingPullRequest.Head.Ref);
}

// Create the commit
string commitMessage = $"Update baselines for build {BuildLink}{buildId} (internal Microsoft link)";
var newCommit = new NewCommit(commitMessage, parentTreeResponse.Sha, headReference.Object.Sha);
var commitResponse = await _client.Git.Commit.Create(_repoOwner, _repoName, newCommit);

string pullRequestBody = $"This PR was created by the `CreateBaselineUpdatePR` tool for build {buildId}. \n\n" +
$"The updated test results can be found at {BuildLink}{buildId} (internal Microsoft link)";
if (matchingPullRequest != null)
{
// Update the existing pull request with the new commit
var referenceUpdate = new ReferenceUpdate(commitResponse.Sha);
await _client.Git.Reference.Update(_repoOwner, _repoName, $"heads/{newBranchName}", referenceUpdate);
newBranchName = existingPullRequest.Head.Ref;

// Update the body of the pull request
var pullRequestUpdate = new PullRequestUpdate
try
{
Body = pullRequestBody
};
await _client.PullRequest.Update(_repoOwner, _repoName, matchingPullRequest.Number, pullRequestUpdate);
// Merge the target branch into the existing pull request
var merge = new NewMerge(newBranchName, headSha);
var mergeResult = await _client.Repository.Merging.Create(_repoOwner, _repoName, merge);
ellahathaway marked this conversation as resolved.
Show resolved Hide resolved
}
catch (Exception e)
{
Log.LogWarning($"Failed to merge the target branch into the existing pull request: {e.Message}");
Log.LogWarning("Continuing with updating the existing pull request. You may need to resolve conflicts manually in the PR.");
}

Log.LogInformation($"Updated existing pull request #{matchingPullRequest.Number}. URL: {matchingPullRequest.HtmlUrl}");
headSha = await GetHeadShaAsync(newBranchName);
}
else

var commitSha = await CreateCommitAsync(parentTreeResponse.Sha, headSha, $"Update baselines for build {BuildLink}{buildId} (internal Microsoft link)");
if (await ShouldMakeUpdatesAsync(headSha, commitSha))
{
var comparison = await _client.Repository.Commit.Compare(_repoOwner, _repoName, headReference.Object.Sha, commitResponse.Sha);
if (!comparison.Files.Any())
string pullRequestBody = $"This PR was created by the `CreateBaselineUpdatePR` tool for build {buildId}. \n\n" +
$"The updated test results can be found at {BuildLink}{buildId} (internal Microsoft link)";
if (existingPullRequest != null)
{
// No changes to commit
Log.LogInformation("No changes to commit. Skipping PR creation.");
return;
await UpdatePullRequestAsync(newBranchName, commitSha, pullRequestBody, existingPullRequest);
}
else
{
await CreatePullRequestAsync(newBranchName, commitSha, targetBranch, title, pullRequestBody);
}
}
}

// Create a new pull request
var newReference = new NewReference("refs/heads/" + newBranchName, commitResponse.Sha);
await _client.Git.Reference.Create(_repoOwner, _repoName, newReference);
private async Task<PullRequest?> GetExistingPullRequestAsync(string title, string targetBranch)
{
var request = new PullRequestRequest
{
Base = targetBranch
};
var existingPullRequest = await _client.PullRequest.GetAllForRepository(_repoOwner, _repoName, request);
return existingPullRequest.FirstOrDefault(pr => pr.Title == title);
mthalman marked this conversation as resolved.
Show resolved Hide resolved
}

var newPullRequest = new NewPullRequest(title, newBranchName, targetBranch)
{
Body = pullRequestBody
};
var pullRequest = await _client.PullRequest.Create(_repoOwner, _repoName, newPullRequest);
private async Task<string> CreateCommitAsync(string newSha, string headSha, string commitMessage)
{
var newCommit = new NewCommit(commitMessage, newSha, headSha);
var commit = await _client.Git.Commit.Create(_repoOwner, _repoName, newCommit);
return commit.Sha;
}

Log.LogInformation($"Created pull request #{pullRequest.Number}. URL: {pullRequest.HtmlUrl}");
private async Task<bool> ShouldMakeUpdatesAsync(string headSha, string commitSha)
{
var comparison = await _client.Repository.Commit.Compare(_repoOwner, _repoName, headSha, commitSha);
if (!comparison.Files.Any())
{
Log.LogInformation("No changes to commit. Skipping PR creation/updates.");
return false;
}
return true;
}

private async Task UpdatePullRequestAsync(string branchName, string commitSha, string body, PullRequest pullRequest)
{
await UpdateReferenceAsync(branchName, commitSha);

var pullRequestUpdate = new PullRequestUpdate
{
Body = body
};
ellahathaway marked this conversation as resolved.
Show resolved Hide resolved
await _client.PullRequest.Update(_repoOwner, _repoName, pullRequest.Number, pullRequestUpdate);

Log.LogInformation($"Updated existing pull request #{pullRequest.Number}. URL: {pullRequest.HtmlUrl}");
}

private async Task CreatePullRequestAsync(string newBranchName, string commitSha, string targetBranch, string title, string body)
{
await CreateReferenceAsync(newBranchName, commitSha);

var newPullRequest = new NewPullRequest(title, newBranchName, targetBranch)
{
Body = body
};
var pullRequest = await _client.PullRequest.Create(_repoOwner, _repoName, newPullRequest);

Log.LogInformation($"Created pull request #{pullRequest.Number}. URL: {pullRequest.HtmlUrl}");
}

private async Task<string> GetHeadShaAsync(string branchName)
{
var reference = await _client.Git.Reference.Get(_repoOwner, _repoName, $"heads/{branchName}");
return reference.Object.Sha;
}

private async Task UpdateReferenceAsync(string branchName, string commitSha)
{
var referenceUpdate = new ReferenceUpdate(commitSha);
await _client.Git.Reference.Update(_repoOwner, _repoName, $"heads/{branchName}", referenceUpdate);
}

private async Task CreateReferenceAsync(string branchName, string commitSha)
{
var newReference = new NewReference($"refs/heads/{branchName}", commitSha);
await _client.Git.Reference.Create(_repoOwner, _repoName, newReference);
}
}