Skip to content

Commit a073f36

Browse files
committed
Add branch protection support for allow_force_push
Issue 709 requested the `allow_force_push` option to be added to the branch protection resource. These changes add that feature, along with the appropriate tests. The API does not support updating the allow force push configuration, so any changes will force a new resource to be created.
1 parent e3a911c commit a073f36

File tree

4 files changed

+126
-0
lines changed

4 files changed

+126
-0
lines changed

docs/resources/branch_protection.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ resource "gitlab_branch_protection" "BranchProtect" {
2121
branch = "BranchProtected"
2222
push_access_level = "developer"
2323
merge_access_level = "developer"
24+
allow_force_push = true
2425
code_owner_approval_required = true
2526
allowed_to_push {
2627
user_id = 5
@@ -64,6 +65,7 @@ resource "gitlab_branch_protection" "main" {
6465

6566
### Optional
6667

68+
- **allow_force_push** (Boolean) Can be set to true to allow users with push access to force push.
6769
- **allowed_to_merge** (Block Set) Defines permissions for action. (see [below for nested schema](#nestedblock--allowed_to_merge))
6870
- **allowed_to_push** (Block Set) Defines permissions for action. (see [below for nested schema](#nestedblock--allowed_to_push))
6971
- **code_owner_approval_required** (Boolean) Can be set to true to require code owner approval before merging.

examples/resources/gitlab_branch_protection/resource.tf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ resource "gitlab_branch_protection" "BranchProtect" {
33
branch = "BranchProtected"
44
push_access_level = "developer"
55
merge_access_level = "developer"
6+
allow_force_push = true
67
code_owner_approval_required = true
78
allowed_to_push {
89
user_id = 5

internal/provider/resource_gitlab_branch_protection.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,13 @@ var _ = registerResource("gitlab_branch_protection", func() *schema.Resource {
7878
Required: true,
7979
ForceNew: true,
8080
},
81+
"allow_force_push": {
82+
Description: "Can be set to true to allow users with push access to force push.",
83+
Type: schema.TypeBool,
84+
Optional: true,
85+
Default: false,
86+
ForceNew: true,
87+
},
8188
"allowed_to_push": schemaAllowedTo(),
8289
"allowed_to_merge": schemaAllowedTo(),
8390
"code_owner_approval_required": {
@@ -114,6 +121,7 @@ func resourceGitlabBranchProtectionCreate(ctx context.Context, d *schema.Resourc
114121

115122
mergeAccessLevel := accessLevelNameToValue[d.Get("merge_access_level").(string)]
116123
pushAccessLevel := accessLevelNameToValue[d.Get("push_access_level").(string)]
124+
allowForcePush := d.Get("allow_force_push").(bool)
117125
codeOwnerApprovalRequired := d.Get("code_owner_approval_required").(bool)
118126

119127
allowedToPush := expandBranchPermissionOptions(d.Get("allowed_to_push").(*schema.Set).List())
@@ -123,6 +131,7 @@ func resourceGitlabBranchProtectionCreate(ctx context.Context, d *schema.Resourc
123131
Name: &branch,
124132
PushAccessLevel: &pushAccessLevel,
125133
MergeAccessLevel: &mergeAccessLevel,
134+
AllowForcePush: &allowForcePush,
126135
AllowedToPush: &allowedToPush,
127136
AllowedToMerge: &allowedToMerge,
128137
CodeOwnerApprovalRequired: &codeOwnerApprovalRequired,
@@ -174,6 +183,10 @@ func resourceGitlabBranchProtectionRead(ctx context.Context, d *schema.ResourceD
174183
}
175184
}
176185

186+
if err := d.Set("allow_force_push", pb.AllowForcePush); err != nil {
187+
return diag.Errorf("error setting allow_force_push: %v", err)
188+
}
189+
177190
// lintignore: R004 // TODO: Resolve this tfproviderlint issue
178191
if err := d.Set("allowed_to_push", convertAllowedToToBranchAccessDescriptions(pb.PushAccessLevels)); err != nil {
179192
return diag.Errorf("error setting allowed_to_push: %v", err)

internal/provider/resource_gitlab_branch_protection_test.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,33 @@ func TestAccGitlabBranchProtection_basic(t *testing.T) {
6262
}),
6363
),
6464
},
65+
// Update the Branch Protection with allow force push enabled
66+
{
67+
Config: testAccGitlabBranchProtectionUpdateConfigAllowForcePushTrue(rInt),
68+
Check: resource.ComposeTestCheckFunc(
69+
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.branch_protect", &pb),
70+
testAccCheckGitlabBranchProtectionPersistsInStateCorrectly("gitlab_branch_protection.branch_protect", &pb),
71+
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
72+
Name: fmt.Sprintf("BranchProtect-%d", rInt),
73+
PushAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
74+
MergeAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
75+
AllowForcePush: true,
76+
}),
77+
),
78+
},
79+
// Update the Branch Protection to get back to initial settings
80+
{
81+
Config: testAccGitlabBranchProtectionConfig(rInt),
82+
Check: resource.ComposeTestCheckFunc(
83+
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.branch_protect", &pb),
84+
testAccCheckGitlabBranchProtectionPersistsInStateCorrectly("gitlab_branch_protection.branch_protect", &pb),
85+
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
86+
Name: fmt.Sprintf("BranchProtect-%d", rInt),
87+
PushAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
88+
MergeAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
89+
}),
90+
),
91+
},
6592
// Update the the Branch Protection code owner approval setting
6693
{
6794
SkipFunc: isRunningInCE,
@@ -180,6 +207,59 @@ func TestAccGitlabBranchProtection_createWithCodeOwnerApproval(t *testing.T) {
180207
})
181208
}
182209

210+
func TestAccGitlabBranchProtection_createWithAllowForcePush(t *testing.T) {
211+
var pb gitlab.ProtectedBranch
212+
rInt := acctest.RandInt()
213+
214+
resource.Test(t, resource.TestCase{
215+
PreCheck: func() { testAccPreCheck(t) },
216+
ProviderFactories: providerFactories,
217+
CheckDestroy: testAccCheckGitlabBranchProtectionDestroy,
218+
Steps: []resource.TestStep{
219+
// Start with allow force push disabled
220+
{
221+
Config: testAccGitlabBranchProtectionConfig(rInt),
222+
Check: resource.ComposeTestCheckFunc(
223+
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.branch_protect", &pb),
224+
testAccCheckGitlabBranchProtectionPersistsInStateCorrectly("gitlab_branch_protection.branch_protect", &pb),
225+
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
226+
Name: fmt.Sprintf("BranchProtect-%d", rInt),
227+
PushAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
228+
MergeAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
229+
}),
230+
),
231+
},
232+
// Create a project and Branch Protection with allow force push enabled
233+
{
234+
Config: testAccGitlabBranchProtectionUpdateConfigAllowForcePushTrue(rInt),
235+
Check: resource.ComposeTestCheckFunc(
236+
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.branch_protect", &pb),
237+
testAccCheckGitlabBranchProtectionPersistsInStateCorrectly("gitlab_branch_protection.branch_protect", &pb),
238+
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
239+
Name: fmt.Sprintf("BranchProtect-%d", rInt),
240+
PushAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
241+
MergeAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
242+
AllowForcePush: true,
243+
}),
244+
),
245+
},
246+
// Update the Branch Protection to get back to initial settings
247+
{
248+
Config: testAccGitlabBranchProtectionConfig(rInt),
249+
Check: resource.ComposeTestCheckFunc(
250+
testAccCheckGitlabBranchProtectionExists("gitlab_branch_protection.branch_protect", &pb),
251+
testAccCheckGitlabBranchProtectionPersistsInStateCorrectly("gitlab_branch_protection.branch_protect", &pb),
252+
testAccCheckGitlabBranchProtectionAttributes(&pb, &testAccGitlabBranchProtectionExpectedAttributes{
253+
Name: fmt.Sprintf("BranchProtect-%d", rInt),
254+
PushAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
255+
MergeAccessLevel: accessLevelValueToName[gitlab.DeveloperPermissions],
256+
}),
257+
),
258+
},
259+
},
260+
})
261+
}
262+
183263
func TestAccGitlabBranchProtection_createWithMultipleAccessLevels(t *testing.T) {
184264
var pb gitlab.ProtectedBranch
185265
rInt := acctest.RandInt()
@@ -258,6 +338,10 @@ func testAccCheckGitlabBranchProtectionPersistsInStateCorrectly(n string, pb *gi
258338
return fmt.Errorf("push access level not persisted in state correctly")
259339
}
260340

341+
if rs.Primary.Attributes["allow_force_push"] != strconv.FormatBool(pb.AllowForcePush) {
342+
return fmt.Errorf("allow_force_push not persisted in state correctly")
343+
}
344+
261345
if rs.Primary.Attributes["code_owner_approval_required"] != strconv.FormatBool(pb.CodeOwnerApprovalRequired) {
262346
return fmt.Errorf("code_owner_approval_required not persisted in state correctly")
263347
}
@@ -301,6 +385,7 @@ type testAccGitlabBranchProtectionExpectedAttributes struct {
301385
Name string
302386
PushAccessLevel string
303387
MergeAccessLevel string
388+
AllowForcePush bool
304389
UsersAllowedToPush []string
305390
UsersAllowedToMerge []string
306391
GroupsAllowedToPush []string
@@ -336,6 +421,10 @@ func testAccCheckGitlabBranchProtectionAttributes(pb *gitlab.ProtectedBranch, wa
336421
return fmt.Errorf("got Merge access level %v; want %v", mergeAccessLevel, accessLevelNameToValue[want.MergeAccessLevel])
337422
}
338423

424+
if pb.AllowForcePush != want.AllowForcePush {
425+
return fmt.Errorf("got allow_force_push %v; want %v", pb.AllowForcePush, want.AllowForcePush)
426+
}
427+
339428
remainingWantedUserIDsAllowedToPush := map[int]struct{}{}
340429
for _, v := range want.UsersAllowedToPush {
341430
users, _, err := testGitlabClient.Users.ListUsers(&gitlab.ListUsersOptions{
@@ -448,6 +537,27 @@ resource "gitlab_branch_protection" "branch_protect" {
448537
`, rInt)
449538
}
450539

540+
func testAccGitlabBranchProtectionUpdateConfigAllowForcePushTrue(rInt int) string {
541+
return fmt.Sprintf(`
542+
resource "gitlab_project" "foo" {
543+
name = "foo-%[1]d"
544+
description = "Terraform acceptance tests"
545+
546+
# So that acceptance tests can be run in a gitlab organization
547+
# with no billing
548+
visibility_level = "public"
549+
}
550+
551+
resource "gitlab_branch_protection" "branch_protect" {
552+
project = gitlab_project.foo.id
553+
branch = "BranchProtect-%[1]d"
554+
push_access_level = "developer"
555+
merge_access_level = "developer"
556+
allow_force_push = true
557+
}
558+
`, rInt)
559+
}
560+
451561
func testAccGitlabBranchProtectionUpdateConfigCodeOwnerTrue(rInt int) string {
452562
return fmt.Sprintf(`
453563
resource "gitlab_project" "foo" {

0 commit comments

Comments
 (0)