Skip to content

Commit

Permalink
add support for arbitrary branch protection rules
Browse files Browse the repository at this point in the history
  • Loading branch information
IMax153 committed Jan 23, 2024
1 parent 19bb1af commit 024a938
Show file tree
Hide file tree
Showing 6 changed files with 148 additions and 55 deletions.
28 changes: 14 additions & 14 deletions terraform/github/repository.tf
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
module "github_repository" {
source = "../modules/github_repository"
for_each = var.repositories
name = each.key
description = each.value.description
topics = each.value.topics
homepage_url = each.value.homepage_url
visibility = each.value.visibility
collaborators = each.value.collaborators
pages = each.value.pages
has_discussions = each.value.has_discussions
is_archived = each.value.is_archived
allow_squash_merge = each.value.allow_squash_merge
allow_rebase_merge = each.value.allow_rebase_merge
has_release_branches = each.value.has_release_branches
source = "../modules/github_repository"
for_each = var.repositories
name = each.key
description = each.value.description
topics = each.value.topics
homepage_url = each.value.homepage_url
visibility = each.value.visibility
collaborators = each.value.collaborators
pages = each.value.pages
has_discussions = each.value.has_discussions
is_archived = each.value.is_archived
allow_squash_merge = each.value.allow_squash_merge
allow_rebase_merge = each.value.allow_rebase_merge
branch_protection_rules = each.value.branch_protection_rules
}
15 changes: 11 additions & 4 deletions terraform/github/terraform.tfvars
Original file line number Diff line number Diff line change
Expand Up @@ -61,17 +61,24 @@ repositories = {
}
effect = {
description = "A fully-fledged functional effect system for TypeScript with a rich standard library"
homepage_url = "https://www.effect.website"
topics = ["effect-system", "fp", "framework", "stack-safe", "typescript", "zio"]
pages = { build_type = "workflow" }
allow_rebase_merge = true
collaborators = [
{ username = "DenisFrezzato", permission = "push" },
{ username = "isthatcentered", permission = "push" },
{ username = "remiguittaut", permission = "push" },
{ username = "rzeigler", permission = "push" },
]
pages = { build_type = "workflow" }
homepage_url = "https://www.effect.website"
topics = ["effect-system", "fp", "framework", "stack-safe", "typescript", "zio"]
has_release_branches = true
branch_protection_rules = {
"next-*" = {
allows_force_pushes = true
required_status_checks = {
strict = true
}
}
}
}
eslint-plugin = {
description = "A set of ESlint and TypeScript rules to work with Effect"
Expand Down
25 changes: 25 additions & 0 deletions terraform/github/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,31 @@ variable "repositories" {
source_branch = optional(string)
source_path = optional(string)
}))
branch_protection_rules = optional(map(object({
allows_deletions = optional(bool)
allows_force_pushes = optional(bool)
blocks_creations = optional(bool)
enforce_admins = optional(bool)
lock_branch = optional(bool)
require_signed_commits = optional(bool)
require_conversation_resolution = optional(bool)
push_restrictions = optional(list(string))
force_push_bypassers = optional(list(string))
required_linear_history = optional(bool)
required_pull_request_reviews = optional(object({
dismiss_stale_reviews = optional(bool)
dismissal_restrictions = optional(list(string))
restrict_dismissals = optional(bool)
pull_request_bypassers = optional(list(string))
require_code_owner_reviews = optional(bool)
required_approving_review_count = optional(number)
require_last_push_approval = optional(bool)
}))
required_status_checks = optional(object({
strict = optional(bool)
contexts = optional(list(string))
}))
})))
}))
}

Expand Down
84 changes: 52 additions & 32 deletions terraform/modules/github_repository/branch.tf
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,66 @@ resource "github_branch_default" "main" {
repository = github_repository.repository.name
}

resource "github_branch_protection" "main" {
resource "github_branch_protection" "rules" {
# Branch protection can only be enabled on private repositories if using a
# paid GitHub plan
count = var.visibility == "public" ? 1 : 0
for_each = var.visibility == "public" ? local.branch_protection_rules : tomap({})

repository_id = github_repository.repository.node_id
pattern = var.default_branch
enforce_admins = true
required_linear_history = true
repository_id = github_repository.repository.node_id
pattern = each.key
allows_deletions = try(each.value.allows_deletions, false)
allows_force_pushes = try(each.value.allows_force_pushes, false)
blocks_creations = try(each.value.blocks_creations, false)
enforce_admins = try(each.value.enforce_admins, false)
lock_branch = try(each.value.lock_branch, false)
require_signed_commits = try(each.value.require_signed_commits, false)
require_conversation_resolution = try(each.value.require_conversation_resolution, false)
push_restrictions = try(each.value.push_restrictions, [])
force_push_bypassers = try(each.value.force_push_bypassers, [])
required_linear_history = try(each.value.required_linear_history, false)

required_status_checks {
strict = true
contexts = null
dynamic "required_pull_request_reviews" {
for_each = each.value.required_pull_request_reviews != null ? [1] : []
content {
dismiss_stale_reviews = try(each.value.required_pull_request_reviews.dismiss_stale_reviews, false)
dismissal_restrictions = try(each.value.required_pull_request_reviews.dismissal_restrictions, [])
restrict_dismissals = try(each.value.required_pull_request_reviews.restrict_dismissals, false)
pull_request_bypassers = try(each.value.required_pull_request_reviews.pull_request_bypassers, [])
require_code_owner_reviews = try(each.value.required_pull_request_reviews.require_code_owner_reviews, false)
required_approving_review_count = try(each.value.required_pull_request_reviews.required_approving_review_count, null)
require_last_push_approval = try(each.value.required_pull_request_reviews.require_last_push_approval, false)
}
}

required_pull_request_reviews {
required_approving_review_count = 0
dynamic "required_status_checks" {
for_each = each.value.required_status_checks != null ? [1] : []
content {
strict = try(each.value.required_status_checks.strict, false)
contexts = try(each.value.required_status_checks.contexts, [])
}
}
}


resource "github_branch_protection" "next-release" {
# Branch protection can only be enabled on private repositories if using a
# paid GitHub plan
count = var.visibility == "public" && var.has_release_branches ? 1 : 0

repository_id = github_repository.repository.node_id
pattern = "next-*"
enforce_admins = true
required_linear_history = false
allows_deletions = false
allows_force_pushes = true
blocks_creations = false

required_status_checks {
strict = true
contexts = null
}
# resource "github_branch_protection" "next-release" {
# # Branch protection can only be enabled on private repositories if using a
# # paid GitHub plan
# count = var.visibility == "public" && var.has_release_branches ? 1 : 0

required_pull_request_reviews {
required_approving_review_count = 0
}
}
# repository_id = github_repository.repository.node_id
# pattern = "next-*"
# enforce_admins = true
# required_linear_history = false
# allows_deletions = false
# allows_force_pushes = true
# blocks_creations = false

# required_status_checks {
# strict = true
# contexts = null
# }

# required_pull_request_reviews {
# required_approving_review_count = 0
# }
# }
1 change: 0 additions & 1 deletion terraform/modules/github_repository/repository.tf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ resource "github_repository" "repository" {
has_projects = var.has_projects
has_wiki = var.visibility == "public"


dynamic "pages" {
for_each = local.pages != null ? [1] : []

Expand Down
50 changes: 46 additions & 4 deletions terraform/modules/github_repository/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -133,8 +133,50 @@ variable "delete_branch_on_merge" {
default = true
}

variable "has_release_branches" {
type = bool
description = "Has next-* branches for releases"
default = false
variable "branch_protection_rules" {
description = "The branch protection rules to apply to the repository (the key of the map is the branch pattern to use)"
type = map(object({
allows_deletions = optional(bool)
allows_force_pushes = optional(bool)
blocks_creations = optional(bool)
enforce_admins = optional(bool)
lock_branch = optional(bool)
require_signed_commits = optional(bool)
require_conversation_resolution = optional(bool)
push_restrictions = optional(list(string))
force_push_bypassers = optional(list(string))
required_linear_history = optional(bool)
required_pull_request_reviews = optional(object({
dismiss_stale_reviews = optional(bool)
dismissal_restrictions = optional(list(string))
restrict_dismissals = optional(bool)
pull_request_bypassers = optional(list(string))
require_code_owner_reviews = optional(bool)
required_approving_review_count = optional(number)
require_last_push_approval = optional(bool)
}))
required_status_checks = optional(object({
strict = optional(bool)
contexts = optional(list(string))
}))
}))
default = {}
}
locals {
default_branch_protection_rule = {
"${var.default_branch}" = {
enforce_admins = true
required_linear_history = true
required_status_checks = {
strict = true
}
required_pull_request_reviews = {
required_approving_review_count = 0
}
}
}
branch_protection_rules = merge(
local.default_branch_protection_rule,
var.branch_protection_rules
)
}

0 comments on commit 024a938

Please sign in to comment.