Skip to content

Commit 533d80f

Browse files
author
Petr Vála
committed
feat: Add rule_type parameter to merge_request_approval_rule
This is working in the API, and is necessary in order to enable Eligible Approvers. Closes: #904
1 parent 8612bf7 commit 533d80f

File tree

4 files changed

+132
-8
lines changed

4 files changed

+132
-8
lines changed

docs/resources/project_approval_rule.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ resource "gitlab_project_approval_rule" "example-three" {
5454
approvals_required = 3
5555
user_ids = [for user in data.gitlab_user.users : user.id]
5656
}
57+
58+
# Example using `approval_rule`
59+
resource "gitlab_branch_protection" "any-approver" {
60+
project = 5
61+
name = "Any name"
62+
rule_type = "any_approver"
63+
approvals_required = 1
64+
}
5765
```
5866

5967
<!-- schema generated by tfplugindocs -->
@@ -70,6 +78,7 @@ resource "gitlab_project_approval_rule" "example-three" {
7078
- **group_ids** (Set of Number) A list of group IDs whose members can approve of the merge request.
7179
- **id** (String) The ID of this resource.
7280
- **protected_branch_ids** (Set of Number) A list of protected branch IDs (not branch names) for which the rule applies.
81+
- **rule_type** (String) String, defaults to 'regular'. The type of rule. `any_approver` is a pre-configured default rule with `approvals_required` at `0`. Valid values are `regular`, `any_approver`.
7382
- **user_ids** (Set of Number) A list of specific User IDs to add to the list of approvers.
7483

7584
## Import

examples/resources/gitlab_project_approval_rule/resource.tf

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,11 @@ resource "gitlab_project_approval_rule" "example-three" {
3636
approvals_required = 3
3737
user_ids = [for user in data.gitlab_user.users : user.id]
3838
}
39+
40+
# Example using `approval_rule`
41+
resource "gitlab_branch_protection" "any-approver" {
42+
project = 5
43+
name = "Any name"
44+
rule_type = "any_approver"
45+
approvals_required = 1
46+
}

internal/provider/resource_gitlab_project_approval_rule.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,24 @@ package provider
33
import (
44
"context"
55
"errors"
6+
"fmt"
67
"log"
78
"strconv"
89

910
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
1011
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
1113
gitlab "github.com/xanzy/go-gitlab"
1214
)
1315

1416
// https://docs.gitlab.com/ee/api/merge_request_approvals.html#create-project-level-rule
1517
var errApprovalRuleNotFound = errors.New("approval rule not found")
1618

1719
var _ = registerResource("gitlab_project_approval_rule", func() *schema.Resource {
20+
var validRuleTypeValues = []string{
21+
"regular",
22+
"any_approver",
23+
}
1824
return &schema.Resource{
1925
Description: "This resource allows you to create and manage multiple approval rules for your GitLab projects. For further information on approval rules, consult the [gitlab documentation](https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals).\n\n" +
2026
"-> This feature requires GitLab Premium.",
@@ -43,6 +49,14 @@ var _ = registerResource("gitlab_project_approval_rule", func() *schema.Resource
4349
Type: schema.TypeInt,
4450
Required: true,
4551
},
52+
"rule_type": {
53+
Description: fmt.Sprintf("String, defaults to 'regular'. The type of rule. `any_approver` is a pre-configured default rule with `approvals_required` at `0`. Valid values are %s.", renderValueListForDocs(validRuleTypeValues)),
54+
Type: schema.TypeString,
55+
ForceNew: true,
56+
Optional: true,
57+
Computed: true,
58+
ValidateDiagFunc: validation.ToDiagFunc(validation.StringInSlice(validRuleTypeValues, false)),
59+
},
4660
"user_ids": {
4761
Description: "A list of specific User IDs to add to the list of approvers.",
4862
Type: schema.TypeSet,
@@ -77,6 +91,10 @@ func resourceGitlabProjectApprovalRuleCreate(ctx context.Context, d *schema.Reso
7791
ProtectedBranchIDs: expandProtectedBranchIDs(d.Get("protected_branch_ids")),
7892
}
7993

94+
if v, ok := d.GetOk("rule_type"); ok {
95+
options.RuleType = gitlab.String(v.(string))
96+
}
97+
8098
project := d.Get("project").(string)
8199

82100
log.Printf("[DEBUG] Project %s create gitlab project-level rule %+v", project, options)
@@ -115,6 +133,7 @@ func resourceGitlabProjectApprovalRuleRead(ctx context.Context, d *schema.Resour
115133

116134
d.Set("name", rule.Name)
117135
d.Set("approvals_required", rule.ApprovalsRequired)
136+
d.Set("rule_type", rule.RuleType)
118137

119138
if err := d.Set("group_ids", flattenApprovalRuleGroupIDs(rule.Groups)); err != nil {
120139
return diag.FromErr(err)

internal/provider/resource_gitlab_project_approval_rule_test.go

Lines changed: 96 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import (
1212
gitlab "github.com/xanzy/go-gitlab"
1313
)
1414

15-
func TestAccGitLabProjectApprovalRule_basic(t *testing.T) {
15+
func TestAccGitLabProjectApprovalRule_Basic(t *testing.T) {
1616
// Set up project, groups, users, and branches to use in the test.
1717

1818
testAccCheck(t)
@@ -43,10 +43,10 @@ func TestAccGitLabProjectApprovalRule_basic(t *testing.T) {
4343
Steps: []resource.TestStep{
4444
// Create rule
4545
{
46-
Config: testAccGitlabProjectApprovalRuleConfig(project.ID, 3, projectUsers[0].ID, groups[0].ID, branches[0].ID),
46+
Config: testAccGitlabProjectApprovalRuleConfig_Basic(project.ID, 3, projectUsers[0].ID, groups[0].ID, branches[0].ID),
4747
Check: resource.ComposeTestCheckFunc(
4848
testAccCheckGitlabProjectApprovalRuleExists("gitlab_project_approval_rule.foo", &projectApprovalRule),
49-
testAccCheckGitlabProjectApprovalRuleAttributes(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes{
49+
testAccCheckGitlabProjectApprovalRuleAttributes_Basic(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes_Basic{
5050
Name: "foo",
5151
ApprovalsRequired: 3,
5252
EligibleApproverIDs: []int{currentUser.ID, projectUsers[0].ID, group0Users[0].ID},
@@ -57,10 +57,10 @@ func TestAccGitLabProjectApprovalRule_basic(t *testing.T) {
5757
},
5858
// Update rule
5959
{
60-
Config: testAccGitlabProjectApprovalRuleConfig(project.ID, 2, projectUsers[1].ID, groups[1].ID, branches[1].ID),
60+
Config: testAccGitlabProjectApprovalRuleConfig_Basic(project.ID, 2, projectUsers[1].ID, groups[1].ID, branches[1].ID),
6161
Check: resource.ComposeTestCheckFunc(
6262
testAccCheckGitlabProjectApprovalRuleExists("gitlab_project_approval_rule.foo", &projectApprovalRule),
63-
testAccCheckGitlabProjectApprovalRuleAttributes(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes{
63+
testAccCheckGitlabProjectApprovalRuleAttributes_Basic(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes_Basic{
6464
Name: "foo",
6565
ApprovalsRequired: 2,
6666
EligibleApproverIDs: []int{currentUser.ID, projectUsers[1].ID, group1Users[0].ID},
@@ -79,15 +79,83 @@ func TestAccGitLabProjectApprovalRule_basic(t *testing.T) {
7979
})
8080
}
8181

82-
type testAccGitlabProjectApprovalRuleExpectedAttributes struct {
82+
func TestAccGitLabProjectApprovalRule_AnyApprover(t *testing.T) {
83+
// Set up project, groups, users, and branches to use in the test.
84+
85+
testAccCheck(t)
86+
testAccCheckEE(t)
87+
88+
project := testAccCreateProject(t)
89+
90+
// Terraform test starts here.
91+
92+
var projectApprovalRule gitlab.ProjectApprovalRule
93+
94+
resource.Test(t, resource.TestCase{
95+
ProviderFactories: providerFactories,
96+
CheckDestroy: testAccCheckGitlabProjectApprovalRuleDestroy(project.ID),
97+
Steps: []resource.TestStep{
98+
// Create rule
99+
{
100+
Config: testAccGitlabProjectApprovalRuleConfig_AnyApprover(project.ID, 3, "any_approver"),
101+
Check: resource.ComposeTestCheckFunc(
102+
testAccCheckGitlabProjectApprovalRuleExists("gitlab_project_approval_rule.bar", &projectApprovalRule),
103+
testAccCheckGitlabProjectApprovalRuleAttributes_AnyApprover(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes_AnyApprover{
104+
Name: "bar",
105+
ApprovalsRequired: 3,
106+
RuleType: "any_approver",
107+
}),
108+
),
109+
},
110+
// Update rule
111+
{
112+
Config: testAccGitlabProjectApprovalRuleConfig_AnyApprover(project.ID, 2, "any_approver"),
113+
Check: resource.ComposeTestCheckFunc(
114+
testAccCheckGitlabProjectApprovalRuleExists("gitlab_project_approval_rule.bar", &projectApprovalRule),
115+
testAccCheckGitlabProjectApprovalRuleAttributes_AnyApprover(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes_AnyApprover{
116+
Name: "bar",
117+
ApprovalsRequired: 2,
118+
RuleType: "any_approver",
119+
}),
120+
),
121+
},
122+
// Re-create rule
123+
{
124+
Config: testAccGitlabProjectApprovalRuleConfig_AnyApprover(project.ID, 2, "regular"),
125+
Check: resource.ComposeTestCheckFunc(
126+
testAccCheckGitlabProjectApprovalRuleExists("gitlab_project_approval_rule.bar", &projectApprovalRule),
127+
testAccCheckGitlabProjectApprovalRuleAttributes_AnyApprover(&projectApprovalRule, &testAccGitlabProjectApprovalRuleExpectedAttributes_AnyApprover{
128+
Name: "bar",
129+
ApprovalsRequired: 2,
130+
RuleType: "regular",
131+
}),
132+
),
133+
},
134+
// Verify import
135+
{
136+
ResourceName: "gitlab_project_approval_rule.bar",
137+
ImportState: true,
138+
ImportStateVerify: true,
139+
},
140+
},
141+
})
142+
}
143+
144+
type testAccGitlabProjectApprovalRuleExpectedAttributes_Basic struct {
83145
Name string
84146
ApprovalsRequired int
85147
EligibleApproverIDs []int
86148
GroupIDs []int
87149
ProtectedBranchIDs []int
88150
}
89151

90-
func testAccCheckGitlabProjectApprovalRuleAttributes(got *gitlab.ProjectApprovalRule, want *testAccGitlabProjectApprovalRuleExpectedAttributes) resource.TestCheckFunc {
152+
type testAccGitlabProjectApprovalRuleExpectedAttributes_AnyApprover struct {
153+
Name string
154+
ApprovalsRequired int
155+
RuleType string
156+
}
157+
158+
func testAccCheckGitlabProjectApprovalRuleAttributes_Basic(got *gitlab.ProjectApprovalRule, want *testAccGitlabProjectApprovalRuleExpectedAttributes_Basic) resource.TestCheckFunc {
91159
return func(s *terraform.State) error {
92160
return InterceptGomegaFailure(func() {
93161
Expect(got.Name).To(Equal(want.Name), "name")
@@ -114,7 +182,17 @@ func testAccCheckGitlabProjectApprovalRuleAttributes(got *gitlab.ProjectApproval
114182
}
115183
}
116184

117-
func testAccGitlabProjectApprovalRuleConfig(project, approvals, userID, groupID, protectedBranchID int) string {
185+
func testAccCheckGitlabProjectApprovalRuleAttributes_AnyApprover(got *gitlab.ProjectApprovalRule, want *testAccGitlabProjectApprovalRuleExpectedAttributes_AnyApprover) resource.TestCheckFunc {
186+
return func(s *terraform.State) error {
187+
return InterceptGomegaFailure(func() {
188+
Expect(got.Name).To(Equal(want.Name), "name")
189+
Expect(got.ApprovalsRequired).To(Equal(want.ApprovalsRequired), "approvals_required")
190+
Expect(got.RuleType).To(Equal(want.RuleType), "rule_type")
191+
})
192+
}
193+
}
194+
195+
func testAccGitlabProjectApprovalRuleConfig_Basic(project, approvals, userID, groupID, protectedBranchID int) string {
118196
return fmt.Sprintf(`
119197
resource "gitlab_project_approval_rule" "foo" {
120198
project = %d
@@ -126,6 +204,16 @@ resource "gitlab_project_approval_rule" "foo" {
126204
}`, project, approvals, userID, groupID, protectedBranchID)
127205
}
128206

207+
func testAccGitlabProjectApprovalRuleConfig_AnyApprover(project, approvals int, rule_type string) string {
208+
return fmt.Sprintf(`
209+
resource "gitlab_project_approval_rule" "bar" {
210+
project = %d
211+
name = "bar"
212+
approvals_required = %d
213+
rule_type = "%s"
214+
}`, project, approvals, rule_type)
215+
}
216+
129217
func testAccCheckGitlabProjectApprovalRuleExists(n string, projectApprovalRule *gitlab.ProjectApprovalRule) resource.TestCheckFunc {
130218
return func(s *terraform.State) error {
131219
rs, ok := s.RootModule().Resources[n]

0 commit comments

Comments
 (0)