Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add project and mr approval rules #13

Merged
merged 2 commits into from
Apr 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,12 @@ No modules.
|------|------|
| [gitlab_branch_protection.default](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/resources/branch_protection) | resource |
| [gitlab_project.default](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/resources/project) | resource |
| [gitlab_project_approval_rule.default](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/resources/project_approval_rule) | resource |
| [gitlab_project_level_mr_approvals.default](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/resources/project_level_mr_approvals) | resource |
| [gitlab_group.default](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/data-sources/group) | data source |
| [gitlab_group.groups](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/data-sources/group) | data source |
| [gitlab_group.project_approval_rule_groups](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/data-sources/group) | data source |
| [gitlab_user.project_approval_rule_users](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/data-sources/user) | data source |
| [gitlab_user.users](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs/data-sources/user) | data source |

## Inputs
Expand All @@ -45,9 +49,11 @@ No modules.
| <a name="input_description"></a> [description](#input\_description) | A description for the GitLab project | `string` | `null` | no |
| <a name="input_initialize_with_readme"></a> [initialize\_with\_readme](#input\_initialize\_with\_readme) | Create default branch with first commit containing a README.md file | `bool` | `true` | no |
| <a name="input_issues_enabled"></a> [issues\_enabled](#input\_issues\_enabled) | Enable issue tracking for the project | `bool` | `false` | no |
| <a name="input_merge_request_approval_rule"></a> [merge\_request\_approval\_rule](#input\_merge\_request\_approval\_rule) | Allows to manage the lifecycle of a Merge Request-level approval rule. | <pre>object({<br> disable_overriding_approvers_per_merge_request = optional(bool, false)<br> merge_requests_author_approval = optional(bool, false)<br> merge_requests_disable_committers_approval = optional(bool, false)<br> reset_approvals_on_push = optional(bool, true)<br> })</pre> | `{}` | no |
| <a name="input_only_allow_merge_if_all_discussions_are_resolved"></a> [only\_allow\_merge\_if\_all\_discussions\_are\_resolved](#input\_only\_allow\_merge\_if\_all\_discussions\_are\_resolved) | Set to true if you want allow merges only if all discussions are resolved. | `bool` | `false` | no |
| <a name="input_only_allow_merge_if_pipeline_succeeds"></a> [only\_allow\_merge\_if\_pipeline\_succeeds](#input\_only\_allow\_merge\_if\_pipeline\_succeeds) | Set to true if you want allow merges only if a pipeline succeeds. | `bool` | `false` | no |
| <a name="input_prevent_secrets"></a> [prevent\_secrets](#input\_prevent\_secrets) | GitLab rejects any files that are likely to contain secrets. | `bool` | `true` | no |
| <a name="input_project_approval_rule"></a> [project\_approval\_rule](#input\_project\_approval\_rule) | Allows to manage the lifecycle of a project-level approval rule. | <pre>object({<br> name = optional(string, "project approval rule")<br> applies_to_all_protected_branches = optional(bool, true)<br> approvals_required = optional(number, 1)<br> groups = optional(list(string), [])<br> protected_branches = optional(list(string), null)<br> users = optional(list(string), [])<br> })</pre> | `{}` | no |
| <a name="input_reject_unsigned_commits"></a> [reject\_unsigned\_commits](#input\_reject\_unsigned\_commits) | GitLab rejects any unsigned commits. | `bool` | `true` | no |
| <a name="input_remove_source_branch_after_merge"></a> [remove\_source\_branch\_after\_merge](#input\_remove\_source\_branch\_after\_merge) | Enable "Delete source branch" option by default for all new merge requests. | `bool` | `true` | no |
| <a name="input_snippets_enabled"></a> [snippets\_enabled](#input\_snippets\_enabled) | Enable snippets for the project | `bool` | `false` | no |
Expand Down
16 changes: 16 additions & 0 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,20 @@ module "test_project" {
groups_allowed_to_merge = ["foo/group2"]
}
}

merge_request_approval_rule = {
disable_overriding_approvers_per_merge_request = true
merge_requests_author_approval = false
merge_requests_disable_committers_approval = false
reset_approvals_on_push = true
}

project_approval_rule = {
name = "project approval rule"
approvals_required = 1
applies_to_all_protected_branches = false
users = ["user1"]
groups = ["foo/group1"]
protected_branches = ["main"]
}
}
30 changes: 30 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,36 @@ resource "gitlab_project" "default" {
}
}

resource "gitlab_project_level_mr_approvals" "default" {
project = gitlab_project.default.id
reset_approvals_on_push = var.merge_request_approval_rule.reset_approvals_on_push
disable_overriding_approvers_per_merge_request = var.merge_request_approval_rule.disable_overriding_approvers_per_merge_request
merge_requests_author_approval = var.merge_request_approval_rule.merge_requests_author_approval
merge_requests_disable_committers_approval = var.merge_request_approval_rule.merge_requests_disable_committers_approval
}

data "gitlab_user" "project_approval_rule_users" {
for_each = try(toset(var.project_approval_rule.users), {})

username = each.value
}

data "gitlab_group" "project_approval_rule_groups" {
for_each = try(toset(var.project_approval_rule.groups), {})

full_path = each.value
}

resource "gitlab_project_approval_rule" "default" {
project = gitlab_project.default.id
name = var.project_approval_rule.name
approvals_required = var.project_approval_rule.approvals_required
applies_to_all_protected_branches = var.project_approval_rule.applies_to_all_protected_branches
protected_branch_ids = try([for branch in var.project_approval_rule.protected_branches : gitlab_branch_protection.default[branch].id], null)
user_ids = try(data.gitlab_user.project_approval_rule_users[*].id, null)
group_ids = try(data.gitlab_group.project_approval_rule_groups[*].id, null)
}

################################################################################
# Branch protection
################################################################################
Expand Down
94 changes: 92 additions & 2 deletions tests/complete.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,41 @@ run "defaults" {
condition = resource.gitlab_branch_protection.default["main"].code_owner_approval_required == false
error_message = "Code owner approval should not be required"
}

assert {
condition = resource.gitlab_project_approval_rule.default.approvals_required == 1
error_message = "Invalid approvals_required value"
}

assert {
condition = resource.gitlab_project_approval_rule.default.name == "project approval rule"
error_message = "Invalid project approval rule name"
}

assert {
condition = resource.gitlab_project_approval_rule.default.applies_to_all_protected_branches == true
error_message = "Invalid applies_to_all_protected_branches value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.disable_overriding_approvers_per_merge_request == false
error_message = "Invalid disable_overriding_approvers_per_merge_request value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.merge_requests_author_approval == false
error_message = "Invalid merge_requests_author_approval value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.merge_requests_disable_committers_approval == false
error_message = "Invalid merge_requests_disable_committers_approval value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.reset_approvals_on_push == true
error_message = "Invalid reset_approvals_on_push value"
}
}

run "complete" {
Expand Down Expand Up @@ -159,6 +194,22 @@ run "complete" {
groups_allowed_to_merge = ["foo/group2"]
}
}

merge_request_approval_rule = {
disable_overriding_approvers_per_merge_request = true
merge_requests_author_approval = true
merge_requests_disable_committers_approval = true
reset_approvals_on_push = false
}

project_approval_rule = {
name = "project approval rule"
approvals_required = 10
applies_to_all_protected_branches = false
users = ["user1"]
groups = ["foo/group1"]
protected_branches = ["main"]
}
}

module {
Expand Down Expand Up @@ -276,8 +327,37 @@ run "complete" {
condition = resource.gitlab_branch_protection.default["develop"].allowed_to_push != null
error_message = "allowed_to_push object should not be null on develop branch"
}
}

assert {
condition = resource.gitlab_project_approval_rule.default.approvals_required == 10
error_message = "Invalid approvals_required value"
}

assert {
condition = resource.gitlab_project_approval_rule.default.applies_to_all_protected_branches == false
error_message = "Invalid applies_to_all_protected_branches value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.disable_overriding_approvers_per_merge_request == true
error_message = "Invalid disable_overriding_approvers_per_merge_request value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.merge_requests_author_approval == true
error_message = "Invalid merge_requests_author_approval value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.merge_requests_disable_committers_approval == true
error_message = "Invalid merge_requests_disable_committers_approval value"
}

assert {
condition = resource.gitlab_project_level_mr_approvals.default.reset_approvals_on_push == false
error_message = "Invalid reset_approvals_on_push value"
}
}

run "failures" {
command = plan
Expand All @@ -292,10 +372,20 @@ run "failures" {

visibility = "visible"
squash_option = "maybe"

project_approval_rule = {
name = "project approval rule"
approvals_required = 1
applies_to_all_protected_branches = true
users = ["user1"]
groups = ["foo/group1"]
protected_branches = ["main"]
}
}

expect_failures = [
var.visibility,
var.squash_option
var.squash_option,
var.project_approval_rule
]
}
40 changes: 35 additions & 5 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,36 @@ variable "branch_protection" {
description = "Branch protection settings"
}

variable "merge_request_approval_rule" {
type = object({
disable_overriding_approvers_per_merge_request = optional(bool, false)
merge_requests_author_approval = optional(bool, false)
merge_requests_disable_committers_approval = optional(bool, false)
reset_approvals_on_push = optional(bool, true)
})
default = {}
description = "Allows to manage the lifecycle of a Merge Request-level approval rule."
}

variable "project_approval_rule" {
type = object({
name = optional(string, "project approval rule")
applies_to_all_protected_branches = optional(bool, true)
approvals_required = optional(number, 1)
groups = optional(list(string), [])
protected_branches = optional(list(string), null)
users = optional(list(string), [])
})
default = {}
description = "Allows to manage the lifecycle of a project-level approval rule."

validation {
condition = var.project_approval_rule.applies_to_all_protected_branches == false || var.project_approval_rule.protected_branches == null
error_message = "Only one of either applies_to_all_protected_branches or protected_branches may be set."
}

}

variable "commit_message_regex" {
type = string
default = null
Expand Down Expand Up @@ -59,6 +89,11 @@ variable "name" {
description = "The name of the project"
}

variable "namespace" {
type = string
description = "The namespace (group or user) of the project"
}

variable "only_allow_merge_if_all_discussions_are_resolved" {
type = bool
default = false
Expand All @@ -77,11 +112,6 @@ variable "prevent_secrets" {
description = "GitLab rejects any files that are likely to contain secrets."
}

variable "namespace" {
type = string
description = "The namespace (group or user) of the project"
}

variable "reject_unsigned_commits" {
type = bool
default = true
Expand Down