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 v4 branch protections #128

Merged
merged 4 commits into from
Nov 6, 2022
Merged
Show file tree
Hide file tree
Changes from 2 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
94 changes: 72 additions & 22 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,17 @@ locals {
topics = concat(local.standard_topics, var.extra_topics)
template = var.template == null ? [] : [var.template]
issue_labels_create = var.issue_labels_create == null ? lookup(var.defaults, "issue_labels_create", local.issue_labels_create_computed) : var.issue_labels_create
branch_protections_v3 = var.branch_protections_v3 == null ? var.branch_protections : var.branch_protections_v3
branch_protections_v3 = [
for b in coalesce(var.branch_protections_v3, var.branch_protections, []) : merge({
branch = null
enforce_admins = null
require_conversation_resolution = null
require_signed_commits = null
required_status_checks = {}
required_pull_request_reviews = {}
restrictions = {}
}, b)
]

issue_labels_create_computed = local.has_issues || length(var.issue_labels) > 0

Expand All @@ -41,20 +51,8 @@ locals {
}

locals {
branch_protections = try([
for b in local.branch_protections_v3 : merge({
branch = null
enforce_admins = null
require_conversation_resolution = null
require_signed_commits = null
required_status_checks = {}
required_pull_request_reviews = {}
restrictions = {}
}, b)
], [])

required_status_checks = [
for b in local.branch_protections :
for b in local.branch_protections_v3 :
length(keys(b.required_status_checks)) > 0 ? [
merge({
strict = null
Expand All @@ -63,7 +61,7 @@ locals {
]

required_pull_request_reviews = [
for b in local.branch_protections :
for b in local.branch_protections_v3 :
length(keys(b.required_pull_request_reviews)) > 0 ? [
merge({
dismiss_stale_reviews = true
Expand All @@ -75,7 +73,7 @@ locals {
]

restrictions = [
for b in local.branch_protections :
for b in local.branch_protections_v3 :
length(keys(b.restrictions)) > 0 ? [
merge({
users = []
Expand Down Expand Up @@ -137,6 +135,7 @@ resource "github_repository" "repository" {
lifecycle {
ignore_changes = [
auto_init,
branches,
taharah marked this conversation as resolved.
Show resolved Hide resolved
license_template,
gitignore_template,
template,
Expand Down Expand Up @@ -177,12 +176,63 @@ resource "github_branch_default" "default" {
}

# ---------------------------------------------------------------------------------------------------------------------
# Branch Protection
# v4 Branch Protection
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection
# ---------------------------------------------------------------------------------------------------------------------

resource "github_branch_protection" "this" {
taharah marked this conversation as resolved.
Show resolved Hide resolved
for_each = length(coalesce(var.branch_protections_v4, {})) > 0 ? var.branch_protections_v4 : {}

# ensure we have all members and collaborators added before applying
# any configuration for them
depends_on = [
github_repository_collaborator.collaborator,
github_team_repository.team_repository,
github_team_repository.team_repository_by_slug,
github_branch.branch,
]

repository_id = github_repository.repository.node_id
pattern = each.key
allows_deletions = each.value.allows_deletions
allows_force_pushes = each.value.allows_force_pushes
blocks_creations = each.value.blocks_creations
enforce_admins = each.value.enforce_admins
push_restrictions = each.value.push_restrictions
require_conversation_resolution = each.value.require_conversation_resolution
require_signed_commits = each.value.require_signed_commits
required_linear_history = each.value.required_linear_history

dynamic "required_pull_request_reviews" {
for_each = each.value.required_pull_request_reviews != null ? [true] : []

content {
dismiss_stale_reviews = each.value.required_pull_request_reviews.dismiss_stale_reviews
dismissal_restrictions = each.value.required_pull_request_reviews.dismissal_restrictions
pull_request_bypassers = each.value.required_pull_request_reviews.pull_request_bypassers
require_code_owner_reviews = each.value.required_pull_request_reviews.require_code_owner_reviews
required_approving_review_count = each.value.required_pull_request_reviews.required_approving_review_count
restrict_dismissals = length(each.value.required_pull_request_reviews.dismissal_restrictions) > 0
}
}

dynamic "required_status_checks" {
for_each = each.value.required_status_checks != null ? [true] : []

content {
strict = each.value.required_status_checks.strict
contexts = each.value.required_status_checks.contexts
}
}
}

# ---------------------------------------------------------------------------------------------------------------------
# v3 Branch Protection
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection_v3
# ---------------------------------------------------------------------------------------------------------------------

resource "github_branch_protection_v3" "branch_protection" {
count = length(local.branch_protections)
count = length(coalesce(var.branch_protections_v4, {})) == 0 ? length(local.branch_protections_v3) : 0

# ensure we have all members and collaborators added before applying
# any configuration for them
Expand All @@ -194,10 +244,10 @@ resource "github_branch_protection_v3" "branch_protection" {
]

repository = github_repository.repository.name
branch = local.branch_protections[count.index].branch
enforce_admins = local.branch_protections[count.index].enforce_admins
require_conversation_resolution = local.branch_protections[count.index].require_conversation_resolution
require_signed_commits = local.branch_protections[count.index].require_signed_commits
branch = local.branch_protections_v3[count.index].branch
enforce_admins = local.branch_protections_v3[count.index].enforce_admins
require_conversation_resolution = local.branch_protections_v3[count.index].require_conversation_resolution
require_signed_commits = local.branch_protections_v3[count.index].require_signed_commits

dynamic "required_status_checks" {
for_each = local.required_status_checks[count.index]
Expand Down
47 changes: 47 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,53 @@ variable "branch_protections_v3" {
# ]
}

variable "branch_protections_v4" {
description = "(Optional) A list of v4 branch protections to apply to the repository. Default is {}."
type = map(
object(
{
allows_deletions = optional(bool, false)
allows_force_pushes = optional(bool, false)
blocks_creations = optional(bool, false)
enforce_admins = optional(bool, false)
push_restrictions = optional(list(string), [])
require_conversation_resolution = optional(bool, false)
require_signed_commits = optional(bool, false)
required_linear_history = optional(bool, false)
required_pull_request_reviews = optional(object(
{
dismiss_stale_reviews = optional(bool, false)
dismissal_restrictions = optional(list(string), [])
pull_request_bypassers = optional(list(string), [])
require_code_owner_reviews = optional(bool, false)
required_approving_review_count = optional(number, 0)
}
))
required_status_checks = optional(object(
{
strict = optional(bool, false)
contexts = optional(list(string), [])
}
))
}
)
)
default = null

validation {
condition = alltrue(
[
for cfg in coalesce(var.branch_protections_v4, {}) : try(
cfg.required_pull_request_reviews.required_approving_review_count >= 0
&& cfg.required_pull_request_reviews.required_approving_review_count <= 6,
true
)
]
)
error_message = "The value for branch_protections_v4.required_pull_request_reviews.required_approving_review_count must be between 0 and 6, inclusively."
}
}

variable "issue_labels_merge_with_github_labels" {
description = "(Optional) Specify if you want to merge and control githubs default set of issue labels."
type = bool
Expand Down
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# ---------------------------------------------------------------------------------------------------------------------

terraform {
required_version = "~> 1.0"
required_version = "~> 1.3"

# branch_protections_v3 are broken in >= 5.3
required_providers {
Expand Down