diff --git a/NGitLab.Mock.Tests/MergeRequestsMockTests.cs b/NGitLab.Mock.Tests/MergeRequestsMockTests.cs index af62b06e..c59f0839 100644 --- a/NGitLab.Mock.Tests/MergeRequestsMockTests.cs +++ b/NGitLab.Mock.Tests/MergeRequestsMockTests.cs @@ -412,4 +412,28 @@ public void Test_merge_request_resource_milestone_events_found() Assert.That(addMilestoneEvents[0].Milestone.Id, Is.EqualTo(milestones[0].Id)); Assert.That(addMilestoneEvents[1].Milestone.Id, Is.EqualTo(milestones[1].Id)); } + + [Test] + public void Test_merge_requests_from_group() + { + var groupId = 12; + using var server = new GitLabConfig() + .WithUser("user1", isDefault: true) + .WithUser("user2") + .WithGroup("parentGroup", configure: group => group.Id = groupId) + .WithProject("project1", @namespace: "parentGroup", configure: project => project + .WithMergeRequest("branch-01", title: "Merge request 1", author: "user1", assignee: "user2") + .WithMergeRequest("branch-02", title: "Merge request 2", author: "user2", assignee: "user1")) + .WithProject("project2", @namespace: "parentGroup", configure: project => project + .WithMergeRequest("branch-03", title: "Merge request 3", author: "user1", assignee: "user2") + .WithMergeRequest("branch-04", title: "Merge request 4", author: "user2", assignee: "user1")) + .BuildServer(); + + var client = server.CreateClient("user1"); + var mrClient = client.GetGroupMergeRequest(groupId); + var mergeRequests = mrClient.Get(new MergeRequestQuery()).ToArray(); + + Assert.That(mergeRequests, Has.Length.EqualTo(4), "Merge requests count is invalid"); + Assert.That(mergeRequests[0].Title, Is.EqualTo("Merge request 1"), "Merge request found is invalid"); + } } diff --git a/NGitLab.Mock/Clients/GitLabClient.cs b/NGitLab.Mock/Clients/GitLabClient.cs index ba0fbe09..515d85ff 100644 --- a/NGitLab.Mock/Clients/GitLabClient.cs +++ b/NGitLab.Mock/Clients/GitLabClient.cs @@ -92,6 +92,10 @@ public IGraphQLClient GraphQL public IMergeRequestClient GetMergeRequest(ProjectId projectId) => new MergeRequestClient(Context, projectId); + public IMergeRequestClient GetGroupMergeRequest(int groupId) => GetGroupMergeRequest((long)groupId); + + public IMergeRequestClient GetGroupMergeRequest(GroupId groupId) => new MergeRequestClient(Context, groupId); + public IMilestoneClient GetMilestone(int projectId) => GetMilestone((long)projectId); public IMilestoneClient GetMilestone(ProjectId projectId) => new MilestoneClient(Context, projectId, MilestoneScope.Projects); diff --git a/NGitLab.Mock/Clients/MergeRequestClient.cs b/NGitLab.Mock/Clients/MergeRequestClient.cs index 38ea22dc..719ea977 100644 --- a/NGitLab.Mock/Clients/MergeRequestClient.cs +++ b/NGitLab.Mock/Clients/MergeRequestClient.cs @@ -13,6 +13,7 @@ namespace NGitLab.Mock.Clients; internal sealed class MergeRequestClient : ClientBase, IMergeRequestClient { private readonly int? _projectId; + private readonly int? _groupId; public MergeRequestClient(ClientContext context) : base(context) @@ -25,6 +26,12 @@ public MergeRequestClient(ClientContext context, ProjectId projectId) _projectId = Server.AllProjects.FindProject(projectId.ValueAsUriParameter()).Id; } + public MergeRequestClient(ClientContext context, GroupId groupId) + : base(context) + { + _groupId = Server.AllGroups.FindGroup(groupId.ValueAsUriParameter()).Id; + } + private void AssertProjectId() { if (_projectId == null) diff --git a/NGitLab/GitLabClient.cs b/NGitLab/GitLabClient.cs index 7bb19461..78506d6e 100644 --- a/NGitLab/GitLabClient.cs +++ b/NGitLab/GitLabClient.cs @@ -156,6 +156,12 @@ public IMergeRequestClient GetMergeRequest(int projectId) public IMergeRequestClient GetMergeRequest(ProjectId projectId) => new MergeRequestClient(_api, projectId); + public IMergeRequestClient GetGroupMergeRequest(int groupId) + => GetGroupMergeRequest((long)groupId); + + public IMergeRequestClient GetGroupMergeRequest(GroupId groupId) + => new MergeRequestClient(groupId, _api); + public IMilestoneClient GetMilestone(int projectId) => GetMilestone((long)projectId); diff --git a/NGitLab/IGitLabClient.cs b/NGitLab/IGitLabClient.cs index 0515a1e0..84b9bd7f 100644 --- a/NGitLab/IGitLabClient.cs +++ b/NGitLab/IGitLabClient.cs @@ -79,6 +79,11 @@ public interface IGitLabClient IMergeRequestClient GetMergeRequest(ProjectId projectId); + [EditorBrowsable(EditorBrowsableState.Never)] + IMergeRequestClient GetGroupMergeRequest(int groupId); + + IMergeRequestClient GetGroupMergeRequest(GroupId groupId); + [EditorBrowsable(EditorBrowsableState.Never)] IMilestoneClient GetMilestone(int projectId); diff --git a/NGitLab/Impl/MergeRequestClient.cs b/NGitLab/Impl/MergeRequestClient.cs index 81e9122b..2a222655 100644 --- a/NGitLab/Impl/MergeRequestClient.cs +++ b/NGitLab/Impl/MergeRequestClient.cs @@ -14,7 +14,7 @@ public class MergeRequestClient : IMergeRequestClient private const string ResourceLabelEventUrl = "/projects/{0}/merge_requests/{1}/resource_label_events"; private const string ResourceMilestoneEventUrl = "/projects/{0}/merge_requests/{1}/resource_milestone_events"; private const string ResourceStateEventUrl = "/projects/{0}/merge_requests/{1}/resource_state_events"; - private readonly string _projectPath; + private readonly string _path; private readonly API _api; [EditorBrowsable(EditorBrowsableState.Never)] @@ -26,13 +26,25 @@ public MergeRequestClient(API api, int projectId) public MergeRequestClient(API api, ProjectId projectId) { _api = api; - _projectPath = $"{Project.Url}/{projectId.ValueAsUriParameter()}"; + _path = $"{Project.Url}/{projectId.ValueAsUriParameter()}"; + } + + [EditorBrowsable(EditorBrowsableState.Never)] + public MergeRequestClient(int groupId, API api) + : this(groupId: (long)groupId, api) + { + } + + public MergeRequestClient(GroupId groupId, API api) + { + _api = api; + _path = $"{Group.Url}/{groupId.ValueAsUriParameter()}"; } public MergeRequestClient(API api) { _api = api; - _projectPath = string.Empty; + _path = string.Empty; } public IEnumerable All => Get(new MergeRequestQuery()); @@ -41,7 +53,7 @@ public MergeRequestClient(API api) public IEnumerable Get(MergeRequestQuery query) { - var url = _projectPath + MergeRequest.Url; + var url = _path + MergeRequest.Url; url = Utils.AddParameter(url, "state", query.State); url = Utils.AddParameter(url, "order_by", query.OrderBy); @@ -71,7 +83,7 @@ public MergeRequest this[int iid] { get { - var url = $"{_projectPath}{MergeRequest.Url}/{iid.ToStringInvariant()}"; + var url = $"{_path}{MergeRequest.Url}/{iid.ToStringInvariant()}"; url = Utils.AddParameter(url, "include_rebase_in_progress", value: true); url = Utils.AddParameter(url, "include_diverged_commits_count", value: true); @@ -81,7 +93,7 @@ public MergeRequest this[int iid] public Task GetByIidAsync(int iid, SingleMergeRequestQuery options, CancellationToken cancellationToken = default) { - var url = $"{_projectPath}{MergeRequest.Url}/{iid.ToStringInvariant()}"; + var url = $"{_path}{MergeRequest.Url}/{iid.ToStringInvariant()}"; if (options != null) { url = Utils.AddParameter(url, "include_rebase_in_progress", options.IncludeRebaseInProgress); @@ -99,83 +111,83 @@ public MergeRequest Create(MergeRequestCreate mergeRequest) return _api .Post().With(mergeRequest) - .To(_projectPath + "/merge_requests"); + .To(_path + "/merge_requests"); } public MergeRequest Update(int mergeRequestIid, MergeRequestUpdate mergeRequest) => _api .Put().With(mergeRequest) - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture)); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture)); public MergeRequest Close(int mergeRequestIid) => _api .Put().With(new MergeRequestUpdateState { NewState = nameof(MergeRequestStateEvent.close) }) - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture)); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture)); public MergeRequest Reopen(int mergeRequestIid) => _api .Put().With(new MergeRequestUpdateState { NewState = nameof(MergeRequestStateEvent.reopen) }) - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture)); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture)); public void Delete(int mergeRequestIid) => _api .Delete() - .Execute(_projectPath + "/merge_requests/" + mergeRequestIid.ToStringInvariant()); + .Execute(_path + "/merge_requests/" + mergeRequestIid.ToStringInvariant()); public MergeRequest CancelMergeWhenPipelineSucceeds(int mergeRequestIid) => _api .Post() - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/cancel_merge_when_pipeline_succeeds"); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/cancel_merge_when_pipeline_succeeds"); public MergeRequest Accept(int mergeRequestIid, MergeRequestAccept message) => _api .Put().With(message) - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/merge"); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/merge"); public MergeRequest Accept(int mergeRequestIid, MergeRequestMerge message) => _api .Put().With(message) - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/merge"); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/merge"); public MergeRequest Approve(int mergeRequestIid, MergeRequestApprove message) => _api .Post().With(message) - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/approve"); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/approve"); public RebaseResult Rebase(int mergeRequestIid) => _api .Put() - .To(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/rebase"); + .To(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/rebase"); public Task RebaseAsync(int mergeRequestIid, MergeRequestRebase options, CancellationToken cancellationToken = default) => _api .Put().With(options) - .ToAsync(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/rebase", cancellationToken); + .ToAsync(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/rebase", cancellationToken); public IEnumerable GetPipelines(int mergeRequestIid) { - return _api.Get().GetAll(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/pipelines"); + return _api.Get().GetAll(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/pipelines"); } public IEnumerable GetParticipants(int mergeRequestIid) { - return _api.Get().GetAll(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/participants"); + return _api.Get().GetAll(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/participants"); } public IEnumerable ClosesIssues(int mergeRequestIid) { - return _api.Get().GetAll(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/closes_issues"); + return _api.Get().GetAll(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/closes_issues"); } public GitLabCollectionResponse GetVersionsAsync(int mergeRequestIid) { - return _api.Get().GetAllAsync(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/versions"); + return _api.Get().GetAllAsync(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/versions"); } public Task TimeStatsAsync(int mergeRequestIid, CancellationToken cancellationToken = default) { - return _api.Get().ToAsync(_projectPath + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/time_stats", cancellationToken); + return _api.Get().ToAsync(_path + "/merge_requests/" + mergeRequestIid.ToString(CultureInfo.InvariantCulture) + "/time_stats", cancellationToken); } - public IMergeRequestCommentClient Comments(int mergeRequestIid) => new MergeRequestCommentClient(_api, _projectPath, mergeRequestIid); + public IMergeRequestCommentClient Comments(int mergeRequestIid) => new MergeRequestCommentClient(_api, _path, mergeRequestIid); - public IMergeRequestDiscussionClient Discussions(int mergeRequestIid) => new MergeRequestDiscussionClient(_api, _projectPath, mergeRequestIid); + public IMergeRequestDiscussionClient Discussions(int mergeRequestIid) => new MergeRequestDiscussionClient(_api, _path, mergeRequestIid); - public IMergeRequestCommitClient Commits(int mergeRequestIid) => new MergeRequestCommitClient(_api, _projectPath, mergeRequestIid); + public IMergeRequestCommitClient Commits(int mergeRequestIid) => new MergeRequestCommitClient(_api, _path, mergeRequestIid); - public IMergeRequestApprovalClient ApprovalClient(int mergeRequestIid) => new MergeRequestApprovalClient(_api, _projectPath, mergeRequestIid); + public IMergeRequestApprovalClient ApprovalClient(int mergeRequestIid) => new MergeRequestApprovalClient(_api, _path, mergeRequestIid); - public IMergeRequestChangeClient Changes(int mergeRequestIid) => new MergeRequestChangeClient(_api, _projectPath, mergeRequestIid); + public IMergeRequestChangeClient Changes(int mergeRequestIid) => new MergeRequestChangeClient(_api, _path, mergeRequestIid); public GitLabCollectionResponse ResourceLabelEventsAsync(int projectId, int mergeRequestIid) { diff --git a/NGitLab/PublicAPI.Unshipped.txt b/NGitLab/PublicAPI.Unshipped.txt index db79fa31..f2bd1505 100644 --- a/NGitLab/PublicAPI.Unshipped.txt +++ b/NGitLab/PublicAPI.Unshipped.txt @@ -54,6 +54,8 @@ NGitLab.GitLabClient.GetEnvironmentClient(NGitLab.Models.ProjectId projectId) -> NGitLab.GitLabClient.GetEvents() -> NGitLab.IEventClient NGitLab.GitLabClient.GetGroupBadgeClient(int groupId) -> NGitLab.IGroupBadgeClient NGitLab.GitLabClient.GetGroupBadgeClient(NGitLab.Models.GroupId groupId) -> NGitLab.IGroupBadgeClient +NGitLab.GitLabClient.GetGroupMergeRequest(int groupId) -> NGitLab.IMergeRequestClient +NGitLab.GitLabClient.GetGroupMergeRequest(NGitLab.Models.GroupId groupId) -> NGitLab.IMergeRequestClient NGitLab.GitLabClient.GetGroupMilestone(int groupId) -> NGitLab.IMilestoneClient NGitLab.GitLabClient.GetGroupMilestone(NGitLab.Models.GroupId groupId) -> NGitLab.IMilestoneClient NGitLab.GitLabClient.GetGroupSearchClient(int groupId) -> NGitLab.ISearchClient @@ -195,6 +197,8 @@ NGitLab.IGitLabClient.GetEnvironmentClient(NGitLab.Models.ProjectId projectId) - NGitLab.IGitLabClient.GetEvents() -> NGitLab.IEventClient NGitLab.IGitLabClient.GetGroupBadgeClient(int groupId) -> NGitLab.IGroupBadgeClient NGitLab.IGitLabClient.GetGroupBadgeClient(NGitLab.Models.GroupId groupId) -> NGitLab.IGroupBadgeClient +NGitLab.IGitLabClient.GetGroupMergeRequest(int groupId) -> NGitLab.IMergeRequestClient +NGitLab.IGitLabClient.GetGroupMergeRequest(NGitLab.Models.GroupId groupId) -> NGitLab.IMergeRequestClient NGitLab.IGitLabClient.GetGroupMilestone(int groupId) -> NGitLab.IMilestoneClient NGitLab.IGitLabClient.GetGroupMilestone(NGitLab.Models.GroupId groupId) -> NGitLab.IMilestoneClient NGitLab.IGitLabClient.GetGroupSearchClient(int groupId) -> NGitLab.ISearchClient @@ -670,9 +674,11 @@ NGitLab.Impl.MergeRequestClient.GetByIidAsync(int iid, NGitLab.Models.SingleMerg NGitLab.Impl.MergeRequestClient.GetParticipants(int mergeRequestIid) -> System.Collections.Generic.IEnumerable NGitLab.Impl.MergeRequestClient.GetPipelines(int mergeRequestIid) -> System.Collections.Generic.IEnumerable NGitLab.Impl.MergeRequestClient.GetVersionsAsync(int mergeRequestIid) -> NGitLab.GitLabCollectionResponse +NGitLab.Impl.MergeRequestClient.MergeRequestClient(int groupId, NGitLab.Impl.API api) -> void NGitLab.Impl.MergeRequestClient.MergeRequestClient(NGitLab.Impl.API api) -> void NGitLab.Impl.MergeRequestClient.MergeRequestClient(NGitLab.Impl.API api, int projectId) -> void NGitLab.Impl.MergeRequestClient.MergeRequestClient(NGitLab.Impl.API api, NGitLab.Models.ProjectId projectId) -> void +NGitLab.Impl.MergeRequestClient.MergeRequestClient(NGitLab.Models.GroupId groupId, NGitLab.Impl.API api) -> void NGitLab.Impl.MergeRequestClient.Rebase(int mergeRequestIid) -> NGitLab.Models.RebaseResult NGitLab.Impl.MergeRequestClient.RebaseAsync(int mergeRequestIid, NGitLab.Models.MergeRequestRebase options, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> System.Threading.Tasks.Task NGitLab.Impl.MergeRequestClient.Reopen(int mergeRequestIid) -> NGitLab.Models.MergeRequest