From 81a18f6c585fc9727652b345e4a9302e8fe728fb Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Thu, 2 Oct 2025 16:06:55 -0300 Subject: [PATCH 1/8] feat: update organization_admins structure to only accept one value --- modules/ruleset/organization_ruleset.tf | 6 +++--- modules/ruleset/organization_ruleset.tftest.hcl | 12 +++++------- modules/ruleset/repository_ruleset.tf | 6 +++--- modules/ruleset/repository_ruleset.tftest.hcl | 12 +++++------- modules/ruleset/variables.tf | 6 +++--- 5 files changed, 19 insertions(+), 23 deletions(-) diff --git a/modules/ruleset/organization_ruleset.tf b/modules/ruleset/organization_ruleset.tf index 039726c..f341b99 100644 --- a/modules/ruleset/organization_ruleset.tf +++ b/modules/ruleset/organization_ruleset.tf @@ -161,12 +161,12 @@ resource "github_organization_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.organization_admins, [])) : [] + for_each = var.bypass_actors != null && var.bypass_actors.organization_admins != null ? [1] : [] content { - actor_id = bypass_actors.value.user_id + actor_id = var.bypass_actors.organization_admins.user_id actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + bypass_mode = coalesce(var.bypass_actors.organization_admins.always_bypass, false) ? "always" : "pull_request" } } } diff --git a/modules/ruleset/organization_ruleset.tftest.hcl b/modules/ruleset/organization_ruleset.tftest.hcl index a066e93..aa8e39e 100644 --- a/modules/ruleset/organization_ruleset.tftest.hcl +++ b/modules/ruleset/organization_ruleset.tftest.hcl @@ -100,12 +100,10 @@ variables { always_bypass = false } ] - organization_admins = [ - { - user_id = 444444 - always_bypass = true - } - ] + organization_admins = { + user_id = 444444 + always_bypass = true + } } } @@ -346,7 +344,7 @@ run "bypass_actor_integrations_test" { # Test the Organization Admin bypass actors run "bypass_actor_organization_admins_test" { assert { - condition = github_organization_ruleset.ruleset[0].bypass_actors[3].actor_id == tonumber(var.bypass_actors.organization_admins[0].user_id) + condition = github_organization_ruleset.ruleset[0].bypass_actors[3].actor_id == tonumber(var.bypass_actors.organization_admins.user_id) error_message = "The bypass actor organization admin id is incorrect." } assert { diff --git a/modules/ruleset/repository_ruleset.tf b/modules/ruleset/repository_ruleset.tf index 90662ba..346d2f9 100644 --- a/modules/ruleset/repository_ruleset.tf +++ b/modules/ruleset/repository_ruleset.tf @@ -146,12 +146,12 @@ resource "github_repository_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.organization_admins, [])) : [] + for_each = var.bypass_actors != null && var.bypass_actors.organization_admins != null ? [1] : [] content { - actor_id = bypass_actors.value.user_id + actor_id = var.bypass_actors.organization_admins.user_id actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + bypass_mode = coalesce(var.bypass_actors.organization_admins.always_bypass, false) ? "always" : "pull_request" } } } diff --git a/modules/ruleset/repository_ruleset.tftest.hcl b/modules/ruleset/repository_ruleset.tftest.hcl index 77e7197..3fa0a3a 100644 --- a/modules/ruleset/repository_ruleset.tftest.hcl +++ b/modules/ruleset/repository_ruleset.tftest.hcl @@ -86,12 +86,10 @@ variables { always_bypass = false } ] - organization_admins = [ - { - user_id = 444444 - always_bypass = true - } - ] + organization_admins = { + user_id = 444444 + always_bypass = true + } } } @@ -334,7 +332,7 @@ run "bypass_actor_integrations_test" { # Test the Organization Admin bypass actors run "bypass_actor_organization_admins_test" { assert { - condition = github_repository_ruleset.ruleset[0].bypass_actors[3].actor_id == tonumber(var.bypass_actors.organization_admins[0].user_id) + condition = github_repository_ruleset.ruleset[0].bypass_actors[3].actor_id == tonumber(var.bypass_actors.organization_admins.user_id) error_message = "The bypass actor organization admin id is incorrect." } assert { diff --git a/modules/ruleset/variables.tf b/modules/ruleset/variables.tf index 2ba4590..8db98f2 100644 --- a/modules/ruleset/variables.tf +++ b/modules/ruleset/variables.tf @@ -17,10 +17,10 @@ variable "bypass_actors" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user_id = string + organization_admins = optional(object({ + user_id = number always_bypass = optional(bool) - }))) + })) }) default = {} description = "An object containing fields for role, team, organization admin, and integration bypass actors. Defaults to `{}`" From c287956e6e51cfacf24f0437b2892599c9536c50 Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Thu, 2 Oct 2025 17:53:19 -0300 Subject: [PATCH 2/8] feat: hardcode actor_id to 1 --- modules/ruleset/README.md | 4 ++-- modules/ruleset/organization_ruleset.tf | 7 ++++--- modules/ruleset/organization_ruleset.tftest.hcl | 5 ++--- modules/ruleset/repository_ruleset.tf | 7 ++++--- modules/ruleset/repository_ruleset.tftest.hcl | 5 ++--- modules/ruleset/variables.tf | 3 +-- 6 files changed, 15 insertions(+), 16 deletions(-) diff --git a/modules/ruleset/README.md b/modules/ruleset/README.md index 21f8990..e127634 100644 --- a/modules/ruleset/README.md +++ b/modules/ruleset/README.md @@ -26,7 +26,7 @@ No modules. | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [bypass\_actors](#input\_bypass\_actors) | An object containing fields for role, team, organization admin, and integration bypass actors. Defaults to `{}` |
object({
repository_roles = optional(list(object({
role_id = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team_id = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user_id = string
always_bypass = optional(bool)
})))
})
| `{}` | no | +| [bypass\_actors](#input\_bypass\_actors) | An object containing fields for role, team, organization admin, and integration bypass actors. Defaults to `{}` |
object({
repository_roles = optional(list(object({
role_id = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team_id = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
})
| `{}` | no | | [enforcement](#input\_enforcement) | The enforcement level of the ruleset. Should be one of either `active`, `evaluate` or `disabled`. Defaults to `active` | `string` | `"active"` | no | | [name](#input\_name) | The name of the ruleset. | `string` | n/a | yes | | [ref\_name\_exclusions](#input\_ref\_name\_exclusions) | A list of ref names or patterns to exclude. Defaults to an empty list. If set and `ruleset_type` is set to `organization` then either `repository_name_inclusions` or `repository_name_exclusions` must be set to a list of atleast 1 string. | `list(string)` | `[]` | no | @@ -39,4 +39,4 @@ No modules. ## Outputs -No outputs. \ No newline at end of file +No outputs. diff --git a/modules/ruleset/organization_ruleset.tf b/modules/ruleset/organization_ruleset.tf index f341b99..2e9695b 100644 --- a/modules/ruleset/organization_ruleset.tf +++ b/modules/ruleset/organization_ruleset.tf @@ -161,12 +161,13 @@ resource "github_organization_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors != null && var.bypass_actors.organization_admins != null ? [1] : [] + for_each = var.bypass_actors != null && var.bypass_actors.organization_admin != null ? [1] : [] content { - actor_id = var.bypass_actors.organization_admins.user_id + # Docs suggest the ID can be fixed to 1 - https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#OrganizationAdmin-2 + actor_id = 1 actor_type = "OrganizationAdmin" - bypass_mode = coalesce(var.bypass_actors.organization_admins.always_bypass, false) ? "always" : "pull_request" + bypass_mode = coalesce(var.bypass_actors.organization_admin.always_bypass, false) ? "always" : "pull_request" } } } diff --git a/modules/ruleset/organization_ruleset.tftest.hcl b/modules/ruleset/organization_ruleset.tftest.hcl index aa8e39e..8b9f251 100644 --- a/modules/ruleset/organization_ruleset.tftest.hcl +++ b/modules/ruleset/organization_ruleset.tftest.hcl @@ -100,8 +100,7 @@ variables { always_bypass = false } ] - organization_admins = { - user_id = 444444 + organization_admin = { always_bypass = true } } @@ -344,7 +343,7 @@ run "bypass_actor_integrations_test" { # Test the Organization Admin bypass actors run "bypass_actor_organization_admins_test" { assert { - condition = github_organization_ruleset.ruleset[0].bypass_actors[3].actor_id == tonumber(var.bypass_actors.organization_admins.user_id) + condition = github_organization_ruleset.ruleset[0].bypass_actors[3].actor_id == 1 error_message = "The bypass actor organization admin id is incorrect." } assert { diff --git a/modules/ruleset/repository_ruleset.tf b/modules/ruleset/repository_ruleset.tf index 346d2f9..f22377a 100644 --- a/modules/ruleset/repository_ruleset.tf +++ b/modules/ruleset/repository_ruleset.tf @@ -146,12 +146,13 @@ resource "github_repository_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors != null && var.bypass_actors.organization_admins != null ? [1] : [] + for_each = var.bypass_actors != null && var.bypass_actors.organization_admin != null ? [1] : [] content { - actor_id = var.bypass_actors.organization_admins.user_id + # Docs suggest the ID can be fixed to 1 - https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#OrganizationAdmin-2 + actor_id = 1 actor_type = "OrganizationAdmin" - bypass_mode = coalesce(var.bypass_actors.organization_admins.always_bypass, false) ? "always" : "pull_request" + bypass_mode = coalesce(var.bypass_actors.organization_admin.always_bypass, false) ? "always" : "pull_request" } } } diff --git a/modules/ruleset/repository_ruleset.tftest.hcl b/modules/ruleset/repository_ruleset.tftest.hcl index 3fa0a3a..58f7403 100644 --- a/modules/ruleset/repository_ruleset.tftest.hcl +++ b/modules/ruleset/repository_ruleset.tftest.hcl @@ -86,8 +86,7 @@ variables { always_bypass = false } ] - organization_admins = { - user_id = 444444 + organization_admin = { always_bypass = true } } @@ -332,7 +331,7 @@ run "bypass_actor_integrations_test" { # Test the Organization Admin bypass actors run "bypass_actor_organization_admins_test" { assert { - condition = github_repository_ruleset.ruleset[0].bypass_actors[3].actor_id == tonumber(var.bypass_actors.organization_admins.user_id) + condition = github_repository_ruleset.ruleset[0].bypass_actors[3].actor_id == 1 error_message = "The bypass actor organization admin id is incorrect." } assert { diff --git a/modules/ruleset/variables.tf b/modules/ruleset/variables.tf index 8db98f2..e0c9369 100644 --- a/modules/ruleset/variables.tf +++ b/modules/ruleset/variables.tf @@ -17,8 +17,7 @@ variable "bypass_actors" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(object({ - user_id = number + organization_admin = optional(object({ always_bypass = optional(bool) })) }) From 2bfbc9b65a4885734b2f48c6e429298d536d8dc6 Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Thu, 2 Oct 2025 18:04:53 -0300 Subject: [PATCH 3/8] refactor: update test name for organization admin --- modules/ruleset/organization_ruleset.tftest.hcl | 2 +- modules/ruleset/repository_ruleset.tftest.hcl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ruleset/organization_ruleset.tftest.hcl b/modules/ruleset/organization_ruleset.tftest.hcl index 8b9f251..549e728 100644 --- a/modules/ruleset/organization_ruleset.tftest.hcl +++ b/modules/ruleset/organization_ruleset.tftest.hcl @@ -341,7 +341,7 @@ run "bypass_actor_integrations_test" { } # Test the Organization Admin bypass actors -run "bypass_actor_organization_admins_test" { +run "bypass_actor_organization_admin_test" { assert { condition = github_organization_ruleset.ruleset[0].bypass_actors[3].actor_id == 1 error_message = "The bypass actor organization admin id is incorrect." diff --git a/modules/ruleset/repository_ruleset.tftest.hcl b/modules/ruleset/repository_ruleset.tftest.hcl index 58f7403..836566e 100644 --- a/modules/ruleset/repository_ruleset.tftest.hcl +++ b/modules/ruleset/repository_ruleset.tftest.hcl @@ -329,7 +329,7 @@ run "bypass_actor_integrations_test" { } # Test the Organization Admin bypass actors -run "bypass_actor_organization_admins_test" { +run "bypass_actor_organization_admin_test" { assert { condition = github_repository_ruleset.ruleset[0].bypass_actors[3].actor_id == 1 error_message = "The bypass actor organization admin id is incorrect." From 6641f4ce3711c740a5a58e9e9cc2bc8fa4a8905b Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Thu, 2 Oct 2025 18:12:22 -0300 Subject: [PATCH 4/8] feat: update organization admin structure and name --- modules/internal_repository/variables.tf | 5 ++--- modules/organization/variables.tf | 10 ++++------ modules/private_repository/variables.tf | 5 ++--- modules/public_repository/variables.tf | 5 ++--- modules/repository_base/variables.tf | 5 ++--- modules/repository_set/variables.tf | 8 +++----- 6 files changed, 15 insertions(+), 23 deletions(-) diff --git a/modules/internal_repository/variables.tf b/modules/internal_repository/variables.tf index 2019a8e..0bfdeec 100644 --- a/modules/internal_repository/variables.tf +++ b/modules/internal_repository/variables.tf @@ -203,10 +203,9 @@ variable "rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) conditions = optional(object({ ref_name = object({ diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 99ffb1f..40fc25a 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -183,10 +183,9 @@ variable "default_branch_protection_rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) }) default = {} @@ -207,10 +206,9 @@ variable "rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) conditions = optional(object({ ref_name = object({ diff --git a/modules/private_repository/variables.tf b/modules/private_repository/variables.tf index 3db58e2..9b32d5e 100644 --- a/modules/private_repository/variables.tf +++ b/modules/private_repository/variables.tf @@ -203,10 +203,9 @@ variable "rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) conditions = optional(object({ ref_name = object({ diff --git a/modules/public_repository/variables.tf b/modules/public_repository/variables.tf index 7d5cf79..6e1cc09 100644 --- a/modules/public_repository/variables.tf +++ b/modules/public_repository/variables.tf @@ -197,10 +197,9 @@ variable "rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) conditions = optional(object({ ref_name = object({ diff --git a/modules/repository_base/variables.tf b/modules/repository_base/variables.tf index a8808e5..f2185f2 100644 --- a/modules/repository_base/variables.tf +++ b/modules/repository_base/variables.tf @@ -271,10 +271,9 @@ variable "rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) conditions = optional(object({ ref_name = object({ diff --git a/modules/repository_set/variables.tf b/modules/repository_set/variables.tf index 0c9b883..4b151a0 100644 --- a/modules/repository_set/variables.tf +++ b/modules/repository_set/variables.tf @@ -177,7 +177,7 @@ variable "internal_repositories" { })) })) description = "A map of internal repositories where the key is the repository name and the value is the configuration" - default = {} + default = {} } variable "has_ghas_license" { @@ -207,10 +207,9 @@ variable "rulesets" { installation_id = number always_bypass = optional(bool) }))) - organization_admins = optional(list(object({ - user = string + organization_admin = optional(object({ always_bypass = optional(bool) - }))) + })) })) conditions = optional(object({ ref_name = object({ @@ -278,4 +277,3 @@ variable "rulesets" { })) default = {} } - From 15ca3694df3c0245fbc294b2de442963b640680e Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Thu, 2 Oct 2025 18:26:29 -0300 Subject: [PATCH 5/8] feat: deprecate unnecessary locals and adopt new organization_admin structure --- modules/organization/rulesets.tf | 40 +++--------------------- modules/organization/rulesets.tftest.hcl | 26 +++++---------- modules/repository_base/rulesets.tf | 21 ++----------- 3 files changed, 14 insertions(+), 73 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index e71ab97..559f4e6 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -6,13 +6,6 @@ locals { ]... )) - all_admin_bypassers = toset(concat( - coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []), []), - [ - for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.organization_admins, []), []) - ]... - )) - all_repository_roles_bypassers = toset(concat( coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []), []), [ @@ -37,14 +30,6 @@ data "github_team" "branch_ruleset_bypasser" { summary_only = true } -data "github_user" "branch_ruleset_bypasser" { - for_each = { - for bypasser in local.all_admin_bypassers : bypasser.user => bypasser.user - } - - username = each.value -} - data "github_organization_custom_role" "branch_ruleset_bypasser" { for_each = { for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role @@ -91,10 +76,7 @@ module "ruleset" { team_id = data.github_team.branch_ruleset_bypasser[bypasser.team].id always_bypass = bypasser.always_bypass }] - organization_admins = [for bypasser in try(toset(coalesce(each.value.bypass_actors.organization_admins, [])), []) : { - user_id = data.github_user.branch_ruleset_bypasser[bypasser.user].id - always_bypass = bypasser.always_bypass - }] + organization_admin = try(each.value.bypass_actors.organization_admin, null) integrations = try(each.value.bypass_actors.integrations, []) } @@ -132,10 +114,7 @@ module "base_default_branch_protection" { team_id = data.github_team.branch_ruleset_bypasser[bypasser.team].id always_bypass = bypasser.always_bypass }] - organization_admins = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.organization_admins, [])), []) : { - user_id = data.github_user.branch_ruleset_bypasser[bypasser.user].id - always_bypass = bypasser.always_bypass - }] + organization_admin = try(var.default_branch_protection_rulesets.bypass_actors.organization_admin, null) integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } @@ -169,10 +148,7 @@ module "minimum_approvals" { team_id = data.github_team.branch_ruleset_bypasser[bypasser.team].id always_bypass = bypasser.always_bypass }] - organization_admins = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.organization_admins, [])), []) : { - user_id = data.github_user.branch_ruleset_bypasser[bypasser.user].id - always_bypass = bypasser.always_bypass - }] + organization_admin = try(var.default_branch_protection_rulesets.bypass_actors.organization_admin, null) integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } @@ -206,10 +182,7 @@ module "dismiss_stale_reviews" { team_id = data.github_team.branch_ruleset_bypasser[bypasser.team].id always_bypass = bypasser.always_bypass }] - organization_admins = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.organization_admins, [])), []) : { - user_id = data.github_user.branch_ruleset_bypasser[bypasser.user].id - always_bypass = bypasser.always_bypass - }] + organization_admin = try(var.default_branch_protection_rulesets.bypass_actors.organization_admin, null) integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } @@ -240,10 +213,7 @@ module "require_signatures" { team_id = data.github_team.branch_ruleset_bypasser[bypasser.team].id always_bypass = bypasser.always_bypass }] - organization_admins = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.organization_admins, [])), []) : { - user_id = data.github_user.branch_ruleset_bypasser[bypasser.user].id - always_bypass = bypasser.always_bypass - }] + organization_admin = try(var.default_branch_protection_rulesets.bypass_actors.organization_admin, null) integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } diff --git a/modules/organization/rulesets.tftest.hcl b/modules/organization/rulesets.tftest.hcl index 41f02ec..948685a 100644 --- a/modules/organization/rulesets.tftest.hcl +++ b/modules/organization/rulesets.tftest.hcl @@ -8,13 +8,6 @@ override_data { } } -override_data { - target = data.github_user.branch_ruleset_bypasser["user5"] - values = { - id = 5 - } -} - variables { github_organization_billing_email = "org_billing_email@focisolutions.com" @@ -59,12 +52,9 @@ variables { always_bypass = false } ] - organization_admins = [ - { - user = "user5" - always_bypass = true - } - ] + organization_admin = { + always_bypass = true + } } } @@ -92,12 +82,10 @@ variables { always_bypass = false } ] - organization_admins = [ - { - user = "user5" - always_bypass = true - } - ] + organization_admin = { + always_bypass = true + } + } conditions = { ref_name = { diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index 06a80ec..b68b6fb 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -5,12 +5,6 @@ locals { ] )) - all_admin_bypassers = toset(flatten( - [ - for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.organization_admins, []), []) - ] - )) - all_repository_roles_bypassers = toset(flatten( [ for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, []), []) @@ -34,14 +28,6 @@ data "github_team" "branch_ruleset_bypasser" { summary_only = true } -data "github_user" "branch_ruleset_bypasser" { - for_each = { - for bypasser in local.all_admin_bypassers : bypasser.user => bypasser.user - } - - username = each.value -} - data "github_organization_custom_role" "branch_ruleset_bypasser" { for_each = { for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role @@ -89,11 +75,8 @@ module "ruleset" { team_id = data.github_team.branch_ruleset_bypasser[bypasser.team].id always_bypass = bypasser.always_bypass }] - organization_admins = [for bypasser in try(toset(coalesce(each.value.bypass_actors.organization_admins, [])), []) : { - user_id = data.github_user.branch_ruleset_bypasser[bypasser.user].id - always_bypass = bypasser.always_bypass - }] - integrations = try(each.value.bypass_actors.integrations, []) + organization_admin = try(each.value.bypass_actors.organization_admin, null) + integrations = try(each.value.bypass_actors.integrations, []) } ref_name_inclusions = each.value.conditions.ref_name.include From bac39aafd79c4bd80d09edba24448fc2fbfa1431 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 2 Oct 2025 21:27:16 +0000 Subject: [PATCH 6/8] terraform-docs: automated action --- modules/internal_repository/README.md | 2 +- modules/organization/README.md | 5 ++--- modules/private_repository/README.md | 2 +- modules/public_repository/README.md | 2 +- modules/repository_base/README.md | 3 +-- modules/repository_set/README.md | 2 +- modules/ruleset/README.md | 2 +- 7 files changed, 8 insertions(+), 10 deletions(-) diff --git a/modules/internal_repository/README.md b/modules/internal_repository/README.md index cd2bda2..e4b9f31 100644 --- a/modules/internal_repository/README.md +++ b/modules/internal_repository/README.md @@ -47,7 +47,7 @@ No resources. | [repository\_team\_permissions](#input\_repository\_team\_permissions) | A map where the keys are github team slugs and the value is the permissions the team should have in the repository | `map(string)` | n/a | yes | | [repository\_user\_permissions](#input\_repository\_user\_permissions) | A map where the keys are github usernames and the value is the permissions the user should have in the repository | `map(string)` | n/a | yes | | [requires\_web\_commit\_signing](#input\_requires\_web\_commit\_signing) | If set commit signatures are required for commits to the organization. Defaults to `false`. | `bool` | `false` | no | -| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | +| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | | [squash\_merge\_commit\_message](#input\_squash\_merge\_commit\_message) | (Optional) Can be `PR_BODY`, `COMMIT_MESSAGES`, or `BLANK` for a default squash merge commit message. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_BODY"` | no | | [squash\_merge\_commit\_title](#input\_squash\_merge\_commit\_title) | (Optional) Can be `PR_TITLE` or `COMMIT_OR_PR_TITLE` for a default squash merge commit title. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_TITLE"` | no | | [template\_repository](#input\_template\_repository) | A (Optional) list of template repositories to use for the repository |
object({
owner = string
repository = string
include_all_branches = bool
})
| `null` | no | diff --git a/modules/organization/README.md b/modules/organization/README.md index 7fa5253..4a59941 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -37,7 +37,6 @@ | [github_organization_settings.organization_settings](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_settings) | resource | | [github_organization_custom_role.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/organization_custom_role) | data source | | [github_team.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/team) | data source | -| [github_user.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/user) | data source | ## Inputs @@ -46,7 +45,7 @@ | [actions\_secrets](#input\_actions\_secrets) | A map of organization-level GitHub Actions secrets to create. The key is the name of the secret and the value is an object describing how to create the secret. |
map(object({
encrypted_value = string
visibility = string
}))
| `{}` | no | | [codespaces\_secrets](#input\_codespaces\_secrets) | A map of organization-level GitHub Codespaces secrets to create. The key is the name of the secret and the value is an object describing how to create the secret. |
map(object({
encrypted_value = string
visibility = string
}))
| `{}` | no | | [custom\_repository\_roles](#input\_custom\_repository\_roles) | A map of custom repository roles to create. The key is the name of the role and the value is the role configurations. |
map(object({
description = string
base_role = string
permissions = list(string)
}))
| n/a | yes | -| [default\_branch\_protection\_rulesets](#input\_default\_branch\_protection\_rulesets) | n/a |
object({
base_protection = optional(object({
enforcement = string
}))
minimum_approvals = optional(object({
enforcement = string
approvals_required = number
}))
dismiss_stale_reviews = optional(object({
enforcement = string
}))
require_signatures = optional(object({
enforcement = string
}))
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
})
| `{}` | no | +| [default\_branch\_protection\_rulesets](#input\_default\_branch\_protection\_rulesets) | n/a |
object({
base_protection = optional(object({
enforcement = string
}))
minimum_approvals = optional(object({
enforcement = string
approvals_required = number
}))
dismiss_stale_reviews = optional(object({
enforcement = string
}))
require_signatures = optional(object({
enforcement = string
}))
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
})
| `{}` | no | | [dependabot\_secrets](#input\_dependabot\_secrets) | A map of organization-level Dependabot secrets to create. The key is the name of the secret and the value is an object describing how to create the secret. |
map(object({
encrypted_value = string
visibility = string
}))
| `{}` | no | | [enable\_community\_manager\_role](#input\_enable\_community\_manager\_role) | If `true` will create a custom repository role for community managers. Defaults to `false`. If `true` the maximum number of `custom_repository_roles` that can be defined will be reduced by one. | `bool` | `false` | no | | [enable\_contractor\_role](#input\_enable\_contractor\_role) | If `true` will create a custom repository role for contractors. Defaults to `false`. If `true` the maximum number of `custom_repository_roles` that can be defined will be reduced by one. | `bool` | `false` | no | @@ -66,7 +65,7 @@ | [github\_organization\_pages\_settings](#input\_github\_organization\_pages\_settings) | Settings for organization page creation. The default setting does not allow members to create public and private pages. |
object({
members_can_create_public = bool,
members_can_create_private = bool
})
|
{
"members_can_create_private": false,
"members_can_create_public": false
}
| no | | [github\_organization\_repository\_settings](#input\_github\_organization\_repository\_settings) | Settings for organization repository creation. The default setting allows members to create internal and private repositories but not public. |
object({
members_can_create_public = bool,
members_can_create_internal = bool,
members_can_create_private = bool
})
|
{
"members_can_create_internal": true,
"members_can_create_private": true,
"members_can_create_public": false
}
| no | | [github\_organization\_requires\_web\_commit\_signing](#input\_github\_organization\_requires\_web\_commit\_signing) | If set commit signatures are required for commits to the organization. Defaults to `false`. | `bool` | `false` | no | -| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
repository_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_workflows = optional(object({
required_workflows = list(object({
repository_id = number
path = string
ref = optional(string)
}))
}))
})
target = string
enforcement = string
}))
| `{}` | no | +| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
repository_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_workflows = optional(object({
required_workflows = list(object({
repository_id = number
path = string
ref = optional(string)
}))
}))
})
target = string
enforcement = string
}))
| `{}` | no | ## Outputs diff --git a/modules/private_repository/README.md b/modules/private_repository/README.md index dd33f99..50d1000 100644 --- a/modules/private_repository/README.md +++ b/modules/private_repository/README.md @@ -47,7 +47,7 @@ No resources. | [repository\_team\_permissions](#input\_repository\_team\_permissions) | A map where the keys are github team slugs and the value is the permissions the team should have in the repository | `map(string)` | n/a | yes | | [repository\_user\_permissions](#input\_repository\_user\_permissions) | A map where the keys are github usernames and the value is the permissions the user should have in the repository | `map(string)` | n/a | yes | | [requires\_web\_commit\_signing](#input\_requires\_web\_commit\_signing) | If set commit signatures are required for commits to the organization. Defaults to `false`. | `bool` | `false` | no | -| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | +| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | | [squash\_merge\_commit\_message](#input\_squash\_merge\_commit\_message) | (Optional) Can be `PR_BODY`, `COMMIT_MESSAGES`, or `BLANK` for a default squash merge commit message. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_BODY"` | no | | [squash\_merge\_commit\_title](#input\_squash\_merge\_commit\_title) | (Optional) Can be `PR_TITLE` or `COMMIT_OR_PR_TITLE` for a default squash merge commit title. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_TITLE"` | no | | [template\_repository](#input\_template\_repository) | A (Optional) list of template repositories to use for the repository |
object({
owner = string
repository = string
include_all_branches = bool
})
| `null` | no | diff --git a/modules/public_repository/README.md b/modules/public_repository/README.md index 5fc5ef1..8cc90f1 100644 --- a/modules/public_repository/README.md +++ b/modules/public_repository/README.md @@ -46,7 +46,7 @@ No resources. | [repository\_team\_permissions](#input\_repository\_team\_permissions) | A map where the keys are github team slugs and the value is the permissions the team should have in the repository | `map(string)` | n/a | yes | | [repository\_user\_permissions](#input\_repository\_user\_permissions) | A map where the keys are github usernames and the value is the permissions the user should have in the repository | `map(string)` | n/a | yes | | [requires\_web\_commit\_signing](#input\_requires\_web\_commit\_signing) | If set commit signatures are required for commits to the organization. Defaults to `false`. | `bool` | `false` | no | -| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | +| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | | [squash\_merge\_commit\_message](#input\_squash\_merge\_commit\_message) | (Optional) Can be `PR_BODY`, `COMMIT_MESSAGES`, or `BLANK` for a default squash merge commit message. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_BODY"` | no | | [squash\_merge\_commit\_title](#input\_squash\_merge\_commit\_title) | (Optional) Can be `PR_TITLE` or `COMMIT_OR_PR_TITLE` for a default squash merge commit title. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_TITLE"` | no | | [template\_repository](#input\_template\_repository) | A (Optional) list of template repositories to use for the repository |
object({
owner = string
repository = string
include_all_branches = bool
})
| `null` | no | diff --git a/modules/repository_base/README.md b/modules/repository_base/README.md index 494de8d..48790d0 100644 --- a/modules/repository_base/README.md +++ b/modules/repository_base/README.md @@ -34,7 +34,6 @@ | [github_repository_ruleset.protected_branch_base_rules](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_ruleset) | resource | | [github_organization_custom_role.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/organization_custom_role) | data source | | [github_team.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/team) | data source | -| [github_user.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/user) | data source | ## Inputs @@ -69,7 +68,7 @@ | [repository\_team\_permissions](#input\_repository\_team\_permissions) | A map where the keys are github team slugs and the value is the permissions the team should have in the repository | `map(string)` | n/a | yes | | [repository\_user\_permissions](#input\_repository\_user\_permissions) | A map where the keys are github usernames and the value is the permissions the user should have in the repository | `map(string)` | n/a | yes | | [requires\_web\_commit\_signing](#input\_requires\_web\_commit\_signing) | If set commit signatures are required for commits to the organization. Defaults to `false`. | `bool` | `false` | no | -| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | +| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
}))
| `{}` | no | | [secret\_scanning](#input\_secret\_scanning) | Enables secret scanning for the repository. If repository is private `advance_security` must also be enabled. | `bool` | `true` | no | | [secret\_scanning\_on\_push](#input\_secret\_scanning\_on\_push) | Enables secret scanning push protection for the repository. If repository is private `advance_security` must also be enabled. | `bool` | `true` | no | | [squash\_merge\_commit\_message](#input\_squash\_merge\_commit\_message) | (Optional) Can be `PR_BODY`, `COMMIT_MESSAGES`, or `BLANK` for a default squash merge commit message. Applicable only if allow\_squash\_merge is `true`. | `string` | `"PR_BODY"` | no | diff --git a/modules/repository_set/README.md b/modules/repository_set/README.md index 5b41b63..b49db66 100644 --- a/modules/repository_set/README.md +++ b/modules/repository_set/README.md @@ -36,7 +36,7 @@ | [internal\_repositories](#input\_internal\_repositories) | A map of internal repositories where the key is the repository name and the value is the configuration |
map(object({
description = string
default_branch = string
protected_branches = list(string)
advance_security = bool
topics = list(string)
homepage = string
delete_head_on_merge = bool
dependabot_security_updates = bool
requires_web_commit_signing = bool
allow_auto_merge = optional(bool)
allow_squash_merge = optional(bool)
allow_rebase_merge = optional(bool)
allow_merge_commit = optional(bool)
squash_merge_commit_title = optional(string)
squash_merge_commit_message = optional(string)
merge_commit_title = optional(string)
merge_commit_message = optional(string)
repository_team_permissions_override = optional(map(string))
user_permissions = optional(map(string))
organization_action_secrets = optional(list(string))
organization_codespace_secrets = optional(list(string))
organization_dependabot_secrets = optional(list(string))
action_secrets = optional(map(string))
codespace_secrets = optional(map(string))
dependabot_secrets = optional(map(string))
environments = optional(map(object({
wait_timer = optional(number)
can_admins_bypass = optional(bool)
prevent_self_review = optional(bool)
action_secrets = optional(map(string))
reviewers = optional(object({
teams = optional(list(string))
users = optional(list(string))
}))
deployment_branch_policy = optional(object({
protected_branches = bool
custom_branch_policies = bool
branch_patterns = list(string)
}))
})))
template_repository = optional(object({
owner = string
repository = string
include_all_branches = bool
}))
license_template = optional(string)
pages = optional(object({
source = optional(object({
branch = string
path = optional(string)
}))
build_type = optional(string)
cname = optional(string)
}))
}))
| `{}` | no | | [private\_repositories](#input\_private\_repositories) | A map of private repositories where the key is the repository name and the value is the configuration |
map(object({
description = string
default_branch = string
protected_branches = list(string)
advance_security = bool
has_vulnerability_alerts = bool
topics = list(string)
homepage = string
delete_head_on_merge = bool
requires_web_commit_signing = bool
dependabot_security_updates = bool
allow_auto_merge = optional(bool)
allow_squash_merge = optional(bool)
allow_rebase_merge = optional(bool)
allow_merge_commit = optional(bool)
squash_merge_commit_title = optional(string)
squash_merge_commit_message = optional(string)
merge_commit_title = optional(string)
merge_commit_message = optional(string)
repository_team_permissions_override = optional(map(string))
user_permissions = optional(map(string))
organization_action_secrets = optional(list(string))
organization_codespace_secrets = optional(list(string))
organization_dependabot_secrets = optional(list(string))
action_secrets = optional(map(string))
codespace_secrets = optional(map(string))
dependabot_secrets = optional(map(string))
environments = optional(map(object({
wait_timer = optional(number)
can_admins_bypass = optional(bool)
prevent_self_review = optional(bool)
action_secrets = optional(map(string))
reviewers = optional(object({
teams = optional(list(string))
users = optional(list(string))
}))
deployment_branch_policy = optional(object({
protected_branches = bool
custom_branch_policies = bool
branch_patterns = list(string)
}))
})))
template_repository = optional(object({
owner = string
repository = string
include_all_branches = bool
}))
license_template = optional(string)
pages = optional(object({
source = optional(object({
branch = string
path = optional(string)
}))
build_type = optional(string)
cname = optional(string)
}))
}))
| n/a | yes | | [public\_repositories](#input\_public\_repositories) | A map of public repositories where the key is the repository name and the value is the configuration |
map(object({
description = string
default_branch = string
protected_branches = list(string)
advance_security = bool
topics = list(string)
homepage = string
delete_head_on_merge = bool
dependabot_security_updates = bool
requires_web_commit_signing = bool
allow_auto_merge = optional(bool)
allow_squash_merge = optional(bool)
allow_rebase_merge = optional(bool)
allow_merge_commit = optional(bool)
squash_merge_commit_title = optional(string)
squash_merge_commit_message = optional(string)
merge_commit_title = optional(string)
merge_commit_message = optional(string)
repository_team_permissions_override = optional(map(string))
user_permissions = optional(map(string))
organization_action_secrets = optional(list(string))
organization_codespace_secrets = optional(list(string))
organization_dependabot_secrets = optional(list(string))
action_secrets = optional(map(string))
codespace_secrets = optional(map(string))
dependabot_secrets = optional(map(string))
environments = optional(map(object({
wait_timer = optional(number)
can_admins_bypass = optional(bool)
prevent_self_review = optional(bool)
action_secrets = optional(map(string))
reviewers = optional(object({
teams = optional(list(string))
users = optional(list(string))
}))
deployment_branch_policy = optional(object({
protected_branches = bool
custom_branch_policies = bool
branch_patterns = list(string)
}))
})))
template_repository = optional(object({
owner = string
repository = string
include_all_branches = bool
}))
license_template = optional(string)
pages = optional(object({
source = optional(object({
branch = string
path = optional(string)
}))
build_type = optional(string)
cname = optional(string)
}))
}))
| n/a | yes | -| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admins = optional(list(object({
user = string
always_bypass = optional(bool)
})))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
repositories = list(string)
}))
| `{}` | no | +| [rulesets](#input\_rulesets) | n/a |
map(object({
bypass_actors = optional(object({
repository_roles = optional(list(object({
role = string
always_bypass = optional(bool)
})))
teams = optional(list(object({
team = string
always_bypass = optional(bool)
})))
integrations = optional(list(object({
installation_id = number
always_bypass = optional(bool)
})))
organization_admin = optional(object({
always_bypass = optional(bool)
}))
}))
conditions = optional(object({
ref_name = object({
include = list(string)
exclude = list(string)
})
}))
rules = object({
branch_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
tag_name_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_author_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
commit_message_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
committer_email_pattern = optional(object({
operator = string
pattern = string
name = optional(string)
negate = optional(bool)
}))
creation = optional(bool)
deletion = optional(bool)
update = optional(bool)
non_fast_forward = optional(bool)
required_linear_history = optional(bool)
required_signatures = optional(bool)
update_allows_fetch_and_merge = optional(bool)
pull_request = optional(object({
dismiss_stale_reviews_on_push = optional(bool)
require_code_owner_review = optional(bool)
require_last_push_approval = optional(bool)
required_approving_review_count = optional(number)
required_review_thread_resolution = optional(bool)
}))
required_status_checks = optional(object({
required_check = list(object({
context = string
integration_id = optional(number)
}))
strict_required_status_check_policy = optional(bool)
}))
required_deployment_environments = optional(list(string))
})
target = string
enforcement = string
repositories = list(string)
}))
| `{}` | no | ## Outputs diff --git a/modules/ruleset/README.md b/modules/ruleset/README.md index e127634..6869210 100644 --- a/modules/ruleset/README.md +++ b/modules/ruleset/README.md @@ -39,4 +39,4 @@ No modules. ## Outputs -No outputs. +No outputs. \ No newline at end of file From 7f169ccf30e8544059cfcc625e427ddfcc682289 Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Thu, 2 Oct 2025 18:42:52 -0300 Subject: [PATCH 7/8] refactor: address gemini comments --- modules/ruleset/organization_ruleset.tf | 2 +- modules/ruleset/repository_ruleset.tf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/ruleset/organization_ruleset.tf b/modules/ruleset/organization_ruleset.tf index 2e9695b..7e7bbb3 100644 --- a/modules/ruleset/organization_ruleset.tf +++ b/modules/ruleset/organization_ruleset.tf @@ -161,7 +161,7 @@ resource "github_organization_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors != null && var.bypass_actors.organization_admin != null ? [1] : [] + for_each = var.bypass_actors.organization_admin != null ? [1] : [] content { # Docs suggest the ID can be fixed to 1 - https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#OrganizationAdmin-2 diff --git a/modules/ruleset/repository_ruleset.tf b/modules/ruleset/repository_ruleset.tf index f22377a..7bfcd59 100644 --- a/modules/ruleset/repository_ruleset.tf +++ b/modules/ruleset/repository_ruleset.tf @@ -146,10 +146,10 @@ resource "github_repository_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors != null && var.bypass_actors.organization_admin != null ? [1] : [] + for_each = var.bypass_actors.organization_admin != null ? [1] : [] content { - # Docs suggest the ID can be fixed to 1 - https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#OrganizationAdmin-2 + # Docs suggest the ID can be fixed to 1 - https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_ruleset#OrganizationAdmin-1 actor_id = 1 actor_type = "OrganizationAdmin" bypass_mode = coalesce(var.bypass_actors.organization_admin.always_bypass, false) ? "always" : "pull_request" From ec589b69a716e4d7097706ba0ce8ad585a1b848b Mon Sep 17 00:00:00 2001 From: vedantthapa Date: Fri, 3 Oct 2025 10:30:50 -0300 Subject: [PATCH 8/8] refactor: update to organization_admin in examples --- examples/ruleset/organization-ruleset.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/ruleset/organization-ruleset.tf b/examples/ruleset/organization-ruleset.tf index 1d24a5b..e13443d 100644 --- a/examples/ruleset/organization-ruleset.tf +++ b/examples/ruleset/organization-ruleset.tf @@ -3,9 +3,9 @@ module "github_org_ruleset" { name = "org-wide-main-pr-rules" bypass_actors = { - organization_admins = [ - { user_id = "admin_id", always_bypass = true } - ] + organization_admin = { + always_bypass = true + } } rules = { branch_name_pattern = {