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

Add ResourceEvents for merge requests #547

Merged
merged 8 commits into from
Oct 24, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
122 changes: 122 additions & 0 deletions NGitLab.Mock.Tests/MergeRequestsMockTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -290,5 +290,127 @@ public void Test_merge_request_with_head_pipeline()
var pipeline = project.Pipelines.Add(branch, JobStatus.Success, user);
Assert.AreEqual(pipeline, mr.HeadPipeline, "A pipeline was just created on the source branch");
}

[Test]
public void Test_merge_request_resource_state_events_found_on_close_and_reopen()
{
using var server = new GitLabConfig()
.WithUser("user1", isDefault: true)
.WithUser("user2")
.WithProject("Test", configure: project => project
.WithMergeRequest("branch-01", title: "Merge request 1", author: "user1", assignee: "user2"))
.BuildServer();

var client = server.CreateClient("user1");
var projectId = server.AllProjects.First().Id;
var mrClient = client.GetMergeRequest(projectId);
var mergeRequest = mrClient.Get(new MergeRequestQuery { Scope = "created_by_me" }).First();

mrClient.Close(mergeRequest.Iid);
mrClient.Reopen(mergeRequest.Iid);

var resourceStateEvents = mrClient.ResourceStateEventsAsync(projectId: projectId, mergeRequestIid: mergeRequest.Iid).ToArray();
Assert.AreEqual(2, resourceStateEvents.Length);

var closeStateEvents = resourceStateEvents.Where(e => string.Equals(e.State, "closed", StringComparison.Ordinal)).ToArray();
Assert.AreEqual(1, closeStateEvents.Length);

var reopenMilestoneEvents = resourceStateEvents.Where(e => string.Equals(e.State, "reopened", StringComparison.Ordinal)).ToArray();
Assert.AreEqual(1, reopenMilestoneEvents.Length);
}

[Test]
public void Test_merge_request_resource_label_events_found()
{
using var server = new GitLabConfig()
.WithUser("user1", isDefault: true)
.WithUser("user2")
.WithProject("Test", configure: project => project
.WithMergeRequest("branch-01", title: "Merge request 1", author: "user1", assignee: "user2"))
.BuildServer();

var client = server.CreateClient("user1");
var projectId = server.AllProjects.First().Id;
var mrClient = client.GetMergeRequest(projectId);
var mergeRequest = mrClient.Get(new MergeRequestQuery { Scope = "created_by_me" }).First();

mrClient.Update(mergeRequest.Iid, new MergeRequestUpdate()
{
AddLabels = "first,second,third",
});

mrClient.Update(mergeRequest.Iid, new MergeRequestUpdate()
{
RemoveLabels = "second",
});

mrClient.Update(mergeRequest.Iid, new MergeRequestUpdate()
{
Labels = "first,second",
});

/* We're expecting this sequence
* 1. Add first
* 1. Add second
* 1. Add third
* 2. Remove second
* 3. Add second
* 3. Remove third
*/
var resourceLabelEvents = mrClient.ResourceLabelEventsAsync(projectId: projectId, mergeRequestIid: mergeRequest.Iid).ToArray();
Assert.AreEqual(6, resourceLabelEvents.Length);

var addLabelEvents = resourceLabelEvents.Where(e => e.Action == ResourceLabelEventAction.Add).ToArray();
Assert.AreEqual(4, addLabelEvents.Length);

var removeLabelEvents = resourceLabelEvents.Where(e => e.Action == ResourceLabelEventAction.Remove).ToArray();
Assert.AreEqual(2, removeLabelEvents.Length);
}

[Test]
public void Test_merge_request_resource_milestone_events_found()
{
using var server = new GitLabConfig()
.WithUser("user1", isDefault: true)
.WithUser("user2")
.WithProject("Test", configure: project => project
.WithMergeRequest("branch-01", title: "Merge request 1", author: "user1", assignee: "user2")
.WithMilestone("Milestone 1")
.WithMilestone("Milestone 2"))
.BuildServer();

var client = server.CreateClient("user1");
var projectId = server.AllProjects.First().Id;
var mrClient = client.GetMergeRequest(projectId);
var mergeRequest = mrClient.Get(new MergeRequestQuery { Scope = "created_by_me" }).First();
var milestones = client.GetMilestone(1).All.ToArray();

mrClient.Update(mergeRequest.Iid, new MergeRequestUpdate()
{
MilestoneId = milestones[0].Id,
});

mrClient.Update(mergeRequest.Iid, new MergeRequestUpdate()
{
MilestoneId = milestones[1].Id,
});

/* We're expecting this sequence
* 1. Add milestone 1
* 2. Remove milestone 1
* 2. Add milestone 2
*/
var resourceMilestoneEvents = mrClient.ResourceMilestoneEventsAsync(projectId: projectId, mergeRequestIid: mergeRequest.Iid).ToArray();
Assert.AreEqual(3, resourceMilestoneEvents.Length);

var removeMilestoneEvents = resourceMilestoneEvents.Where(e => e.Action == ResourceMilestoneEventAction.Remove).ToArray();
Assert.AreEqual(1, removeMilestoneEvents.Length);
Assert.AreEqual(milestones[0].Id, removeMilestoneEvents[0].Milestone.Id);

var addMilestoneEvents = resourceMilestoneEvents.Where(e => e.Action == ResourceMilestoneEventAction.Add).ToArray();
Assert.AreEqual(2, addMilestoneEvents.Length);
Assert.AreEqual(milestones[0].Id, addMilestoneEvents[0].Milestone.Id);
Assert.AreEqual(milestones[1].Id, addMilestoneEvents[1].Milestone.Id);
}
}
}
105 changes: 2 additions & 103 deletions NGitLab.Mock/Clients/IssueClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public Models.Issue Edit(IssueEdit issueEdit)
if (issueEdit.MilestoneId.HasValue)
{
issueToModify.Milestone = GetMilestone(projectId, issueEdit.MilestoneId.Value);
CreateResourceMilestoneEvents(issueToModify.Id, prevMilestone, issueToModify.Milestone);
Server.ResourceMilestoneEvents.CreateResourceMilestoneEvents(Context.User, issueToModify.Id, prevMilestone, issueToModify.Milestone, "Issue");
}

issueToModify.Title = issueEdit.Title;
Expand All @@ -107,7 +107,7 @@ public Models.Issue Edit(IssueEdit issueEdit)

if (labelsEdit is not null)
{
CreateResourceLabelEvents(issueToModify.Labels, labelsEdit, issueToModify.Id);
Server.ResourceLabelEvents.CreateResourceLabelEvents(Context.User, issueToModify.Labels, labelsEdit, issueToModify.Id, "issue");
issueToModify.Labels = labelsEdit;
}

Expand Down Expand Up @@ -451,106 +451,5 @@ private IEnumerable<Issue> FilterByQuery(IEnumerable<Issue> issues, IssueQuery q

return issues;
}

private void CreateResourceLabelEvents(string[] previousLabels, string[] newLabels, int resourceId)
{
var currentUser = Context.User;

foreach (var label in previousLabels)
{
if (!newLabels.Any(l => string.Equals(l, label, StringComparison.OrdinalIgnoreCase)))
{
Server.ResourceLabelEvents.Add(new ResourceLabelEvent()
{
Action = ResourceLabelEventAction.Remove,
Label = new Label() { Name = label },
ResourceId = resourceId,
CreatedAt = DateTime.UtcNow,
Id = Server.GetNewResourceLabelEventId(),
User = new Author()
{
Id = currentUser.Id,
Email = currentUser.Email,
AvatarUrl = currentUser.AvatarUrl,
Name = currentUser.Name,
State = currentUser.State.ToString(),
Username = currentUser.UserName,
CreatedAt = currentUser.CreatedAt,
WebUrl = currentUser.WebUrl,
},
ResourceType = "issue",
});
}
}

foreach (var label in newLabels)
{
if (!previousLabels.Any(l => string.Equals(l, label, StringComparison.OrdinalIgnoreCase)))
{
Server.ResourceLabelEvents.Add(new ResourceLabelEvent()
{
Action = ResourceLabelEventAction.Add,
Label = new Label() { Name = label },
ResourceId = resourceId,
CreatedAt = DateTime.UtcNow,
Id = Server.GetNewResourceLabelEventId(),
User = new Author()
{
Id = currentUser.Id,
Email = currentUser.Email,
AvatarUrl = currentUser.AvatarUrl,
Name = currentUser.Name,
State = currentUser.State.ToString(),
Username = currentUser.UserName,
CreatedAt = currentUser.CreatedAt,
WebUrl = currentUser.WebUrl,
},
ResourceType = "issue",
});
}
}
}

private void CreateResourceMilestoneEvents(int resourceId, Milestone previousMilestone, Milestone newMilestone)
{
if (previousMilestone is null)
{
CreateResourceMilestoneEvent(resourceId, newMilestone, ResourceMilestoneEventAction.Add);
}
else if (newMilestone is not null && previousMilestone is not null)
{
if (newMilestone.Id != previousMilestone.Id)
{
CreateResourceMilestoneEvent(resourceId, previousMilestone, ResourceMilestoneEventAction.Remove);
}

CreateResourceMilestoneEvent(resourceId, newMilestone, ResourceMilestoneEventAction.Add);
}
}

private void CreateResourceMilestoneEvent(int resourceId, Milestone milestone, ResourceMilestoneEventAction action)
{
var currentUser = Context.User;
Server.ResourceMilestoneEvents.Add(new ResourceMilestoneEvent()
{
Action = action,
Milestone = milestone,
ResourceId = resourceId,
CreatedAt = DateTime.UtcNow,
Id = Server.GetNewResourceLabelEventId(),
User = new Author()
{
Id = currentUser.Id,
Email = currentUser.Email,
AvatarUrl = currentUser.AvatarUrl,
Name = currentUser.Name,
State = currentUser.State.ToString(),
Username = currentUser.UserName,
CreatedAt = currentUser.CreatedAt,
WebUrl = currentUser.WebUrl,
},
ResourceType = "issue",
});
}
}
}
80 changes: 73 additions & 7 deletions NGitLab.Mock/Clients/MergeRequestClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using NGitLab.Mock.Internals;
using NGitLab.Models;

namespace NGitLab.Mock.Clients
Expand Down Expand Up @@ -262,6 +263,8 @@ public Models.MergeRequest Close(int mergeRequestIid)

mergeRequest.ClosedAt = DateTimeOffset.UtcNow;
mergeRequest.UpdatedAt = DateTimeOffset.UtcNow;

Server.ResourceStateEvents.CreateResourceStateEvent(Context.User, "closed", mergeRequest.Id, "MergeRequest");
return mergeRequest.ToMergeRequestClient();
}
}
Expand Down Expand Up @@ -326,22 +329,43 @@ public Models.MergeRequest Create(MergeRequestCreate mergeRequestCreate)
mergeRequest.Description = mergeRequestCreate.Description;
mergeRequest.ShouldRemoveSourceBranch = mergeRequestCreate.RemoveSourceBranch;
mergeRequest.Squash = mergeRequestCreate.Squash;
SetLabels(mergeRequest, mergeRequestCreate.Labels);
SetLabels(mergeRequest, mergeRequestCreate.Labels, labelsToAdd: null, labelsToRemove: null);

return mergeRequest.ToMergeRequestClient();
}
}

private static void SetLabels(MergeRequest mergeRequest, string labels)
private void SetLabels(MergeRequest mergeRequest, string labels, string labelsToAdd, string labelsToRemove)
{
if (labels != null)
if (labels is not null || labelsToAdd is not null || labelsToRemove is not null)
{
var newLabels = mergeRequest.Labels.ToArray();
if (labels is not null)
{
newLabels = labels.Split(',').Distinct(StringComparer.Ordinal).ToArray();
}

if (labelsToAdd is not null)
{
newLabels = newLabels.Concat(labelsToAdd.Split(',')).Distinct(StringComparer.Ordinal).ToArray();
}

if (labelsToRemove is not null)
{
newLabels = newLabels.Except(labelsToRemove.Split(','), StringComparer.Ordinal).Distinct(StringComparer.Ordinal).ToArray();
}

if (newLabels is not null)
{
Server.ResourceLabelEvents.CreateResourceLabelEvents(Context.User, mergeRequest.Labels.ToArray(), newLabels, mergeRequest.Id, "MergeRequest");
}

mergeRequest.Labels.Clear();
foreach (var label in labels.Split(','))
foreach (var newLabel in newLabels)
{
if (!string.IsNullOrEmpty(label))
if (!string.IsNullOrEmpty(newLabel))
{
mergeRequest.Labels.Add(label);
mergeRequest.Labels.Add(newLabel);
}
}
}
Expand Down Expand Up @@ -571,6 +595,8 @@ public Models.MergeRequest Reopen(int mergeRequestIid)

mergeRequest.ClosedAt = null;
mergeRequest.UpdatedAt = DateTimeOffset.UtcNow;

Server.ResourceStateEvents.CreateResourceStateEvent(Context.User, "reopened", mergeRequest.Id, "MergeRequest");
return mergeRequest.ToMergeRequestClient();
}
}
Expand Down Expand Up @@ -621,6 +647,13 @@ public Models.MergeRequest Update(int mergeRequestIid, MergeRequestUpdate mergeR
}
}

if (mergeRequestUpdate.MilestoneId != null)
{
var prevMilestone = mergeRequest.Milestone;
mergeRequest.Milestone = GetMilestone(project.Id, mergeRequestUpdate.MilestoneId.Value);
Server.ResourceMilestoneEvents.CreateResourceMilestoneEvents(Context.User, mergeRequest.Id, prevMilestone, mergeRequest.Milestone, "MergeRequest");
}

if (mergeRequestUpdate.ReviewerIds != null)
{
foreach (var reviewerId in mergeRequestUpdate.ReviewerIds)
Expand Down Expand Up @@ -658,7 +691,7 @@ public Models.MergeRequest Update(int mergeRequestIid, MergeRequestUpdate mergeR
mergeRequest.Title = mergeRequestUpdate.Title;
}

SetLabels(mergeRequest, mergeRequestUpdate.Labels);
SetLabels(mergeRequest, mergeRequestUpdate.Labels, mergeRequestUpdate.AddLabels, mergeRequestUpdate.RemoveLabels);

mergeRequest.UpdatedAt = DateTimeOffset.UtcNow;
return mergeRequest.ToMergeRequestClient();
Expand All @@ -681,5 +714,38 @@ public IMergeRequestDiscussionClient Discussions(int mergeRequestIid)

return new MergeRequestDiscussionClient(Context, _projectId.GetValueOrDefault(), mergeRequestIid);
}

public GitLabCollectionResponse<Models.ResourceLabelEvent> ResourceLabelEventsAsync(int projectId, int mergeRequestIid)
{
using (Context.BeginOperationScope())
{
var mergeRequest = GetMergeRequest(projectId, mergeRequestIid);
var resourceLabelEvents = Server.ResourceLabelEvents.Get(mergeRequest.Id);

return GitLabCollectionResponse.Create(resourceLabelEvents.Select(rle => rle.ToClientResourceLabelEvent()));
}
}

public GitLabCollectionResponse<Models.ResourceMilestoneEvent> ResourceMilestoneEventsAsync(int projectId, int mergeRequestIid)
{
using (Context.BeginOperationScope())
{
var mergeRequest = GetMergeRequest(projectId, mergeRequestIid);
var resourceMilestoneEvents = Server.ResourceMilestoneEvents.Get(mergeRequest.Id);

return GitLabCollectionResponse.Create(resourceMilestoneEvents.Select(rme => rme.ToClientResourceMilestoneEvent()));
}
}

public GitLabCollectionResponse<Models.ResourceStateEvent> ResourceStateEventsAsync(int projectId, int mergeRequestIid)
{
using (Context.BeginOperationScope())
{
var mergeRequest = GetMergeRequest(projectId, mergeRequestIid);
var resourceStateEvents = Server.ResourceStateEvents.Get(mergeRequest.Id);

return GitLabCollectionResponse.Create(resourceStateEvents.Select(rle => rle.ToClientResourceStateEvent()));
}
}
}
}
Loading