diff --git a/modules/common_repository/README.md b/modules/common_repository/README.md index 6b66bd5..7ddfa01 100644 --- a/modules/common_repository/README.md +++ b/modules/common_repository/README.md @@ -32,38 +32,48 @@ module "repo_docs" { ## Requirements | Name | Version | -|------|---------| +| ---- | ------- | | [terraform](#requirement\_terraform) | >= 1.9.0 | | [github](#requirement\_github) | ~> 6.0 | ## Providers | Name | Version | -|------|---------| +| ---- | ------- | | [github](#provider\_github) | ~> 6.0 | ## Resources | Name | Type | -|------|------| +| ---- | ---- | | [github_branch_protection.repo_protection](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection) | resource | | [github_issue_label.repo_labels](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/issue_label) | resource | | [github_repository.repo](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository) | resource | | [github_repository_collaborators.repo_collaborators](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_collaborators) | resource | +| [github_repository_environment.env](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_environment) | resource | +| [github_repository_ruleset.merge_queue](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_ruleset) | resource | ## Inputs | Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| +| ---- | ----------- | ---- | ------- | :------: | | [all\_members\_permission](#input\_all\_members\_permission) | Permission for all organization members | `string` | `"triage"` | no | +| [allow\_merge\_commit](#input\_allow\_merge\_commit) | Allow merge commits on pull requests | `bool` | `true` | no | +| [allow\_rebase\_merge](#input\_allow\_rebase\_merge) | Allow rebase merging on pull requests | `bool` | `true` | no | +| [allow\_squash\_merge](#input\_allow\_squash\_merge) | Allow squash merging on pull requests | `bool` | `true` | no | +| [archived](#input\_archived) | Whether the repository is archived | `bool` | `false` | no | | [branch\_protection](#input\_branch\_protection) | Configure branch protection if true | `bool` | `true` | no | -| [description](#input\_description) | Repository description | `string` | `""` | no | +| [description](#input\_description) | Repository description | `string` | n/a | yes | +| [environments](#input\_environments) | GitHub environments to create for this repository |
list(object({
name = string
reviewers = optional(object({
teams = optional(list(string), [])
users = optional(list(string), [])
}))
deployment_branch_policy = optional(object({
protected_branches = optional(bool, true)
custom_branch_policies = optional(bool, false)
}))
}))
| `[]` | no | | [is\_template](#input\_is\_template) | Set this to true if this is a template repository | `bool` | `false` | no | | [labels](#input\_labels) | List of labels to configure on the repository |
list(object({
name = string
color = string
description = string
}))
| `null` | no | +| [merge\_queue](#input\_merge\_queue) | Enable GitHub merge queue for the default branch. When set, a repository ruleset is created that requires PRs to pass through the merge queue before merging. |
object({
merge_method = optional(string, "SQUASH")
min_entries_to_merge = optional(number, 1)
max_entries_to_merge = optional(number, 5)
check_response_timeout_minutes = optional(number, 90)
grouping_strategy = optional(string, "ALLGREEN")
})
| `null` | no | | [name](#input\_name) | The name of the repository | `string` | n/a | yes | | [pages](#input\_pages) | Configuration for github pages |
object({
source = optional(object({
branch = string
path = string
}))
build_type = optional(string, "legacy")
cname = optional(string)
})
| `null` | no | +| [push\_allowances](#input\_push\_allowances) | Actors allowed to push to the protected branch. When set, restricts both direct pushes and PR merges to these actors only. Actor names must begin with '/' for users or 'org-name/' for teams. | `list(string)` | `null` | no | | [required\_approvals](#input\_required\_approvals) | Number of approvals required before merging a pull request | `number` | `1` | no | | [required\_status\_checks](#input\_required\_status\_checks) | A list of status checks that must pass before a PR can merge | `list(string)` | `[]` | no | +| [strict\_status\_checks](#input\_strict\_status\_checks) | Require the PR branch to be up to date with the base branch before merging. Disable when using merge queues, which handle this automatically. | `bool` | `true` | no | | [teams](#input\_teams) | Teams with access to this repository |
list(object({
team_id = string
permission = string
}))
| `[]` | no | | [use\_public\_template](#input\_use\_public\_template) | Use the public\_template repository as the template for a new repository | `bool` | `true` | no | | [users](#input\_users) | Users with access to this repository |
list(object({
username = string
permission = string
}))
| `[]` | no | diff --git a/modules/common_repository/main.tf b/modules/common_repository/main.tf index fa0f0b1..e90bcc9 100644 --- a/modules/common_repository/main.tf +++ b/modules/common_repository/main.tf @@ -98,13 +98,54 @@ resource "github_branch_protection" "repo_protection" { } required_status_checks { - strict = true + strict = var.strict_status_checks contexts = var.required_status_checks } depends_on = [github_repository.repo, github_repository_collaborators.repo_collaborators] } +data "github_team" "merge_queue_bypass" { + for_each = var.merge_queue != null ? toset(["wg-infra", "org-admins"]) : [] + slug = each.value +} + +resource "github_repository_ruleset" "merge_queue" { + count = var.merge_queue != null ? 1 : 0 + name = "merge-queue" + repository = github_repository.repo.name + target = "branch" + enforcement = "active" + + conditions { + ref_name { + include = ["~DEFAULT_BRANCH"] + exclude = [] + } + } + + dynamic "bypass_actors" { + for_each = data.github_team.merge_queue_bypass + content { + actor_id = bypass_actors.value.id + actor_type = "Team" + bypass_mode = "pull_request" + } + } + + rules { + merge_queue { + merge_method = var.merge_queue.merge_method + min_entries_to_merge = var.merge_queue.min_entries_to_merge + max_entries_to_merge = var.merge_queue.max_entries_to_merge + check_response_timeout_minutes = var.merge_queue.check_response_timeout_minutes + grouping_strategy = var.merge_queue.grouping_strategy + } + } + + depends_on = [github_repository.repo] +} + resource "github_repository_environment" "env" { for_each = { for env in var.environments : diff --git a/modules/common_repository/variables.tf b/modules/common_repository/variables.tf index 4512a3a..0d9fd38 100644 --- a/modules/common_repository/variables.tf +++ b/modules/common_repository/variables.tf @@ -26,6 +26,12 @@ variable "required_status_checks" { default = [] } +variable "strict_status_checks" { + description = "Require the PR branch to be up to date with the base branch before merging. Disable when using merge queues, which handle this automatically." + type = bool + default = true +} + variable "visibility" { description = "Repository visibility (public or private)" type = string @@ -175,6 +181,28 @@ variable "environments" { } } +variable "merge_queue" { + description = "Enable GitHub merge queue for the default branch. When set, a repository ruleset is created that requires PRs to pass through the merge queue before merging." + type = object({ + merge_method = optional(string, "SQUASH") + min_entries_to_merge = optional(number, 1) + max_entries_to_merge = optional(number, 5) + check_response_timeout_minutes = optional(number, 90) + grouping_strategy = optional(string, "ALLGREEN") + }) + default = null + + validation { + condition = var.merge_queue == null || contains(["MERGE", "SQUASH", "REBASE"], var.merge_queue.merge_method) + error_message = "merge_method must be MERGE, SQUASH, or REBASE" + } + + validation { + condition = var.merge_queue == null || contains(["ALLGREEN", "HEADGREEN"], var.merge_queue.grouping_strategy) + error_message = "grouping_strategy must be ALLGREEN or HEADGREEN" + } +} + variable "all_members_permission" { description = "Permission for all organization members" type = string diff --git a/repositories.tf b/repositories.tf index 0a1f401..e7d4fbc 100644 --- a/repositories.tf +++ b/repositories.tf @@ -107,11 +107,12 @@ module "repo_fulfillment_service" { ] required_approvals = null required_status_checks = [ - "ci/prow/unit", "e2e-vmaas-full-install / e2e" ] - push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] - environments = [{ name = "e2e-test" }] + push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] + environments = [{ name = "e2e-test" }] + merge_queue = {} + strict_status_checks = false pages = { build_type = "workflow" source = { @@ -138,11 +139,12 @@ module "repo_cloudkit_operator" { ] required_approvals = null required_status_checks = [ - "ci/prow/temp", "e2e-vmaas-full-install / e2e" ] - push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] - environments = [{ name = "e2e-test" }] + push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] + environments = [{ name = "e2e-test" }] + merge_queue = {} + strict_status_checks = false } module "repo_cloudkit_aap" { @@ -162,11 +164,12 @@ module "repo_cloudkit_aap" { ] required_approvals = null required_status_checks = [ - "ci/prow/temp", "e2e-vmaas-full-install / e2e" ] - push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] - environments = [{ name = "e2e-test" }] + push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] + environments = [{ name = "e2e-test" }] + merge_queue = {} + strict_status_checks = false } module "repo_cloudkit_aap_ee" { @@ -215,9 +218,11 @@ module "repo_osac_installer" { "e2e-vmaas-full-install / e2e" ] - required_approvals = null - push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] - environments = [{ name = "e2e-test" }] + required_approvals = null + push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] + environments = [{ name = "e2e-test" }] + merge_queue = {} + strict_status_checks = false } module "repo_enhancement_proposals" { @@ -244,9 +249,11 @@ module "repo_osac_test_infra" { permission = "admin" } ] - required_approvals = null - push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] - environments = [{ name = "e2e-test" }] + required_approvals = null + push_allowances = ["/openshift-merge-robot", "osac-project/wg-infra", "osac-project/org-admins"] + environments = [{ name = "e2e-test" }] + merge_queue = {} + strict_status_checks = false } module "repo_massopencloud_templates" {