Skip to content

Commit e1bdb47

Browse files
author
Huseyin Unal
committed
Add Project-level MR approvals
1 parent f60dc34 commit e1bdb47

File tree

4 files changed

+320
-0
lines changed

4 files changed

+320
-0
lines changed

gitlab/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ func Provider() terraform.ResourceProvider {
8989
"gitlab_group_cluster": resourceGitlabGroupCluster(),
9090
"gitlab_group_ldap_link": resourceGitlabGroupLdapLink(),
9191
"gitlab_project_mirror": resourceGitlabProjectMirror(),
92+
"gitlab_project_level_mr_approvals": resourceGitlabProjectLevelMRApprovals(),
9293
},
9394

9495
ConfigureFunc: providerConfigure,
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"log"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
8+
gitlab "github.com/xanzy/go-gitlab"
9+
)
10+
11+
func resourceGitlabProjectLevelMRApprovals() *schema.Resource {
12+
return &schema.Resource{
13+
Create: resourceGitlabProjectLevelMRApprovalsCreate,
14+
Read: resourceGitlabProjectLevelMRApprovalsRead,
15+
Update: resourceGitlabProjectLevelMRApprovalsUpdate,
16+
Delete: resourceGitlabProjectLevelMRApprovalsDelete,
17+
Importer: &schema.ResourceImporter{
18+
State: schema.ImportStatePassthrough,
19+
},
20+
Schema: map[string]*schema.Schema{
21+
"project_id": {
22+
Type: schema.TypeString,
23+
ForceNew: true,
24+
Required: true,
25+
},
26+
"reset_approvals_on_push": {
27+
Type: schema.TypeBool,
28+
Optional: true,
29+
},
30+
"disable_overriding_approvers_per_merge_request": {
31+
Type: schema.TypeBool,
32+
Optional: true,
33+
},
34+
"merge_requests_author_approval": {
35+
Type: schema.TypeBool,
36+
Optional: true,
37+
},
38+
"merge_requests_disable_committers_approval": {
39+
Type: schema.TypeBool,
40+
Optional: true,
41+
},
42+
},
43+
}
44+
}
45+
46+
func resourceGitlabProjectLevelMRApprovalsCreate(d *schema.ResourceData, meta interface{}) error {
47+
client := meta.(*gitlab.Client)
48+
49+
projectId := d.Get("project_id").(string)
50+
51+
options := &gitlab.ChangeApprovalConfigurationOptions{
52+
ResetApprovalsOnPush: gitlab.Bool(d.Get("reset_approvals_on_push").(bool)),
53+
DisableOverridingApproversPerMergeRequest: gitlab.Bool(d.Get("disable_overriding_approvers_per_merge_request").(bool)),
54+
MergeRequestsAuthorApproval: gitlab.Bool(d.Get("merge_requests_author_approval").(bool)),
55+
MergeRequestsDisableCommittersApproval: gitlab.Bool(d.Get("merge_requests_disable_committers_approval").(bool)),
56+
}
57+
58+
log.Printf("[DEBUG] Creating new MR approval configuration for project %s: %#v", projectId, options)
59+
60+
_, _, err := client.Projects.ChangeApprovalConfiguration(projectId, options)
61+
if err != nil {
62+
return fmt.Errorf("Error creating approval configuration: %s", err)
63+
}
64+
65+
d.SetId(projectId)
66+
return resourceGitlabProjectLevelMRApprovalsRead(d, meta)
67+
}
68+
69+
func resourceGitlabProjectLevelMRApprovalsRead(d *schema.ResourceData, meta interface{}) error {
70+
client := meta.(*gitlab.Client)
71+
72+
projectId := d.Id()
73+
log.Printf("[DEBUG] Reading gitlab approval configuration for project %s", projectId)
74+
75+
approvalConfig, _, err := client.Projects.GetApprovalConfiguration(projectId)
76+
if err != nil {
77+
return fmt.Errorf("Error reading approval configuration: %s", err)
78+
}
79+
80+
d.Set("projectId", projectId)
81+
d.Set("reset_approvals_on_push", approvalConfig.ResetApprovalsOnPush)
82+
d.Set("disable_overriding_approvers_per_merge_request", approvalConfig.DisableOverridingApproversPerMergeRequest)
83+
d.Set("merge_requests_author_approval", approvalConfig.MergeRequestsAuthorApproval)
84+
d.Set("merge_requests_disable_committers_approval", approvalConfig.MergeRequestsDisableCommittersApproval)
85+
86+
return nil
87+
}
88+
89+
func resourceGitlabProjectLevelMRApprovalsUpdate(d *schema.ResourceData, meta interface{}) error {
90+
client := meta.(*gitlab.Client)
91+
options := &gitlab.ChangeApprovalConfigurationOptions{}
92+
93+
if d.HasChange("reset_approvals_on_push") {
94+
options.ResetApprovalsOnPush = gitlab.Bool(d.Get("reset_approvals_on_push").(bool))
95+
}
96+
if d.HasChange("disable_overriding_approvers_per_merge_request") {
97+
options.DisableOverridingApproversPerMergeRequest = gitlab.Bool(d.Get("disable_overriding_approvers_per_merge_request").(bool))
98+
}
99+
if d.HasChange("merge_requests_author_approval") {
100+
options.MergeRequestsAuthorApproval = gitlab.Bool(d.Get("merge_requests_author_approval").(bool))
101+
}
102+
if d.HasChange("merge_requests_disable_committers_approval") {
103+
options.MergeRequestsDisableCommittersApproval = gitlab.Bool(d.Get("merge_requests_disable_committers_approval").(bool))
104+
}
105+
106+
_, _, err := client.Projects.ChangeApprovalConfiguration(d.Id(), options)
107+
if err != nil {
108+
return fmt.Errorf("Error updating approval configuration: %s", err)
109+
}
110+
111+
return resourceGitlabProjectLevelMRApprovalsRead(d, meta)
112+
}
113+
114+
func resourceGitlabProjectLevelMRApprovalsDelete(d *schema.ResourceData, meta interface{}) error {
115+
client := meta.(*gitlab.Client)
116+
projectId := d.Id()
117+
118+
options := &gitlab.ChangeApprovalConfigurationOptions{
119+
ResetApprovalsOnPush: gitlab.Bool(true),
120+
DisableOverridingApproversPerMergeRequest: gitlab.Bool(false),
121+
MergeRequestsAuthorApproval: gitlab.Bool(false),
122+
MergeRequestsDisableCommittersApproval: gitlab.Bool(false),
123+
}
124+
125+
log.Printf("[DEBUG] Resetting approval configuration for project %s: %#v", projectId, options)
126+
127+
_, _, err := client.Projects.ChangeApprovalConfiguration(projectId, options)
128+
return err
129+
}
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package gitlab
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/helper/acctest"
8+
"github.com/hashicorp/terraform-plugin-sdk/helper/resource"
9+
"github.com/hashicorp/terraform-plugin-sdk/terraform"
10+
gitlab "github.com/xanzy/go-gitlab"
11+
)
12+
13+
func TestAccGitlabProjectLevelMRApprovals_basic(t *testing.T) {
14+
15+
var projectApprovals gitlab.ProjectApprovals
16+
rInt := acctest.RandInt()
17+
18+
resource.Test(t, resource.TestCase{
19+
PreCheck: func() { testAccPreCheck(t) },
20+
Providers: testAccProviders,
21+
CheckDestroy: testAccCheckGitlabProjectLevelMRApprovalsDestroy,
22+
Steps: []resource.TestStep{
23+
{
24+
Config: testAccGitlabProjectLevelMRApprovalsUpdateConfig(rInt),
25+
Check: resource.ComposeTestCheckFunc(
26+
testAccCheckGitlabProjectLevelMRApprovalsExists("gitlab_project_level_mr_approvals.foo", &projectApprovals),
27+
testAccCheckGitlabProjectLevelMRApprovalsAttributes(&projectApprovals, &testAccGitlabProjectLevelMRApprovalsExpectedAttributes{
28+
resetApprovalsOnPush: true,
29+
disableOverridingApproversPerMergeRequest: true,
30+
mergeRequestsAuthorApproval: true,
31+
mergeRequestsDisableCommittersApproval: true,
32+
}),
33+
),
34+
},
35+
},
36+
})
37+
}
38+
39+
type testAccGitlabProjectLevelMRApprovalsExpectedAttributes struct {
40+
resetApprovalsOnPush bool
41+
disableOverridingApproversPerMergeRequest bool
42+
mergeRequestsAuthorApproval bool
43+
mergeRequestsDisableCommittersApproval bool
44+
}
45+
46+
func testAccCheckGitlabProjectLevelMRApprovalsAttributes(projectApprovals *gitlab.ProjectApprovals, want *testAccGitlabProjectLevelMRApprovalsExpectedAttributes) resource.TestCheckFunc {
47+
return func(s *terraform.State) error {
48+
if projectApprovals.ResetApprovalsOnPush != want.resetApprovalsOnPush {
49+
return fmt.Errorf("got reset_approvals_on_push %t; want %t", projectApprovals.ResetApprovalsOnPush, want.resetApprovalsOnPush)
50+
}
51+
if projectApprovals.DisableOverridingApproversPerMergeRequest != want.disableOverridingApproversPerMergeRequest {
52+
return fmt.Errorf("got disable_overriding_approvers_per_merge_request %t; want %t", projectApprovals.DisableOverridingApproversPerMergeRequest, want.disableOverridingApproversPerMergeRequest)
53+
}
54+
if projectApprovals.MergeRequestsAuthorApproval != want.mergeRequestsAuthorApproval {
55+
return fmt.Errorf("got merge_requests_author_approval %t; want %t", projectApprovals.MergeRequestsAuthorApproval, want.mergeRequestsAuthorApproval)
56+
}
57+
if projectApprovals.MergeRequestsDisableCommittersApproval != want.mergeRequestsDisableCommittersApproval {
58+
return fmt.Errorf("got merge_requests_disable_committers_approval %t; want %t", projectApprovals.MergeRequestsDisableCommittersApproval, want.mergeRequestsDisableCommittersApproval)
59+
}
60+
return nil
61+
}
62+
}
63+
64+
func testAccCheckGitlabProjectLevelMRApprovalsDestroy(s *terraform.State) error {
65+
conn := testAccProvider.Meta().(*gitlab.Client)
66+
67+
for _, rs := range s.RootModule().Resources {
68+
if rs.Type != "gitlab_project" {
69+
continue
70+
}
71+
72+
gotRepo, resp, err := conn.Projects.GetProject(rs.Primary.ID, nil)
73+
if err == nil {
74+
if gotRepo != nil && fmt.Sprintf("%d", gotRepo.ID) == rs.Primary.ID {
75+
if gotRepo.MarkedForDeletionAt == nil {
76+
return fmt.Errorf("Repository still exists.")
77+
}
78+
}
79+
}
80+
if resp.StatusCode != 404 {
81+
return err
82+
}
83+
return nil
84+
}
85+
return nil
86+
}
87+
88+
func testAccCheckGitlabProjectLevelMRApprovalsExists(n string, projectApprovals *gitlab.ProjectApprovals) resource.TestCheckFunc {
89+
return func(s *terraform.State) error {
90+
rs, ok := s.RootModule().Resources[n]
91+
if !ok {
92+
return fmt.Errorf("Not Found: %s", n)
93+
}
94+
95+
project_id := rs.Primary.ID
96+
if project_id == "" {
97+
return fmt.Errorf("No project ID is set")
98+
}
99+
conn := testAccProvider.Meta().(*gitlab.Client)
100+
101+
gotApprovalConfig, _, err := conn.Projects.GetApprovalConfiguration(project_id)
102+
if err != nil {
103+
return err
104+
}
105+
106+
*projectApprovals = *gotApprovalConfig
107+
return nil
108+
}
109+
}
110+
111+
func testAccGitlabProjectLevelMRApprovalsUpdateConfig(rInt int) string {
112+
return fmt.Sprintf(`
113+
resource "gitlab_project" "foo" {
114+
name = "foo-%d"
115+
description = "Terraform acceptance tests"
116+
visibility_level = "public"
117+
}
118+
119+
resource "gitlab_project_level_mr_approvals" "foo" {
120+
project_id = gitlab_project.foo.id
121+
reset_approvals_on_push = true
122+
disable_overriding_approvers_per_merge_request = true
123+
merge_requests_author_approval = true
124+
merge_requests_disable_committers_approval = true
125+
}
126+
`, rInt)
127+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
---
2+
layout: "gitlab"
3+
page_title: "GitLab: gitlab_project_level_mr_approvals"
4+
sidebar_current: "docs-gitlab-resource-project-level-mr-approvals"
5+
description: |-
6+
Configures project-level MR approvals.
7+
---
8+
9+
# gitlab\_project\_approvals\_configuration
10+
11+
This resource allows you to configure project-level MR approvals. for your GitLab projects.
12+
For further information on merge request approvals, consult the [GitLab API
13+
documentation](https://docs.gitlab.com/ee/api/merge_request_approvals.html#project-level-mr-approvals).
14+
15+
16+
## Example Usage
17+
18+
```hcl
19+
resource "gitlab_project" "foo" {
20+
name = "Example"
21+
description = "My example project"
22+
}
23+
24+
resource "gitlab_project_level_mr_approvals" "foo" {
25+
project_id = gitlab_project.foo.id
26+
reset_approvals_on_push = true
27+
disable_overriding_approvers_per_merge_request = false
28+
merge_requests_author_approval = false
29+
merge_requests_disable_committers_approval = true
30+
}
31+
```
32+
33+
## Argument Reference
34+
35+
The following arguments are supported:
36+
37+
* `project_id` - (Required) The ID of the project to change MR approval configuration.
38+
39+
* `reset_approvals_on_push` - (Optional) Set to `true` if you want to remove all approvals in a merge request when new commits are pushed to its source branch. Default is `true`.
40+
41+
* `disable_overriding_approvers_per_merge_request` - (Optional) By default, users are able to edit the approval rules in merge requests. If set to true,
42+
the approval rules for all new merge requests will be determined by the default approval rules. Default is `false`.
43+
44+
* `merge_requests_author_approval` - (Optional) Set to `true` if you want to allow merge request authors to self-approve merge requests. Authors
45+
also need to be included in the approvers list in order to be able to approve their merge request. Default is `false`.
46+
47+
* `merge_requests_disable_committers_approval` - (Optional) Set to `true` if you want to prevent approval of merge requests by merge request committers. Default is `false`.
48+
49+
## Attributes Reference
50+
51+
The resource exports the following attributes:
52+
53+
* `id` - The unique id assigned to the approval configuration by the GitLab server.
54+
55+
## Importing approval configuration
56+
57+
You can import an approval configuration to terraform state using `terraform import <resource> <id>`.
58+
The `id` must be an integer for the id of the approval configuration you want to import,
59+
For example:
60+
61+
```bash
62+
$ terraform import gitlab_project_level_mr_approvals.foo 53
63+
```

0 commit comments

Comments
 (0)