From 91d08851dfb4e0a437b67479123ed8a1c640e138 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 13:55:51 -0400 Subject: [PATCH 01/72] fmted and wip of ruleset support. Testing out setting bypasses --- modules/organization/rulesets.tf | 91 +++++++++++++++++++ modules/organization/variables.tf | 31 +++++-- modules/private_repository/outputs.tf | 2 +- modules/private_repository/variables.tf | 8 +- modules/public_repository/outputs.tf | 2 +- modules/public_repository/repository.tf | 2 +- modules/public_repository/variables.tf | 8 +- modules/repository_base/outputs.tf | 2 +- modules/repository_base/variables.tf | 2 +- .../repository_set/organization-secrets.tf | 8 +- 10 files changed, 133 insertions(+), 23 deletions(-) create mode 100644 modules/organization/rulesets.tf diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf new file mode 100644 index 0000000..4bf4099 --- /dev/null +++ b/modules/organization/rulesets.tf @@ -0,0 +1,91 @@ +locals { + branch_ruleset_team_bypassers = [ + for ruleset, ruleset_config in var.branch_rulesets : { + for team_slug in ruleset_config.bypass_actors.teams : "${ruleset}:${team_slug}" => team_slug + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null + ] + + branch_ruleset_app_bypassers = [ + for ruleset, ruleset_config in var.branch_rulesets : { + for app_slug in ruleset_config.bypass_actors.integrations : "${ruleset}:${app_slug}" => app_slug + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.integrations != null + ] + + branch_ruleset_admin_bypassers = [ + for ruleset, ruleset_config in var.branch_rulesets : { + for user in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${user}" => user + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null + ] +} + + +data "github_team" "branch_ruleset_bypasser" { + for_each = local.branch_ruleset_team_bypassers + + slug = each.value + summary_only = true +} + +data "github_app" "branch_ruleset_bypasser" { + for_each = local.branch_ruleset_app_bypassers + + slug = each.value +} + +data "github_user" "branch_ruleset_bypasser" { + for_each = local.branch_ruleset_admin_bypassers + + username = each.value +} + +resource "organization_ruleset" "branch_ruleset" { + for_each = var.branch_ruleset + + name = each.key + target = "branch" + enforcement = each.value.disable != null && each.value.disable ? "disabled" : "active" #Might want this to just be a string so it can also be set to evaluate + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] + + content { + actor_id = bypass_actors.value + actor_type = "RepositoryRole" + bypass_mode = "always" + } + } + + rules { + + } + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] + + content { + actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].id + actor_type = "Team" + bypass_mode = "always" #Todo make configurable + } + } + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.integrations, [])) : [] + + content { + actor_id = data.github_app.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].node_id + actor_type = "Integration" + bypass_mode = "always" + } + } + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] + + content { + actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].id + actor_type = "OrganizationAdmin" + bypass_mode = "always" + } + } +} \ No newline at end of file diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 271739b..d13ec49 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -135,8 +135,8 @@ variable "custom_repository_roles" { variable "actions_secrets" { type = map(object({ - encrypted_value = string - visibility = string + encrypted_value = string + visibility = string })) description = "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." default = {} @@ -144,8 +144,8 @@ variable "actions_secrets" { variable "codespaces_secrets" { type = map(object({ - encrypted_value = string - visibility = string + encrypted_value = string + visibility = string })) description = "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." default = {} @@ -153,10 +153,29 @@ variable "codespaces_secrets" { variable "dependabot_secrets" { type = map(object({ - encrypted_value = string - visibility = string + encrypted_value = string + visibility = string })) description = "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." default = {} } +variable "branch_rulesets" { + type = map(object({ + bypass_actors = optional(object({ + repository_roles = list(string) + teams = list(string) + integrations = list(string) + organization_admins = list(string) + })) + disable = optional(boolean) + })) + default = {} +} + +variable "tag_rulesets" { + type = map(object({ + disable = optional(boolean) + })) + default = {} +} \ No newline at end of file diff --git a/modules/private_repository/outputs.tf b/modules/private_repository/outputs.tf index 0d1a523..c3adac2 100644 --- a/modules/private_repository/outputs.tf +++ b/modules/private_repository/outputs.tf @@ -1,4 +1,4 @@ output "id" { - value = module.repository_base.id + value = module.repository_base.id description = "The ID of the repository" } \ No newline at end of file diff --git a/modules/private_repository/variables.tf b/modules/private_repository/variables.tf index b9a111a..d1712bd 100644 --- a/modules/private_repository/variables.tf +++ b/modules/private_repository/variables.tf @@ -65,19 +65,19 @@ variable "advance_security" { variable "action_secrets" { description = "An (Optional) map of GitHub Actions secrets to create for this repository. The key is the name of the secret and the value is the encrypted value." type = map(string) - default = {} + default = {} } variable "codespace_secrets" { description = "An (Optional) map of Github Codespace secrets to create for this repository. The key is the name of the secret and the value is the encrypted value." type = map(string) - default = {} + default = {} } variable "dependabot_secrets" { description = "An (Optional) map of Dependabot secrets to create for this repository. The key is the name of the secret and the value is the encrypted value." type = map(string) - default = {} + default = {} } variable "environments" { @@ -90,7 +90,7 @@ variable "environments" { variable "template_repository" { description = "A (Optional) list of template repositories to use for the repository" - type = object({ + type = object({ owner = string repository = string include_all_branches = bool diff --git a/modules/public_repository/outputs.tf b/modules/public_repository/outputs.tf index 0d1a523..c3adac2 100644 --- a/modules/public_repository/outputs.tf +++ b/modules/public_repository/outputs.tf @@ -1,4 +1,4 @@ output "id" { - value = module.repository_base.id + value = module.repository_base.id description = "The ID of the repository" } \ No newline at end of file diff --git a/modules/public_repository/repository.tf b/modules/public_repository/repository.tf index 7eb7e5e..4e60eb7 100644 --- a/modules/public_repository/repository.tf +++ b/modules/public_repository/repository.tf @@ -30,7 +30,7 @@ module "repository_base" { action_secrets = var.action_secrets environments = var.environments - + template_repository = var.template_repository license_template = var.license_template } \ No newline at end of file diff --git a/modules/public_repository/variables.tf b/modules/public_repository/variables.tf index 3e84e32..16dcf34 100644 --- a/modules/public_repository/variables.tf +++ b/modules/public_repository/variables.tf @@ -65,19 +65,19 @@ variable "advance_security" { variable "action_secrets" { description = "An (Optional) map of GitHub Actions secrets to create for this repository. The key is the name of the secret and the value is the encrypted value." type = map(string) - default = {} + default = {} } variable "codespace_secrets" { description = "An (Optional) map of GitHub Codespace secrets to create for this repository. The key is the name of the secret and the value is the encrypted value." type = map(string) - default = {} + default = {} } variable "dependabot_secrets" { description = "An (Optional) map of Dependabot secrets to create for this repository. The key is the name of the secret and the value is the encrypted value." type = map(string) - default = {} + default = {} } variable "environments" { @@ -90,7 +90,7 @@ variable "environments" { variable "template_repository" { description = "A (Optional) list of template repositories to use for the repository" - type = object({ + type = object({ owner = string repository = string include_all_branches = bool diff --git a/modules/repository_base/outputs.tf b/modules/repository_base/outputs.tf index 33078a8..1d91b91 100644 --- a/modules/repository_base/outputs.tf +++ b/modules/repository_base/outputs.tf @@ -1,4 +1,4 @@ output "id" { - value = github_repository.repository.repo_id + value = github_repository.repository.repo_id description = "The ID of the repository" } \ No newline at end of file diff --git a/modules/repository_base/variables.tf b/modules/repository_base/variables.tf index a9a2f0d..bd3e647 100644 --- a/modules/repository_base/variables.tf +++ b/modules/repository_base/variables.tf @@ -144,7 +144,7 @@ variable "environments" { variable "template_repository" { description = "A (Optional) list of template repositories to use for the repository" - type = object({ + type = object({ owner = string repository = string include_all_branches = bool diff --git a/modules/repository_set/organization-secrets.tf b/modules/repository_set/organization-secrets.tf index 12c0127..599a08c 100644 --- a/modules/repository_set/organization-secrets.tf +++ b/modules/repository_set/organization-secrets.tf @@ -1,5 +1,5 @@ locals { - coalesced_public_repositories = coalesce(var.public_repositories, {}) + coalesced_public_repositories = coalesce(var.public_repositories, {}) coalesced_private_repositories = coalesce(var.private_repositories, {}) organization_action_secrets = distinct(flatten(concat( @@ -42,20 +42,20 @@ locals { resource "github_actions_organization_secret_repositories" "org__action_secret_repo_access" { for_each = local.organization_action_secrets_repository_id_list - secret_name = each.key + secret_name = each.key selected_repository_ids = each.value } resource "github_codespaces_organization_secret_repositories" "org__codespace_secret_repo_access" { for_each = local.codespace_secrets_repository_id_list - secret_name = each.key + secret_name = each.key selected_repository_ids = each.value } resource "github_dependabot_organization_secret_repositories" "org__dependabot_secret_repo_access" { for_each = local.dependabot_secrets_id_list - secret_name = each.key + secret_name = each.key selected_repository_ids = each.value } \ No newline at end of file From 0e403a26886054a87f91dadaba82db19999eebd7 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:08:40 -0400 Subject: [PATCH 02/72] typo --- modules/organization/rulesets.tf | 2 +- modules/organization/variables.tf | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 4bf4099..0a6639a 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -56,7 +56,7 @@ resource "organization_ruleset" "branch_ruleset" { } rules { - + } dynamic "bypass_actors" { diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index d13ec49..00760da 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -168,14 +168,14 @@ variable "branch_rulesets" { integrations = list(string) organization_admins = list(string) })) - disable = optional(boolean) + disable = optional(bool) })) default = {} } variable "tag_rulesets" { type = map(object({ - disable = optional(boolean) + disable = optional(bool) })) default = {} } \ No newline at end of file From f8045f8fe8af8b7bd8f39a273a643315488da380 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:15:31 -0400 Subject: [PATCH 03/72] Bad resource name --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 0a6639a..26c3c23 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -38,7 +38,7 @@ data "github_user" "branch_ruleset_bypasser" { username = each.value } -resource "organization_ruleset" "branch_ruleset" { +resource "github_organization_ruleset" "branch_ruleset" { for_each = var.branch_ruleset name = each.key From c137dbab610f369b604e87f0e0287b580e57938c Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:16:59 -0400 Subject: [PATCH 04/72] bad var reference --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 26c3c23..3dd247b 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -39,7 +39,7 @@ data "github_user" "branch_ruleset_bypasser" { } resource "github_organization_ruleset" "branch_ruleset" { - for_each = var.branch_ruleset + for_each = var.branch_rulesets name = each.key target = "branch" From 832fa421e6ae54f1d2a0a99b240e5364bc7a9763 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:20:45 -0400 Subject: [PATCH 05/72] have to merge all the maps --- modules/organization/rulesets.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 3dd247b..2cfb145 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,21 +1,21 @@ locals { - branch_ruleset_team_bypassers = [ + branch_ruleset_team_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { for team_slug in ruleset_config.bypass_actors.teams : "${ruleset}:${team_slug}" => team_slug } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null - ] + ]...) - branch_ruleset_app_bypassers = [ + branch_ruleset_app_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { for app_slug in ruleset_config.bypass_actors.integrations : "${ruleset}:${app_slug}" => app_slug } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.integrations != null - ] + ]...) - branch_ruleset_admin_bypassers = [ + branch_ruleset_admin_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { for user in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${user}" => user } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null - ] + ]...) } From 43f4ba7bdb1caec3057b9f8f8271d85c9959b2dc Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:21:46 -0400 Subject: [PATCH 06/72] coalesece disable --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 2cfb145..a206f5e 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -43,7 +43,7 @@ resource "github_organization_ruleset" "branch_ruleset" { name = each.key target = "branch" - enforcement = each.value.disable != null && each.value.disable ? "disabled" : "active" #Might want this to just be a string so it can also be set to evaluate + enforcement = coalesce(each.value.disable, false) ? "disabled" : "active" #Might want this to just be a string so it can also be set to evaluate dynamic "bypass_actors" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] From 3c8e824cd936bc454a38b22aec10fe8c414b15c7 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:35:57 -0400 Subject: [PATCH 07/72] Removed github app datasource --- modules/organization/rulesets.tf | 35 +++++++++++++++++++------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index a206f5e..996ae71 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -5,17 +5,23 @@ locals { } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null ]...) - branch_ruleset_app_bypassers = merge([ - for ruleset, ruleset_config in var.branch_rulesets : { - for app_slug in ruleset_config.bypass_actors.integrations : "${ruleset}:${app_slug}" => app_slug - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.integrations != null - ]...) - branch_ruleset_admin_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { for user in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${user}" => user } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null ]...) + + branch_ruleset_custom_repository_roles = merge([ + for ruleset, ruleset_config in var.branch_rulesets : { + for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null && !contains(keys(github_base_role_ids), role) + ]...) + + github_base_role_ids = { + "maintain" = 2 + "write" = 4 + "admin" = 5 + } } @@ -26,18 +32,19 @@ data "github_team" "branch_ruleset_bypasser" { summary_only = true } -data "github_app" "branch_ruleset_bypasser" { - for_each = local.branch_ruleset_app_bypassers - - slug = each.value -} - data "github_user" "branch_ruleset_bypasser" { for_each = local.branch_ruleset_admin_bypassers username = each.value } +#github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles +data "github_organization_custom_role" "branch_ruleset_bypasser" { + for_each = local.branch_ruleset_custom_repository_roles + + name = each.value +} + resource "github_organization_ruleset" "branch_ruleset" { for_each = var.branch_rulesets @@ -49,7 +56,7 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] content { - actor_id = bypass_actors.value + actor_id = lookup(github_base_role_ids, bypass_actors.value, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"]) actor_type = "RepositoryRole" bypass_mode = "always" } @@ -73,7 +80,7 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.integrations, [])) : [] content { - actor_id = data.github_app.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].node_id + actor_id = bypass_actors.value actor_type = "Integration" bypass_mode = "always" } From 05ef245fd71fc313987afaaa0c6096301f4ea5d5 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:36:55 -0400 Subject: [PATCH 08/72] changed list(string) to list(number) --- modules/organization/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 00760da..8f490e3 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -165,7 +165,7 @@ variable "branch_rulesets" { bypass_actors = optional(object({ repository_roles = list(string) teams = list(string) - integrations = list(string) + integrations = list(number) organization_admins = list(string) })) disable = optional(bool) From dac45edf59da84d22e70996f0fa3e86dc107db44 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:38:08 -0400 Subject: [PATCH 09/72] I need to get my linting working --- modules/organization/rulesets.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 996ae71..a0f35df 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -14,7 +14,7 @@ locals { branch_ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.branch_rulesets : { for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null && !contains(keys(github_base_role_ids), role) + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null && !contains(keys(local.github_base_role_ids), role) ]...) github_base_role_ids = { @@ -56,7 +56,7 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] content { - actor_id = lookup(github_base_role_ids, bypass_actors.value, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"]) + actor_id = lookup(local.github_base_role_ids, bypass_actors.value, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"]) actor_type = "RepositoryRole" bypass_mode = "always" } From 1be1393b70b834c57876a5166d7465fb7fe928da Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:39:51 -0400 Subject: [PATCH 10/72] moved conditional --- modules/organization/rulesets.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index a0f35df..590c631 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -13,8 +13,8 @@ locals { branch_ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null && !contains(keys(local.github_base_role_ids), role) + for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role if !contains(keys(local.github_base_role_ids)) + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null ]...) github_base_role_ids = { From 2b21c6a62524925d4dcab1efc78ab063c2147b53 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:40:47 -0400 Subject: [PATCH 11/72] I don't know how that happened --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 590c631..b2984d7 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -13,7 +13,7 @@ locals { branch_ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role if !contains(keys(local.github_base_role_ids)) + for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role if !contains(keys(local.github_base_role_ids), role) } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null ]...) From 8522c036b6b76d05f1665aea75e4c94e256ed89c Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:43:35 -0400 Subject: [PATCH 12/72] forgot to access id from datasource --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index b2984d7..1736775 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -56,7 +56,7 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"]) + actor_id = lookup(local.github_base_role_ids, bypass_actors.value, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].id) actor_type = "RepositoryRole" bypass_mode = "always" } From 6f11801324f1506af69615838e5af4c5ec689ea1 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:52:44 -0400 Subject: [PATCH 13/72] allow for bypass mode to be changed --- modules/organization/rulesets.tf | 22 +++++++++++----------- modules/organization/variables.tf | 20 ++++++++++++++++---- 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 1736775..056b178 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,19 +1,19 @@ locals { branch_ruleset_team_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for team_slug in ruleset_config.bypass_actors.teams : "${ruleset}:${team_slug}" => team_slug + for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser}" => bypasser.team } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null ]...) branch_ruleset_admin_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for user in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${user}" => user + for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser}" => bypasser.user } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null ]...) branch_ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for role in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${role}" => role if !contains(keys(local.github_base_role_ids), role) + for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null ]...) @@ -56,9 +56,9 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].id) + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.role}"].id) actor_type = "RepositoryRole" - bypass_mode = "always" + bypass_mode = bypass_actors.value.always_bypass ? "always" : "pull_request" } } @@ -70,9 +70,9 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] content { - actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].id + actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.team}"].id actor_type = "Team" - bypass_mode = "always" #Todo make configurable + bypass_mode =bypass_actors.value.always_bypass ? "always" : "pull_request" } } @@ -80,9 +80,9 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.integrations, [])) : [] content { - actor_id = bypass_actors.value + actor_id = bypass_actors.value.installation_id actor_type = "Integration" - bypass_mode = "always" + bypass_mode = bypass_actors.value.always_bypass ? "always" : "pull_request" } } @@ -90,9 +90,9 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] content { - actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value}"].id + actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.user}"].id actor_type = "OrganizationAdmin" - bypass_mode = "always" + bypass_mode = bypass_actors.value.always_bypass ? "always" : "pull_request" } } } \ No newline at end of file diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 8f490e3..146d6f9 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -163,10 +163,22 @@ variable "dependabot_secrets" { variable "branch_rulesets" { type = map(object({ bypass_actors = optional(object({ - repository_roles = list(string) - teams = list(string) - integrations = list(number) - organization_admins = list(string) + 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) + }))) })) disable = optional(bool) })) From 2c164ac420634155811a5826a43c576a608a0246 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:55:15 -0400 Subject: [PATCH 14/72] come on tyler --- modules/organization/rulesets.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 056b178..41c597c 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,19 +1,19 @@ locals { branch_ruleset_team_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser}" => bypasser.team + for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser.team}" => bypasser.team } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null ]...) branch_ruleset_admin_bypassers = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser}" => bypasser.user + for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser.user}" => bypasser.user } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null ]...) branch_ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.branch_rulesets : { - for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) + for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null ]...) From 56e53cb37c11e7b1feee8f3c7ee7983ebbabbbec Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 14:56:45 -0400 Subject: [PATCH 15/72] coallesce always bypass to false --- modules/organization/rulesets.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 41c597c..8092f1a 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -58,7 +58,7 @@ resource "github_organization_ruleset" "branch_ruleset" { content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.role}"].id) actor_type = "RepositoryRole" - bypass_mode = bypass_actors.value.always_bypass ? "always" : "pull_request" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } } @@ -72,7 +72,7 @@ resource "github_organization_ruleset" "branch_ruleset" { content { actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.team}"].id actor_type = "Team" - bypass_mode =bypass_actors.value.always_bypass ? "always" : "pull_request" + bypass_mode =coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } } @@ -82,7 +82,7 @@ resource "github_organization_ruleset" "branch_ruleset" { content { actor_id = bypass_actors.value.installation_id actor_type = "Integration" - bypass_mode = bypass_actors.value.always_bypass ? "always" : "pull_request" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } } @@ -92,7 +92,7 @@ resource "github_organization_ruleset" "branch_ruleset" { content { actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.user}"].id actor_type = "OrganizationAdmin" - bypass_mode = bypass_actors.value.always_bypass ? "always" : "pull_request" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } } } \ No newline at end of file From 9b8714196e2dc27f0631df97cc2db9c13f46fbb4 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:43:25 -0400 Subject: [PATCH 16/72] first iteration of allowing rule definition --- modules/organization/rulesets.tf | 98 +++++++++++++++++++++++++++++-- modules/organization/variables.tf | 67 ++++++++++++++++++--- 2 files changed, 153 insertions(+), 12 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 8092f1a..853e8ee 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -19,8 +19,8 @@ locals { github_base_role_ids = { "maintain" = 2 - "write" = 4 - "admin" = 5 + "write" = 4 + "admin" = 5 } } @@ -40,9 +40,9 @@ data "github_user" "branch_ruleset_bypasser" { #github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { - for_each = local.branch_ruleset_custom_repository_roles + for_each = local.branch_ruleset_custom_repository_roles - name = each.value + name = each.value } resource "github_organization_ruleset" "branch_ruleset" { @@ -63,7 +63,95 @@ resource "github_organization_ruleset" "branch_ruleset" { } rules { + dynamic "branch_name_pattern" { + for_each = toset(compact([each.value.rules.branch_name_pattern])) + + content { + operator = branch_name_pattern.value.operator + pattern = branch_name_pattern.value.pattern + name = branch_name_pattern.value.name + negate = coalesce(branch_name_pattern.value.negate, false) + } + } + + dynamic "commit_author_email_pattern" { + for_each = toset(compact([each.value.rules.commit_author_email_pattern])) + + content { + operator = commit_author_email_pattern.value.operator + pattern = commit_author_email_pattern.value.pattern + name = commit_author_email_pattern.value.name + negate = coalesce(commit_author_email_pattern.value.negate, false) + } + } + + dynamic "commit_message_pattern" { + for_each = toset(compact([each.value.rules.commit_message_pattern])) + + content { + operator = commit_message_pattern.value.operator + pattern = commit_message_pattern.value.pattern + name = commit_message_pattern.value.name + negate = coalesce(commit_message_pattern.value.negate, false) + } + } + + dynamic "committer_email_pattern" { + for_each = toset(compact([each.value.rules.committer_email_pattern])) + + content { + operator = committer_email_pattern.value.operator + pattern = committer_email_pattern.value.pattern + name = committer_email_pattern.value.name + negate = coalesce(committer_email_pattern.value.negate, false) + } + } + + dynamic "pull_request" { + for_each = toset(compact([each.value.rules.pull_request])) + content { + dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) + require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) + require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) + required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) + required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) + } + } + + dynamic "required_status_checks" { + for_each = toset(compact([each.value.rules.required_status_checks])) + + content { + strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + + dynamic "required_check" { + for_each = required_status_checks.required_check + + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } + } + } + + dynamic "required_workflows" { + for_each = toset(compact([each.value.rules.required_workflows])) + + content { + + dynamic "required_workflow" { + for_each = required_workflows.value.required_workflows + + content { + repository_id = required_workflow.value.repository_id + path = required_workflow.value.path + ref = coalesce(required_workflow.value.ref, "main") + } + } + } + } } dynamic "bypass_actors" { @@ -72,7 +160,7 @@ resource "github_organization_ruleset" "branch_ruleset" { content { actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.team}"].id actor_type = "Team" - bypass_mode =coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } } diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 146d6f9..be5db59 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -163,23 +163,76 @@ variable "dependabot_secrets" { variable "branch_rulesets" { type = map(object({ bypass_actors = optional(object({ - repository_roles = optional(list(object({ - role = string + repository_roles = optional(list(object({ + role = string always_bypass = optional(bool) }))) - teams = optional(list(object({ - team = string + teams = optional(list(object({ + team = string always_bypass = optional(bool) }))) - integrations = optional(list(object({ + integrations = optional(list(object({ installation_id = number - always_bypass = optional(bool) + always_bypass = optional(bool) }))) organization_admins = optional(list(object({ - user = string + user = string always_bypass = optional(bool) }))) })) + rules = object({ + branch_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) + })) + comitter_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) + })) + })) + }) disable = optional(bool) })) default = {} From c14cbd4917c265bde128ca7d9de1602d09c911c7 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:46:42 -0400 Subject: [PATCH 17/72] testing removal of problem rules --- modules/organization/rulesets.tf | 66 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 853e8ee..9c29948 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -119,39 +119,39 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - dynamic "required_status_checks" { - for_each = toset(compact([each.value.rules.required_status_checks])) - - content { - strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - - dynamic "required_check" { - for_each = required_status_checks.required_check - - content { - context = required_check.value.context - integration_id = required_check.value.integration_id - } - } - } - } - - dynamic "required_workflows" { - for_each = toset(compact([each.value.rules.required_workflows])) - - content { - - dynamic "required_workflow" { - for_each = required_workflows.value.required_workflows - - content { - repository_id = required_workflow.value.repository_id - path = required_workflow.value.path - ref = coalesce(required_workflow.value.ref, "main") - } - } - } - } + # dynamic "required_status_checks" { + # for_each = toset(compact([each.value.rules.required_status_checks])) + + # content { + # strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + + # dynamic "required_check" { + # for_each = required_status_checks.required_check + + # content { + # context = required_check.value.context + # integration_id = required_check.value.integration_id + # } + # } + # } + # } + + # dynamic "required_workflows" { + # for_each = toset(compact([each.value.rules.required_workflows])) + + # content { + + # dynamic "required_workflow" { + # for_each = required_workflows.value.required_workflows + + # content { + # repository_id = required_workflow.value.repository_id + # path = required_workflow.value.path + # ref = coalesce(required_workflow.value.ref, "main") + # } + # } + # } + # } } dynamic "bypass_actors" { From 08ca2b3994614a0adc3f81d3a745e8fa54e450a8 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:51:06 -0400 Subject: [PATCH 18/72] changed toset and compact to use a try instead of compact --- modules/organization/rulesets.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 9c29948..4b53eb4 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -64,7 +64,7 @@ resource "github_organization_ruleset" "branch_ruleset" { rules { dynamic "branch_name_pattern" { - for_each = toset(compact([each.value.rules.branch_name_pattern])) + for_each = try(toset([each.value.rules.branch_name_pattern]), []) content { operator = branch_name_pattern.value.operator @@ -75,7 +75,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "commit_author_email_pattern" { - for_each = toset(compact([each.value.rules.commit_author_email_pattern])) + for_each = try(toset([each.value.rules.commit_author_email_pattern]), []) content { operator = commit_author_email_pattern.value.operator @@ -86,7 +86,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "commit_message_pattern" { - for_each = toset(compact([each.value.rules.commit_message_pattern])) + for_each = try(toset([each.value.rules.commit_message_pattern]), []) content { operator = commit_message_pattern.value.operator @@ -97,7 +97,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "committer_email_pattern" { - for_each = toset(compact([each.value.rules.committer_email_pattern])) + for_each = try(toset([each.value.rules.committer_email_pattern]), []) content { operator = committer_email_pattern.value.operator @@ -108,7 +108,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "pull_request" { - for_each = toset(compact([each.value.rules.pull_request])) + for_each = try(toset([each.value.rules.pull_request]), []) content { dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) From f3bfa7121cf1d3fabc9def92c3d765785d119085 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:53:00 -0400 Subject: [PATCH 19/72] focusing on branch_name_pattern --- modules/organization/rulesets.tf | 80 ++++++++++++++++---------------- 1 file changed, 40 insertions(+), 40 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 4b53eb4..04dcf22 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -67,57 +67,57 @@ resource "github_organization_ruleset" "branch_ruleset" { for_each = try(toset([each.value.rules.branch_name_pattern]), []) content { - operator = branch_name_pattern.value.operator - pattern = branch_name_pattern.value.pattern - name = branch_name_pattern.value.name + operator = try(branch_name_pattern.value.operator, "") + pattern = try(branch_name_pattern.value.pattern, "") + name = try(branch_name_pattern.value.name, "") negate = coalesce(branch_name_pattern.value.negate, false) } } - dynamic "commit_author_email_pattern" { - for_each = try(toset([each.value.rules.commit_author_email_pattern]), []) + # dynamic "commit_author_email_pattern" { + # for_each = try(toset([each.value.rules.commit_author_email_pattern]), []) - content { - operator = commit_author_email_pattern.value.operator - pattern = commit_author_email_pattern.value.pattern - name = commit_author_email_pattern.value.name - negate = coalesce(commit_author_email_pattern.value.negate, false) - } - } + # content { + # operator = commit_author_email_pattern.value.operator + # pattern = commit_author_email_pattern.value.pattern + # name = commit_author_email_pattern.value.name + # negate = coalesce(commit_author_email_pattern.value.negate, false) + # } + # } - dynamic "commit_message_pattern" { - for_each = try(toset([each.value.rules.commit_message_pattern]), []) + # dynamic "commit_message_pattern" { + # for_each = try(toset([each.value.rules.commit_message_pattern]), []) - content { - operator = commit_message_pattern.value.operator - pattern = commit_message_pattern.value.pattern - name = commit_message_pattern.value.name - negate = coalesce(commit_message_pattern.value.negate, false) - } - } + # content { + # operator = commit_message_pattern.value.operator + # pattern = commit_message_pattern.value.pattern + # name = commit_message_pattern.value.name + # negate = coalesce(commit_message_pattern.value.negate, false) + # } + # } - dynamic "committer_email_pattern" { - for_each = try(toset([each.value.rules.committer_email_pattern]), []) + # dynamic "committer_email_pattern" { + # for_each = try(toset([each.value.rules.committer_email_pattern]), []) - content { - operator = committer_email_pattern.value.operator - pattern = committer_email_pattern.value.pattern - name = committer_email_pattern.value.name - negate = coalesce(committer_email_pattern.value.negate, false) - } - } + # content { + # operator = committer_email_pattern.value.operator + # pattern = committer_email_pattern.value.pattern + # name = committer_email_pattern.value.name + # negate = coalesce(committer_email_pattern.value.negate, false) + # } + # } - dynamic "pull_request" { - for_each = try(toset([each.value.rules.pull_request]), []) + # dynamic "pull_request" { + # for_each = try(toset([each.value.rules.pull_request]), []) - content { - dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) - require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) - require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) - required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) - required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) - } - } + # content { + # dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) + # require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) + # require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) + # required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) + # required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) + # } + # } # dynamic "required_status_checks" { # for_each = toset(compact([each.value.rules.required_status_checks])) From e86bf35547c4a8ba657c514e741a909113c1e6ef Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:54:08 -0400 Subject: [PATCH 20/72] removed caolesce --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 04dcf22..d06b1b0 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -70,7 +70,7 @@ resource "github_organization_ruleset" "branch_ruleset" { operator = try(branch_name_pattern.value.operator, "") pattern = try(branch_name_pattern.value.pattern, "") name = try(branch_name_pattern.value.name, "") - negate = coalesce(branch_name_pattern.value.negate, false) + negate = try(branch_name_pattern.value.negate, false) } } From e2a8b8b331c20cf206c6633cc12c3a86880bcc76 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:57:01 -0400 Subject: [PATCH 21/72] setting to null --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index d06b1b0..92502cb 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -64,7 +64,7 @@ resource "github_organization_ruleset" "branch_ruleset" { rules { dynamic "branch_name_pattern" { - for_each = try(toset([each.value.rules.branch_name_pattern]), []) + for_each = try([each.value.rules.branch_name_pattern], null) content { operator = try(branch_name_pattern.value.operator, "") From 70cdfc4841d551f8f0127235daaf81a45d0d7e1e Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 15:58:49 -0400 Subject: [PATCH 22/72] using ternary --- modules/organization/rulesets.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 92502cb..e1de3a5 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -64,13 +64,13 @@ resource "github_organization_ruleset" "branch_ruleset" { rules { dynamic "branch_name_pattern" { - for_each = try([each.value.rules.branch_name_pattern], null) + for_each = each.value.rules.branch_name_pattern != null ? [each.value.rules.branch_name_pattern] : [] content { - operator = try(branch_name_pattern.value.operator, "") - pattern = try(branch_name_pattern.value.pattern, "") - name = try(branch_name_pattern.value.name, "") - negate = try(branch_name_pattern.value.negate, false) + operator = branch_name_pattern.value.operator + pattern = branch_name_pattern.value.pattern + name = branch_name_pattern.value.name + negate = coalesce(branch_name_pattern.value.negate, false) } } From 67c1a12b0c41cb1f1493062ca48ffb9c9282fe00 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 16:00:55 -0400 Subject: [PATCH 23/72] changed rest to ternary --- modules/organization/rulesets.tf | 74 ++++++++++++++++---------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index e1de3a5..d4b53c7 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -74,50 +74,50 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - # dynamic "commit_author_email_pattern" { - # for_each = try(toset([each.value.rules.commit_author_email_pattern]), []) + dynamic "commit_author_email_pattern" { + for_each = each.value.rules.commit_author_email_pattern != null ? [each.value.rules.commit_author_email_pattern] : [] - # content { - # operator = commit_author_email_pattern.value.operator - # pattern = commit_author_email_pattern.value.pattern - # name = commit_author_email_pattern.value.name - # negate = coalesce(commit_author_email_pattern.value.negate, false) - # } - # } + content { + operator = commit_author_email_pattern.value.operator + pattern = commit_author_email_pattern.value.pattern + name = commit_author_email_pattern.value.name + negate = coalesce(commit_author_email_pattern.value.negate, false) + } + } - # dynamic "commit_message_pattern" { - # for_each = try(toset([each.value.rules.commit_message_pattern]), []) + dynamic "commit_message_pattern" { + for_each = each.value.rules.commit_message_pattern != null ? [each.value.rules.commit_message_pattern] : [] - # content { - # operator = commit_message_pattern.value.operator - # pattern = commit_message_pattern.value.pattern - # name = commit_message_pattern.value.name - # negate = coalesce(commit_message_pattern.value.negate, false) - # } - # } + content { + operator = commit_message_pattern.value.operator + pattern = commit_message_pattern.value.pattern + name = commit_message_pattern.value.name + negate = coalesce(commit_message_pattern.value.negate, false) + } + } - # dynamic "committer_email_pattern" { - # for_each = try(toset([each.value.rules.committer_email_pattern]), []) + dynamic "committer_email_pattern" { + for_each = each.value.rules.committer_email_pattern != null ? [each.value.rules.committer_email_pattern] : [] - # content { - # operator = committer_email_pattern.value.operator - # pattern = committer_email_pattern.value.pattern - # name = committer_email_pattern.value.name - # negate = coalesce(committer_email_pattern.value.negate, false) - # } - # } + content { + operator = committer_email_pattern.value.operator + pattern = committer_email_pattern.value.pattern + name = committer_email_pattern.value.name + negate = coalesce(committer_email_pattern.value.negate, false) + } + } - # dynamic "pull_request" { - # for_each = try(toset([each.value.rules.pull_request]), []) + dynamic "pull_request" { + for_each = each.value.rules.pull_request != null ? [each.value.rules.pull_request] : [] - # content { - # dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) - # require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) - # require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) - # required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) - # required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) - # } - # } + content { + dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) + require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) + require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) + required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) + required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) + } + } # dynamic "required_status_checks" { # for_each = toset(compact([each.value.rules.required_status_checks])) From 7ec4124edf09116403e05ea0329fc6abc96d986d Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 16:02:07 -0400 Subject: [PATCH 24/72] typo --- modules/organization/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index be5db59..00743ef 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -199,7 +199,7 @@ variable "branch_rulesets" { name = optional(string) negate = optional(bool) })) - comitter_email_pattern = optional(object({ + committer_email_pattern = optional(object({ operator = string pattern = string name = optional(string) From 070d6eebe993a52091be346031b090995bac09db Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 16:04:34 -0400 Subject: [PATCH 25/72] Added the problem rules back in --- modules/organization/rulesets.tf | 66 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index d4b53c7..6a2c120 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -119,39 +119,39 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - # dynamic "required_status_checks" { - # for_each = toset(compact([each.value.rules.required_status_checks])) - - # content { - # strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - - # dynamic "required_check" { - # for_each = required_status_checks.required_check - - # content { - # context = required_check.value.context - # integration_id = required_check.value.integration_id - # } - # } - # } - # } - - # dynamic "required_workflows" { - # for_each = toset(compact([each.value.rules.required_workflows])) - - # content { - - # dynamic "required_workflow" { - # for_each = required_workflows.value.required_workflows - - # content { - # repository_id = required_workflow.value.repository_id - # path = required_workflow.value.path - # ref = coalesce(required_workflow.value.ref, "main") - # } - # } - # } - # } + dynamic "required_status_checks" { + for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [] + + content { + strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + + dynamic "required_check" { + for_each = required_status_checks.required_check + + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } + } + } + + dynamic "required_workflows" { + for_each = each.value.rules.required_workflows ? [each.value.rules.required_workflows] : [] + + content { + + dynamic "required_workflow" { + for_each = required_workflows.value.required_workflows + + content { + repository_id = required_workflow.value.repository_id + path = required_workflow.value.path + ref = coalesce(required_workflow.value.ref, "main") + } + } + } + } } dynamic "bypass_actors" { From c53a0c9460bb522c9065a421aea81f8ab1c0abb2 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Mon, 11 Mar 2024 16:14:42 -0400 Subject: [PATCH 26/72] setting default for context name --- modules/organization/rulesets.tf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 6a2c120..dbdd54c 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -120,7 +120,9 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [] + for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [{ + context = "Context Name Missing" + }] content { strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy From 2769390725243212b4452a4f3d911a40dd8e26ee Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:17:19 -0400 Subject: [PATCH 27/72] upgraded version --- modules/organization/versions.tf | 2 +- modules/private_repository/versions.tf | 2 +- modules/public_repository/versions.tf | 2 +- modules/repository_base/versions.tf | 2 +- modules/repository_set/versions.tf | 2 +- modules/team/versions.tf | 2 +- modules/team_set/versions.tf | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/organization/versions.tf b/modules/organization/versions.tf index 99d757e..d32b1bb 100644 --- a/modules/organization/versions.tf +++ b/modules/organization/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } \ No newline at end of file diff --git a/modules/private_repository/versions.tf b/modules/private_repository/versions.tf index d6e8a27..99316dd 100644 --- a/modules/private_repository/versions.tf +++ b/modules/private_repository/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } \ No newline at end of file diff --git a/modules/public_repository/versions.tf b/modules/public_repository/versions.tf index d6e8a27..99316dd 100644 --- a/modules/public_repository/versions.tf +++ b/modules/public_repository/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } \ No newline at end of file diff --git a/modules/repository_base/versions.tf b/modules/repository_base/versions.tf index d6e8a27..99316dd 100644 --- a/modules/repository_base/versions.tf +++ b/modules/repository_base/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } \ No newline at end of file diff --git a/modules/repository_set/versions.tf b/modules/repository_set/versions.tf index d6e8a27..99316dd 100644 --- a/modules/repository_set/versions.tf +++ b/modules/repository_set/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } \ No newline at end of file diff --git a/modules/team/versions.tf b/modules/team/versions.tf index 99d757e..d32b1bb 100644 --- a/modules/team/versions.tf +++ b/modules/team/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } \ No newline at end of file diff --git a/modules/team_set/versions.tf b/modules/team_set/versions.tf index a369b06..95d7d87 100644 --- a/modules/team_set/versions.tf +++ b/modules/team_set/versions.tf @@ -3,7 +3,7 @@ terraform { required_providers { github = { source = "integrations/github" - version = "5.42.0" + version = "6.1.0" } } } From 7d5c3bf2222a9ea8ea27ef3dd0d745f60eb9adea Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:25:01 -0400 Subject: [PATCH 28/72] moved things around --- modules/organization/rulesets.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index dbdd54c..38f9ced 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -125,8 +125,6 @@ resource "github_organization_ruleset" "branch_ruleset" { }] content { - strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - dynamic "required_check" { for_each = required_status_checks.required_check @@ -135,6 +133,8 @@ resource "github_organization_ruleset" "branch_ruleset" { integration_id = required_check.value.integration_id } } + + strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy } } From e53f3ebedc2af10673c1891776bac63d691cfa2d Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:28:02 -0400 Subject: [PATCH 29/72] default value isn't correct --- modules/organization/rulesets.tf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 38f9ced..07b8a4a 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -121,7 +121,9 @@ resource "github_organization_ruleset" "branch_ruleset" { dynamic "required_status_checks" { for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [{ - context = "Context Name Missing" + required_check = { + context = "Context Name Missing" + } }] content { From e271d33f38ee23b562c83da04f75c2dc64cc3d1d Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:28:24 -0400 Subject: [PATCH 30/72] default value should be an empty list --- modules/organization/rulesets.tf | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 07b8a4a..c9b05d1 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -120,11 +120,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [{ - required_check = { - context = "Context Name Missing" - } - }] + for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [] content { dynamic "required_check" { From d40df08f40e8d67f067dc5819255497506df5ef2 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:30:55 -0400 Subject: [PATCH 31/72] does it just hate this property? --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index c9b05d1..2f473bd 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -120,7 +120,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks ? [each.value.rules.required_status_checks] : [] + for_each = each.value.rules.required_status_checks ? [] : [] content { dynamic "required_check" { From b3692526c7980e5c0f2ffcbc913d4bb455ca54f9 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:31:51 -0400 Subject: [PATCH 32/72] removed required_status_chekcs --- modules/organization/rulesets.tf | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 2f473bd..6aae921 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -119,22 +119,22 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks ? [] : [] - - content { - dynamic "required_check" { - for_each = required_status_checks.required_check - - content { - context = required_check.value.context - integration_id = required_check.value.integration_id - } - } - - strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - } - } + # dynamic "required_status_checks" { + # for_each = each.value.rules.required_status_checks ? [] : [] + + # content { + # dynamic "required_check" { + # for_each = required_status_checks.required_check + + # content { + # context = required_check.value.context + # integration_id = required_check.value.integration_id + # } + # } + + # strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + # } + # } dynamic "required_workflows" { for_each = each.value.rules.required_workflows ? [each.value.rules.required_workflows] : [] From 485bf5bdd53c2158949847ddb5fdc01b1b601dff Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:34:59 -0400 Subject: [PATCH 33/72] fixing conditional --- modules/organization/rulesets.tf | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 6aae921..35ef2cf 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -119,25 +119,25 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - # dynamic "required_status_checks" { - # for_each = each.value.rules.required_status_checks ? [] : [] + dynamic "required_status_checks" { + for_each = each.value.rules.required_status_checks != null ? [] : [] - # content { - # dynamic "required_check" { - # for_each = required_status_checks.required_check + content { + dynamic "required_check" { + for_each = required_status_checks.required_check - # content { - # context = required_check.value.context - # integration_id = required_check.value.integration_id - # } - # } + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } - # strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - # } - # } + strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + } + } dynamic "required_workflows" { - for_each = each.value.rules.required_workflows ? [each.value.rules.required_workflows] : [] + for_each = each.value.rules.required_workflows != null ? [each.value.rules.required_workflows] : [] content { From 00f8a11ba092102ee1e7d181b8264af29c8390e7 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:37:05 -0400 Subject: [PATCH 34/72] property is bugged --- modules/organization/rulesets.tf | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 35ef2cf..4a4edfa 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -119,22 +119,22 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks != null ? [] : [] - - content { - dynamic "required_check" { - for_each = required_status_checks.required_check - - content { - context = required_check.value.context - integration_id = required_check.value.integration_id - } - } - - strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - } - } + # dynamic "required_status_checks" { + # for_each = each.value.rules.required_status_checks != null ? [] : [] + + # content { + # dynamic "required_check" { + # for_each = required_status_checks.required_check + + # content { + # context = required_check.value.context + # integration_id = required_check.value.integration_id + # } + # } + + # strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + # } + # } dynamic "required_workflows" { for_each = each.value.rules.required_workflows != null ? [each.value.rules.required_workflows] : [] From 6862a02b915c79f6f10de7d70fb930e66acc303c Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:38:35 -0400 Subject: [PATCH 35/72] if this failes I don't understand why --- modules/organization/rulesets.tf | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 4a4edfa..8347a59 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -119,22 +119,22 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - # dynamic "required_status_checks" { - # for_each = each.value.rules.required_status_checks != null ? [] : [] - - # content { - # dynamic "required_check" { - # for_each = required_status_checks.required_check - - # content { - # context = required_check.value.context - # integration_id = required_check.value.integration_id - # } - # } - - # strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy - # } - # } + dynamic "required_status_checks" { + for_each = [] + + content { + dynamic "required_check" { + for_each = required_status_checks.required_check + + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } + + strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + } + } dynamic "required_workflows" { for_each = each.value.rules.required_workflows != null ? [each.value.rules.required_workflows] : [] From 462f504dd0282c0e4d820d329f96fc3ff968e2ab Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:40:21 -0400 Subject: [PATCH 36/72] so why does this fail? --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 8347a59..35ef2cf 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -120,7 +120,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = [] + for_each = each.value.rules.required_status_checks != null ? [] : [] content { dynamic "required_check" { From ebc48b56f5b34492515d10a889cfa5fa7c27bb56 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 09:42:43 -0400 Subject: [PATCH 37/72] change conditional? --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 35ef2cf..c1d3d1b 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -120,7 +120,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks != null ? [] : [] + for_each = each.value.rules.required_status_checks == null ? [] : [] content { dynamic "required_check" { From 69a883593fca3c81525f0879a83fa9d9bd0e3915 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 10:55:20 -0400 Subject: [PATCH 38/72] trying to use compact --- modules/organization/rulesets.tf | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index c1d3d1b..7f83a4b 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -63,6 +63,13 @@ resource "github_organization_ruleset" "branch_ruleset" { } rules { + creation = each.value.rules.creation + update = each.value.rules.update + deletion = each.value.rules.deletion + non_fast_forward = each.value.rules.non_fast_forward + required_linear_history = each.value.rules.required_linear_history + required_signatures = each.value.rules.required_signatures + dynamic "branch_name_pattern" { for_each = each.value.rules.branch_name_pattern != null ? [each.value.rules.branch_name_pattern] : [] @@ -120,7 +127,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks == null ? [] : [] + for_each = compact([each.value.rules.required_status_checks]) content { dynamic "required_check" { From baf53d561872b39078c7fbc1f75f426b9eab9c19 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 10:57:18 -0400 Subject: [PATCH 39/72] what am I doing? --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 7f83a4b..b1b63a1 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -131,7 +131,7 @@ resource "github_organization_ruleset" "branch_ruleset" { content { dynamic "required_check" { - for_each = required_status_checks.required_check + for_each = required_status_checks.value.required_check content { context = required_check.value.context From ddf3f48b999793e673a0d57ec817e2b1dfe9ddcd Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 10:58:22 -0400 Subject: [PATCH 40/72] please let this work --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index b1b63a1..e894e4f 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -127,7 +127,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "required_status_checks" { - for_each = compact([each.value.rules.required_status_checks]) + for_each = each.value.rules.required_status_checks != null ? [each.value.rules.required_status_checks] : [] content { dynamic "required_check" { From 3a8a884471e3401e69592fcdbaf3af550f393a6c Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 10:59:50 -0400 Subject: [PATCH 41/72] why am I like this? --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index e894e4f..f000d33 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -139,7 +139,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } } - strict_required_status_checks_policy = required_status_checks.strict_required_status_check_policy + strict_required_status_checks_policy = required_status_checks.value.strict_required_status_check_policy } } From 38f2db1bec2dd1ae41870b2fb7d9b9784adbfa4b Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 11:09:12 -0400 Subject: [PATCH 42/72] added conditions --- modules/organization/rulesets.tf | 20 ++++++++++++++++++++ modules/organization/variables.tf | 10 ++++++++++ 2 files changed, 30 insertions(+) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index f000d33..59164f4 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -190,4 +190,24 @@ resource "github_organization_ruleset" "branch_ruleset" { bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } } + + dynamic "conditions" { + for_each = each.value.conditions != null ? [each.value.conditions] : [] + + content { + ref_name { + include = conditions.value.ref_name.include + exclude = conditions.value.ref_name.exclude + } + + dynamic "repository_name" { + for_each = condition.value.repository_name != null ? [condition.value.repository_name] : [] + + content { + include = repository_name.value.include + exclude = repository_name.value.exclude + } + } + } + } } \ No newline at end of file diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 00743ef..d015656 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -180,6 +180,16 @@ variable "branch_rulesets" { always_bypass = optional(bool) }))) })) + conditions = optional(object({ + ref_name = object({ + include = list(string) + exclude = list(string) + }) + repository_name = optional(object({ + include = list(string) + exclude = list(string) + })) + })) rules = object({ branch_name_pattern = optional(object({ operator = string From 51d205239cc23a2bb5786ae7963d3c74aa541ab0 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 11:10:06 -0400 Subject: [PATCH 43/72] I can't keep doing this --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 59164f4..799a915 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -201,7 +201,7 @@ resource "github_organization_ruleset" "branch_ruleset" { } dynamic "repository_name" { - for_each = condition.value.repository_name != null ? [condition.value.repository_name] : [] + for_each = conditions.value.repository_name != null ? [conditions.value.repository_name] : [] content { include = repository_name.value.include From fde2e1ab68489b5d9a1d04cf571b036686c3f25d Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 11:36:50 -0400 Subject: [PATCH 44/72] added tagname pattern and ability to choose target --- modules/organization/rulesets.tf | 37 ++++++++++++++++++++----------- modules/organization/variables.tf | 16 ++++++------- 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 799a915..a86f32c 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,18 +1,18 @@ locals { - branch_ruleset_team_bypassers = merge([ - for ruleset, ruleset_config in var.branch_rulesets : { + ruleset_team_bypassers = merge([ + for ruleset, ruleset_config in var.rulesets : { for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser.team}" => bypasser.team } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null ]...) - branch_ruleset_admin_bypassers = merge([ - for ruleset, ruleset_config in var.branch_rulesets : { + ruleset_admin_bypassers = merge([ + for ruleset, ruleset_config in var.rulesets : { for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser.user}" => bypasser.user } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null ]...) - branch_ruleset_custom_repository_roles = merge([ - for ruleset, ruleset_config in var.branch_rulesets : { + ruleset_custom_repository_roles = merge([ + for ruleset, ruleset_config in var.rulesets : { for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null ]...) @@ -26,31 +26,31 @@ locals { data "github_team" "branch_ruleset_bypasser" { - for_each = local.branch_ruleset_team_bypassers + for_each = local.ruleset_team_bypassers slug = each.value summary_only = true } data "github_user" "branch_ruleset_bypasser" { - for_each = local.branch_ruleset_admin_bypassers + for_each = local.ruleset_admin_bypassers username = each.value } #github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { - for_each = local.branch_ruleset_custom_repository_roles + for_each = local.ruleset_custom_repository_roles name = each.value } -resource "github_organization_ruleset" "branch_ruleset" { - for_each = var.branch_rulesets +resource "github_organization_ruleset" "ruleset" { + for_each = var.rulesets name = each.key - target = "branch" - enforcement = coalesce(each.value.disable, false) ? "disabled" : "active" #Might want this to just be a string so it can also be set to evaluate + target = each.target + enforcement = coalesce(each.value.disable, false) ? "disabled" : "active" dynamic "bypass_actors" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] @@ -81,6 +81,17 @@ resource "github_organization_ruleset" "branch_ruleset" { } } + dynamic "tag_name_pattern" { + for_each = each.value.rules.tag_name_pattern != null ? [each.value.rules.tag_name_pattern] : [] + + content { + operator = tag_name_pattern.value.operator + pattern = tag_name_pattern.value.pattern + name = tag_name_pattern.value.name + negate = coalesce(tag_name_pattern.value.negate, false) + } + } + dynamic "commit_author_email_pattern" { for_each = each.value.rules.commit_author_email_pattern != null ? [each.value.rules.commit_author_email_pattern] : [] diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index d015656..35d5700 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -160,7 +160,7 @@ variable "dependabot_secrets" { default = {} } -variable "branch_rulesets" { +variable "rulesets" { type = map(object({ bypass_actors = optional(object({ repository_roles = optional(list(object({ @@ -197,6 +197,12 @@ variable "branch_rulesets" { 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 @@ -243,13 +249,7 @@ variable "branch_rulesets" { })) })) }) - disable = optional(bool) - })) - default = {} -} - -variable "tag_rulesets" { - type = map(object({ + target = string disable = optional(bool) })) default = {} From f553f3c897a3cf4cd6ab981550efb024bdd37842 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 11:38:26 -0400 Subject: [PATCH 45/72] allow customizing enforcement --- modules/organization/rulesets.tf | 2 +- modules/organization/variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index a86f32c..7e589da 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -50,7 +50,7 @@ resource "github_organization_ruleset" "ruleset" { name = each.key target = each.target - enforcement = coalesce(each.value.disable, false) ? "disabled" : "active" + enforcement = each.value.enforcement dynamic "bypass_actors" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 35d5700..ae6748f 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -250,7 +250,7 @@ variable "rulesets" { })) }) target = string - disable = optional(bool) + enforcement = string })) default = {} } \ No newline at end of file From aae77eabe28531bcb9e459170e4303c6dade38be Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 11:39:39 -0400 Subject: [PATCH 46/72] I have to stop forgetting value --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 7e589da..d8114ed 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -49,7 +49,7 @@ resource "github_organization_ruleset" "ruleset" { for_each = var.rulesets name = each.key - target = each.target + target = each.value.target enforcement = each.value.enforcement dynamic "bypass_actors" { From 8faed2c5038da0528e3dceb69a99b00fae3198c6 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 13:39:01 -0400 Subject: [PATCH 47/72] first version of repository rulesets --- modules/organization/variables.tf | 2 +- modules/private_repository/repository.tf | 2 + modules/private_repository/variables.tf | 91 ++++++++++ modules/public_repository/repository.tf | 2 + modules/public_repository/variables.tf | 91 ++++++++++ modules/repository_base/rulesets.tf | 215 +++++++++++++++++++++++ modules/repository_base/variables.tf | 91 ++++++++++ modules/repository_set/repositories.tf | 16 ++ modules/repository_set/variables.tf | 92 ++++++++++ 9 files changed, 601 insertions(+), 1 deletion(-) create mode 100644 modules/repository_base/rulesets.tf diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index ae6748f..8b33cb0 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -249,7 +249,7 @@ variable "rulesets" { })) })) }) - target = string + target = string enforcement = string })) default = {} diff --git a/modules/private_repository/repository.tf b/modules/private_repository/repository.tf index e95445b..45e1cc1 100644 --- a/modules/private_repository/repository.tf +++ b/modules/private_repository/repository.tf @@ -33,4 +33,6 @@ module "repository_base" { template_repository = var.template_repository license_template = var.license_template + + rulesets = var.rulesets } diff --git a/modules/private_repository/variables.tf b/modules/private_repository/variables.tf index d1712bd..73a5df6 100644 --- a/modules/private_repository/variables.tf +++ b/modules/private_repository/variables.tf @@ -102,4 +102,95 @@ variable "license_template" { description = "The (Optional) license template to use for the repository" type = string default = null +} + +variable "rulesets" { + type = 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) + 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 + })) + default = {} } \ No newline at end of file diff --git a/modules/public_repository/repository.tf b/modules/public_repository/repository.tf index 4e60eb7..7acc30e 100644 --- a/modules/public_repository/repository.tf +++ b/modules/public_repository/repository.tf @@ -33,4 +33,6 @@ module "repository_base" { template_repository = var.template_repository license_template = var.license_template + + rulesets = var.rulesets } \ No newline at end of file diff --git a/modules/public_repository/variables.tf b/modules/public_repository/variables.tf index 16dcf34..e596f51 100644 --- a/modules/public_repository/variables.tf +++ b/modules/public_repository/variables.tf @@ -102,4 +102,95 @@ variable "license_template" { description = "The (Optional) license template to apply to the repository" type = string default = null +} + +variable "rulesets" { + type = 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) + 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 + })) + default = {} } \ No newline at end of file diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf new file mode 100644 index 0000000..c0be64e --- /dev/null +++ b/modules/repository_base/rulesets.tf @@ -0,0 +1,215 @@ +locals { + ruleset_team_bypassers = merge([ + for ruleset, ruleset_config in var.rulesets : { + for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser.team}" => bypasser.team + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null + ]...) + + ruleset_admin_bypassers = merge([ + for ruleset, ruleset_config in var.rulesets : { + for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser.user}" => bypasser.user + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null + ]...) + + ruleset_custom_repository_roles = merge([ + for ruleset, ruleset_config in var.rulesets : { + for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) + } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null + ]...) + + github_base_role_ids = { + "maintain" = 2 + "write" = 4 + "admin" = 5 + } +} + + +data "github_team" "branch_ruleset_bypasser" { + for_each = local.ruleset_team_bypassers + + slug = each.value + summary_only = true +} + +data "github_user" "branch_ruleset_bypasser" { + for_each = local.ruleset_admin_bypassers + + username = each.value +} + +#github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles +data "github_organization_custom_role" "branch_ruleset_bypasser" { + for_each = local.ruleset_custom_repository_roles + + name = each.value +} + +resource "github_repository_ruleset" "ruleset" { + for_each = var.rulesets + + name = each.key + target = each.value.target + enforcement = each.value.enforcement + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] + + content { + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.role}"].id) + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + rules { + creation = each.value.rules.creation + update = each.value.rules.update + deletion = each.value.rules.deletion + non_fast_forward = each.value.rules.non_fast_forward + required_linear_history = each.value.rules.required_linear_history + required_signatures = each.value.rules.required_signatures + + dynamic "branch_name_pattern" { + for_each = each.value.rules.branch_name_pattern != null ? [each.value.rules.branch_name_pattern] : [] + + content { + operator = branch_name_pattern.value.operator + pattern = branch_name_pattern.value.pattern + name = branch_name_pattern.value.name + negate = coalesce(branch_name_pattern.value.negate, false) + } + } + + dynamic "tag_name_pattern" { + for_each = each.value.rules.tag_name_pattern != null ? [each.value.rules.tag_name_pattern] : [] + + content { + operator = tag_name_pattern.value.operator + pattern = tag_name_pattern.value.pattern + name = tag_name_pattern.value.name + negate = coalesce(tag_name_pattern.value.negate, false) + } + } + + dynamic "commit_author_email_pattern" { + for_each = each.value.rules.commit_author_email_pattern != null ? [each.value.rules.commit_author_email_pattern] : [] + + content { + operator = commit_author_email_pattern.value.operator + pattern = commit_author_email_pattern.value.pattern + name = commit_author_email_pattern.value.name + negate = coalesce(commit_author_email_pattern.value.negate, false) + } + } + + dynamic "commit_message_pattern" { + for_each = each.value.rules.commit_message_pattern != null ? [each.value.rules.commit_message_pattern] : [] + + content { + operator = commit_message_pattern.value.operator + pattern = commit_message_pattern.value.pattern + name = commit_message_pattern.value.name + negate = coalesce(commit_message_pattern.value.negate, false) + } + } + + dynamic "committer_email_pattern" { + for_each = each.value.rules.committer_email_pattern != null ? [each.value.rules.committer_email_pattern] : [] + + content { + operator = committer_email_pattern.value.operator + pattern = committer_email_pattern.value.pattern + name = committer_email_pattern.value.name + negate = coalesce(committer_email_pattern.value.negate, false) + } + } + + dynamic "pull_request" { + for_each = each.value.rules.pull_request != null ? [each.value.rules.pull_request] : [] + + content { + dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) + require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) + require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) + required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) + required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) + } + } + + dynamic "required_status_checks" { + for_each = each.value.rules.required_status_checks != null ? [each.value.rules.required_status_checks] : [] + + content { + dynamic "required_check" { + for_each = required_status_checks.value.required_check + + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } + + strict_required_status_checks_policy = required_status_checks.value.strict_required_status_check_policy + } + } + + dynamic "required_workflows" { + for_each = each.value.rules.required_workflows != null ? [each.value.rules.required_workflows] : [] + + content { + + dynamic "required_workflow" { + for_each = required_workflows.value.required_workflows + + content { + repository_id = required_workflow.value.repository_id + path = required_workflow.value.path + ref = coalesce(required_workflow.value.ref, "main") + } + } + } + } + } + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] + + content { + actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.team}"].id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.integrations, [])) : [] + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] + + content { + actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.user}"].id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "conditions" { + for_each = each.value.conditions != null ? [each.value.conditions] : [] + + content { + ref_name { + include = conditions.value.ref_name.include + exclude = conditions.value.ref_name.exclude + } + } + } +} \ No newline at end of file diff --git a/modules/repository_base/variables.tf b/modules/repository_base/variables.tf index bd3e647..4dc9ef9 100644 --- a/modules/repository_base/variables.tf +++ b/modules/repository_base/variables.tf @@ -156,4 +156,95 @@ variable "license_template" { description = "The (Optional) license template to use for the repository" type = string default = null +} + +variable "rulesets" { + type = 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) + 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 + })) + default = {} } \ No newline at end of file diff --git a/modules/repository_set/repositories.tf b/modules/repository_set/repositories.tf index af80a83..552b078 100644 --- a/modules/repository_set/repositories.tf +++ b/modules/repository_set/repositories.tf @@ -1,3 +1,16 @@ +locals { + rulesets_by_public_repository = { + for repo_name, repo_config in var.public_repositories : repo_name => { + for ruleset_name, ruleset_config in var.rulesets : ruleset_name => ruleset_config if contains(ruleset_config.repositories, repo_name) + } + } + rulesets_by_private_repository = { + for repo_name, repo_config in var.private_repositories : repo_name => { + for ruleset_name, ruleset_config in var.rulesets : ruleset_name => ruleset_config if contains(ruleset_config.repositories, repo_name) + } + } +} + module "public_repositories" { source = "../public_repository" @@ -20,6 +33,7 @@ module "public_repositories" { environments = each.value.environments template_repository = each.value.template_repository license_template = each.value.license_template + rulesets = lookup(local.rulesets_by_public_repository, each.key, {}) } module "private_repositories" { @@ -44,4 +58,6 @@ module "private_repositories" { environments = each.value.environments template_repository = each.value.template_repository license_template = each.value.license_template + rulesets = lookup(local.rulesets_by_public_repository, each.key, {}) + } diff --git a/modules/repository_set/variables.tf b/modules/repository_set/variables.tf index aac97f7..2add808 100644 --- a/modules/repository_set/variables.tf +++ b/modules/repository_set/variables.tf @@ -65,3 +65,95 @@ variable "default_repository_team_permissions" { type = map(string) description = "A map where the keys are github team slugs and the value is the permissions the team should have by default for every repository. If an entry exists in `repository_team_permissions_override` for a repository then that will take precedence over this default." } + +variable "rulesets" { + type = 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) + 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 + repositories = list(string) + })) + default = {} +} \ No newline at end of file From 010ff47fabdbb6fa6424a11b029ae95601e1af77 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Tue, 12 Mar 2024 14:01:04 -0400 Subject: [PATCH 48/72] updating versions --- modules/foundations-github-organization/versions.tf | 2 +- modules/github-gcloud-oidc/versions.tf | 2 +- modules/organization/versions.tf | 2 +- modules/team/versions.tf | 2 +- modules/team_set/versions.tf | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/foundations-github-organization/versions.tf b/modules/foundations-github-organization/versions.tf index ac486db..d9723ab 100644 --- a/modules/foundations-github-organization/versions.tf +++ b/modules/foundations-github-organization/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.7.1" required_providers { github = { source = "hashicorp/github" diff --git a/modules/github-gcloud-oidc/versions.tf b/modules/github-gcloud-oidc/versions.tf index 6381a79..70969c9 100644 --- a/modules/github-gcloud-oidc/versions.tf +++ b/modules/github-gcloud-oidc/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.7.1" required_providers { google = { source = "hashicorp/google" diff --git a/modules/organization/versions.tf b/modules/organization/versions.tf index d32b1bb..99316dd 100644 --- a/modules/organization/versions.tf +++ b/modules/organization/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.7.1" required_providers { github = { source = "integrations/github" diff --git a/modules/team/versions.tf b/modules/team/versions.tf index d32b1bb..99316dd 100644 --- a/modules/team/versions.tf +++ b/modules/team/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.7.1" required_providers { github = { source = "integrations/github" diff --git a/modules/team_set/versions.tf b/modules/team_set/versions.tf index 95d7d87..7b667b4 100644 --- a/modules/team_set/versions.tf +++ b/modules/team_set/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.3" + required_version = ">= 1.7.1" required_providers { github = { source = "integrations/github" From c300f2969692426e74d7410bd4be815803a888b5 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 09:13:40 -0400 Subject: [PATCH 49/72] fixed repo ruleset --- modules/private_repository/variables.tf | 21 +++++++------------ modules/public_repository/variables.tf | 21 +++++++------------ modules/repository_base/rulesets.tf | 28 +++++++++---------------- modules/repository_base/variables.tf | 21 +++++++------------ modules/repository_set/variables.tf | 21 +++++++------------ 5 files changed, 42 insertions(+), 70 deletions(-) diff --git a/modules/private_repository/variables.tf b/modules/private_repository/variables.tf index 73a5df6..ec040b5 100644 --- a/modules/private_repository/variables.tf +++ b/modules/private_repository/variables.tf @@ -161,12 +161,13 @@ variable "rulesets" { 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) + 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) @@ -181,13 +182,7 @@ variable "rulesets" { })) strict_required_status_check_policy = optional(bool) })) - required_workflows = optional(object({ - required_workflows = list(object({ - repository_id = number - path = string - ref = optional(string) - })) - })) + required_deployment_environments = optional(list(string)) }) target = string enforcement = string diff --git a/modules/public_repository/variables.tf b/modules/public_repository/variables.tf index e596f51..ba047b8 100644 --- a/modules/public_repository/variables.tf +++ b/modules/public_repository/variables.tf @@ -161,12 +161,13 @@ variable "rulesets" { 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) + 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) @@ -181,13 +182,7 @@ variable "rulesets" { })) strict_required_status_check_policy = optional(bool) })) - required_workflows = optional(object({ - required_workflows = list(object({ - repository_id = number - path = string - ref = optional(string) - })) - })) + required_deployment_environments = optional(list(string)) }) target = string enforcement = string diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index c0be64e..f5bc78a 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -63,12 +63,13 @@ resource "github_repository_ruleset" "ruleset" { } rules { - creation = each.value.rules.creation - update = each.value.rules.update - deletion = each.value.rules.deletion - non_fast_forward = each.value.rules.non_fast_forward - required_linear_history = each.value.rules.required_linear_history - required_signatures = each.value.rules.required_signatures + creation = each.value.rules.creation + update = each.value.rules.update + deletion = each.value.rules.deletion + non_fast_forward = each.value.rules.non_fast_forward + required_linear_history = each.value.rules.required_linear_history + required_signatures = each.value.rules.required_signatures + update_allows_fetch_and_merge = each.value.rules.update_allows_fetch_and_merge dynamic "branch_name_pattern" { for_each = each.value.rules.branch_name_pattern != null ? [each.value.rules.branch_name_pattern] : [] @@ -154,20 +155,11 @@ resource "github_repository_ruleset" "ruleset" { } } - dynamic "required_workflows" { - for_each = each.value.rules.required_workflows != null ? [each.value.rules.required_workflows] : [] + dynamic "required_deployments" { + for_each = each.value.rules.required_deployment_environments != null ? [each.value.rules.required_deployment_environments] : [] content { - - dynamic "required_workflow" { - for_each = required_workflows.value.required_workflows - - content { - repository_id = required_workflow.value.repository_id - path = required_workflow.value.path - ref = coalesce(required_workflow.value.ref, "main") - } - } + required_deployment_environments = required_deployments.value } } } diff --git a/modules/repository_base/variables.tf b/modules/repository_base/variables.tf index 4dc9ef9..9a49ac2 100644 --- a/modules/repository_base/variables.tf +++ b/modules/repository_base/variables.tf @@ -215,12 +215,13 @@ variable "rulesets" { 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) + 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) @@ -235,13 +236,7 @@ variable "rulesets" { })) strict_required_status_check_policy = optional(bool) })) - required_workflows = optional(object({ - required_workflows = list(object({ - repository_id = number - path = string - ref = optional(string) - })) - })) + required_deployment_environments = optional(list(string)) }) target = string enforcement = string diff --git a/modules/repository_set/variables.tf b/modules/repository_set/variables.tf index 2add808..5d7a6ab 100644 --- a/modules/repository_set/variables.tf +++ b/modules/repository_set/variables.tf @@ -123,12 +123,13 @@ variable "rulesets" { 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) + 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) @@ -143,13 +144,7 @@ variable "rulesets" { })) strict_required_status_check_policy = optional(bool) })) - required_workflows = optional(object({ - required_workflows = list(object({ - repository_id = number - path = string - ref = optional(string) - })) - })) + required_deployment_environments = optional(list(string)) }) target = string enforcement = string From 48fb05163585b9c034f0bb52ed9df87cc6352a0f Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 09:22:09 -0400 Subject: [PATCH 50/72] fixing null issue --- modules/organization/rulesets.tf | 12 ++++++------ modules/repository_base/rulesets.tf | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index d8114ed..5079b5e 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,20 +1,20 @@ locals { ruleset_team_bypassers = merge([ for ruleset, ruleset_config in var.rulesets : { - for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser.team}" => bypasser.team - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null + for bypasser in coalesce(ruleset_config.bypass_actors.teams, []) : "${ruleset}:${bypasser.team}" => bypasser.team + } if ruleset_config.bypass_actors != null ]...) ruleset_admin_bypassers = merge([ for ruleset, ruleset_config in var.rulesets : { - for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser.user}" => bypasser.user - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null + for bypasser in coalesce(ruleset_config.bypass_actors.organization_admins, []) : "${ruleset}:${bypasser.user}" => bypasser.user + } if ruleset_config.bypass_actors != null ]...) ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.rulesets : { - for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null + for bypasser in coalesce(ruleset_config.bypass_actors.repository_roles, []) : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) + } if ruleset_config.bypass_actors != null ]...) github_base_role_ids = { diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index f5bc78a..f8bc0ca 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -1,20 +1,20 @@ locals { ruleset_team_bypassers = merge([ for ruleset, ruleset_config in var.rulesets : { - for bypasser in ruleset_config.bypass_actors.teams : "${ruleset}:${bypasser.team}" => bypasser.team - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.teams != null + for bypasser in coalesce(ruleset_config.bypass_actors.teams, []) : "${ruleset}:${bypasser.team}" => bypasser.team + } if ruleset_config.bypass_actors != null ]...) ruleset_admin_bypassers = merge([ for ruleset, ruleset_config in var.rulesets : { - for bypasser in ruleset_config.bypass_actors.organization_admins : "${ruleset}:${bypasser.user}" => bypasser.user - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.organization_admins != null + for bypasser in coalesce(ruleset_config.bypass_actors.organization_admins, []) : "${ruleset}:${bypasser.user}" => bypasser.user + } if ruleset_config.bypass_actors != null ]...) ruleset_custom_repository_roles = merge([ for ruleset, ruleset_config in var.rulesets : { - for bypasser in ruleset_config.bypass_actors.repository_roles : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) - } if ruleset_config.bypass_actors != null && ruleset_config.bypass_actors.repository_roles != null + for bypasser in coalesce(ruleset_config.bypass_actors.repository_roles, []) : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) + } if ruleset_config.bypass_actors != null ]...) github_base_role_ids = { From c15253ca53d8d47fda96158c18e7ecc41930d666 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:15:57 -0400 Subject: [PATCH 51/72] added some ruleset tempaltes --- modules/organization/rulesets.tf | 315 ++++++++++++++++++++++++++---- modules/organization/variables.tf | 37 ++++ 2 files changed, 319 insertions(+), 33 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 5079b5e..2090e29 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,21 +1,24 @@ locals { - ruleset_team_bypassers = merge([ - for ruleset, ruleset_config in var.rulesets : { - for bypasser in coalesce(ruleset_config.bypass_actors.teams, []) : "${ruleset}:${bypasser.team}" => bypasser.team - } if ruleset_config.bypass_actors != null - ]...) - - ruleset_admin_bypassers = merge([ - for ruleset, ruleset_config in var.rulesets : { - for bypasser in coalesce(ruleset_config.bypass_actors.organization_admins, []) : "${ruleset}:${bypasser.user}" => bypasser.user - } if ruleset_config.bypass_actors != null - ]...) - - ruleset_custom_repository_roles = merge([ - for ruleset, ruleset_config in var.rulesets : { - for bypasser in coalesce(ruleset_config.bypass_actors.repository_roles, []) : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) - } if ruleset_config.bypass_actors != null - ]...) + all_team_bypassers = toset(concat( + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []), + [ + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.teams, ruleset_config.bypass_actors), []) + ]... + )) + + all_admin_bypassers = toset(concat( + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []), + [ + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.organization_admins, ruleset_config.bypass_actors), []) + ]... + )) + + all_repository_roles_bypassers = toset(concat( + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []), + [ + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, ruleset_config.bypass_actors), []) + ]... + )) github_base_role_ids = { "maintain" = 2 @@ -26,21 +29,27 @@ locals { data "github_team" "branch_ruleset_bypasser" { - for_each = local.ruleset_team_bypassers + for_each = { + for team in local.all_team_bypassers : team => team + } slug = each.value summary_only = true } data "github_user" "branch_ruleset_bypasser" { - for_each = local.ruleset_admin_bypassers + for_each = { + for user in local.all_admin_bypassers: user => user + } username = each.value } #github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { - for_each = local.ruleset_custom_repository_roles + for_each = { + for role in local.all_repository_roles_bypassers : role => role if !contains(keys(local.github_base_role_ids), role) + } name = each.value } @@ -52,16 +61,6 @@ resource "github_organization_ruleset" "ruleset" { target = each.value.target enforcement = each.value.enforcement - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] - - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - rules { creation = each.value.rules.creation update = each.value.rules.update @@ -172,11 +171,21 @@ resource "github_organization_ruleset" "ruleset" { } } + dynamic "bypass_actors" { + for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] + + content { + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + dynamic "bypass_actors" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] content { - actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.team}"].id + actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id actor_type = "Team" bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } @@ -196,7 +205,7 @@ resource "github_organization_ruleset" "ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] content { - actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.user}"].id + actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id actor_type = "OrganizationAdmin" bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } @@ -221,4 +230,244 @@ resource "github_organization_ruleset" "ruleset" { } } } -} \ No newline at end of file +} + +resource "github_organization_ruleset" "base_default_branch_protection" { + count = var.default_branch_protection_rulesets.base_protection ? 1 : 0 + name = "base_default_branch_protection" + target = "branch" + enforcement = var.default_branch_protection_rulesets.base_protection.enforcement + + conditions { + ref_name { + include = ["~DEFAULT_BRANCH"] + exclude = [] + } + } + + rules { + deletion = true + non_fast_forward = true + pull_request { + require_last_push_approval = true + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } +} + +resource "github_organization_ruleset" "minimum_approvals" { + count = var.default_branch_protection_rulesets.minimum_approvals ? 1 : 0 + name = "minimum_approvals" + target = "branch" + enforcement = var.default_branch_protection_rulesets.minimum_approvals.enforcement + + conditions { + ref_name { + include = ["~DEFAULT_BRANCH"] + exclude = [] + } + } + + rules { + pull_request { + required_approving_review_count = var.default_branch_protection_rulesets.minimum_approvals.approvals_required + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } +} + +resource "github_organization_ruleset" "dismiss_stale_reviews" { + count = var.default_branch_protection_rulesets.dismiss_stale_reviews ? 1 : 0 + name = "dismiss_stale_reviews" + target = "branch" + enforcement = var.default_branch_protection_rulesets.dismiss_stale_reviews.enforcement + + conditions { + ref_name { + include = ["~DEFAULT_BRANCH"] + exclude = [] + } + } + + rules { + pull_request { + dismiss_stale_reviews_on_push = true + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } +} + +resource "github_organization_ruleset" "require_signatures" { + count = var.default_branch_protection_rulesets.require_signatures ? 1 : 0 + name = "require_signatures" + target = "branch" + enforcement = var.default_branch_protection_rulesets.require_signatures.enforcement + + conditions { + ref_name { + include = ["~DEFAULT_BRANCH"] + exclude = [] + } + } + + rules { + required_signatures = true + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + + content { + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } +} diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 8b33cb0..c260b2f 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -160,6 +160,43 @@ variable "dependabot_secrets" { default = {} } +variable "default_branch_protection_rulesets" { + type = 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) + }))) + })) + }) + default = {} +} + variable "rulesets" { type = map(object({ bypass_actors = optional(object({ From 3a67a857272c2855146e855a6ee21c0381267bb1 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:22:40 -0400 Subject: [PATCH 52/72] you have to include repository_name --- modules/organization/rulesets.tf | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 2090e29..568620c 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -243,6 +243,11 @@ resource "github_organization_ruleset" "base_default_branch_protection" { include = ["~DEFAULT_BRANCH"] exclude = [] } + + repository_name { + include = ["~ALL"] + exclude = [] + } } rules { @@ -305,6 +310,11 @@ resource "github_organization_ruleset" "minimum_approvals" { include = ["~DEFAULT_BRANCH"] exclude = [] } + + repository_name { + include = ["~ALL"] + exclude = [] + } } rules { @@ -365,6 +375,11 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { include = ["~DEFAULT_BRANCH"] exclude = [] } + + repository_name { + include = ["~ALL"] + exclude = [] + } } rules { @@ -425,6 +440,11 @@ resource "github_organization_ruleset" "require_signatures" { include = ["~DEFAULT_BRANCH"] exclude = [] } + + repository_name { + include = ["~ALL"] + exclude = [] + } } rules { From 6adaa3537f226268b383dd2ef798ed0ac77cf334 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:26:39 -0400 Subject: [PATCH 53/72] removed coalesce --- modules/organization/rulesets.tf | 44 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 568620c..7ebca0a 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,22 +1,22 @@ locals { all_team_bypassers = toset(concat( - coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []), + try(var.default_branch_protection_rulesets.bypass_actors.teams, []), [ - for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.teams, ruleset_config.bypass_actors), []) + for _, ruleset_config in var.rulesets : try(ruleset_config.bypass_actors.teams, []) ]... )) all_admin_bypassers = toset(concat( - coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []), + try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []), [ - for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.organization_admins, ruleset_config.bypass_actors), []) + for _, ruleset_config in var.rulesets : try(ruleset_config.bypass_actors.organization_admins, []) ]... )) all_repository_roles_bypassers = toset(concat( - coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []), + try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []), [ - for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, ruleset_config.bypass_actors), []) + for _, ruleset_config in var.rulesets : try(ruleset_config.bypass_actors.repository_roles, []) ]... )) @@ -259,7 +259,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -269,7 +269,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) content { actor_id = bypass_actors.value.installation_id @@ -279,7 +279,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -289,7 +289,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) @@ -324,7 +324,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -334,7 +334,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) content { actor_id = bypass_actors.value.installation_id @@ -344,7 +344,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -354,7 +354,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) @@ -389,7 +389,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -399,7 +399,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) content { actor_id = bypass_actors.value.installation_id @@ -409,7 +409,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -419,7 +419,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) @@ -452,7 +452,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -462,7 +462,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) content { actor_id = bypass_actors.value.installation_id @@ -472,7 +472,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -482,7 +482,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, var.default_branch_protection_rulesets.bypass_actors), []) + for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) From aadd0e6ba9e6e992cb5622819fe798d431fbd5ed Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:28:28 -0400 Subject: [PATCH 54/72] fixed count statement --- modules/organization/rulesets.tf | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 7ebca0a..f737df3 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -233,7 +233,7 @@ resource "github_organization_ruleset" "ruleset" { } resource "github_organization_ruleset" "base_default_branch_protection" { - count = var.default_branch_protection_rulesets.base_protection ? 1 : 0 + count = var.default_branch_protection_rulesets.base_protection != null ? 1 : 0 name = "base_default_branch_protection" target = "branch" enforcement = var.default_branch_protection_rulesets.base_protection.enforcement @@ -300,7 +300,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } resource "github_organization_ruleset" "minimum_approvals" { - count = var.default_branch_protection_rulesets.minimum_approvals ? 1 : 0 + count = var.default_branch_protection_rulesets.minimum_approvals != null ? 1 : 0 name = "minimum_approvals" target = "branch" enforcement = var.default_branch_protection_rulesets.minimum_approvals.enforcement @@ -365,7 +365,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } resource "github_organization_ruleset" "dismiss_stale_reviews" { - count = var.default_branch_protection_rulesets.dismiss_stale_reviews ? 1 : 0 + count = var.default_branch_protection_rulesets.dismiss_stale_reviews != null ? 1 : 0 name = "dismiss_stale_reviews" target = "branch" enforcement = var.default_branch_protection_rulesets.dismiss_stale_reviews.enforcement @@ -430,7 +430,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } resource "github_organization_ruleset" "require_signatures" { - count = var.default_branch_protection_rulesets.require_signatures ? 1 : 0 + count = var.default_branch_protection_rulesets.require_signatures != null ? 1 : 0 name = "require_signatures" target = "branch" enforcement = var.default_branch_protection_rulesets.require_signatures.enforcement From 982591014e9b4e550d6ce8556618de4ee85422ee Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:35:06 -0400 Subject: [PATCH 55/72] added coalesce back in --- modules/organization/rulesets.tf | 44 ++++++++++++++++---------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index f737df3..dcc2cf0 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -1,22 +1,22 @@ locals { all_team_bypassers = toset(concat( - try(var.default_branch_protection_rulesets.bypass_actors.teams, []), + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []), []), [ - for _, ruleset_config in var.rulesets : try(ruleset_config.bypass_actors.teams, []) + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.teams, []), []) ]... )) all_admin_bypassers = toset(concat( - try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []), + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []), []), [ - for _, ruleset_config in var.rulesets : try(ruleset_config.bypass_actors.organization_admins, []) + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.organization_admins, []), []) ]... )) all_repository_roles_bypassers = toset(concat( - try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []), + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []), []), [ - for _, ruleset_config in var.rulesets : try(ruleset_config.bypass_actors.repository_roles, []) + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, []), []) ]... )) @@ -259,7 +259,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -269,7 +269,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) content { actor_id = bypass_actors.value.installation_id @@ -279,7 +279,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -289,7 +289,7 @@ resource "github_organization_ruleset" "base_default_branch_protection" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) @@ -324,7 +324,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -334,7 +334,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) content { actor_id = bypass_actors.value.installation_id @@ -344,7 +344,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -354,7 +354,7 @@ resource "github_organization_ruleset" "minimum_approvals" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) @@ -389,7 +389,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -399,7 +399,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) content { actor_id = bypass_actors.value.installation_id @@ -409,7 +409,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -419,7 +419,7 @@ resource "github_organization_ruleset" "dismiss_stale_reviews" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) @@ -452,7 +452,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.teams, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) content { actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id @@ -462,7 +462,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) content { actor_id = bypass_actors.value.installation_id @@ -472,7 +472,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) content { actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id @@ -482,7 +482,7 @@ resource "github_organization_ruleset" "require_signatures" { } dynamic "bypass_actors" { - for_each = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) content { actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) From 0da979321ef4c80d13d0f5fa273364d5bcb2a399 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:38:44 -0400 Subject: [PATCH 56/72] bad references --- modules/organization/rulesets.tf | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index dcc2cf0..a74bd21 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -30,7 +30,7 @@ locals { data "github_team" "branch_ruleset_bypasser" { for_each = { - for team in local.all_team_bypassers : team => team + for bypasser in local.all_team_bypassers : bypasser.team => bypasser.team } slug = each.value @@ -39,7 +39,7 @@ data "github_team" "branch_ruleset_bypasser" { data "github_user" "branch_ruleset_bypasser" { for_each = { - for user in local.all_admin_bypassers: user => user + for bypasser in local.all_admin_bypassers: bypasser.user => bypasser.user } username = each.value @@ -48,7 +48,7 @@ data "github_user" "branch_ruleset_bypasser" { #github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { for_each = { - for role in local.all_repository_roles_bypassers : role => role if !contains(keys(local.github_base_role_ids), role) + for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) } name = each.value From f13aa9b740ffabd09ae5c37b19b42616141ce0d9 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:47:22 -0400 Subject: [PATCH 57/72] trying something --- modules/organization/rulesets.tf | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index a74bd21..d58a915 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -45,10 +45,9 @@ data "github_user" "branch_ruleset_bypasser" { username = each.value } -#github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { for_each = { - for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) + for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role } name = each.value From f941a1240cf196e9246610662dd9301b8ad0f827 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:51:56 -0400 Subject: [PATCH 58/72] updated repo ruleset --- modules/repository_base/rulesets.tf | 55 +++++++++++++++++------------ 1 file changed, 32 insertions(+), 23 deletions(-) diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index f8bc0ca..b6d03b3 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -1,21 +1,24 @@ locals { - ruleset_team_bypassers = merge([ - for ruleset, ruleset_config in var.rulesets : { - for bypasser in coalesce(ruleset_config.bypass_actors.teams, []) : "${ruleset}:${bypasser.team}" => bypasser.team - } if ruleset_config.bypass_actors != null - ]...) - - ruleset_admin_bypassers = merge([ - for ruleset, ruleset_config in var.rulesets : { - for bypasser in coalesce(ruleset_config.bypass_actors.organization_admins, []) : "${ruleset}:${bypasser.user}" => bypasser.user - } if ruleset_config.bypass_actors != null - ]...) - - ruleset_custom_repository_roles = merge([ - for ruleset, ruleset_config in var.rulesets : { - for bypasser in coalesce(ruleset_config.bypass_actors.repository_roles, []) : "${ruleset}:${bypasser.role}" => bypasser.role if !contains(keys(local.github_base_role_ids), bypasser.role) - } if ruleset_config.bypass_actors != null - ]...) + all_team_bypassers = toset(concat( + coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []), []), + [ + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.teams, []), []) + ]... + )) + + 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, []), []), + [ + for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, []), []) + ]... + )) github_base_role_ids = { "maintain" = 2 @@ -26,21 +29,27 @@ locals { data "github_team" "branch_ruleset_bypasser" { - for_each = local.ruleset_team_bypassers + for_each = { + for bypasser in local.all_team_bypassers : bypasser.team => bypasser.team + } slug = each.value summary_only = true } data "github_user" "branch_ruleset_bypasser" { - for_each = local.ruleset_admin_bypassers + for_each = { + for bypasser in local.all_admin_bypassers: bypasser.user => bypasser.user + } username = each.value } #github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { - for_each = local.ruleset_custom_repository_roles + for_each = { + for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role + } name = each.value } @@ -56,7 +65,7 @@ resource "github_repository_ruleset" "ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.role}"].id) + actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) actor_type = "RepositoryRole" bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } @@ -168,7 +177,7 @@ resource "github_repository_ruleset" "ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] content { - actor_id = data.github_team.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.team}"].id + actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id actor_type = "Team" bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } @@ -188,7 +197,7 @@ resource "github_repository_ruleset" "ruleset" { for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] content { - actor_id = data.github_user.branch_ruleset_bypasser["${each.key}:${bypass_actors.value.user}"].id + actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id actor_type = "OrganizationAdmin" bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" } From 22a535ffa937883ee142b8a07c3c48d8e9ecae70 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:52:28 -0400 Subject: [PATCH 59/72] removed bad vars --- modules/repository_base/rulesets.tf | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index b6d03b3..dc28f89 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -1,20 +1,17 @@ locals { all_team_bypassers = toset(concat( - coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []), []), [ for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.teams, []), []) ]... )) 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, []), []), [ for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, []), []) ]... From 53baaec3aa9ff4fefea84b6d19cfe8ea6a476c49 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 11:56:36 -0400 Subject: [PATCH 60/72] flatten isntead of concate --- modules/repository_base/rulesets.tf | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index dc28f89..c7f94d4 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -1,20 +1,20 @@ locals { - all_team_bypassers = toset(concat( + all_team_bypassers = toset(flatten( [ for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.teams, []), []) - ]... + ] )) - all_admin_bypassers = toset(concat( + all_admin_bypassers = toset(flatten( [ for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.organization_admins, []), []) - ]... + ] )) - all_repository_roles_bypassers = toset(concat( + all_repository_roles_bypassers = toset(flatten( [ for _, ruleset_config in var.rulesets : coalesce(try(ruleset_config.bypass_actors.repository_roles, []), []) - ]... + ] )) github_base_role_ids = { From 8e340dae6f7e0a7034dba7622d09c5c74d2ed0c2 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 12:02:33 -0400 Subject: [PATCH 61/72] moved a rule setting --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index d58a915..d5c850a 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -253,7 +253,6 @@ resource "github_organization_ruleset" "base_default_branch_protection" { deletion = true non_fast_forward = true pull_request { - require_last_push_approval = true } } @@ -318,6 +317,7 @@ resource "github_organization_ruleset" "minimum_approvals" { rules { pull_request { + require_last_push_approval = true required_approving_review_count = var.default_branch_protection_rulesets.minimum_approvals.approvals_required } } From 0f2d9b7039a1d3bd77f6ddbaf41709eafea5815d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 14 Mar 2024 16:04:30 +0000 Subject: [PATCH 62/72] terraform-docs: automated action --- .../foundations-github-organization/README.md | 2 +- modules/github-gcloud-oidc/README.md | 2 +- modules/organization/README.md | 42 ++++++++++++------- modules/private_repository/README.md | 3 +- modules/public_repository/README.md | 3 +- modules/repository_base/README.md | 29 +++++++------ modules/repository_set/README.md | 11 ++--- modules/team/README.md | 12 +++--- modules/team_set/README.md | 4 +- 9 files changed, 63 insertions(+), 45 deletions(-) diff --git a/modules/foundations-github-organization/README.md b/modules/foundations-github-organization/README.md index 97e355f..2beae51 100644 --- a/modules/foundations-github-organization/README.md +++ b/modules/foundations-github-organization/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | +| [terraform](#requirement\_terraform) | >= 1.7.1 | | [github](#requirement\_github) | 5.44.0 | ## Providers diff --git a/modules/github-gcloud-oidc/README.md b/modules/github-gcloud-oidc/README.md index 0609fcd..e4a7411 100644 --- a/modules/github-gcloud-oidc/README.md +++ b/modules/github-gcloud-oidc/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | +| [terraform](#requirement\_terraform) | >= 1.7.1 | | [google](#requirement\_google) | >= 3.77 | | [google-beta](#requirement\_google-beta) | >= 3.77 | diff --git a/modules/organization/README.md b/modules/organization/README.md index 7166a13..a26cbcf 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -2,14 +2,14 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [github](#requirement\_github) | 5.42.0 | +| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [github](#requirement\_github) | 6.1.0 | ## Providers | Name | Version | |------|---------| -| [github](#provider\_github) | 5.42.0 | +| [github](#provider\_github) | 6.1.0 | ## Modules @@ -19,25 +19,34 @@ No modules. | Name | Type | |------|------| -| [github_actions_organization_secret.action_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/actions_organization_secret) | resource | -| [github_codespaces_organization_secret.codespace_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/codespaces_organization_secret) | resource | -| [github_dependabot_organization_secret.dependabot_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/dependabot_organization_secret) | resource | -| [github_membership.membership_for_user](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/membership) | resource | -| [github_organization_block.blocked_user](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/organization_block) | resource | -| [github_organization_custom_role.community_manager_role](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/organization_custom_role) | resource | -| [github_organization_custom_role.contractor_role](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/organization_custom_role) | resource | -| [github_organization_custom_role.custom_repository_role](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/organization_custom_role) | resource | -| [github_organization_custom_role.security_engineer_role](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/organization_custom_role) | resource | -| [github_organization_settings.organization_settings](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/organization_settings) | resource | +| [github_actions_organization_secret.action_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/actions_organization_secret) | resource | +| [github_codespaces_organization_secret.codespace_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/codespaces_organization_secret) | resource | +| [github_dependabot_organization_secret.dependabot_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/dependabot_organization_secret) | resource | +| [github_membership.membership_for_user](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/membership) | resource | +| [github_organization_block.blocked_user](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_block) | resource | +| [github_organization_custom_role.community_manager_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | +| [github_organization_custom_role.contractor_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | +| [github_organization_custom_role.custom_repository_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | +| [github_organization_custom_role.security_engineer_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | +| [github_organization_ruleset.base_default_branch_protection](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | +| [github_organization_ruleset.dismiss_stale_reviews](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | +| [github_organization_ruleset.minimum_approvals](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | +| [github_organization_ruleset.require_signatures](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | +| [github_organization_ruleset.ruleset](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | +| [github_organization_settings.organization_settings](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_settings) | resource | +| [github_organization_custom_role.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/organization_custom_role) | data source | +| [github_team.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/team) | data source | +| [github_user.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/user) | data source | ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| [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 | +| [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 | -| [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 | +| [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 | +| [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 | | [enable\_security\_engineer\_role](#input\_enable\_security\_engineer\_role) | If `true` will create a custom repository role for security engineers. Defaults to `false`. If `true` the maximum number of `custom_repository_roles` that can be defined will be reduced by one. | `bool` | `false` | no | @@ -57,6 +66,7 @@ No modules. | [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 = optional(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 f516dee..33b9030 100644 --- a/modules/private_repository/README.md +++ b/modules/private_repository/README.md @@ -3,7 +3,7 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.7.1 | -| [github](#requirement\_github) | 5.42.0 | +| [github](#requirement\_github) | 6.1.0 | ## Providers @@ -38,6 +38,7 @@ No resources. | [name](#input\_name) | The name of the repository to create/import. | `string` | n/a | yes | | [protected\_branches](#input\_protected\_branches) | A list of ref names or patterns that should be protected. Defaults `["main"]` | `list(string)` |
[
"main"
]
| no | | [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 | +| [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 | | [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 | | [topics](#input\_topics) | The topics to apply to the repository | `list(string)` | `[]` | no | diff --git a/modules/public_repository/README.md b/modules/public_repository/README.md index 038a54e..378cd61 100644 --- a/modules/public_repository/README.md +++ b/modules/public_repository/README.md @@ -3,7 +3,7 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.7.1 | -| [github](#requirement\_github) | 5.42.0 | +| [github](#requirement\_github) | 6.1.0 | ## Providers @@ -38,6 +38,7 @@ No resources. | [name](#input\_name) | The name of the repository to create/import. | `string` | n/a | yes | | [protected\_branches](#input\_protected\_branches) | A list of ref names or patterns that should be protected. Defaults `["main"]` | `list(string)` |
[
"main"
]
| no | | [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 | +| [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 | | [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 | | [topics](#input\_topics) | The topics to apply to the repository | `list(string)` | `[]` | no | diff --git a/modules/repository_base/README.md b/modules/repository_base/README.md index f357a5d..ace4b89 100644 --- a/modules/repository_base/README.md +++ b/modules/repository_base/README.md @@ -3,13 +3,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.7.1 | -| [github](#requirement\_github) | 5.42.0 | +| [github](#requirement\_github) | 6.1.0 | ## Providers | Name | Version | |------|---------| -| [github](#provider\_github) | 5.42.0 | +| [github](#provider\_github) | 6.1.0 | ## Modules @@ -19,16 +19,20 @@ No modules. | Name | Type | |------|------| -| [github_actions_environment_secret.environment_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/actions_environment_secret) | resource | -| [github_actions_secret.actions_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/actions_secret) | resource | -| [github_branch_default.default_branch](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/branch_default) | resource | -| [github_codespaces_secret.codespaces_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/codespaces_secret) | resource | -| [github_dependabot_secret.dependabot_secret](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/dependabot_secret) | resource | -| [github_repository.repository](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/repository) | resource | -| [github_repository_collaborators.collaborators](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/repository_collaborators) | resource | -| [github_repository_dependabot_security_updates.automated_security_fixes](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/repository_dependabot_security_updates) | resource | -| [github_repository_environment.environment](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/repository_environment) | resource | -| [github_repository_ruleset.protected_branch_base_rules](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/repository_ruleset) | resource | +| [github_actions_environment_secret.environment_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/actions_environment_secret) | resource | +| [github_actions_secret.actions_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/actions_secret) | resource | +| [github_branch_default.default_branch](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/branch_default) | resource | +| [github_codespaces_secret.codespaces_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/codespaces_secret) | resource | +| [github_dependabot_secret.dependabot_secret](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/dependabot_secret) | resource | +| [github_repository.repository](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository) | resource | +| [github_repository_collaborators.collaborators](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_collaborators) | resource | +| [github_repository_dependabot_security_updates.automated_security_fixes](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_dependabot_security_updates) | resource | +| [github_repository_environment.environment](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_environment) | resource | +| [github_repository_ruleset.protected_branch_base_rules](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_ruleset) | resource | +| [github_repository_ruleset.ruleset](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_ruleset) | resource | +| [github_organization_custom_role.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/organization_custom_role) | data source | +| [github_team.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/team) | data source | +| [github_user.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/user) | data source | ## Inputs @@ -55,6 +59,7 @@ No modules. | [name](#input\_name) | The name of the repository to create/import. | `string` | n/a | yes | | [protected\_branches](#input\_protected\_branches) | A list of ref names or patterns that should be protected. Setting to `[]` means no protection. Defaults `["~DEFAULT_BRANCH"]` | `list(string)` |
[
"~DEFAULT_BRANCH"
]
| no | | [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 | +| [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 | | [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 | | [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_set/README.md b/modules/repository_set/README.md index 534a87f..250cf2f 100644 --- a/modules/repository_set/README.md +++ b/modules/repository_set/README.md @@ -3,13 +3,13 @@ | Name | Version | |------|---------| | [terraform](#requirement\_terraform) | >= 1.7.1 | -| [github](#requirement\_github) | 5.42.0 | +| [github](#requirement\_github) | 6.1.0 | ## Providers | Name | Version | |------|---------| -| [github](#provider\_github) | 5.42.0 | +| [github](#provider\_github) | 6.1.0 | ## Modules @@ -22,9 +22,9 @@ | Name | Type | |------|------| -| [github_actions_organization_secret_repositories.org__action_secret_repo_access](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/actions_organization_secret_repositories) | resource | -| [github_codespaces_organization_secret_repositories.org__codespace_secret_repo_access](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/codespaces_organization_secret_repositories) | resource | -| [github_dependabot_organization_secret_repositories.org__dependabot_secret_repo_access](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/dependabot_organization_secret_repositories) | resource | +| [github_actions_organization_secret_repositories.org__action_secret_repo_access](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/actions_organization_secret_repositories) | resource | +| [github_codespaces_organization_secret_repositories.org__codespace_secret_repo_access](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/codespaces_organization_secret_repositories) | resource | +| [github_dependabot_organization_secret_repositories.org__dependabot_secret_repo_access](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/dependabot_organization_secret_repositories) | resource | ## Inputs @@ -33,6 +33,7 @@ | [default\_repository\_team\_permissions](#input\_default\_repository\_team\_permissions) | A map where the keys are github team slugs and the value is the permissions the team should have by default for every repository. If an entry exists in `repository_team_permissions_override` for a repository then that will take precedence over this default. | `map(string)` | n/a | yes | | [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
repository_team_permissions_override = map(string)
protected_branches = list(string)
advance_security = bool
has_vulnerability_alerts = bool
topics = list(string)
homepage = string
delete_head_on_merge = bool
allow_auto_merge = bool
dependabot_security_updates = bool
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({
action_secrets = optional(map(string))
})))
template_repository = optional(object({
owner = string
repository = string
include_all_branches = bool
}))
license_template = 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
repository_team_permissions_override = map(string)
protected_branches = list(string)
advance_security = bool
topics = list(string)
homepage = string
delete_head_on_merge = bool
allow_auto_merge = bool
dependabot_security_updates = bool
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({
action_secrets = optional(map(string))
})))
template_repository = optional(object({
owner = string
repository = string
include_all_branches = bool
}))
license_template = 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 | ## Outputs diff --git a/modules/team/README.md b/modules/team/README.md index ff3387c..b7cf9c2 100644 --- a/modules/team/README.md +++ b/modules/team/README.md @@ -2,14 +2,14 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [github](#requirement\_github) | 5.42.0 | +| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [github](#requirement\_github) | 6.1.0 | ## Providers | Name | Version | |------|---------| -| [github](#provider\_github) | 5.42.0 | +| [github](#provider\_github) | 6.1.0 | ## Modules @@ -19,9 +19,9 @@ No modules. | Name | Type | |------|------| -| [github_team.team](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/team) | resource | -| [github_team_membership.maintainers](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/team_membership) | resource | -| [github_team_membership.members](https://registry.terraform.io/providers/integrations/github/5.42.0/docs/resources/team_membership) | resource | +| [github_team.team](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/team) | resource | +| [github_team_membership.maintainers](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/team_membership) | resource | +| [github_team_membership.members](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/team_membership) | resource | ## Inputs diff --git a/modules/team_set/README.md b/modules/team_set/README.md index e209b1f..df175c3 100644 --- a/modules/team_set/README.md +++ b/modules/team_set/README.md @@ -2,8 +2,8 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.3 | -| [github](#requirement\_github) | 5.42.0 | +| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [github](#requirement\_github) | 6.1.0 | ## Providers From 0e8bf976a78c2627d7fc20365e630e2a6cd513f3 Mon Sep 17 00:00:00 2001 From: TylerMizuyabu Date: Thu, 14 Mar 2024 13:55:47 -0400 Subject: [PATCH 63/72] Update modules/repository_set/repositories.tf Not using the correct local variable Co-authored-by: Ben Zarboni <99673202+bzarboni1@users.noreply.github.com> Signed-off-by: TylerMizuyabu --- modules/repository_set/repositories.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/repository_set/repositories.tf b/modules/repository_set/repositories.tf index 552b078..4a390b9 100644 --- a/modules/repository_set/repositories.tf +++ b/modules/repository_set/repositories.tf @@ -58,6 +58,6 @@ module "private_repositories" { environments = each.value.environments template_repository = each.value.template_repository license_template = each.value.license_template - rulesets = lookup(local.rulesets_by_public_repository, each.key, {}) + rulesets = lookup(local.rulesets_by_private_repository, each.key, {}) } From 76febc3c166034ec650514d748e630b238d4712b Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 14:30:00 -0400 Subject: [PATCH 64/72] reduced tf version requirement to 1.3 --- modules/foundations-github-organization/versions.tf | 2 +- modules/github-gcloud-oidc/versions.tf | 2 +- modules/organization/versions.tf | 2 +- modules/private_repository/versions.tf | 2 +- modules/public_repository/versions.tf | 2 +- modules/repository_base/versions.tf | 2 +- modules/repository_set/versions.tf | 2 +- modules/team/versions.tf | 2 +- modules/team_set/versions.tf | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/foundations-github-organization/versions.tf b/modules/foundations-github-organization/versions.tf index d9723ab..ac486db 100644 --- a/modules/foundations-github-organization/versions.tf +++ b/modules/foundations-github-organization/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "hashicorp/github" diff --git a/modules/github-gcloud-oidc/versions.tf b/modules/github-gcloud-oidc/versions.tf index 70969c9..6381a79 100644 --- a/modules/github-gcloud-oidc/versions.tf +++ b/modules/github-gcloud-oidc/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { google = { source = "hashicorp/google" diff --git a/modules/organization/versions.tf b/modules/organization/versions.tf index 99316dd..d32b1bb 100644 --- a/modules/organization/versions.tf +++ b/modules/organization/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" diff --git a/modules/private_repository/versions.tf b/modules/private_repository/versions.tf index 99316dd..d32b1bb 100644 --- a/modules/private_repository/versions.tf +++ b/modules/private_repository/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" diff --git a/modules/public_repository/versions.tf b/modules/public_repository/versions.tf index 99316dd..d32b1bb 100644 --- a/modules/public_repository/versions.tf +++ b/modules/public_repository/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" diff --git a/modules/repository_base/versions.tf b/modules/repository_base/versions.tf index 99316dd..d32b1bb 100644 --- a/modules/repository_base/versions.tf +++ b/modules/repository_base/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" diff --git a/modules/repository_set/versions.tf b/modules/repository_set/versions.tf index 99316dd..d32b1bb 100644 --- a/modules/repository_set/versions.tf +++ b/modules/repository_set/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" diff --git a/modules/team/versions.tf b/modules/team/versions.tf index 99316dd..d32b1bb 100644 --- a/modules/team/versions.tf +++ b/modules/team/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" diff --git a/modules/team_set/versions.tf b/modules/team_set/versions.tf index 7b667b4..95d7d87 100644 --- a/modules/team_set/versions.tf +++ b/modules/team_set/versions.tf @@ -1,5 +1,5 @@ terraform { - required_version = ">= 1.7.1" + required_version = ">= 1.3" required_providers { github = { source = "integrations/github" From 90b40517898636755b7ed42cad2f63ac5601e663 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 14 Mar 2024 18:30:22 +0000 Subject: [PATCH 65/72] terraform-docs: automated action --- modules/foundations-github-organization/README.md | 2 +- modules/github-gcloud-oidc/README.md | 2 +- modules/organization/README.md | 2 +- modules/private_repository/README.md | 2 +- modules/public_repository/README.md | 2 +- modules/repository_base/README.md | 2 +- modules/repository_set/README.md | 2 +- modules/team/README.md | 2 +- modules/team_set/README.md | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/modules/foundations-github-organization/README.md b/modules/foundations-github-organization/README.md index 2beae51..97e355f 100644 --- a/modules/foundations-github-organization/README.md +++ b/modules/foundations-github-organization/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 5.44.0 | ## Providers diff --git a/modules/github-gcloud-oidc/README.md b/modules/github-gcloud-oidc/README.md index e4a7411..0609fcd 100644 --- a/modules/github-gcloud-oidc/README.md +++ b/modules/github-gcloud-oidc/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [google](#requirement\_google) | >= 3.77 | | [google-beta](#requirement\_google-beta) | >= 3.77 | diff --git a/modules/organization/README.md b/modules/organization/README.md index a26cbcf..f7f3026 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers diff --git a/modules/private_repository/README.md b/modules/private_repository/README.md index 33b9030..f318c8a 100644 --- a/modules/private_repository/README.md +++ b/modules/private_repository/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers diff --git a/modules/public_repository/README.md b/modules/public_repository/README.md index 378cd61..77eb62a 100644 --- a/modules/public_repository/README.md +++ b/modules/public_repository/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers diff --git a/modules/repository_base/README.md b/modules/repository_base/README.md index ace4b89..faa3189 100644 --- a/modules/repository_base/README.md +++ b/modules/repository_base/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers diff --git a/modules/repository_set/README.md b/modules/repository_set/README.md index 250cf2f..6f09872 100644 --- a/modules/repository_set/README.md +++ b/modules/repository_set/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers diff --git a/modules/team/README.md b/modules/team/README.md index b7cf9c2..0991dfc 100644 --- a/modules/team/README.md +++ b/modules/team/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers diff --git a/modules/team_set/README.md b/modules/team_set/README.md index df175c3..468ce69 100644 --- a/modules/team_set/README.md +++ b/modules/team_set/README.md @@ -2,7 +2,7 @@ | Name | Version | |------|---------| -| [terraform](#requirement\_terraform) | >= 1.7.1 | +| [terraform](#requirement\_terraform) | >= 1.3 | | [github](#requirement\_github) | 6.1.0 | ## Providers From 7a0692584b19cb1b1a1054f4fb3f40d20f7ad9e2 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 15:50:15 -0400 Subject: [PATCH 66/72] created shared ruleset module --- modules/organization/rulesets.tf | 509 +++++++----------------- modules/organization/variables.tf | 4 +- modules/repository_base/rulesets.tf | 172 ++------ modules/ruleset/organization_ruleset.tf | 172 ++++++++ modules/ruleset/repository_ruleset.tf | 157 ++++++++ modules/ruleset/variables.tf | 165 ++++++++ modules/ruleset/versions.tf | 9 + 7 files changed, 668 insertions(+), 520 deletions(-) create mode 100644 modules/ruleset/organization_ruleset.tf create mode 100644 modules/ruleset/repository_ruleset.tf create mode 100644 modules/ruleset/variables.tf create mode 100644 modules/ruleset/versions.tf diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index d5c850a..502a3bb 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -39,7 +39,7 @@ data "github_team" "branch_ruleset_bypasser" { data "github_user" "branch_ruleset_bypasser" { for_each = { - for bypasser in local.all_admin_bypassers: bypasser.user => bypasser.user + for bypasser in local.all_admin_bypassers : bypasser.user => bypasser.user } username = each.value @@ -53,14 +53,18 @@ data "github_organization_custom_role" "branch_ruleset_bypasser" { name = each.value } -resource "github_organization_ruleset" "ruleset" { +module "ruleset" { + source = "../ruleset" + for_each = var.rulesets name = each.key target = each.value.target enforcement = each.value.enforcement - rules { + ruleset_type = "organization" + + rules = { creation = each.value.rules.creation update = each.value.rules.update deletion = each.value.rules.deletion @@ -68,425 +72,178 @@ resource "github_organization_ruleset" "ruleset" { required_linear_history = each.value.rules.required_linear_history required_signatures = each.value.rules.required_signatures - dynamic "branch_name_pattern" { - for_each = each.value.rules.branch_name_pattern != null ? [each.value.rules.branch_name_pattern] : [] - - content { - operator = branch_name_pattern.value.operator - pattern = branch_name_pattern.value.pattern - name = branch_name_pattern.value.name - negate = coalesce(branch_name_pattern.value.negate, false) - } - } - - dynamic "tag_name_pattern" { - for_each = each.value.rules.tag_name_pattern != null ? [each.value.rules.tag_name_pattern] : [] - - content { - operator = tag_name_pattern.value.operator - pattern = tag_name_pattern.value.pattern - name = tag_name_pattern.value.name - negate = coalesce(tag_name_pattern.value.negate, false) - } - } - - dynamic "commit_author_email_pattern" { - for_each = each.value.rules.commit_author_email_pattern != null ? [each.value.rules.commit_author_email_pattern] : [] - - content { - operator = commit_author_email_pattern.value.operator - pattern = commit_author_email_pattern.value.pattern - name = commit_author_email_pattern.value.name - negate = coalesce(commit_author_email_pattern.value.negate, false) - } - } - - dynamic "commit_message_pattern" { - for_each = each.value.rules.commit_message_pattern != null ? [each.value.rules.commit_message_pattern] : [] - - content { - operator = commit_message_pattern.value.operator - pattern = commit_message_pattern.value.pattern - name = commit_message_pattern.value.name - negate = coalesce(commit_message_pattern.value.negate, false) - } - } - - dynamic "committer_email_pattern" { - for_each = each.value.rules.committer_email_pattern != null ? [each.value.rules.committer_email_pattern] : [] - - content { - operator = committer_email_pattern.value.operator - pattern = committer_email_pattern.value.pattern - name = committer_email_pattern.value.name - negate = coalesce(committer_email_pattern.value.negate, false) - } - } - - dynamic "pull_request" { - for_each = each.value.rules.pull_request != null ? [each.value.rules.pull_request] : [] - - content { - dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) - require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) - require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) - required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) - required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) - } - } - - dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks != null ? [each.value.rules.required_status_checks] : [] - - content { - dynamic "required_check" { - for_each = required_status_checks.value.required_check - - content { - context = required_check.value.context - integration_id = required_check.value.integration_id - } - } - - strict_required_status_checks_policy = required_status_checks.value.strict_required_status_check_policy - } - } - - dynamic "required_workflows" { - for_each = each.value.rules.required_workflows != null ? [each.value.rules.required_workflows] : [] - - content { - - dynamic "required_workflow" { - for_each = required_workflows.value.required_workflows - - content { - repository_id = required_workflow.value.repository_id - path = required_workflow.value.path - ref = coalesce(required_workflow.value.ref, "main") - } - } - } - } - } - - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] - - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] - - content { - actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id - actor_type = "Team" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.integrations, [])) : [] - - content { - actor_id = bypass_actors.value.installation_id - actor_type = "Integration" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] - - content { - actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id - actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "conditions" { - for_each = each.value.conditions != null ? [each.value.conditions] : [] - - content { - ref_name { - include = conditions.value.ref_name.include - exclude = conditions.value.ref_name.exclude - } - - dynamic "repository_name" { - for_each = conditions.value.repository_name != null ? [conditions.value.repository_name] : [] - - content { - include = repository_name.value.include - exclude = repository_name.value.exclude - } - } - } - } + branch_name_pattern = each.value.rules.branch_name_pattern + tag_name_pattern = each.value.rules.tag_name_pattern + commit_author_email_pattern = each.value.rules.commit_author_email_pattern + commit_message_pattern = each.value.rules.commit_message_pattern + committer_email_pattern = each.value.rules.committer_email_pattern + pull_request = each.value.rules.pull_request != null + required_status_checks = each.value.rules.required_status_checks + required_workflows = each.value.rules.required_workflows + } + + bypass_actors = { + repository_roles = [for bypasser in try(toset(coalesce(each.value.bypass_actors.repository_roles, [])), []) : { + role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) + always_bypass = role.always_bypass + }] + teams = [for bypasser in try(toset(coalesce(each.value.bypass_actors.teams, [])), []) : { + 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.repository_roles, []) + } + + ref_name_inclusions = each.value.conditions.ref_name.include + ref_name_exclusions = each.value.conditions.ref_name.exclude + repository_name_inclusions = each.value.conditions.repository_name.include + repository_name_exclusions = each.value.conditions.repository_name.exclude } -resource "github_organization_ruleset" "base_default_branch_protection" { - count = var.default_branch_protection_rulesets.base_protection != null ? 1 : 0 +module "base_default_branch_protection" { + source = "../ruleset" + count = var.default_branch_protection_rulesets.base_protection != null ? 1 : 0 + name = "base_default_branch_protection" target = "branch" enforcement = var.default_branch_protection_rulesets.base_protection.enforcement - conditions { - ref_name { - include = ["~DEFAULT_BRANCH"] - exclude = [] - } + ruleset_type = "organization" - repository_name { - include = ["~ALL"] - exclude = [] - } - } + ref_name_inclusions = ["~DEFAULT_BRANCH"] + repository_name_inclusions = ["~ALL"] - rules { + rules = { deletion = true non_fast_forward = true - pull_request { - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) - - content { - actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id - actor_type = "Team" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) - - content { - actor_id = bypass_actors.value.installation_id - actor_type = "Integration" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) - - content { - actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id - actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) - - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } + pull_request = {} + } + + bypass_actors = { + repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { + role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) + always_bypass = role.always_bypass + }] + teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { + 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 + }] + integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) } } -resource "github_organization_ruleset" "minimum_approvals" { - count = var.default_branch_protection_rulesets.minimum_approvals != null ? 1 : 0 +module "minimum_approvals" { + source = "../ruleset" + count = var.default_branch_protection_rulesets.minimum_approvals != null ? 1 : 0 + name = "minimum_approvals" target = "branch" enforcement = var.default_branch_protection_rulesets.minimum_approvals.enforcement - conditions { - ref_name { - include = ["~DEFAULT_BRANCH"] - exclude = [] - } + ruleset_type = "organization" - repository_name { - include = ["~ALL"] - exclude = [] - } - } + ref_name_inclusions = ["~DEFAULT_BRANCH"] + repository_name_inclusions = ["~ALL"] - rules { - pull_request { - require_last_push_approval = true + rules = { + pull_request = { + require_last_push_approval = true required_approving_review_count = var.default_branch_protection_rulesets.minimum_approvals.approvals_required } } - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) - - content { - actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id - actor_type = "Team" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) - - content { - actor_id = bypass_actors.value.installation_id - actor_type = "Integration" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) - - content { - actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id - actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } + bypass_actors = { + repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { + role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) + always_bypass = role.always_bypass + }] + teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { + 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 + }] + integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) } +} - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } -} +module "dismiss_stale_reviews" { + source = "../ruleset" + count = var.default_branch_protection_rulesets.dismiss_stale_reviews != null ? 1 : 0 -resource "github_organization_ruleset" "dismiss_stale_reviews" { - count = var.default_branch_protection_rulesets.dismiss_stale_reviews != null ? 1 : 0 name = "dismiss_stale_reviews" target = "branch" enforcement = var.default_branch_protection_rulesets.dismiss_stale_reviews.enforcement - conditions { - ref_name { - include = ["~DEFAULT_BRANCH"] - exclude = [] - } + ruleset_type = "organization" - repository_name { - include = ["~ALL"] - exclude = [] - } - } + ref_name_inclusions = ["~DEFAULT_BRANCH"] + repository_name_inclusions = ["~ALL"] - rules { - pull_request { + rules = { + pull_request = { dismiss_stale_reviews_on_push = true } } - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) - - content { - actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id - actor_type = "Team" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) - - content { - actor_id = bypass_actors.value.installation_id - actor_type = "Integration" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) - - content { - actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id - actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) - - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } + bypass_actors = { + repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { + role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) + always_bypass = role.always_bypass + }] + teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { + 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 + }] + integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) } } -resource "github_organization_ruleset" "require_signatures" { - count = var.default_branch_protection_rulesets.require_signatures != null ? 1 : 0 +module "require_signatures" { + source = "../ruleset" + count = var.default_branch_protection_rulesets.require_signatures != null ? 1 : 0 + name = "require_signatures" target = "branch" enforcement = var.default_branch_protection_rulesets.require_signatures.enforcement - conditions { - ref_name { - include = ["~DEFAULT_BRANCH"] - exclude = [] - } + ruleset_type = "organization" - repository_name { - include = ["~ALL"] - exclude = [] - } - } + ref_name_inclusions = ["~DEFAULT_BRANCH"] + repository_name_inclusions = ["~ALL"] - rules { + rules = { required_signatures = true } - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.teams, []),[]) - - content { - actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id - actor_type = "Team" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.integrations, []),[]) - - content { - actor_id = bypass_actors.value.installation_id - actor_type = "Integration" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.organization_admins, []),[]) - - content { - actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id - actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = coalesce(try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []),[]) - - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } -} + bypass_actors = { + repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { + role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) + always_bypass = role.always_bypass + }] + teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { + 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 + }] + integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + } +} \ No newline at end of file diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index c260b2f..3708ac1 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -222,10 +222,10 @@ variable "rulesets" { include = list(string) exclude = list(string) }) - repository_name = optional(object({ + repository_name = object({ include = list(string) exclude = list(string) - })) + }) })) rules = object({ branch_name_pattern = optional(object({ diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index c7f94d4..e72beba 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -36,13 +36,12 @@ data "github_team" "branch_ruleset_bypasser" { data "github_user" "branch_ruleset_bypasser" { for_each = { - for bypasser in local.all_admin_bypassers: bypasser.user => bypasser.user + for bypasser in local.all_admin_bypassers : bypasser.user => bypasser.user } username = each.value } -#github_organization_custom_role is actualy repository custom roles. The provider doesn't seem to support custom github organization roles data "github_organization_custom_role" "branch_ruleset_bypasser" { for_each = { for bypasser in local.all_repository_roles_bypassers : bypasser.role => bypasser.role @@ -51,24 +50,18 @@ data "github_organization_custom_role" "branch_ruleset_bypasser" { name = each.value } -resource "github_repository_ruleset" "ruleset" { +module "ruleset" { + source = "../ruleset" + for_each = var.rulesets name = each.key target = each.value.target enforcement = each.value.enforcement - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.repository_roles, [])) : [] - - content { - actor_id = lookup(local.github_base_role_ids, bypass_actors.value.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypass_actors.value.role}"].id) - actor_type = "RepositoryRole" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } + ruleset_type = "repository" - rules { + rules = { creation = each.value.rules.creation update = each.value.rules.update deletion = each.value.rules.deletion @@ -77,137 +70,32 @@ resource "github_repository_ruleset" "ruleset" { required_signatures = each.value.rules.required_signatures update_allows_fetch_and_merge = each.value.rules.update_allows_fetch_and_merge - dynamic "branch_name_pattern" { - for_each = each.value.rules.branch_name_pattern != null ? [each.value.rules.branch_name_pattern] : [] - - content { - operator = branch_name_pattern.value.operator - pattern = branch_name_pattern.value.pattern - name = branch_name_pattern.value.name - negate = coalesce(branch_name_pattern.value.negate, false) - } - } - - dynamic "tag_name_pattern" { - for_each = each.value.rules.tag_name_pattern != null ? [each.value.rules.tag_name_pattern] : [] - - content { - operator = tag_name_pattern.value.operator - pattern = tag_name_pattern.value.pattern - name = tag_name_pattern.value.name - negate = coalesce(tag_name_pattern.value.negate, false) - } - } - - dynamic "commit_author_email_pattern" { - for_each = each.value.rules.commit_author_email_pattern != null ? [each.value.rules.commit_author_email_pattern] : [] - - content { - operator = commit_author_email_pattern.value.operator - pattern = commit_author_email_pattern.value.pattern - name = commit_author_email_pattern.value.name - negate = coalesce(commit_author_email_pattern.value.negate, false) - } - } - - dynamic "commit_message_pattern" { - for_each = each.value.rules.commit_message_pattern != null ? [each.value.rules.commit_message_pattern] : [] - - content { - operator = commit_message_pattern.value.operator - pattern = commit_message_pattern.value.pattern - name = commit_message_pattern.value.name - negate = coalesce(commit_message_pattern.value.negate, false) - } - } - - dynamic "committer_email_pattern" { - for_each = each.value.rules.committer_email_pattern != null ? [each.value.rules.committer_email_pattern] : [] - - content { - operator = committer_email_pattern.value.operator - pattern = committer_email_pattern.value.pattern - name = committer_email_pattern.value.name - negate = coalesce(committer_email_pattern.value.negate, false) - } - } - - dynamic "pull_request" { - for_each = each.value.rules.pull_request != null ? [each.value.rules.pull_request] : [] - - content { - dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) - require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) - require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) - required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) - required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) - } - } - - dynamic "required_status_checks" { - for_each = each.value.rules.required_status_checks != null ? [each.value.rules.required_status_checks] : [] - - content { - dynamic "required_check" { - for_each = required_status_checks.value.required_check - - content { - context = required_check.value.context - integration_id = required_check.value.integration_id - } - } - - strict_required_status_checks_policy = required_status_checks.value.strict_required_status_check_policy - } - } - - dynamic "required_deployments" { - for_each = each.value.rules.required_deployment_environments != null ? [each.value.rules.required_deployment_environments] : [] - - content { - required_deployment_environments = required_deployments.value - } - } - } - - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.teams, [])) : [] - - content { - actor_id = data.github_team.branch_ruleset_bypasser["${bypass_actors.value.team}"].id - actor_type = "Team" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } + branch_name_pattern = each.value.rules.branch_name_pattern + tag_name_pattern = each.value.rules.tag_name_pattern + commit_author_email_pattern = each.value.rules.commit_author_email_pattern + commit_message_pattern = each.value.rules.commit_message_pattern + committer_email_pattern = each.value.rules.committer_email_pattern + pull_request = each.value.rules.pull_request != null + required_status_checks = each.value.rules.required_status_checks + required_deployment_environments = each.value.rules.required_deployment_environments } - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.integrations, [])) : [] - - content { - actor_id = bypass_actors.value.installation_id - actor_type = "Integration" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } - } - - dynamic "bypass_actors" { - for_each = each.value.bypass_actors != null ? toset(coalesce(each.value.bypass_actors.organization_admins, [])) : [] - - content { - actor_id = data.github_user.branch_ruleset_bypasser["${bypass_actors.value.user}"].id - actor_type = "OrganizationAdmin" - bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" - } + bypass_actors = { + repository_roles = [for bypasser in try(toset(coalesce(each.value.bypass_actors.repository_roles, [])), []) : { + role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) + always_bypass = role.always_bypass + }] + teams = [for bypasser in try(toset(coalesce(each.value.bypass_actors.teams, [])), []) : { + 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.repository_roles, []) } - dynamic "conditions" { - for_each = each.value.conditions != null ? [each.value.conditions] : [] - - content { - ref_name { - include = conditions.value.ref_name.include - exclude = conditions.value.ref_name.exclude - } - } - } + ref_name_inclusions = each.value.conditions.ref_name.include + ref_name_exclusions = each.value.conditions.ref_name.exclude } \ No newline at end of file diff --git a/modules/ruleset/organization_ruleset.tf b/modules/ruleset/organization_ruleset.tf new file mode 100644 index 0000000..b2b531f --- /dev/null +++ b/modules/ruleset/organization_ruleset.tf @@ -0,0 +1,172 @@ +resource "github_organization_ruleset" "ruleset" { + count = var.ruleset_type == "organization" ? 1 : 0 + + name = var.name + target = var.target + enforcement = var.enforcement + + dynamic "conditions" { + for_each = length(concat(var.ref_name_inclusions, var.ref_name_exclusions)) > 0 ? [1] : [] + content { + ref_name { + include = var.ref_name_inclusions + exclude = var.ref_name_exclusions + } + + repository_name { + include = var.repository_name_inclusions + exclude = var.repository_name_exclusions + } + } + } + + rules { + creation = var.rules.creation + update = var.rules.update + deletion = var.rules.deletion + non_fast_forward = var.rules.non_fast_forward + required_linear_history = var.rules.required_linear_history + required_signatures = var.rules.required_signatures + + dynamic "branch_name_pattern" { + for_each = var.rules.branch_name_pattern != null ? [var.rules.branch_name_pattern] : [] + + content { + operator = branch_name_pattern.value.operator + pattern = branch_name_pattern.value.pattern + name = branch_name_pattern.value.name + negate = coalesce(branch_name_pattern.value.negate, false) + } + } + + dynamic "tag_name_pattern" { + for_each = var.rules.tag_name_pattern != null ? [var.rules.tag_name_pattern] : [] + + content { + operator = tag_name_pattern.value.operator + pattern = tag_name_pattern.value.pattern + name = tag_name_pattern.value.name + negate = coalesce(tag_name_pattern.value.negate, false) + } + } + + dynamic "commit_author_email_pattern" { + for_each = var.rules.commit_author_email_pattern != null ? [var.rules.commit_author_email_pattern] : [] + + content { + operator = commit_author_email_pattern.value.operator + pattern = commit_author_email_pattern.value.pattern + name = commit_author_email_pattern.value.name + negate = coalesce(commit_author_email_pattern.value.negate, false) + } + } + + dynamic "commit_message_pattern" { + for_each = var.rules.commit_message_pattern != null ? [var.rules.commit_message_pattern] : [] + + content { + operator = commit_message_pattern.value.operator + pattern = commit_message_pattern.value.pattern + name = commit_message_pattern.value.name + negate = coalesce(commit_message_pattern.value.negate, false) + } + } + + dynamic "committer_email_pattern" { + for_each = var.rules.committer_email_pattern != null ? [var.rules.committer_email_pattern] : [] + + content { + operator = committer_email_pattern.value.operator + pattern = committer_email_pattern.value.pattern + name = committer_email_pattern.value.name + negate = coalesce(committer_email_pattern.value.negate, false) + } + } + + dynamic "pull_request" { + for_each = var.rules.pull_request != null ? [var.rules.pull_request] : [] + + content { + dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) + require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) + require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) + required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) + required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) + } + } + + dynamic "required_status_checks" { + for_each = var.rules.required_status_checks != null ? [var.rules.required_status_checks] : [] + + content { + dynamic "required_check" { + for_each = required_status_checks.value.required_check + + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } + + strict_required_status_checks_policy = required_status_checks.value.strict_required_status_check_policy + } + } + + dynamic "required_workflows" { + for_each = var.rules.required_workflows != null ? [var.rules.required_workflows] : [] + + content { + + dynamic "required_workflow" { + for_each = required_workflows.value.required_workflows + + content { + repository_id = required_workflow.value.repository_id + path = required_workflow.value.path + ref = coalesce(required_workflow.value.ref, "main") + } + } + } + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.repository_roles, [])) : [] + + content { + actor_id = bypass_actors.value.role_id + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.teams, [])) : [] + + content { + actor_id = bypass_actors.value.team_id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.integrations, [])) : [] + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.organization_admins, [])) : [] + + content { + actor_id = bypass_actors.value.user_id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } +} \ No newline at end of file diff --git a/modules/ruleset/repository_ruleset.tf b/modules/ruleset/repository_ruleset.tf new file mode 100644 index 0000000..0af90b2 --- /dev/null +++ b/modules/ruleset/repository_ruleset.tf @@ -0,0 +1,157 @@ +resource "github_repository_ruleset" "ruleset" { + count = var.ruleset_type == "repository" ? 1 : 0 + name = var.name + target = var.target + enforcement = var.enforcement + + dynamic "conditions" { + for_each = length(concat(var.ref_name_inclusions, var.ref_name_exclusions)) > 0 ? [1] : [] + content { + ref_name { + include = var.ref_name_inclusions + exclude = var.ref_name_exclusions + } + } + } + + rules { + creation = var.rules.creation + update = var.rules.update + deletion = var.rules.deletion + non_fast_forward = var.rules.non_fast_forward + required_linear_history = var.rules.required_linear_history + required_signatures = var.rules.required_signatures + update_allows_fetch_and_merge = var.rules.update_allows_fetch_and_merge + + dynamic "branch_name_pattern" { + for_each = var.rules.branch_name_pattern != null ? [var.rules.branch_name_pattern] : [] + + content { + operator = branch_name_pattern.value.operator + pattern = branch_name_pattern.value.pattern + name = branch_name_pattern.value.name + negate = coalesce(branch_name_pattern.value.negate, false) + } + } + + dynamic "tag_name_pattern" { + for_each = var.rules.tag_name_pattern != null ? [var.rules.tag_name_pattern] : [] + + content { + operator = tag_name_pattern.value.operator + pattern = tag_name_pattern.value.pattern + name = tag_name_pattern.value.name + negate = coalesce(tag_name_pattern.value.negate, false) + } + } + + dynamic "commit_author_email_pattern" { + for_each = var.rules.commit_author_email_pattern != null ? [var.rules.commit_author_email_pattern] : [] + + content { + operator = commit_author_email_pattern.value.operator + pattern = commit_author_email_pattern.value.pattern + name = commit_author_email_pattern.value.name + negate = coalesce(commit_author_email_pattern.value.negate, false) + } + } + + dynamic "commit_message_pattern" { + for_each = var.rules.commit_message_pattern != null ? [var.rules.commit_message_pattern] : [] + + content { + operator = commit_message_pattern.value.operator + pattern = commit_message_pattern.value.pattern + name = commit_message_pattern.value.name + negate = coalesce(commit_message_pattern.value.negate, false) + } + } + + dynamic "committer_email_pattern" { + for_each = var.rules.committer_email_pattern != null ? [var.rules.committer_email_pattern] : [] + + content { + operator = committer_email_pattern.value.operator + pattern = committer_email_pattern.value.pattern + name = committer_email_pattern.value.name + negate = coalesce(committer_email_pattern.value.negate, false) + } + } + + dynamic "pull_request" { + for_each = var.rules.pull_request != null ? [var.rules.pull_request] : [] + + content { + dismiss_stale_reviews_on_push = coalesce(pull_request.value.dismiss_stale_reviews_on_push, false) + require_code_owner_review = coalesce(pull_request.value.require_code_owner_review, false) + require_last_push_approval = coalesce(pull_request.value.require_last_push_approval, false) + required_approving_review_count = coalesce(pull_request.value.required_approving_review_count, 0) + required_review_thread_resolution = coalesce(pull_request.value.required_review_thread_resolution, false) + } + } + + dynamic "required_status_checks" { + for_each = var.rules.required_status_checks != null ? [var.rules.required_status_checks] : [] + + content { + dynamic "required_check" { + for_each = required_status_checks.value.required_check + + content { + context = required_check.value.context + integration_id = required_check.value.integration_id + } + } + + strict_required_status_checks_policy = required_status_checks.value.strict_required_status_check_policy + } + } + + dynamic "required_deployments" { + for_each = var.rules.required_deployment_environments != null ? [var.rules.required_deployment_environments] : [] + + content { + required_deployment_environments = required_deployments.value + } + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors.repository_roles != null ? [var.bypass_actors.repository_roles] : [] + + content { + actor_id = bypass_actors.value.role_id + actor_type = "RepositoryRole" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.teams, [])) : [] + + content { + actor_id = bypass_actors.value.team_id + actor_type = "Team" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.integrations, [])) : [] + + content { + actor_id = bypass_actors.value.installation_id + actor_type = "Integration" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } + + dynamic "bypass_actors" { + for_each = var.bypass_actors != null ? toset(coalesce(var.bypass_actors.organization_admins, [])) : [] + + content { + actor_id = bypass_actors.value.user_id + actor_type = "OrganizationAdmin" + bypass_mode = coalesce(bypass_actors.value.always_bypass, false) ? "always" : "pull_request" + } + } +} \ No newline at end of file diff --git a/modules/ruleset/variables.tf b/modules/ruleset/variables.tf new file mode 100644 index 0000000..1c245d9 --- /dev/null +++ b/modules/ruleset/variables.tf @@ -0,0 +1,165 @@ +variable "name" { + type = string + description = "The name of the ruleset." +} + +variable "bypass_actors" { + type = 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) + }))) + }) + default = {} + description = "An object containing fields for role, team, organization admin, and integration bypass actors. Defaults to `{}`" +} + +variable "rules" { + type = 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_workflows = optional(object({ + required_workflows = list(object({ + repository_id = number + path = string + ref = optional(string) + })) + })) + required_deployment_environments = optional(list(string)) + }) + description = "An object containing fields for all the rule definitions the ruleset should enforce." +} + +variable "ref_name_inclusions" { + type = list(string) + description = "A list of ref names or patterns to include. 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." + default = [] +} + +variable "ref_name_exclusions" { + type = list(string) + description = "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." + default = [] +} + +variable "repository_name_inclusions" { + type = list(string) + description = "A list of repository names or patterns to include. If `ruleset_type` is set to `repository` then this field is ignored." + default = [] +} + +variable "repository_name_exclusions" { + type = list(string) + description = "A list of repository names or patterns to exclude. If `ruleset_type` is set to `repository` then this field is ignored." + default = [] +} + +variable "conditions" { + type = object({ + ref_name = optional(object({ + include = list(string) + exclude = list(string) + })) + repository_name = optional(object({ + include = list(string) + exclude = list(string) + })) + }) + description = "An object that describes what branches and repositories the ruleset should apply to. If `ruleset_type` is set to `repository` then this field is optional and repository_name is ignored." + default = {} +} + +variable "target" { + type = string + description = "The target of the ruleset. Should be one of either `branch` or `tag`." + validation { + condition = can(regex("branch|tag", var.target)) + error_message = "The target must be either `branch` or `tag`." + } +} + +variable "ruleset_type" { + type = string + description = "The type of rulset to make. Should be one of ether `organization` or `repository`." + validation { + condition = can(regex("organization|repository", var.ruleset_type)) + error_message = "The ruleset type must be either `organization` or `repository`." + } +} + +variable "enforcement" { + type = string + description = "The enforcement level of the ruleset. Should be one of either `active`, `evaluate` or `disabled`. Defaults to `active`" + default = "active" + validation { + condition = can(regex("active|evaluate|disabled", var.enforcement)) + error_message = "The enforcement level must be either `active`, `evaluate` or `disabled`." + } +} + +variable "repository" { + type = string + description = "The repository to create the ruleset under. Only applicable if `ruleset_type` is set to `repository`. Defaults to \"\"" + default = "" +} \ No newline at end of file diff --git a/modules/ruleset/versions.tf b/modules/ruleset/versions.tf new file mode 100644 index 0000000..d32b1bb --- /dev/null +++ b/modules/ruleset/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">= 1.3" + required_providers { + github = { + source = "integrations/github" + version = "6.1.0" + } + } +} \ No newline at end of file From 1c10ea590ca0c8695e1e06c804fc983ffad84186 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 14 Mar 2024 19:50:37 +0000 Subject: [PATCH 67/72] terraform-docs: automated action --- modules/organization/README.md | 15 ++++++----- modules/repository_base/README.md | 5 ++-- modules/ruleset/README.md | 44 +++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+), 9 deletions(-) create mode 100644 modules/ruleset/README.md diff --git a/modules/organization/README.md b/modules/organization/README.md index f7f3026..6cee7f2 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -13,7 +13,13 @@ ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [base\_default\_branch\_protection](#module\_base\_default\_branch\_protection) | ../ruleset | n/a | +| [dismiss\_stale\_reviews](#module\_dismiss\_stale\_reviews) | ../ruleset | n/a | +| [minimum\_approvals](#module\_minimum\_approvals) | ../ruleset | n/a | +| [require\_signatures](#module\_require\_signatures) | ../ruleset | n/a | +| [ruleset](#module\_ruleset) | ../ruleset | n/a | ## Resources @@ -28,11 +34,6 @@ No modules. | [github_organization_custom_role.contractor_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | | [github_organization_custom_role.custom_repository_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | | [github_organization_custom_role.security_engineer_role](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_custom_role) | resource | -| [github_organization_ruleset.base_default_branch_protection](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | -| [github_organization_ruleset.dismiss_stale_reviews](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | -| [github_organization_ruleset.minimum_approvals](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | -| [github_organization_ruleset.require_signatures](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | -| [github_organization_ruleset.ruleset](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | | [github_organization_settings.organization_settings](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_settings) | resource | | [github_organization_custom_role.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/organization_custom_role) | data source | | [github_team.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/team) | data source | @@ -66,7 +67,7 @@ No modules. | [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 = optional(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_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 | ## Outputs diff --git a/modules/repository_base/README.md b/modules/repository_base/README.md index faa3189..d05a568 100644 --- a/modules/repository_base/README.md +++ b/modules/repository_base/README.md @@ -13,7 +13,9 @@ ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| [ruleset](#module\_ruleset) | ../ruleset | n/a | ## Resources @@ -29,7 +31,6 @@ No modules. | [github_repository_dependabot_security_updates.automated_security_fixes](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_dependabot_security_updates) | resource | | [github_repository_environment.environment](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_environment) | resource | | [github_repository_ruleset.protected_branch_base_rules](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_ruleset) | resource | -| [github_repository_ruleset.ruleset](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_ruleset) | resource | | [github_organization_custom_role.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/organization_custom_role) | data source | | [github_team.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/team) | data source | | [github_user.branch_ruleset_bypasser](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/data-sources/user) | data source | diff --git a/modules/ruleset/README.md b/modules/ruleset/README.md new file mode 100644 index 0000000..1809db2 --- /dev/null +++ b/modules/ruleset/README.md @@ -0,0 +1,44 @@ +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.3 | +| [github](#requirement\_github) | 6.1.0 | + +## Providers + +| Name | Version | +|------|---------| +| [github](#provider\_github) | 6.1.0 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [github_organization_ruleset.ruleset](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/organization_ruleset) | resource | +| [github_repository_ruleset.ruleset](https://registry.terraform.io/providers/integrations/github/6.1.0/docs/resources/repository_ruleset) | resource | + +## Inputs + +| 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 | +| [conditions](#input\_conditions) | An object that describes what branches and repositories the ruleset should apply to. If `ruleset_type` is set to `repository` then this field is optional and repository\_name is ignored. |
object({
ref_name = optional(object({
include = list(string)
exclude = list(string)
}))
repository_name = optional(object({
include = list(string)
exclude = list(string)
}))
})
| `{}` | 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 | +| [ref\_name\_inclusions](#input\_ref\_name\_inclusions) | A list of ref names or patterns to include. 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 | +| [repository](#input\_repository) | The repository to create the ruleset under. Only applicable if `ruleset_type` is set to `repository`. Defaults to "" | `string` | `""` | no | +| [repository\_name\_exclusions](#input\_repository\_name\_exclusions) | A list of repository names or patterns to exclude. If `ruleset_type` is set to `repository` then this field is ignored. | `list(string)` | `[]` | no | +| [repository\_name\_inclusions](#input\_repository\_name\_inclusions) | A list of repository names or patterns to include. If `ruleset_type` is set to `repository` then this field is ignored. | `list(string)` | `[]` | no | +| [rules](#input\_rules) | An object containing fields for all the rule definitions the ruleset should enforce. |
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_workflows = optional(object({
required_workflows = list(object({
repository_id = number
path = string
ref = optional(string)
}))
}))
required_deployment_environments = optional(list(string))
})
| n/a | yes | +| [ruleset\_type](#input\_ruleset\_type) | The type of rulset to make. Should be one of ether `organization` or `repository`. | `string` | n/a | yes | +| [target](#input\_target) | The target of the ruleset. Should be one of either `branch` or `tag`. | `string` | n/a | yes | + +## Outputs + +No outputs. \ No newline at end of file From 7889f8019d224e39a41446bf4f72f0e2c0cb1d9e Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 15:53:37 -0400 Subject: [PATCH 68/72] typo --- modules/organization/rulesets.tf | 10 +++++----- modules/repository_base/rulesets.tf | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 502a3bb..167725d 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -85,7 +85,7 @@ module "ruleset" { bypass_actors = { repository_roles = [for bypasser in try(toset(coalesce(each.value.bypass_actors.repository_roles, [])), []) : { role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) - always_bypass = role.always_bypass + always_bypass = bypasser.always_bypass }] teams = [for bypasser in try(toset(coalesce(each.value.bypass_actors.teams, [])), []) : { team_id = data.github_team.branch_ruleset_bypasser["${bypasser.team}"].id @@ -126,7 +126,7 @@ module "base_default_branch_protection" { bypass_actors = { repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) - always_bypass = role.always_bypass + always_bypass = bypasser.always_bypass }] teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { team_id = data.github_team.branch_ruleset_bypasser["${bypasser.team}"].id @@ -163,7 +163,7 @@ module "minimum_approvals" { bypass_actors = { repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) - always_bypass = role.always_bypass + always_bypass = bypasser.always_bypass }] teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { team_id = data.github_team.branch_ruleset_bypasser["${bypasser.team}"].id @@ -200,7 +200,7 @@ module "dismiss_stale_reviews" { bypass_actors = { repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) - always_bypass = role.always_bypass + always_bypass = bypasser.always_bypass }] teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { team_id = data.github_team.branch_ruleset_bypasser["${bypasser.team}"].id @@ -234,7 +234,7 @@ module "require_signatures" { bypass_actors = { repository_roles = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.repository_roles, [])), []) : { role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) - always_bypass = role.always_bypass + always_bypass = bypasser.always_bypass }] teams = [for bypasser in try(toset(coalesce(var.default_branch_protection_rulesets.bypass_actors.teams, [])), []) : { team_id = data.github_team.branch_ruleset_bypasser["${bypasser.team}"].id diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index e72beba..ae3d654 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -83,7 +83,7 @@ module "ruleset" { bypass_actors = { repository_roles = [for bypasser in try(toset(coalesce(each.value.bypass_actors.repository_roles, [])), []) : { role_id = lookup(local.github_base_role_ids, bypasser.role, data.github_organization_custom_role.branch_ruleset_bypasser["${bypasser.role}"].id) - always_bypass = role.always_bypass + always_bypass = bypasser.always_bypass }] teams = [for bypasser in try(toset(coalesce(each.value.bypass_actors.teams, [])), []) : { team_id = data.github_team.branch_ruleset_bypasser["${bypasser.team}"].id From 96353c693982ebb64a60779d28f295a8dd76bfbd Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 15:55:19 -0400 Subject: [PATCH 69/72] bad copilot --- modules/organization/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 167725d..25ef4cf 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -77,7 +77,7 @@ module "ruleset" { commit_author_email_pattern = each.value.rules.commit_author_email_pattern commit_message_pattern = each.value.rules.commit_message_pattern committer_email_pattern = each.value.rules.committer_email_pattern - pull_request = each.value.rules.pull_request != null + pull_request = each.value.rules.pull_request required_status_checks = each.value.rules.required_status_checks required_workflows = each.value.rules.required_workflows } From 80bddd3c2e1d209d17c185fb2643e118743b142a Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 15:56:21 -0400 Subject: [PATCH 70/72] I hate you copilot --- modules/repository_base/rulesets.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/repository_base/rulesets.tf b/modules/repository_base/rulesets.tf index ae3d654..a199f5d 100644 --- a/modules/repository_base/rulesets.tf +++ b/modules/repository_base/rulesets.tf @@ -75,7 +75,7 @@ module "ruleset" { commit_author_email_pattern = each.value.rules.commit_author_email_pattern commit_message_pattern = each.value.rules.commit_message_pattern committer_email_pattern = each.value.rules.committer_email_pattern - pull_request = each.value.rules.pull_request != null + pull_request = each.value.rules.pull_request required_status_checks = each.value.rules.required_status_checks required_deployment_environments = each.value.rules.required_deployment_environments } From 5a810f5afca157d199baa04337b0bfe144b6d75c Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 16:00:26 -0400 Subject: [PATCH 71/72] logic error --- modules/ruleset/repository_ruleset.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ruleset/repository_ruleset.tf b/modules/ruleset/repository_ruleset.tf index 0af90b2..bcaa162 100644 --- a/modules/ruleset/repository_ruleset.tf +++ b/modules/ruleset/repository_ruleset.tf @@ -117,7 +117,7 @@ resource "github_repository_ruleset" "ruleset" { } dynamic "bypass_actors" { - for_each = var.bypass_actors.repository_roles != null ? [var.bypass_actors.repository_roles] : [] + for_each = var.bypass_actors.repository_roles != null ? toset(coalesce(var.bypass_actors.repository_roles, [])) : [] content { actor_id = bypass_actors.value.role_id From e838480026be8b1db02b913c0ef4c226a94c8979 Mon Sep 17 00:00:00 2001 From: Tyler Mizuyabu Date: Thu, 14 Mar 2024 16:04:00 -0400 Subject: [PATCH 72/72] what am i doing --- modules/organization/rulesets.tf | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/organization/rulesets.tf b/modules/organization/rulesets.tf index 25ef4cf..a51af05 100644 --- a/modules/organization/rulesets.tf +++ b/modules/organization/rulesets.tf @@ -95,7 +95,7 @@ module "ruleset" { user_id = data.github_user.branch_ruleset_bypasser["${bypasser.user}"].id always_bypass = bypasser.always_bypass }] - integrations = try(each.value.bypass_actors.repository_roles, []) + integrations = try(each.value.bypass_actors.integrations, []) } ref_name_inclusions = each.value.conditions.ref_name.include @@ -136,7 +136,7 @@ module "base_default_branch_protection" { user_id = data.github_user.branch_ruleset_bypasser["${bypasser.user}"].id always_bypass = bypasser.always_bypass }] - integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } @@ -173,7 +173,7 @@ module "minimum_approvals" { user_id = data.github_user.branch_ruleset_bypasser["${bypasser.user}"].id always_bypass = bypasser.always_bypass }] - integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } @@ -210,7 +210,7 @@ module "dismiss_stale_reviews" { user_id = data.github_user.branch_ruleset_bypasser["${bypasser.user}"].id always_bypass = bypasser.always_bypass }] - integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } @@ -244,6 +244,6 @@ module "require_signatures" { user_id = data.github_user.branch_ruleset_bypasser["${bypasser.user}"].id always_bypass = bypasser.always_bypass }] - integrations = try(var.default_branch_protection_rulesets.bypass_actors.repository_roles, []) + integrations = try(var.default_branch_protection_rulesets.bypass_actors.integrations, []) } } \ No newline at end of file