Skip to content

Commit

Permalink
Add protected branches client (#24)
Browse files Browse the repository at this point in the history
Co-authored-by: Gérald Barré <[email protected]>
Co-authored-by: Louis Zanella <[email protected]>
  • Loading branch information
3 people authored Jun 21, 2021
1 parent c08a5d0 commit b52d08d
Show file tree
Hide file tree
Showing 12 changed files with 207 additions and 3 deletions.
5 changes: 5 additions & 0 deletions NGitLab.Mock/Clients/GitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,5 +83,10 @@ public IEventClient GetProjectEvents(int projectId)
public IWikiClient GetWikiClient(int projectId) => new WikiClient(Context, projectId);

public IProjectLevelApprovalRulesClient GetProjectLevelApprovalRulesClient(int projectId) => new ProjectLevelApprovalRulesClient(Context, projectId);

public IProtectedBranchClient GetProtectedBranchClient(int projectId)
{
throw new System.NotImplementedException();
}
}
}
66 changes: 66 additions & 0 deletions NGitLab.Tests/ProtectedBranchTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System.Threading.Tasks;
using NGitLab.Models;
using NGitLab.Tests.Docker;
using NUnit.Framework;

namespace NGitLab.Tests
{
public class ProtectedBranchTests
{
[Test]
public async Task ProtectBranch_Test()
{
using var context = await GitLabTestContext.CreateAsync();
var project = context.CreateProject(initializeWithCommits: true);
var branchClient = context.Client.GetRepository(project.Id).Branches;
var branch = branchClient.Create(new BranchCreate() { Name = "protectedBranch", Ref = project.DefaultBranch });
var protectedBranchClient = context.Client.GetProtectedBranchClient(project.Id);
var branchProtect = new BranchProtect(branch.Name)
{
PushAccessLevel = AccessLevel.Maintainer,
MergeAccessLevel = AccessLevel.NoAccess,
AllowForcePush = true,
AllowedToPush = new AccessLevelInfo[]
{
new AccessLevelInfo()
{
AccessLevel = AccessLevel.Admin,
Description = "Admin",
},
},
AllowedToUnprotect = new AccessLevelInfo[]
{
new AccessLevelInfo()
{
AccessLevel = AccessLevel.NoAccess,
Description = "Example",
},
},
};

// Protect branch
ProtectedBranchAndBranchProtectAreEquals(branchProtect, protectedBranchClient.ProtectBranch(branchProtect));

// Get branch
ProtectedBranchAndBranchProtectAreEquals(branchProtect, protectedBranchClient.GetProtectedBranch(branch.Name));

// Get branches
Assert.IsNotEmpty(protectedBranchClient.GetProtectedBranches());
var protectedBranches = protectedBranchClient.GetProtectedBranches(branch.Name);
Assert.IsNotEmpty(protectedBranches);
ProtectedBranchAndBranchProtectAreEquals(branchProtect, protectedBranches[0]);

// Unprotect branch
protectedBranchClient.UnprotectBranch(branch.Name);
Assert.IsEmpty(protectedBranchClient.GetProtectedBranches(branch.Name));
}

private void ProtectedBranchAndBranchProtectAreEquals(BranchProtect branchProtect, ProtectedBranch protectedBranch)
{
Assert.AreEqual(branchProtect.BranchName, protectedBranch.Name);
Assert.AreEqual(branchProtect.PushAccessLevel, protectedBranch.PushAccessLevels[0].AccessLevel);
Assert.AreEqual(branchProtect.MergeAccessLevel, protectedBranch.MergeAccessLevels[0].AccessLevel);
Assert.AreEqual(branchProtect.AllowForcePush, protectedBranch.AllowForcePush);
}
}
}
3 changes: 3 additions & 0 deletions NGitLab/GitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -191,5 +191,8 @@ public IProjectLevelApprovalRulesClient GetProjectLevelApprovalRulesClient(int p
{
return new ProjectLevelApprovalRulesClient(_api, projectId);
}

public IProtectedBranchClient GetProtectedBranchClient(int projectId)
=> new ProtectedBranchClient(_api, projectId);
}
}
2 changes: 1 addition & 1 deletion NGitLab/IBranchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ public interface IBranchClient

void Delete(string name);
}
}
}
2 changes: 2 additions & 0 deletions NGitLab/IGitLabClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,5 +79,7 @@ public interface IGitLabClient
IGroupVariableClient GetGroupVariableClient(int groupId);

IProjectLevelApprovalRulesClient GetProjectLevelApprovalRulesClient(int projectId);

IProtectedBranchClient GetProtectedBranchClient(int projectId);
}
}
15 changes: 15 additions & 0 deletions NGitLab/IProtectedBranchClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using NGitLab.Models;

namespace NGitLab
{
public interface IProtectedBranchClient
{
ProtectedBranch ProtectBranch(BranchProtect branchProtect);

void UnprotectBranch(string branchName);

ProtectedBranch GetProtectedBranch(string branchName);

ProtectedBranch[] GetProtectedBranches(string search = null);
}
}
2 changes: 1 addition & 1 deletion NGitLab/Impl/BranchClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,4 @@ public BranchClient(API api, string repoPath)

public void Delete(string name) => _api.Delete().Execute(_repoPath + "/branches/" + Uri.EscapeDataString(name));
}
}
}
31 changes: 31 additions & 0 deletions NGitLab/Impl/ProtectedBranchClient.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System;
using NGitLab.Models;

namespace NGitLab.Impl
{
internal sealed class ProtectedBranchClient : IProtectedBranchClient
{
private readonly API _api;
private readonly int _projectId;
private readonly string _protectedBranchesUrl;

public ProtectedBranchClient(API api, int projectId)
{
_api = api;
_projectId = projectId;
_protectedBranchesUrl = $"{Project.Url}/{_projectId}/protected_branches";
}

public ProtectedBranch ProtectBranch(BranchProtect branchProtect)
=> _api.Post().With(branchProtect).To<ProtectedBranch>(_protectedBranchesUrl);

public void UnprotectBranch(string branchName)
=> _api.Delete().Execute($"{_protectedBranchesUrl}/{Uri.EscapeDataString(branchName)}");

public ProtectedBranch GetProtectedBranch(string branchName)
=> _api.Get().To<ProtectedBranch>($"{_protectedBranchesUrl}/{Uri.EscapeDataString(branchName)}");

public ProtectedBranch[] GetProtectedBranches(string search = null)
=> _api.Get().To<ProtectedBranch[]>(Utils.AddParameter(_protectedBranchesUrl, "search", search));
}
}
4 changes: 3 additions & 1 deletion NGitLab/Models/AccessLevel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace NGitLab.Models
/// <remarks>https://github.com/gitlabhq/gitlabhq/blob/master/doc/api/members.md</remarks>
public enum AccessLevel
{
NoAccess = 0,
Guest = 10,
Reporter = 20,
Developer = 30,
Expand All @@ -19,5 +20,6 @@ public enum AccessLevel
/// Only valid for groups.
/// </summary>
Owner = 50,
Admin = 60,
}
}
}
14 changes: 14 additions & 0 deletions NGitLab/Models/AccessLevelInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System.Runtime.Serialization;

namespace NGitLab.Models
{
[DataContract]
public class AccessLevelInfo
{
[DataMember(Name = "access_level")]
public AccessLevel AccessLevel { get; set; }

[DataMember(Name = "access_level_description")]
public string Description { get; set; }
}
}
40 changes: 40 additions & 0 deletions NGitLab/Models/BranchProtect.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System.Runtime.Serialization;

namespace NGitLab.Models
{
[DataContract]
public class BranchProtect
{
public BranchProtect(string branchName)
{
BranchName = branchName;
}

[DataMember(Name = "name")]
public string BranchName { get; set; }

[DataMember(Name = "push_access_level")]
public AccessLevel? PushAccessLevel { get; set; } = null;

[DataMember(Name = "merge_access_level")]
public AccessLevel? MergeAccessLevel { get; set; } = null;

[DataMember(Name = "unprotect_access_level")]
public AccessLevel? UnprotectAccessLevel { get; set; } = null;

[DataMember(Name = "allow_force_push")]
public bool AllowForcePush { get; set; } = false;

[DataMember(Name = "allowed_to_merge")]
public AccessLevelInfo[] AllowedToMerge { get; set; }

[DataMember(Name = "allowed_to_push")]
public AccessLevelInfo[] AllowedToPush { get; set; }

[DataMember(Name = "allowed_to_unprotect")]
public AccessLevelInfo[] AllowedToUnprotect { get; set; }

[DataMember(Name = "code_owner_approval_required")]
public bool CodeOwnerApprovalRequired { get; set; } = false;
}
}
26 changes: 26 additions & 0 deletions NGitLab/Models/ProtectedBranch.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Runtime.Serialization;

namespace NGitLab.Models
{
[DataContract]
public class ProtectedBranch
{
[DataMember(Name = "id")]
public long Id { get; set; }

[DataMember(Name = "name")]
public string Name { get; set; }

[DataMember(Name = "push_access_levels")]
public AccessLevelInfo[] PushAccessLevels { get; set; }

[DataMember(Name = "merge_access_levels")]
public AccessLevelInfo[] MergeAccessLevels { get; set; }

[DataMember(Name = "allow_force_push")]
public bool AllowForcePush { get; set; }

[DataMember(Name = "code_owner_approval_required")]
public bool CodeOwnerApprovalRequired { get; set; }
}
}

0 comments on commit b52d08d

Please sign in to comment.