From 47253b223d0a9a215f0589b10ca2805a3b596369 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Fri, 23 Aug 2024 11:17:59 +0200 Subject: [PATCH 01/11] feat(module): add root module to call submodules --- .gitignore | 3 +- README.md | 50 ++++++++++--- main.tf | 42 ++++++++++- outputs.tf | 5 +- variables.tf | 200 +++++++++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 278 insertions(+), 22 deletions(-) diff --git a/.gitignore b/.gitignore index 0807788..724373e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,4 +39,5 @@ backend.tf.json **/*.temp **/*.bak **/*.*swp -**/.DS_Store \ No newline at end of file +**/.DS_Store +.terraform.lock.hcl diff --git a/README.md b/README.md index 3fa9097..db4fbb3 100644 --- a/README.md +++ b/README.md @@ -20,31 +20,59 @@ TODO ## Providers -| Name | Version | -|------|---------| -| random | >= 3.0 | +No providers. ## Modules -No modules. +| Name | Source | Version | +|------|--------|---------| +| actions_runner_group | ./modules/actions_runner_group | n/a | +| organization_settings | ./modules/organization_settings | n/a | ## Resources -| Name | Type | -|------|------| -| [random_pet.template](https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/pet) | resource | +No resources. ## Inputs | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| -| length | The length of the random name | `number` | `2` | no | +| advanced_security_enabled_for_new_repositories | Whether or not advanced security is enabled for new repositories. Defaults to false. | `bool` | `null` | no | +| allows_public_repositories | Whether public repositories can be added to the runner group | `bool` | `null` | no | +| billing_email | The billing email address for the organization. | `string` | n/a | yes | +| blog | The blog URL for the organization. | `string` | `null` | no | +| company | The company name for the organization. | `string` | `null` | no | +| default_repository_permission | The default permission for organization members to create new repositories. Can be one of read, write, admin, or none. Defaults to read. | `string` | `null` | no | +| dependabot_alerts_enabled_for_new_repositories | Whether or not dependabot alerts are enabled for new repositories. Defaults to false. | `bool` | `null` | no | +| dependabot_security_updates_enabled_for_new_repositories | Whether or not dependabot security updates are enabled for new repositories. Defaults to false. | `bool` | `null` | no | +| dependency_graph_enabled_for_new_repositories | Whether or not dependency graph is enabled for new repositories. Defaults to false. | `bool` | `null` | no | +| description | The description for the organization. | `string` | `null` | no | +| email | The email address for the organization. | `string` | `null` | no | +| has_organization_projects | Whether or not organization projects are enabled for the organization. | `bool` | `null` | no | +| has_repository_projects | Whether or not repository projects are enabled for the organization. | `bool` | `null` | no | +| location | The location for the organization. | `string` | `null` | no | +| members_can_create_internal_repositories | Whether or not organization members can create new internal repositories. For Enterprise Organizations only. | `bool` | `null` | no | +| members_can_create_pages | Whether or not organization members can create new pages. Defaults to true. | `bool` | `null` | no | +| members_can_create_private_pages | Whether or not organization members can create new private pages. Defaults to true. | `bool` | `null` | no | +| members_can_create_private_repositories | Whether or not organization members can create new private repositories. Defaults to true. | `bool` | `null` | no | +| members_can_create_public_pages | Whether or not organization members can create new public pages. Defaults to true. | `bool` | `null` | no | +| members_can_create_public_repositories | Whether or not organization members can create new public repositories. Defaults to true. | `bool` | `null` | no | +| members_can_create_repositories | Whether or not organization members can create new repositories. Defaults to true. | `bool` | `null` | no | +| members_can_fork_private_repositories | Whether or not organization members can fork private repositories. Defaults to false. | `bool` | `null` | no | +| organization_name | The name for the organization. | `string` | `null` | no | +| restricted_to_workflows | If true, the runner group will be restricted to running only the workflows specified in the selected_workflows array. Defaults to false. | `bool` | `null` | no | +| runner_group_name | Name of the runner group | `string` | n/a | yes | +| secret_scanning_enabled_for_new_repositories | Whether or not secret scanning is enabled for new repositories. Defaults to false. | `bool` | `null` | no | +| secret_scanning_push_protection_enabled_for_new_repositories | Whether or not secret scanning push protection is enabled for new repositories. Defaults to false. | `bool` | `null` | no | +| selected_repository_ids | IDs of the repositories which should be added to the runner group | `list(string)` | `[]` | no | +| selected_workflows | List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true. | `list(string)` | `[]` | no | +| twitter_username | The Twitter username for the organization. | `string` | `null` | no | +| visibility | Visibility of a runner group. Whether the runner group can include all, selected, or private repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | `null` | no | +| web_commit_signoff_required | Whether or not commit signatures are required for commits to the organization. Defaults to false. | `bool` | `null` | no | ## Outputs -| Name | Description | -|------|-------------| -| random_pet_name | The generated random pet name | +No outputs. ## Contributing diff --git a/main.tf b/main.tf index 74e76fd..52239ac 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,41 @@ -resource "random_pet" "template" { - length = var.length +module "organization_settings" { + source = "./modules/organization_settings" + + billing_email = var.billing_email + company = var.company + blog = var.blog + email = var.email + twitter_username = var.twitter_username + location = var.location + name = var.organization_name + description = var.description + has_organization_projects = var.has_organization_projects + has_repository_projects = var.has_repository_projects + default_repository_permission = var.default_repository_permission + members_can_create_repositories = var.members_can_create_repositories + members_can_create_public_repositories = var.members_can_create_public_repositories + members_can_create_private_repositories = var.members_can_create_private_repositories + members_can_create_internal_repositories = var.members_can_create_internal_repositories + members_can_create_pages = var.members_can_create_pages + members_can_create_public_pages = var.members_can_create_public_pages + members_can_create_private_pages = var.members_can_create_private_pages + members_can_fork_private_repositories = var.members_can_fork_private_repositories + web_commit_signoff_required = var.web_commit_signoff_required + advanced_security_enabled_for_new_repositories = var.advanced_security_enabled_for_new_repositories + dependabot_alerts_enabled_for_new_repositories = var.dependabot_alerts_enabled_for_new_repositories + dependabot_security_updates_enabled_for_new_repositories = var.dependabot_security_updates_enabled_for_new_repositories + dependency_graph_enabled_for_new_repositories = var.dependency_graph_enabled_for_new_repositories + secret_scanning_enabled_for_new_repositories = var.secret_scanning_enabled_for_new_repositories + secret_scanning_push_protection_enabled_for_new_repositories = var.secret_scanning_push_protection_enabled_for_new_repositories +} + +module "actions_runner_group" { + source = "./modules/actions_runner_group" + + name = var.runner_group_name + restricted_to_workflows = var.restricted_to_workflows + selected_repository_ids = var.selected_repository_ids + selected_workflows = var.selected_workflows + visibility = var.visibility + allows_public_repositories = var.allows_public_repositories } diff --git a/outputs.tf b/outputs.tf index c44df14..8b13789 100644 --- a/outputs.tf +++ b/outputs.tf @@ -1,4 +1 @@ -output "random_pet_name" { - description = "The generated random pet name" - value = random_pet.template.id -} + diff --git a/variables.tf b/variables.tf index 6348a57..540b873 100644 --- a/variables.tf +++ b/variables.tf @@ -1,5 +1,197 @@ -variable "length" { - description = "The length of the random name" - type = number - default = 2 +################################ +# GitHub Organization Settings # +################################ + +variable "billing_email" { + description = "The billing email address for the organization." + type = string +} + +variable "company" { + description = "The company name for the organization." + type = string + default = null +} + +variable "blog" { + description = "The blog URL for the organization." + type = string + default = null +} + +variable "email" { + description = "The email address for the organization." + type = string + default = null +} + +variable "twitter_username" { + description = "The Twitter username for the organization." + type = string + default = null +} + +variable "location" { + description = "The location for the organization." + type = string + default = null +} + +variable "organization_name" { + description = "The name for the organization." + type = string + default = null +} + +variable "description" { + description = "The description for the organization." + type = string + default = null +} + +variable "has_organization_projects" { + description = "Whether or not organization projects are enabled for the organization." + type = bool + default = null +} + +variable "has_repository_projects" { + description = "Whether or not repository projects are enabled for the organization." + type = bool + default = null +} + +variable "default_repository_permission" { + description = "The default permission for organization members to create new repositories. Can be one of read, write, admin, or none. Defaults to read." + type = string + default = null +} + +variable "members_can_create_repositories" { + description = "Whether or not organization members can create new repositories. Defaults to true." + type = bool + default = null +} + +variable "members_can_create_public_repositories" { + description = "Whether or not organization members can create new public repositories. Defaults to true." + type = bool + default = null +} + +variable "members_can_create_private_repositories" { + description = "Whether or not organization members can create new private repositories. Defaults to true." + type = bool + default = null +} + +variable "members_can_create_internal_repositories" { + description = "Whether or not organization members can create new internal repositories. For Enterprise Organizations only." + type = bool + default = null +} + +variable "members_can_create_pages" { + description = "Whether or not organization members can create new pages. Defaults to true." + type = bool + default = null +} + +variable "members_can_create_public_pages" { + description = "Whether or not organization members can create new public pages. Defaults to true." + type = bool + default = null +} + +variable "members_can_create_private_pages" { + description = "Whether or not organization members can create new private pages. Defaults to true." + type = bool + default = null +} + +variable "members_can_fork_private_repositories" { + description = "Whether or not organization members can fork private repositories. Defaults to false." + type = bool + default = null +} + +variable "web_commit_signoff_required" { + description = "Whether or not commit signatures are required for commits to the organization. Defaults to false." + type = bool + default = null +} + +variable "advanced_security_enabled_for_new_repositories" { + description = "Whether or not advanced security is enabled for new repositories. Defaults to false." + type = bool + default = null +} + +variable "dependabot_alerts_enabled_for_new_repositories" { + description = "Whether or not dependabot alerts are enabled for new repositories. Defaults to false." + type = bool + default = null +} + +variable "dependabot_security_updates_enabled_for_new_repositories" { + description = "Whether or not dependabot security updates are enabled for new repositories. Defaults to false." + type = bool + default = null +} + +variable "dependency_graph_enabled_for_new_repositories" { + description = "Whether or not dependency graph is enabled for new repositories. Defaults to false." + type = bool + default = null +} + +variable "secret_scanning_enabled_for_new_repositories" { + description = "Whether or not secret scanning is enabled for new repositories. Defaults to false." + type = bool + default = null +} + +variable "secret_scanning_push_protection_enabled_for_new_repositories" { + description = "Whether or not secret scanning push protection is enabled for new repositories. Defaults to false." + type = bool + default = null +} + +############################### +# GitHub Actions Runner Group # +############################### + +variable "runner_group_name" { + description = "Name of the runner group" + type = string +} + +variable "restricted_to_workflows" { + description = "If true, the runner group will be restricted to running only the workflows specified in the selected_workflows array. Defaults to false." + type = bool + default = null +} + +variable "selected_repository_ids" { + description = "IDs of the repositories which should be added to the runner group" + type = list(string) + default = [] +} + +variable "selected_workflows" { + description = "List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true." + type = list(string) + default = [] +} + +variable "visibility" { + description = "Visibility of a runner group. Whether the runner group can include all, selected, or private repositories. A value of private is not currently supported due to limitations in the GitHub API." + type = string + default = null +} + +variable "allows_public_repositories" { + description = "Whether public repositories can be added to the runner group" + type = bool + default = null } From 05140d941513c588ddf13c446dd861a48267a66f Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Fri, 23 Aug 2024 11:30:03 +0200 Subject: [PATCH 02/11] fix typo --- modules/organization_settings/outputs.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/organization_settings/outputs.tf b/modules/organization_settings/outputs.tf index 51fa0a1..6b6d0bd 100644 --- a/modules/organization_settings/outputs.tf +++ b/modules/organization_settings/outputs.tf @@ -1,4 +1,4 @@ output "id" { description = "The ID of the organization settings." - value = github_organization_setting.this.id + value = github_organization_settings.this.id } From 775947ec108a5d70da5d7c6067a09bffeccba001 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Fri, 23 Aug 2024 11:42:41 +0200 Subject: [PATCH 03/11] fix broken visibility github.com/integrations/terraform-provider-github/issues/2363 --- modules/actions_runner_group/variables.tf | 7 +++++-- variables.tf | 7 +++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/actions_runner_group/variables.tf b/modules/actions_runner_group/variables.tf index 4c6b65a..822bfc8 100644 --- a/modules/actions_runner_group/variables.tf +++ b/modules/actions_runner_group/variables.tf @@ -22,9 +22,12 @@ variable "selected_workflows" { } variable "visibility" { - description = "Visibility of a runner group. Whether the runner group can include all, selected, or private repositories. A value of private is not currently supported due to limitations in the GitHub API." + description = "Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API." type = string - default = null + validation { + condition = can(regex("^(all|selected|private)$", var.visibility)) + error_message = "visibility must be one of 'all' 'selected' or 'private'" + } } variable "allows_public_repositories" { diff --git a/variables.tf b/variables.tf index 540b873..9a64c14 100644 --- a/variables.tf +++ b/variables.tf @@ -185,9 +185,12 @@ variable "selected_workflows" { } variable "visibility" { - description = "Visibility of a runner group. Whether the runner group can include all, selected, or private repositories. A value of private is not currently supported due to limitations in the GitHub API." + description = "Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API." type = string - default = null + validation { + condition = can(regex("^(all|selected|private)$", var.visibility)) + error_message = "visibility must be one of 'all' 'selected' or 'private'" + } } variable "allows_public_repositories" { From 286b3c328b08e7d8d523d5b52ca40e8e777f1910 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Fri, 23 Aug 2024 11:43:56 +0200 Subject: [PATCH 04/11] remove unused provider --- versions.tf | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/versions.tf b/versions.tf index 0cf661c..6964268 100644 --- a/versions.tf +++ b/versions.tf @@ -1,10 +1,3 @@ terraform { - required_version = ">= 1.0" - - required_providers { - random = { - source = "hashicorp/random" - version = ">= 3.0" - } - } + required_version = ">= 1.3" } From 71795a3e80724d5352225334675dd18caef55fbe Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Fri, 23 Aug 2024 11:44:54 +0200 Subject: [PATCH 05/11] docs --- README.md | 5 ++--- modules/actions_runner_group/README.md | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index db4fbb3..5815750 100644 --- a/README.md +++ b/README.md @@ -15,8 +15,7 @@ TODO | Name | Version | |------|---------| -| terraform | >= 1.0 | -| random | >= 3.0 | +| terraform | >= 1.3 | ## Providers @@ -67,7 +66,7 @@ No resources. | selected_repository_ids | IDs of the repositories which should be added to the runner group | `list(string)` | `[]` | no | | selected_workflows | List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true. | `list(string)` | `[]` | no | | twitter_username | The Twitter username for the organization. | `string` | `null` | no | -| visibility | Visibility of a runner group. Whether the runner group can include all, selected, or private repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | `null` | no | +| visibility | Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | n/a | yes | | web_commit_signoff_required | Whether or not commit signatures are required for commits to the organization. Defaults to false. | `bool` | `null` | no | ## Outputs diff --git a/modules/actions_runner_group/README.md b/modules/actions_runner_group/README.md index 5451bdf..ec1ed44 100644 --- a/modules/actions_runner_group/README.md +++ b/modules/actions_runner_group/README.md @@ -37,7 +37,7 @@ No modules. | restricted_to_workflows | If true, the runner group will be restricted to running only the workflows specified in the selected_workflows array. Defaults to false. | `bool` | `null` | no | | selected_repository_ids | IDs of the repositories which should be added to the runner group | `list(string)` | `[]` | no | | selected_workflows | List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true. | `list(string)` | `[]` | no | -| visibility | Visibility of a runner group. Whether the runner group can include all, selected, or private repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | `null` | no | +| visibility | Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | n/a | yes | ## Outputs From 42492b42278c990df33e60a07d8f406e58231a71 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Tue, 27 Aug 2024 16:40:29 +0200 Subject: [PATCH 06/11] add organization_ruleset --- modules/organization_ruleset/README.md | 59 ++++++++ modules/organization_ruleset/main.tf | 155 ++++++++++++++++++++++ modules/organization_ruleset/outputs.tf | 13 ++ modules/organization_ruleset/variables.tf | 123 +++++++++++++++++ 4 files changed, 350 insertions(+) create mode 100644 modules/organization_ruleset/README.md create mode 100644 modules/organization_ruleset/main.tf create mode 100644 modules/organization_ruleset/outputs.tf create mode 100644 modules/organization_ruleset/variables.tf diff --git a/modules/organization_ruleset/README.md b/modules/organization_ruleset/README.md new file mode 100644 index 0000000..a4f8373 --- /dev/null +++ b/modules/organization_ruleset/README.md @@ -0,0 +1,59 @@ + + + +## Requirements + +No requirements. + +## Providers + +| Name | Version | +|------|---------| +| github | n/a | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [github_organization_ruleset.this](https://registry.terraform.io/providers/hashicorp/github/latest/docs/resources/organization_ruleset) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| bypass_actors | The actors that can bypass the rules in this ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#bypass_actors | ```list(object({ actor_id = number actor_type = string bypass_mode = optional(string) }))``` | `[]` | no | +| conditions | Parameters for an organization ruleset condition. `ref_name` is required alongside one of `repository_name` or `repository_id`. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#conditions | ```list(object({ ref_name = list(object({ exclude = list(string) include = list(string) })) repository_id = optional(list(number), []) repository_name = optional(list(object({ exclude = list(string) include = list(string) })), []) }))``` | `[]` | no | +| enforcement | Possible values for Enforcement are `disabled`, `active`, `evaluate`. Note: `evaluate` is currently only supported for owners of type organization. | `string` | n/a | yes | +| name | The name of the ruleset. | `string` | n/a | yes | +| rules | Rules within the ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#rules | ```list(object({ # Enterprise only! Use `conditions` block for matching branches. branch_name_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) # Enterprise only! commit_author_email_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) # Enterprise only! commit_message_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) # Enterprise only! committer_email_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) creation = optional(bool) deletion = optional(bool) non_fast_forward = optional(bool) pull_request = optional(list(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_linear_history = optional(bool) required_signatures = optional(bool) required_status_checks = optional(list(object({ required_check = list(object({ context = string integration_id = optional(number) })) strict_required_status_checks_policy = optional(bool) })), []) required_workflows = optional(list(object({ required_workflow = list(object({ repository_id = number path = string ref = optional(string) })) })), []) tag_name_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) update = optional(bool) }))``` | n/a | yes | +| target | Possible values are `branch` and `tag`. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| etag | n/a | +| node_id | GraphQL global node id for use with v4 API. | +| ruleset_id | GitHub ID for the ruleset. | + + +## Contributing + +Contributions are welcome and appreciated! + +Found an issue or want to request a feature? [Open an issue](TODO) + +Want to fix a bug you found or add some functionality? Fork, clone, commit, push, and PR and we'll check it out. + +If you have any issues or are waiting a long time for a PR to get merged then feel free to ping us at [hello@masterpoint.io](mailto:hello@masterpoint.io). + +## Built By + +[![Masterpoint Logo](https://i.imgur.com/RDLnuQO.png)](https://masterpoint.io) + + + diff --git a/modules/organization_ruleset/main.tf b/modules/organization_ruleset/main.tf new file mode 100644 index 0000000..6eeb05c --- /dev/null +++ b/modules/organization_ruleset/main.tf @@ -0,0 +1,155 @@ +resource "github_organization_ruleset" "this" { + name = var.name + + enforcement = var.enforcement + + dynamic "rules" { + for_each = var.rules + content { + dynamic "branch_name_pattern" { + for_each = rules.value.branch_name_pattern + + content { + operator = branch_name_pattern.value.operator + pattern = branch_name_pattern.value.pattern + name = branch_name_pattern.value.name + negate = branch_name_pattern.value.negate + } + } + + dynamic "commit_author_email_pattern" { + for_each = rules.value.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 = commit_author_email_pattern.value.negate + } + } + + dynamic "commit_message_pattern" { + for_each = rules.value.commit_message_pattern + + content { + operator = commit_message_pattern.value.operator + pattern = commit_message_pattern.value.pattern + name = commit_message_pattern.value.name + negate = commit_message_pattern.value.negate + } + } + + dynamic "committer_email_pattern" { + for_each = rules.value.committer_email_pattern + + content { + operator = committer_email_pattern.value.operator + pattern = committer_email_pattern.value.pattern + name = committer_email_pattern.value.name + negate = committer_email_pattern.value.negate + } + } + + creation = rules.value.creation + deletion = rules.value.deletion + non_fast_forward = rules.value.non_fast_forward + + dynamic "pull_request" { + for_each = rules.value.pull_request + + content { + dismiss_stale_reviews_on_push = pull_request.value.dismiss_stale_reviews_on_push + require_code_owner_review = pull_request.value.require_code_owner_review + require_last_push_approval = pull_request.value.require_last_push_approval + required_approving_review_count = pull_request.value.required_approving_review_count + required_review_thread_resolution = pull_request.value.required_review_thread_resolution + } + } + + required_linear_history = rules.value.required_linear_history + required_signatures = rules.value.required_signatures + + dynamic "required_status_checks" { + for_each = rules.value.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_checks_policy + } + } + + dynamic "required_workflows" { + for_each = rules.value.required_workflows + + content { + dynamic "required_workflow" { + for_each = required_workflows.value.required_workflow + + content { + repository_id = required_workflow.value.repository_id + path = required_workflow.value.path + ref = required_workflow.value.ref + } + } + } + } + + dynamic "tag_name_pattern" { + for_each = rules.value.tag_name_pattern + + content { + operator = tag_name_pattern.value.operator + pattern = tag_name_pattern.value.pattern + name = tag_name_pattern.value.name + negate = tag_name_pattern.value.negate + } + } + + update = rules.value.update + } + } + + target = var.target + + dynamic "bypass_actors" { + for_each = var.bypass_actors + content { + actor_id = bypass_actors.value.actor_id + actor_type = bypass_actors.value.actor_type + bypass_mode = bypass_actors.value.bypass_mode + } + } + + dynamic "conditions" { + for_each = var.conditions + content { + dynamic "ref_name" { + for_each = conditions.value.ref_name + + content { + exclude = ref_name.value.exclude + include = ref_name.value.include + } + } + + repository_id = conditions.value.repository_id + + dynamic "repository_name" { + for_each = conditions.value.repository_name + + content { + exclude = repository_name.value.exclude + include = repository_name.value.include + } + } + } + } +} diff --git a/modules/organization_ruleset/outputs.tf b/modules/organization_ruleset/outputs.tf new file mode 100644 index 0000000..281b2ec --- /dev/null +++ b/modules/organization_ruleset/outputs.tf @@ -0,0 +1,13 @@ +output "etag" { + value = github_organization_ruleset.this[*].etag +} + +output "node_id" { + value = github_organization_ruleset.this[*].node_id + description = "GraphQL global node id for use with v4 API." +} + +output "ruleset_id" { + value = github_organization_ruleset.this[*].ruleset_id + description = "GitHub ID for the ruleset." +} diff --git a/modules/organization_ruleset/variables.tf b/modules/organization_ruleset/variables.tf new file mode 100644 index 0000000..ae7f701 --- /dev/null +++ b/modules/organization_ruleset/variables.tf @@ -0,0 +1,123 @@ +variable "enforcement" { + description = "Possible values for Enforcement are `disabled`, `active`, `evaluate`. Note: `evaluate` is currently only supported for owners of type organization." + type = string + validation { + condition = var.enforcement == "disabled" || var.enforcement == "active" || var.enforcement == "evaluate" + error_message = "Enforcement must be either 'disabled', 'active', or 'evaluate'." + } +} + +variable "name" { + description = "The name of the ruleset." + type = string +} + +variable "rules" { + description = "Rules within the ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#rules" + type = list(object({ + # Enterprise only! Use `conditions` block for matching branches. + branch_name_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + # Enterprise only! + commit_author_email_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + # Enterprise only! + commit_message_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + # Enterprise only! + committer_email_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + creation = optional(bool) + deletion = optional(bool) + non_fast_forward = optional(bool) + pull_request = optional(list(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_linear_history = optional(bool) + required_signatures = optional(bool) + required_status_checks = optional(list(object({ + required_check = list(object({ + context = string + integration_id = optional(number) + })) + strict_required_status_checks_policy = optional(bool) + })), []) + required_workflows = optional(list(object({ + required_workflow = list(object({ + repository_id = number + path = string + ref = optional(string) + })) + })), []) + tag_name_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + update = optional(bool) + })) + validation { + condition = length(var.rules) == 1 + error_message = "Only one rules block is allowed." + } + validation { + condition = length(var.rules[*].branch_name_pattern) <= 1 && length(var.rules[*].commit_author_email_pattern) <= 1 && length(var.rules[*].commit_message_pattern) <= 1 && length(var.rules[*].committer_email_pattern) <= 1 && length(var.rules[*].pull_request) <= 1 && length(var.rules[*].required_status_checks) <= 1 && length(var.rules[*].required_workflows) <= 1 && length(var.rules[*].tag_name_pattern) <= 1 + error_message = "commit_author_email_pattern, commit_message_pattern, committer_email_pattern, pull_request, required_status_checks, required_workflows, and tag_name_pattern can have a maximum of one block." + } +} + +variable "target" { + description = "Possible values are `branch` and `tag`." + type = string + validation { + condition = var.target == "branch" || var.target == "tag" + error_message = "Target must be either 'branch' or 'tag'." + } +} + +variable "bypass_actors" { + description = "The actors that can bypass the rules in this ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#bypass_actors" + type = list(object({ + actor_id = number + actor_type = string + bypass_mode = optional(string) + })) + default = [] +} + +variable "conditions" { + description = "Parameters for an organization ruleset condition. `ref_name` is required alongside one of `repository_name` or `repository_id`. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#conditions" + type = list(object({ + ref_name = list(object({ + exclude = list(string) + include = list(string) + })) + repository_id = optional(list(number), []) + repository_name = optional(list(object({ + exclude = list(string) + include = list(string) + })), []) + })) + default = [] +} From f4ad32680cfb3bb3ee9afa967bae7be287e410c6 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Thu, 5 Sep 2024 20:42:30 +0200 Subject: [PATCH 07/11] add organization variable --- .gitignore | 1 + main.tf | 101 +++++++++++++++++- .../actions_organization_variable/README.md | 61 +++++++++++ modules/actions_organization_variable/main.tf | 6 ++ .../actions_organization_variable/outputs.tf | 15 +++ .../variables.tf | 24 +++++ .../actions_organization_variable/versions.tf | 9 ++ modules/actions_runner_group/variables.tf | 7 +- modules/organization_settings/README.md | 2 + modules/organization_settings/main.tf | 10 ++ variables.tf | 41 +++++++ 11 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 modules/actions_organization_variable/README.md create mode 100644 modules/actions_organization_variable/main.tf create mode 100644 modules/actions_organization_variable/outputs.tf create mode 100644 modules/actions_organization_variable/variables.tf create mode 100644 modules/actions_organization_variable/versions.tf diff --git a/.gitignore b/.gitignore index 724373e..f18c1ff 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ # Ignore override files as they are usually used to override resources locally *override.tf *override.tf.json +providers.tf # .tfstate files *.tfstate diff --git a/main.tf b/main.tf index 52239ac..df10a2c 100644 --- a/main.tf +++ b/main.tf @@ -30,7 +30,8 @@ module "organization_settings" { } module "actions_runner_group" { - source = "./modules/actions_runner_group" + source = "./modules/actions_runner_group" + for_each = var.actions_runner_groups name = var.runner_group_name restricted_to_workflows = var.restricted_to_workflows @@ -39,3 +40,101 @@ module "actions_runner_group" { visibility = var.visibility allows_public_repositories = var.allows_public_repositories } + +module "organization_block" { + source = "./modules/organization_block" + for_each = toset(var.blocked_usernames) + + username = each.value +} + +module "organization_ruleset" { + for_each = var.organization_rulesets +} + +variable "organization_rulesets" { + description = "A map of organization rulesets to create. The map key is the name of the ruleset." + type = map(object({ + enforcement = string + rules = list(object({ + # Enterprise only! Use `conditions` block for matching branches. + branch_name_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + # Enterprise only! + commit_author_email_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + # Enterprise only! + commit_message_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + # Enterprise only! + committer_email_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + creation = optional(bool) + deletion = optional(bool) + non_fast_forward = optional(bool) + pull_request = optional(list(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_linear_history = optional(bool) + required_signatures = optional(bool) + required_status_checks = optional(list(object({ + required_check = list(object({ + context = string + integration_id = optional(number) + })) + strict_required_status_checks_policy = optional(bool) + })), []) + required_workflows = optional(list(object({ + required_workflow = list(object({ + repository_id = number + path = string + ref = optional(string) + })) + })), []) + tag_name_pattern = optional(list(object({ + operator = string + pattern = string + name = optional(string) + negate = optional(bool) + })), []) + update = optional(bool) + })) + target = string + bypass_actors = optional(list(object({ + actor_id = number + actor_type = string + bypass_mode = optional(string) + })), []) + })) +} + +module "organization_secret" { + source = "./modules/actions_organization_secrets" + for_each = var.organization_secrets + + secret_name = each.key + encrypted_value = each.value.encrypted_value + plaintext_value = each.value.plaintext_value + visibility = each.value.visibility + selected_repository_ids = each.value.selected_repository_ids +} diff --git a/modules/actions_organization_variable/README.md b/modules/actions_organization_variable/README.md new file mode 100644 index 0000000..c5b6838 --- /dev/null +++ b/modules/actions_organization_variable/README.md @@ -0,0 +1,61 @@ + + + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >=1.3.0 | +| github | >= 6.2.3 | + +## Providers + +| Name | Version | +|------|---------| +| github | >= 6.2.3 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [github_actions_organization_variable.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_variable) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| selected_repository_ids | An array of repository ids that can access the organization secret. | `list(string)` | `null` | no | +| value | Value of the variable. | `string` | n/a | yes | +| variable_name | Name of the variable. | `string` | n/a | yes | +| visibility | Configures the access that repositories have to the organization variable. Must be one of `all`, `private`, `selected`. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| created_at | n/a | +| updated_at | n/a | +| value | n/a | +| variable_name | n/a | + + +## Contributing + +Contributions are welcome and appreciated! + +Found an issue or want to request a feature? [Open an issue](TODO) + +Want to fix a bug you found or add some functionality? Fork, clone, commit, push, and PR and we'll check it out. + +If you have any issues or are waiting a long time for a PR to get merged then feel free to ping us at [hello@masterpoint.io](mailto:hello@masterpoint.io). + +## Built By + +[![Masterpoint Logo](https://i.imgur.com/RDLnuQO.png)](https://masterpoint.io) + + + diff --git a/modules/actions_organization_variable/main.tf b/modules/actions_organization_variable/main.tf new file mode 100644 index 0000000..24f1c7f --- /dev/null +++ b/modules/actions_organization_variable/main.tf @@ -0,0 +1,6 @@ +resource "github_actions_organization_variable" "this" { + variable_name = var.variable_name + visibility = var.visibility + value = var.value + selected_repository_ids = var.selected_repository_ids +} diff --git a/modules/actions_organization_variable/outputs.tf b/modules/actions_organization_variable/outputs.tf new file mode 100644 index 0000000..6a7e8c4 --- /dev/null +++ b/modules/actions_organization_variable/outputs.tf @@ -0,0 +1,15 @@ +output "created_at" { + value = github_actions_organization_variable.this.created_at +} + +output "updated_at" { + value = github_actions_organization_variable.this.updated_at +} + +output "variable_name" { + value = github_actions_organization_variable.this.variable_name +} + +output "value" { + value = github_actions_organization_variable.this.value +} diff --git a/modules/actions_organization_variable/variables.tf b/modules/actions_organization_variable/variables.tf new file mode 100644 index 0000000..4e1d18b --- /dev/null +++ b/modules/actions_organization_variable/variables.tf @@ -0,0 +1,24 @@ +variable "variable_name" { + type = string + description = "Name of the variable." +} + +variable "value" { + type = string + description = "Value of the variable." +} + +variable "visibility" { + type = string + description = "Configures the access that repositories have to the organization variable. Must be one of `all`, `private`, `selected`." + validation { + condition = var.visibility == "all" || var.visibility == "private" || var.visibility == "selected" + error_message = "Visibility must be one of 'all', 'private', or 'selected'." + } +} + +variable "selected_repository_ids" { + type = list(string) + description = "An array of repository ids that can access the organization secret." + default = null +} diff --git a/modules/actions_organization_variable/versions.tf b/modules/actions_organization_variable/versions.tf new file mode 100644 index 0000000..a6a814d --- /dev/null +++ b/modules/actions_organization_variable/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">=1.3.0" + required_providers { + github = { + source = "integrations/github" + version = ">= 6.2.3" + } + } +} diff --git a/modules/actions_runner_group/variables.tf b/modules/actions_runner_group/variables.tf index 822bfc8..b8d681c 100644 --- a/modules/actions_runner_group/variables.tf +++ b/modules/actions_runner_group/variables.tf @@ -12,20 +12,21 @@ variable "restricted_to_workflows" { variable "selected_repository_ids" { description = "IDs of the repositories which should be added to the runner group" type = list(string) - default = [] + default = null } variable "selected_workflows" { description = "List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true." type = list(string) - default = [] + default = null } variable "visibility" { description = "Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API." type = string + default = null validation { - condition = can(regex("^(all|selected|private)$", var.visibility)) + condition = can(regex("^(all|selected|private)$", var.visibility)) || var.visibility == null error_message = "visibility must be one of 'all' 'selected' or 'private'" } } diff --git a/modules/organization_settings/README.md b/modules/organization_settings/README.md index e7782c5..8013ec5 100644 --- a/modules/organization_settings/README.md +++ b/modules/organization_settings/README.md @@ -26,6 +26,7 @@ No modules. | Name | Type | |------|------| +| [github_organization_oidc_subject_claim_customization_template.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_oidc_subject_claim_customization_template) | resource | | [github_organization_settings.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_settings) | resource | ## Inputs @@ -54,6 +55,7 @@ No modules. | members_can_create_repositories | Whether or not organization members can create new repositories. Defaults to true. | `bool` | `null` | no | | members_can_fork_private_repositories | Whether or not organization members can fork private repositories. Defaults to false. | `bool` | `null` | no | | name | The name for the organization. | `string` | `null` | no | +| oidc_subject_include_claim_keys | A list of claim keys to include in the OIDC subject claim customization template. | `list(string)` | `null` | no | | secret_scanning_enabled_for_new_repositories | Whether or not secret scanning is enabled for new repositories. Defaults to false. | `bool` | `null` | no | | secret_scanning_push_protection_enabled_for_new_repositories | Whether or not secret scanning push protection is enabled for new repositories. Defaults to false. | `bool` | `null` | no | | twitter_username | The Twitter username for the organization. | `string` | `null` | no | diff --git a/modules/organization_settings/main.tf b/modules/organization_settings/main.tf index 8aaaf73..a30471f 100644 --- a/modules/organization_settings/main.tf +++ b/modules/organization_settings/main.tf @@ -26,3 +26,13 @@ resource "github_organization_settings" "this" { secret_scanning_enabled_for_new_repositories = var.secret_scanning_enabled_for_new_repositories secret_scanning_push_protection_enabled_for_new_repositories = var.secret_scanning_push_protection_enabled_for_new_repositories } + +resource "github_actions_organization_oidc_subject_claim_customization_template" "this" { + include_claim_keys = var.oidc_subject_include_claim_keys +} + +variable "oidc_subject_include_claim_keys" { + type = list(string) + description = "A list of claim keys to include in the OIDC subject claim customization template." + default = null +} diff --git a/variables.tf b/variables.tf index 9a64c14..96bea9e 100644 --- a/variables.tf +++ b/variables.tf @@ -198,3 +198,44 @@ variable "allows_public_repositories" { type = bool default = null } + +################# +# Blocked users # +################# + +variable "blocked_usernames" { + type = list(string) + description = "A list of usernames to block from your GitHub organization." + default = [] +} + +######################### +# Actions runner groups # +######################### + +variable "actions_runner_groups" { + type = map(object({ + restricted_to_workflows = optional(list(string)) + selected_repository_ids = optional(list(string)) + selected_workflows = optional(list(string)) + visibility = optional(string) + allows_public_repositories = optional(bool) + })) + description = "A map of actions runner groups to create in your GitHub organization. Map key is the name of the runner group." + default = {} +} + +################################ +# Organization actions secrets # +################################ + +variable "organization_secrets" { + description = "A map of organization secrets to create. The map key is the secret name." + type = map(object({ + encrypted_value = optional(string) + plaintext_value = optional(string) + visibility = string + selected_repository_ids = optional(list(string)) + })) + default = {} +} From c11a74e2b1faedf877c8009e8470f7cd8cab30f7 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Thu, 5 Sep 2024 21:09:25 +0200 Subject: [PATCH 08/11] feat: github actions organization secrets --- .../actions_organization_secrets/README.md | 60 +++++++++++++++++++ modules/actions_organization_secrets/main.tf | 7 +++ .../actions_organization_secrets/outputs.tf | 6 ++ .../actions_organization_secrets/variables.tf | 32 ++++++++++ .../actions_organization_secrets/versions.tf | 9 +++ 5 files changed, 114 insertions(+) create mode 100644 modules/actions_organization_secrets/README.md create mode 100644 modules/actions_organization_secrets/main.tf create mode 100644 modules/actions_organization_secrets/outputs.tf create mode 100644 modules/actions_organization_secrets/variables.tf create mode 100644 modules/actions_organization_secrets/versions.tf diff --git a/modules/actions_organization_secrets/README.md b/modules/actions_organization_secrets/README.md new file mode 100644 index 0000000..02eb605 --- /dev/null +++ b/modules/actions_organization_secrets/README.md @@ -0,0 +1,60 @@ + + + +## Requirements + +| Name | Version | +|------|---------| +| terraform | >=1.3.0 | +| github | >= 6.2.3 | + +## Providers + +| Name | Version | +|------|---------| +| github | >= 6.2.3 | + +## Modules + +No modules. + +## Resources + +| Name | Type | +|------|------| +| [github_actions_organization_secret.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_secret) | resource | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| encrypted_value | Encrypted value of the secret using the GitHub public key in Base64 format. | `string` | `null` | no | +| plaintext_value | Plaintext value of the secret to be encrypted. | `string` | `null` | no | +| secret_name | Name of the secret. | `string` | n/a | yes | +| selected_repository_ids | An array of repository ids that can access the organization secret. | `list(string)` | `null` | no | +| visibility | Configures the access that repositories have to the organization secret. Must be one of `all`, `private`, `selected`. | `string` | n/a | yes | + +## Outputs + +| Name | Description | +|------|-------------| +| created_at | n/a | +| updated_at | n/a | + + +## Contributing + +Contributions are welcome and appreciated! + +Found an issue or want to request a feature? [Open an issue](TODO) + +Want to fix a bug you found or add some functionality? Fork, clone, commit, push, and PR and we'll check it out. + +If you have any issues or are waiting a long time for a PR to get merged then feel free to ping us at [hello@masterpoint.io](mailto:hello@masterpoint.io). + +## Built By + +[![Masterpoint Logo](https://i.imgur.com/RDLnuQO.png)](https://masterpoint.io) + + + diff --git a/modules/actions_organization_secrets/main.tf b/modules/actions_organization_secrets/main.tf new file mode 100644 index 0000000..9d82556 --- /dev/null +++ b/modules/actions_organization_secrets/main.tf @@ -0,0 +1,7 @@ +resource "github_actions_organization_secret" "this" { + secret_name = var.secret_name + encrypted_value = var.encrypted_value + plaintext_value = var.plaintext_value + visibility = var.visibility + selected_repository_ids = var.selected_repository_ids +} diff --git a/modules/actions_organization_secrets/outputs.tf b/modules/actions_organization_secrets/outputs.tf new file mode 100644 index 0000000..df6cde4 --- /dev/null +++ b/modules/actions_organization_secrets/outputs.tf @@ -0,0 +1,6 @@ +output "created_at" { + value = github_actions_organization_secret.this.created_at +} +output "updated_at" { + value = github_actions_organization_secret.this.updated_at +} diff --git a/modules/actions_organization_secrets/variables.tf b/modules/actions_organization_secrets/variables.tf new file mode 100644 index 0000000..428c68e --- /dev/null +++ b/modules/actions_organization_secrets/variables.tf @@ -0,0 +1,32 @@ +variable "secret_name" { + type = string + description = "Name of the secret." +} + +variable "encrypted_value" { + type = string + description = "Encrypted value of the secret using the GitHub public key in Base64 format." + default = null +} + +variable "plaintext_value" { + type = string + description = "Plaintext value of the secret to be encrypted." + sensitive = true + default = null +} + +variable "visibility" { + type = string + description = "Configures the access that repositories have to the organization secret. Must be one of `all`, `private`, `selected`." + validation { + condition = var.visibility == "all" || var.visibility == "private" || var.visibility == "selected" + error_message = "Visibility must be either 'all' or 'private'." + } +} + +variable "selected_repository_ids" { + type = list(string) + description = "An array of repository ids that can access the organization secret." + default = null +} diff --git a/modules/actions_organization_secrets/versions.tf b/modules/actions_organization_secrets/versions.tf new file mode 100644 index 0000000..a6a814d --- /dev/null +++ b/modules/actions_organization_secrets/versions.tf @@ -0,0 +1,9 @@ +terraform { + required_version = ">=1.3.0" + required_providers { + github = { + source = "integrations/github" + version = ">= 6.2.3" + } + } +} From ac9a39fd0b579c2ea00288559434567e71ab51de Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Thu, 5 Sep 2024 21:10:17 +0200 Subject: [PATCH 09/11] docs --- modules/actions_runner_group/README.md | 6 +++--- modules/organization_settings/README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/actions_runner_group/README.md b/modules/actions_runner_group/README.md index ec1ed44..4cd557c 100644 --- a/modules/actions_runner_group/README.md +++ b/modules/actions_runner_group/README.md @@ -35,9 +35,9 @@ No modules. | allows_public_repositories | Whether public repositories can be added to the runner group | `bool` | `null` | no | | name | Name of the runner group | `string` | n/a | yes | | restricted_to_workflows | If true, the runner group will be restricted to running only the workflows specified in the selected_workflows array. Defaults to false. | `bool` | `null` | no | -| selected_repository_ids | IDs of the repositories which should be added to the runner group | `list(string)` | `[]` | no | -| selected_workflows | List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true. | `list(string)` | `[]` | no | -| visibility | Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | n/a | yes | +| selected_repository_ids | IDs of the repositories which should be added to the runner group | `list(string)` | `null` | no | +| selected_workflows | List of workflows the runner group should be allowed to run. This setting will be ignored unless restricted_to_workflows is set to true. | `list(string)` | `null` | no | +| visibility | Visibility of a runner group. Whether the runner group can include `all`, `selected`, or `private` repositories. A value of private is not currently supported due to limitations in the GitHub API. | `string` | `null` | no | ## Outputs diff --git a/modules/organization_settings/README.md b/modules/organization_settings/README.md index 8013ec5..4f3f88b 100644 --- a/modules/organization_settings/README.md +++ b/modules/organization_settings/README.md @@ -26,7 +26,7 @@ No modules. | Name | Type | |------|------| -| [github_organization_oidc_subject_claim_customization_template.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_oidc_subject_claim_customization_template) | resource | +| [github_actions_organization_oidc_subject_claim_customization_template.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_organization_oidc_subject_claim_customization_template) | resource | | [github_organization_settings.this](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_settings) | resource | ## Inputs From 84fd1d801d2e7127c787091d03365da231fc5a21 Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Thu, 5 Sep 2024 21:59:39 +0200 Subject: [PATCH 10/11] remove ruleset --- modules/organization_ruleset/README.md | 59 -------- modules/organization_ruleset/main.tf | 155 ---------------------- modules/organization_ruleset/outputs.tf | 13 -- modules/organization_ruleset/variables.tf | 123 ----------------- 4 files changed, 350 deletions(-) delete mode 100644 modules/organization_ruleset/README.md delete mode 100644 modules/organization_ruleset/main.tf delete mode 100644 modules/organization_ruleset/outputs.tf delete mode 100644 modules/organization_ruleset/variables.tf diff --git a/modules/organization_ruleset/README.md b/modules/organization_ruleset/README.md deleted file mode 100644 index a4f8373..0000000 --- a/modules/organization_ruleset/README.md +++ /dev/null @@ -1,59 +0,0 @@ - - - -## Requirements - -No requirements. - -## Providers - -| Name | Version | -|------|---------| -| github | n/a | - -## Modules - -No modules. - -## Resources - -| Name | Type | -|------|------| -| [github_organization_ruleset.this](https://registry.terraform.io/providers/hashicorp/github/latest/docs/resources/organization_ruleset) | resource | - -## Inputs - -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| bypass_actors | The actors that can bypass the rules in this ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#bypass_actors | ```list(object({ actor_id = number actor_type = string bypass_mode = optional(string) }))``` | `[]` | no | -| conditions | Parameters for an organization ruleset condition. `ref_name` is required alongside one of `repository_name` or `repository_id`. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#conditions | ```list(object({ ref_name = list(object({ exclude = list(string) include = list(string) })) repository_id = optional(list(number), []) repository_name = optional(list(object({ exclude = list(string) include = list(string) })), []) }))``` | `[]` | no | -| enforcement | Possible values for Enforcement are `disabled`, `active`, `evaluate`. Note: `evaluate` is currently only supported for owners of type organization. | `string` | n/a | yes | -| name | The name of the ruleset. | `string` | n/a | yes | -| rules | Rules within the ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#rules | ```list(object({ # Enterprise only! Use `conditions` block for matching branches. branch_name_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) # Enterprise only! commit_author_email_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) # Enterprise only! commit_message_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) # Enterprise only! committer_email_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) creation = optional(bool) deletion = optional(bool) non_fast_forward = optional(bool) pull_request = optional(list(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_linear_history = optional(bool) required_signatures = optional(bool) required_status_checks = optional(list(object({ required_check = list(object({ context = string integration_id = optional(number) })) strict_required_status_checks_policy = optional(bool) })), []) required_workflows = optional(list(object({ required_workflow = list(object({ repository_id = number path = string ref = optional(string) })) })), []) tag_name_pattern = optional(list(object({ operator = string pattern = string name = optional(string) negate = optional(bool) })), []) update = optional(bool) }))``` | n/a | yes | -| target | Possible values are `branch` and `tag`. | `string` | n/a | yes | - -## Outputs - -| Name | Description | -|------|-------------| -| etag | n/a | -| node_id | GraphQL global node id for use with v4 API. | -| ruleset_id | GitHub ID for the ruleset. | - - -## Contributing - -Contributions are welcome and appreciated! - -Found an issue or want to request a feature? [Open an issue](TODO) - -Want to fix a bug you found or add some functionality? Fork, clone, commit, push, and PR and we'll check it out. - -If you have any issues or are waiting a long time for a PR to get merged then feel free to ping us at [hello@masterpoint.io](mailto:hello@masterpoint.io). - -## Built By - -[![Masterpoint Logo](https://i.imgur.com/RDLnuQO.png)](https://masterpoint.io) - - - diff --git a/modules/organization_ruleset/main.tf b/modules/organization_ruleset/main.tf deleted file mode 100644 index 6eeb05c..0000000 --- a/modules/organization_ruleset/main.tf +++ /dev/null @@ -1,155 +0,0 @@ -resource "github_organization_ruleset" "this" { - name = var.name - - enforcement = var.enforcement - - dynamic "rules" { - for_each = var.rules - content { - dynamic "branch_name_pattern" { - for_each = rules.value.branch_name_pattern - - content { - operator = branch_name_pattern.value.operator - pattern = branch_name_pattern.value.pattern - name = branch_name_pattern.value.name - negate = branch_name_pattern.value.negate - } - } - - dynamic "commit_author_email_pattern" { - for_each = rules.value.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 = commit_author_email_pattern.value.negate - } - } - - dynamic "commit_message_pattern" { - for_each = rules.value.commit_message_pattern - - content { - operator = commit_message_pattern.value.operator - pattern = commit_message_pattern.value.pattern - name = commit_message_pattern.value.name - negate = commit_message_pattern.value.negate - } - } - - dynamic "committer_email_pattern" { - for_each = rules.value.committer_email_pattern - - content { - operator = committer_email_pattern.value.operator - pattern = committer_email_pattern.value.pattern - name = committer_email_pattern.value.name - negate = committer_email_pattern.value.negate - } - } - - creation = rules.value.creation - deletion = rules.value.deletion - non_fast_forward = rules.value.non_fast_forward - - dynamic "pull_request" { - for_each = rules.value.pull_request - - content { - dismiss_stale_reviews_on_push = pull_request.value.dismiss_stale_reviews_on_push - require_code_owner_review = pull_request.value.require_code_owner_review - require_last_push_approval = pull_request.value.require_last_push_approval - required_approving_review_count = pull_request.value.required_approving_review_count - required_review_thread_resolution = pull_request.value.required_review_thread_resolution - } - } - - required_linear_history = rules.value.required_linear_history - required_signatures = rules.value.required_signatures - - dynamic "required_status_checks" { - for_each = rules.value.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_checks_policy - } - } - - dynamic "required_workflows" { - for_each = rules.value.required_workflows - - content { - dynamic "required_workflow" { - for_each = required_workflows.value.required_workflow - - content { - repository_id = required_workflow.value.repository_id - path = required_workflow.value.path - ref = required_workflow.value.ref - } - } - } - } - - dynamic "tag_name_pattern" { - for_each = rules.value.tag_name_pattern - - content { - operator = tag_name_pattern.value.operator - pattern = tag_name_pattern.value.pattern - name = tag_name_pattern.value.name - negate = tag_name_pattern.value.negate - } - } - - update = rules.value.update - } - } - - target = var.target - - dynamic "bypass_actors" { - for_each = var.bypass_actors - content { - actor_id = bypass_actors.value.actor_id - actor_type = bypass_actors.value.actor_type - bypass_mode = bypass_actors.value.bypass_mode - } - } - - dynamic "conditions" { - for_each = var.conditions - content { - dynamic "ref_name" { - for_each = conditions.value.ref_name - - content { - exclude = ref_name.value.exclude - include = ref_name.value.include - } - } - - repository_id = conditions.value.repository_id - - dynamic "repository_name" { - for_each = conditions.value.repository_name - - content { - exclude = repository_name.value.exclude - include = repository_name.value.include - } - } - } - } -} diff --git a/modules/organization_ruleset/outputs.tf b/modules/organization_ruleset/outputs.tf deleted file mode 100644 index 281b2ec..0000000 --- a/modules/organization_ruleset/outputs.tf +++ /dev/null @@ -1,13 +0,0 @@ -output "etag" { - value = github_organization_ruleset.this[*].etag -} - -output "node_id" { - value = github_organization_ruleset.this[*].node_id - description = "GraphQL global node id for use with v4 API." -} - -output "ruleset_id" { - value = github_organization_ruleset.this[*].ruleset_id - description = "GitHub ID for the ruleset." -} diff --git a/modules/organization_ruleset/variables.tf b/modules/organization_ruleset/variables.tf deleted file mode 100644 index ae7f701..0000000 --- a/modules/organization_ruleset/variables.tf +++ /dev/null @@ -1,123 +0,0 @@ -variable "enforcement" { - description = "Possible values for Enforcement are `disabled`, `active`, `evaluate`. Note: `evaluate` is currently only supported for owners of type organization." - type = string - validation { - condition = var.enforcement == "disabled" || var.enforcement == "active" || var.enforcement == "evaluate" - error_message = "Enforcement must be either 'disabled', 'active', or 'evaluate'." - } -} - -variable "name" { - description = "The name of the ruleset." - type = string -} - -variable "rules" { - description = "Rules within the ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#rules" - type = list(object({ - # Enterprise only! Use `conditions` block for matching branches. - branch_name_pattern = optional(list(object({ - operator = string - pattern = string - name = optional(string) - negate = optional(bool) - })), []) - # Enterprise only! - commit_author_email_pattern = optional(list(object({ - operator = string - pattern = string - name = optional(string) - negate = optional(bool) - })), []) - # Enterprise only! - commit_message_pattern = optional(list(object({ - operator = string - pattern = string - name = optional(string) - negate = optional(bool) - })), []) - # Enterprise only! - committer_email_pattern = optional(list(object({ - operator = string - pattern = string - name = optional(string) - negate = optional(bool) - })), []) - creation = optional(bool) - deletion = optional(bool) - non_fast_forward = optional(bool) - pull_request = optional(list(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_linear_history = optional(bool) - required_signatures = optional(bool) - required_status_checks = optional(list(object({ - required_check = list(object({ - context = string - integration_id = optional(number) - })) - strict_required_status_checks_policy = optional(bool) - })), []) - required_workflows = optional(list(object({ - required_workflow = list(object({ - repository_id = number - path = string - ref = optional(string) - })) - })), []) - tag_name_pattern = optional(list(object({ - operator = string - pattern = string - name = optional(string) - negate = optional(bool) - })), []) - update = optional(bool) - })) - validation { - condition = length(var.rules) == 1 - error_message = "Only one rules block is allowed." - } - validation { - condition = length(var.rules[*].branch_name_pattern) <= 1 && length(var.rules[*].commit_author_email_pattern) <= 1 && length(var.rules[*].commit_message_pattern) <= 1 && length(var.rules[*].committer_email_pattern) <= 1 && length(var.rules[*].pull_request) <= 1 && length(var.rules[*].required_status_checks) <= 1 && length(var.rules[*].required_workflows) <= 1 && length(var.rules[*].tag_name_pattern) <= 1 - error_message = "commit_author_email_pattern, commit_message_pattern, committer_email_pattern, pull_request, required_status_checks, required_workflows, and tag_name_pattern can have a maximum of one block." - } -} - -variable "target" { - description = "Possible values are `branch` and `tag`." - type = string - validation { - condition = var.target == "branch" || var.target == "tag" - error_message = "Target must be either 'branch' or 'tag'." - } -} - -variable "bypass_actors" { - description = "The actors that can bypass the rules in this ruleset. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#bypass_actors" - type = list(object({ - actor_id = number - actor_type = string - bypass_mode = optional(string) - })) - default = [] -} - -variable "conditions" { - description = "Parameters for an organization ruleset condition. `ref_name` is required alongside one of `repository_name` or `repository_id`. See https://registry.terraform.io/providers/integrations/github/latest/docs/resources/organization_ruleset#conditions" - type = list(object({ - ref_name = list(object({ - exclude = list(string) - include = list(string) - })) - repository_id = optional(list(number), []) - repository_name = optional(list(object({ - exclude = list(string) - include = list(string) - })), []) - })) - default = [] -} From ecabb213ef592c7ff3a889ffb0b64e733a399a6e Mon Sep 17 00:00:00 2001 From: Kevin Mahoney Date: Fri, 6 Sep 2024 15:23:50 +0200 Subject: [PATCH 11/11] trigger title check