Verified Commit 62fafba7 authored by Patrick Rice's avatar Patrick Rice 🫖 Committed by GitLab
Browse files

Merge branch 'add_code_owner_approval_required' into 'main'

feat(groups): add code_owner_approval_required in a group's default_branch_protection_defaults

See merge request !2725
parents b1e8a478 a761b80f
Loading
Loading
Loading
Loading
Loading
+53 −0
Original line number Diff line number Diff line
@@ -166,3 +166,56 @@ func Test_GroupProtectedBranches_Integration(t *testing.T) {
	assert.Error(t, err)
	assert.Equal(t, 404, resp.StatusCode)
}

func Test_GroupsCreateGroup_CodeOwnerApprovalRequired_Integration(t *testing.T) {
	// GIVEN a GitLab client
	client := SetupIntegrationClient(t)

	// WHEN creating a group with CodeOwnerApprovalRequired enabled
	group, _, err := client.Groups.CreateGroup(&gitlab.CreateGroupOptions{
		Name: gitlab.Ptr("code-owner-create-test"),
		Path: gitlab.Ptr("code-owner-create-test"),
		DefaultBranchProtectionDefaults: &gitlab.DefaultBranchProtectionDefaultsOptions{
			CodeOwnerApprovalRequired: gitlab.Ptr(true),
		},
	})
	require.NoError(t, err, "Failed to create group")

	// THEN the setting should be enabled
	require.NotNil(t, group.DefaultBranchProtectionDefaults)
	assert.True(t, group.DefaultBranchProtectionDefaults.CodeOwnerApprovalRequired)

	// AND WHEN retrieving the group
	retrievedGroup, _, err := client.Groups.GetGroup(group.ID, nil)
	require.NoError(t, err)

	// THEN it should persist
	require.NotNil(t, retrievedGroup.DefaultBranchProtectionDefaults)
	assert.True(t, retrievedGroup.DefaultBranchProtectionDefaults.CodeOwnerApprovalRequired)
}

func Test_GroupsUpdateGroup_CodeOwnerApprovalRequired_Integration(t *testing.T) {
	// GIVEN a GitLab client and a test group
	client := SetupIntegrationClient(t)
	group := CreateTestGroup(t, client)

	// WHEN updating CodeOwnerApprovalRequired to true
	updatedGroup, _, err := client.Groups.UpdateGroup(group.ID, &gitlab.UpdateGroupOptions{
		DefaultBranchProtectionDefaults: &gitlab.DefaultBranchProtectionDefaultsOptions{
			CodeOwnerApprovalRequired: gitlab.Ptr(true),
		},
	})
	require.NoError(t, err)

	// THEN the update response should reflect the change
	require.NotNil(t, updatedGroup.DefaultBranchProtectionDefaults)
	assert.True(t, updatedGroup.DefaultBranchProtectionDefaults.CodeOwnerApprovalRequired)

	// AND WHEN retrieving the group again
	retrievedGroup, _, err := client.Groups.GetGroup(group.ID, nil)
	require.NoError(t, err)

	// THEN the setting should persist
	require.NotNil(t, retrievedGroup.DefaultBranchProtectionDefaults)
	assert.True(t, retrievedGroup.DefaultBranchProtectionDefaults.CodeOwnerApprovalRequired)
}
+14 −8
Original line number Diff line number Diff line
@@ -189,6 +189,7 @@ type BranchProtectionDefaults struct {
	AllowForcePush            bool                `json:"allow_force_push,omitempty"`
	AllowedToMerge            []*GroupAccessLevel `json:"allowed_to_merge,omitempty"`
	DeveloperCanInitialPush   bool                `json:"developer_can_initial_push,omitempty"`
	CodeOwnerApprovalRequired bool                `json:"code_owner_approval_required,omitempty"`
}

// GroupAccessLevel represents default branch protection defaults access levels.
@@ -425,6 +426,7 @@ type DefaultBranchProtectionDefaultsOptions struct {
	AllowForcePush            *bool                `url:"allow_force_push,omitempty" json:"allow_force_push,omitempty"`
	AllowedToMerge            *[]*GroupAccessLevel `url:"allowed_to_merge,omitempty" json:"allowed_to_merge,omitempty"`
	DeveloperCanInitialPush   *bool                `url:"developer_can_initial_push,omitempty" json:"developer_can_initial_push,omitempty"`
	CodeOwnerApprovalRequired *bool                `url:"code_owner_approval_required,omitempty" json:"code_owner_approval_required,omitempty"`
}

// EncodeValues implements the query.Encoder interface
@@ -435,6 +437,9 @@ func (d *DefaultBranchProtectionDefaultsOptions) EncodeValues(key string, v *url
	if d.DeveloperCanInitialPush != nil {
		v.Add(key+"[developer_can_initial_push]", strconv.FormatBool(*d.DeveloperCanInitialPush))
	}
	if d.CodeOwnerApprovalRequired != nil {
		v.Add(key+"[code_owner_approval_required]", strconv.FormatBool(*d.CodeOwnerApprovalRequired))
	}
	// The GitLab API only accepts one value for `allowed_to_merge` even when multiples are
	// provided on the request.  The API will take the highest permission level.  For instance,
	// if 'developer' and 'maintainer' are provided, the API will take 'maintainer'.
@@ -455,6 +460,7 @@ func (d *DefaultBranchProtectionDefaultsOptions) EncodeValues(key string, v *url
			}
		}
	}

	return nil
}

+19 −2
Original line number Diff line number Diff line
@@ -221,7 +221,8 @@ func TestCreateGroupDefaultBranchSettings(t *testing.T) {
						{
							"access_level": 40
						}
					]
					],
					"code_owner_approval_required": true
				}
			}
			`)
@@ -241,6 +242,7 @@ func TestCreateGroupDefaultBranchSettings(t *testing.T) {
					AccessLevel: Ptr(AccessLevelValue(40)),
				},
			},
			CodeOwnerApprovalRequired: Ptr(true),
		},
	}

@@ -265,6 +267,7 @@ func TestCreateGroupDefaultBranchSettings(t *testing.T) {
					AccessLevel: Ptr(MaintainerPermissions),
				},
			},
			CodeOwnerApprovalRequired: true,
		},
	}

@@ -275,8 +278,13 @@ func TestCreateGroupDefaultBranchSettings(t *testing.T) {
	// Validate the request does what we want it to
	allowedToMerge := *jsonRequestBody.DefaultBranchProtectionDefaults.AllowedToMerge
	allowedToPush := *jsonRequestBody.DefaultBranchProtectionDefaults.AllowedToPush

	assert.Equal(t, Ptr(MaintainerPermissions), allowedToMerge[0].AccessLevel)
	assert.Equal(t, Ptr(MaintainerPermissions), allowedToPush[0].AccessLevel)
	assert.True(
		t,
		*jsonRequestBody.DefaultBranchProtectionDefaults.CodeOwnerApprovalRequired,
	)
}

func TestTransferGroup(t *testing.T) {
@@ -1389,6 +1397,12 @@ func TestCreateGroupDefaultBranchSettingsWithAvatar(t *testing.T) {
			testFormBody(t, r, "path", "g")
			testFormBody(t, r, "default_branch_protection_defaults[allowed_to_push][][access_level]", "40")
			testFormBody(t, r, "default_branch_protection_defaults[allowed_to_merge][][access_level]", "40")
			testFormBody(
				t,
				r,
				"default_branch_protection_defaults[code_owner_approval_required]",
				"true",
			)

			fmt.Fprint(w, `
			{
@@ -1406,7 +1420,8 @@ func TestCreateGroupDefaultBranchSettingsWithAvatar(t *testing.T) {
						{
							"access_level": 40
						}
					]
					],
					"code_owner_approval_required": true
				},
				"avatar_url":"http://localhost/uploads/-/system/group/avatar/999/avatar.png"
			}
@@ -1433,6 +1448,7 @@ func TestCreateGroupDefaultBranchSettingsWithAvatar(t *testing.T) {
					AccessLevel: Ptr(AccessLevelValue(40)),
				},
			},
			CodeOwnerApprovalRequired: Ptr(true),
		},
	}

@@ -1460,6 +1476,7 @@ func TestCreateGroupDefaultBranchSettingsWithAvatar(t *testing.T) {
					AccessLevel: Ptr(MaintainerPermissions),
				},
			},
			CodeOwnerApprovalRequired: true,
		},
	}