Skip to content

Commit d17416d

Browse files
committed
feat: add v4 branch protections
Signed-off-by: Trevor Wood <Trevor.G.Wood@gmail.com>
1 parent f94103f commit d17416d

File tree

3 files changed

+120
-23
lines changed

3 files changed

+120
-23
lines changed

main.tf

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,17 @@ locals {
2727
topics = concat(local.standard_topics, var.extra_topics)
2828
template = var.template == null ? [] : [var.template]
2929
issue_labels_create = var.issue_labels_create == null ? lookup(var.defaults, "issue_labels_create", local.issue_labels_create_computed) : var.issue_labels_create
30-
branch_protections_v3 = var.branch_protections_v3 == null ? var.branch_protections : var.branch_protections_v3
30+
branch_protections_v3 = [
31+
for b in coalesce(var.branch_protections_v3, var.branch_protections, []) : merge({
32+
branch = null
33+
enforce_admins = null
34+
require_conversation_resolution = null
35+
require_signed_commits = null
36+
required_status_checks = {}
37+
required_pull_request_reviews = {}
38+
restrictions = {}
39+
}, b)
40+
]
3141

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

@@ -41,20 +51,8 @@ locals {
4151
}
4252

4353
locals {
44-
branch_protections = try([
45-
for b in local.branch_protections_v3 : merge({
46-
branch = null
47-
enforce_admins = null
48-
require_conversation_resolution = null
49-
require_signed_commits = null
50-
required_status_checks = {}
51-
required_pull_request_reviews = {}
52-
restrictions = {}
53-
}, b)
54-
], [])
55-
5654
required_status_checks = [
57-
for b in local.branch_protections :
55+
for b in local.branch_protections_v3 :
5856
length(keys(b.required_status_checks)) > 0 ? [
5957
merge({
6058
strict = null
@@ -63,7 +61,7 @@ locals {
6361
]
6462

6563
required_pull_request_reviews = [
66-
for b in local.branch_protections :
64+
for b in local.branch_protections_v3 :
6765
length(keys(b.required_pull_request_reviews)) > 0 ? [
6866
merge({
6967
dismiss_stale_reviews = true
@@ -75,7 +73,7 @@ locals {
7573
]
7674

7775
restrictions = [
78-
for b in local.branch_protections :
76+
for b in local.branch_protections_v3 :
7977
length(keys(b.restrictions)) > 0 ? [
8078
merge({
8179
users = []
@@ -137,6 +135,7 @@ resource "github_repository" "repository" {
137135
lifecycle {
138136
ignore_changes = [
139137
auto_init,
138+
branches,
140139
license_template,
141140
gitignore_template,
142141
template,
@@ -177,12 +176,63 @@ resource "github_branch_default" "default" {
177176
}
178177

179178
# ---------------------------------------------------------------------------------------------------------------------
180-
# Branch Protection
179+
# v4 Branch Protection
180+
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection
181+
# ---------------------------------------------------------------------------------------------------------------------
182+
183+
resource "github_branch_protection" "this" {
184+
for_each = coalesce(var.branch_protections_v4, {})
185+
186+
# ensure we have all members and collaborators added before applying
187+
# any configuration for them
188+
depends_on = [
189+
github_repository_collaborator.collaborator,
190+
github_team_repository.team_repository,
191+
github_team_repository.team_repository_by_slug,
192+
github_branch.branch,
193+
]
194+
195+
repository_id = github_repository.repository.node_id
196+
pattern = each.key
197+
allows_deletions = each.value.allows_deletions
198+
allows_force_pushes = each.value.allows_force_pushes
199+
blocks_creations = each.value.blocks_creations
200+
enforce_admins = each.value.enforce_admins
201+
push_restrictions = each.value.push_restrictions
202+
require_conversation_resolution = each.value.require_conversation_resolution
203+
require_signed_commits = each.value.require_signed_commits
204+
required_linear_history = each.value.required_linear_history
205+
206+
dynamic "required_pull_request_reviews" {
207+
for_each = each.value.required_pull_request_reviews != null ? [true] : []
208+
209+
content {
210+
dismiss_stale_reviews = each.value.required_pull_request_reviews.dismiss_stale_reviews
211+
dismissal_restrictions = each.value.required_pull_request_reviews.dismissal_restrictions
212+
pull_request_bypassers = each.value.required_pull_request_reviews.pull_request_bypassers
213+
require_code_owner_reviews = each.value.required_pull_request_reviews.require_code_owner_reviews
214+
required_approving_review_count = each.value.required_pull_request_reviews.required_approving_review_count
215+
restrict_dismissals = length(each.value.required_pull_request_reviews.dismissal_restrictions) > 0
216+
}
217+
}
218+
219+
dynamic "required_status_checks" {
220+
for_each = each.value.required_status_checks != null ? [true] : []
221+
222+
content {
223+
strict = each.value.required_status_checks.strict
224+
contexts = each.value.required_status_checks.contexts
225+
}
226+
}
227+
}
228+
229+
# ---------------------------------------------------------------------------------------------------------------------
230+
# v3 Branch Protection
181231
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection_v3
182232
# ---------------------------------------------------------------------------------------------------------------------
183233

184234
resource "github_branch_protection_v3" "branch_protection" {
185-
count = length(local.branch_protections)
235+
count = var.branch_protections_v4 == null ? length(local.branch_protections_v3) : 0
186236

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

196246
repository = github_repository.repository.name
197-
branch = local.branch_protections[count.index].branch
198-
enforce_admins = local.branch_protections[count.index].enforce_admins
199-
require_conversation_resolution = local.branch_protections[count.index].require_conversation_resolution
200-
require_signed_commits = local.branch_protections[count.index].require_signed_commits
247+
branch = local.branch_protections_v3[count.index].branch
248+
enforce_admins = local.branch_protections_v3[count.index].enforce_admins
249+
require_conversation_resolution = local.branch_protections_v3[count.index].require_conversation_resolution
250+
require_signed_commits = local.branch_protections_v3[count.index].require_signed_commits
201251

202252
dynamic "required_status_checks" {
203253
for_each = local.required_status_checks[count.index]

variables.tf

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,53 @@ variable "branch_protections_v3" {
351351
# ]
352352
}
353353

354+
variable "branch_protections_v4" {
355+
description = "(Optional) A list of v4 branch protections to apply to the repository. Default is {}."
356+
type = map(
357+
object(
358+
{
359+
allows_deletions = optional(bool, false)
360+
allows_force_pushes = optional(bool, false)
361+
blocks_creations = optional(bool, false)
362+
enforce_admins = optional(bool, false)
363+
push_restrictions = optional(list(string), [])
364+
require_conversation_resolution = optional(bool, false)
365+
require_signed_commits = optional(bool, false)
366+
required_linear_history = optional(bool, false)
367+
required_pull_request_reviews = optional(object(
368+
{
369+
dismiss_stale_reviews = optional(bool, false)
370+
dismissal_restrictions = optional(list(string), [])
371+
pull_request_bypassers = optional(list(string), [])
372+
require_code_owner_reviews = optional(bool, false)
373+
required_approving_review_count = optional(number, 0)
374+
}
375+
))
376+
required_status_checks = optional(object(
377+
{
378+
strict = optional(bool, false)
379+
contexts = optional(list(string), [])
380+
}
381+
))
382+
}
383+
)
384+
)
385+
default = null
386+
387+
validation {
388+
condition = alltrue(
389+
[
390+
for cfg in coalesce(var.branch_protections_v4, {}) : try(
391+
cfg.required_pull_request_reviews.required_approving_review_count >= 0
392+
&& cfg.required_pull_request_reviews.required_approving_review_count <= 6,
393+
true
394+
)
395+
]
396+
)
397+
error_message = "The value for branch_protections_v4.required_pull_request_reviews.required_approving_review_count must be between 0 and 6, inclusively."
398+
}
399+
}
400+
354401
variable "issue_labels_merge_with_github_labels" {
355402
description = "(Optional) Specify if you want to merge and control githubs default set of issue labels."
356403
type = bool

versions.tf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
# ---------------------------------------------------------------------------------------------------------------------
44

55
terraform {
6-
required_version = "~> 1.0"
6+
required_version = "~> 1.3"
77

88
# branch_protections_v3 are broken in >= 5.3
99
required_providers {

0 commit comments

Comments
 (0)