Skip to content

Commit

Permalink
[FEAT] Add support for "Require approval of the most recent reviewabl…
Browse files Browse the repository at this point in the history
…e push" (#2839)

Add support for "Require approval of the most recent reviewable push"

Co-authored-by: Nick Floyd <139819+nickfloyd@users.noreply.github.com>
  • Loading branch information
ChrisAnn and nickfloyd committed Jan 3, 2024
1 parent 3e92a69 commit b1a2cf5
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 10 deletions.
18 changes: 18 additions & 0 deletions Octokit.Tests.Integration/Clients/RepositoryBranchesClientTests.cs
Expand Up @@ -292,6 +292,7 @@ public async Task GetsBranchProtection()
Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions);
Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireLastPushApproval);

Assert.Null(protection.Restrictions);

Expand Down Expand Up @@ -320,6 +321,7 @@ public async Task GetsBranchProtectionWithRepositoryId()
Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions);
Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireLastPushApproval);

Assert.Null(protection.Restrictions);

Expand Down Expand Up @@ -349,6 +351,7 @@ public async Task GetsBranchProtectionForOrgRepo()
Assert.Equal(0, protection.RequiredPullRequestReviews.DismissalRestrictions.Users.Count);
Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireLastPushApproval);

Assert.Equal(1, protection.Restrictions.Teams.Count);
Assert.Equal(0, protection.Restrictions.Users.Count);
Expand All @@ -373,6 +376,7 @@ public async Task GetsBranchProtectionForOrgRepoWithRepositoryId()
Assert.Equal(0, protection.RequiredPullRequestReviews.DismissalRestrictions.Users.Count);
Assert.True(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireLastPushApproval);

Assert.Equal(1, protection.Restrictions.Teams.Count);
Assert.Equal(0, protection.Restrictions.Users.Count);
Expand Down Expand Up @@ -404,6 +408,7 @@ public async Task UpdatesBranchProtection()
Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions);
Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireLastPushApproval);
Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount);

Assert.Null(protection.Restrictions);
Expand Down Expand Up @@ -432,6 +437,7 @@ public async Task UpdatesBranchProtectionWithRepositoryId()
Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions);
Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.True(protection.RequiredPullRequestReviews.RequireLastPushApproval);
Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount);

Assert.Null(protection.Restrictions);
Expand Down Expand Up @@ -461,6 +467,7 @@ public async Task UpdatesBranchProtectionForOrgRepo()
Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions);
Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.False(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.False(protection.RequiredPullRequestReviews.RequireLastPushApproval);
Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount);

Assert.Empty(protection.Restrictions.Teams);
Expand Down Expand Up @@ -490,6 +497,7 @@ public async Task UpdatesBranchProtectionForOrgRepoWithRepositoryId()
Assert.Null(protection.RequiredPullRequestReviews.DismissalRestrictions);
Assert.False(protection.RequiredPullRequestReviews.DismissStaleReviews);
Assert.False(protection.RequiredPullRequestReviews.RequireCodeOwnerReviews);
Assert.False(protection.RequiredPullRequestReviews.RequireLastPushApproval);
Assert.Equal(2, protection.RequiredPullRequestReviews.RequiredApprovingReviewCount);

Assert.Empty(protection.Restrictions.Teams);
Expand Down Expand Up @@ -798,6 +806,7 @@ public async Task GetsReviewEnforcement()
Assert.Null(requiredReviews.DismissalRestrictions);
Assert.True(requiredReviews.DismissStaleReviews);
Assert.True(requiredReviews.RequireCodeOwnerReviews);
Assert.True(requiredReviews.RequireLastPushApproval);
}
}

Expand All @@ -813,6 +822,7 @@ public async Task GetsReviewEnforcementWithRepositoryId()
Assert.Null(requiredReviews.DismissalRestrictions);
Assert.True(requiredReviews.DismissStaleReviews);
Assert.True(requiredReviews.RequireCodeOwnerReviews);
Assert.True(requiredReviews.RequireLastPushApproval);
}
}

Expand All @@ -829,6 +839,7 @@ public async Task GetsReviewEnforcementForOrgRepo()
Assert.Equal(0, requiredReviews.DismissalRestrictions.Users.Count);
Assert.True(requiredReviews.DismissStaleReviews);
Assert.True(requiredReviews.RequireCodeOwnerReviews);
Assert.True(requiredReviews.RequireLastPushApproval);
}
}

Expand All @@ -845,6 +856,7 @@ public async Task GetsReviewEnforcementForOrgRepoWithRepositoryId()
Assert.Equal(0, requiredReviews.DismissalRestrictions.Users.Count);
Assert.True(requiredReviews.DismissStaleReviews);
Assert.True(requiredReviews.RequireCodeOwnerReviews);
Assert.True(requiredReviews.RequireLastPushApproval);
}
}
}
Expand All @@ -865,6 +877,7 @@ public async Task UpdatesReviewEnforcement()
Assert.Null(requiredReviews.DismissalRestrictions);
Assert.False(requiredReviews.DismissStaleReviews);
Assert.True(requiredReviews.RequireCodeOwnerReviews);
Assert.True(requiredReviews.RequireLastPushApproval);
Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount);
}
}
Expand All @@ -883,6 +896,7 @@ public async Task UpdatesReviewEnforcementWithRepositoryId()
Assert.Null(requiredReviews.DismissalRestrictions);
Assert.False(requiredReviews.DismissStaleReviews);
Assert.True(requiredReviews.RequireCodeOwnerReviews);
Assert.True(requiredReviews.RequireLastPushApproval);
Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount);
}
}
Expand All @@ -905,6 +919,7 @@ public async Task UpdatesReviewEnforcementForOrgRepo()
Assert.Null(requiredReviews.DismissalRestrictions);
Assert.False(requiredReviews.DismissStaleReviews);
Assert.False(requiredReviews.RequireCodeOwnerReviews);
Assert.False(requiredReviews.RequireLastPushApproval);
Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount);
}
}
Expand All @@ -927,6 +942,7 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithRepositoryId()
Assert.Null(requiredReviews.DismissalRestrictions);
Assert.False(requiredReviews.DismissStaleReviews);
Assert.False(requiredReviews.RequireCodeOwnerReviews);
Assert.False(requiredReviews.RequireLastPushApproval);
Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount);
}
}
Expand All @@ -950,6 +966,7 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnly()
Assert.Empty(requiredReviews.DismissalRestrictions.Users);
Assert.False(requiredReviews.DismissStaleReviews);
Assert.False(requiredReviews.RequireCodeOwnerReviews);
Assert.False(requiredReviews.RequireLastPushApproval);
Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount);
}
}
Expand All @@ -973,6 +990,7 @@ public async Task UpdatesReviewEnforcementForOrgRepoWithAdminOnlyWithRepositoryI
Assert.Empty(requiredReviews.DismissalRestrictions.Users);
Assert.False(requiredReviews.DismissStaleReviews);
Assert.False(requiredReviews.RequireCodeOwnerReviews);
Assert.False(requiredReviews.RequireLastPushApproval);
Assert.Equal(2, requiredReviews.RequiredApprovingReviewCount);
}
}
Expand Down
Expand Up @@ -28,7 +28,7 @@ internal async static Task ProtectDefaultBranch(this IGitHubClient client, Repos
// Protect default branch
var update = new BranchProtectionSettingsUpdate(
new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "build", "test" }),
new BranchProtectionRequiredReviewsUpdate(true, true, 3),
new BranchProtectionRequiredReviewsUpdate(true, true, 3, true),
null,
true,
true,
Expand Down Expand Up @@ -78,7 +78,7 @@ internal async static Task<TeamContext> ProtectDefaultBranchWithTeam(this IGitHu
// Protect default branch
var protection = new BranchProtectionSettingsUpdate(
new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "build", "test" }),
new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(new BranchProtectionTeamCollection { team.TeamName }), true, true, 3),
new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(new BranchProtectionTeamCollection { team.TeamName }), true, true, 3, true),
new BranchProtectionPushRestrictionsUpdate(new BranchProtectionTeamCollection { team.TeamName }),
true);
await client.Repository.Branch.UpdateBranchProtection(repoContext.RepositoryOwner, repoContext.RepositoryName, repoContext.RepositoryDefaultBranch, protection);
Expand All @@ -105,7 +105,7 @@ internal async static Task<OrganizationRepositoryWithTeamContext> CreateOrganiza
// Protect default branch
var protection = new BranchProtectionSettingsUpdate(
new BranchProtectionRequiredStatusChecksUpdate(true, new[] { "build", "test" }),
new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(new BranchProtectionTeamCollection { contextOrgTeam.TeamName }), true, true, 3),
new BranchProtectionRequiredReviewsUpdate(new BranchProtectionRequiredReviewsDismissalRestrictionsUpdate(new BranchProtectionTeamCollection { contextOrgTeam.TeamName }), true, true, 3, true),
new BranchProtectionPushRestrictionsUpdate(new BranchProtectionTeamCollection { contextOrgTeam.TeamName }),
true);
await client.Repository.Branch.UpdateBranchProtection(contextOrgRepo.RepositoryOwner, contextOrgRepo.RepositoryName, "main", protection);
Expand Down
18 changes: 14 additions & 4 deletions Octokit/Models/Request/BranchProtectionUpdate.cs
Expand Up @@ -370,11 +370,13 @@ public class BranchProtectionRequiredReviewsUpdate
/// <param name="dismissStaleReviews">Dismiss approved reviews automatically when a new commit is pushed.</param>
/// <param name="requireCodeOwnerReviews">Blocks merge until code owners have reviewed.</param>
/// <param name="requiredApprovingReviewCount">Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6.</param>
public BranchProtectionRequiredReviewsUpdate(bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount)
/// <param name="requireLastPushApproval">Whether the most recent push must be approved by someone other than the person who pushed it. Default: false.</param>
public BranchProtectionRequiredReviewsUpdate(bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount, bool requireLastPushApproval = false)
{
DismissStaleReviews = dismissStaleReviews;
RequireCodeOwnerReviews = requireCodeOwnerReviews;
RequiredApprovingReviewCount = requiredApprovingReviewCount;
RequireLastPushApproval = requireLastPushApproval;
}

/// <summary>
Expand All @@ -384,14 +386,16 @@ public BranchProtectionRequiredReviewsUpdate(bool dismissStaleReviews, bool requ
/// <param name="dismissStaleReviews">Dismiss approved reviews automatically when a new commit is pushed.</param>
/// <param name="requireCodeOwnerReviews">Blocks merge until code owners have reviewed.</param>
/// <param name="requiredApprovingReviewCount">Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6.</param>
public BranchProtectionRequiredReviewsUpdate(BranchProtectionRequiredReviewsDismissalRestrictionsUpdate dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount)
/// <param name="requireLastPushApproval">Whether the most recent push must be approved by someone other than the person who pushed it. Default: false.</param>
public BranchProtectionRequiredReviewsUpdate(BranchProtectionRequiredReviewsDismissalRestrictionsUpdate dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount, bool requireLastPushApproval = false)
{
Ensure.ArgumentNotNull(dismissalRestrictions, nameof(dismissalRestrictions));

DismissalRestrictions = dismissalRestrictions;
DismissStaleReviews = dismissStaleReviews;
RequireCodeOwnerReviews = requireCodeOwnerReviews;
RequiredApprovingReviewCount = requiredApprovingReviewCount;
RequireLastPushApproval = requireLastPushApproval;
}

/// <summary>
Expand All @@ -413,16 +417,22 @@ public BranchProtectionRequiredReviewsUpdate(BranchProtectionRequiredReviewsDism
/// Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6.
/// </summary>
public int RequiredApprovingReviewCount { get; protected set; }

/// <summary>
/// Whether the most recent push must be approved by someone other than the person who pushed it. Default: false
/// </summary>
public bool RequireLastPushApproval { get; protected set; }

internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2} RequiredApprovingReviewCount: {3}",
return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2} RequiredApprovingReviewCount: {3} RequireLastPushApproval: {4}",
DismissalRestrictions?.DebuggerDisplay ?? "disabled",
DismissStaleReviews,
RequireCodeOwnerReviews,
RequiredApprovingReviewCount);
RequiredApprovingReviewCount,
RequireLastPushApproval);
}
}
}
Expand Down
13 changes: 10 additions & 3 deletions Octokit/Models/Response/BranchProtection.cs
Expand Up @@ -236,12 +236,13 @@ public class BranchProtectionRequiredReviews
{
public BranchProtectionRequiredReviews() { }

public BranchProtectionRequiredReviews(BranchProtectionRequiredReviewsDismissalRestrictions dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount)
public BranchProtectionRequiredReviews(BranchProtectionRequiredReviewsDismissalRestrictions dismissalRestrictions, bool dismissStaleReviews, bool requireCodeOwnerReviews, int requiredApprovingReviewCount, bool requireLastPushApproval)
{
DismissalRestrictions = dismissalRestrictions;
DismissStaleReviews = dismissStaleReviews;
RequireCodeOwnerReviews = requireCodeOwnerReviews;
RequiredApprovingReviewCount = requiredApprovingReviewCount;
RequireLastPushApproval = requireLastPushApproval;
}

/// <summary>
Expand All @@ -263,16 +264,22 @@ public BranchProtectionRequiredReviews(BranchProtectionRequiredReviewsDismissalR
/// Specify the number of reviewers required to approve pull requests. Use a number between 1 and 6.
/// </summary>
public int RequiredApprovingReviewCount { get; private set; }

/// <summary>
/// Whether the most recent push must be approved by someone other than the person who pushed it. Default: false
/// </summary>
public bool RequireLastPushApproval { get; protected set; }

internal string DebuggerDisplay
{
get
{
return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2} RequiredApprovingReviewCount: {3}",
return string.Format(CultureInfo.InvariantCulture, "DismissalRestrictions: {0} DismissStaleReviews: {1} RequireCodeOwnerReviews: {2} RequiredApprovingReviewCount: {3} RequireLastPushApproval: {4}",
DismissalRestrictions?.DebuggerDisplay ?? "disabled",
DismissStaleReviews,
RequireCodeOwnerReviews,
RequiredApprovingReviewCount);
RequiredApprovingReviewCount,
RequireLastPushApproval);
}
}
}
Expand Down

0 comments on commit b1a2cf5

Please sign in to comment.