Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/pre-commit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
- name: install hcledit
run: |
curl -sSLo ./hcledit.tar.gz https://github.com/minamijoyo/hcledit/releases/download/v0.2.10/hcledit_0.2.10_linux_amd64.tar.gz
tar -xzf hcledit.tar.gz
tar -xzf hcledit.tar.gz hcledit
chmod +x hcledit
mv hcledit /usr/local/bin/hcledit

Expand All @@ -31,8 +31,8 @@ jobs:

- name: install tf-docs
run: |
curl -sSLo ./terraform-docs.tar.gz https://terraform-docs.io/dl/v0.17.0/terraform-docs-v0.17.0-linux-amd64.tar.gz
tar -xzf terraform-docs.tar.gz
curl -sSLo ./terraform-docs.tar.gz https://terraform-docs.io/dl/v0.24.0/terraform-docs-v0.24.0-linux-amd64.tar.gz
tar -xzf terraform-docs.tar.gz terraform-docs
chmod +x terraform-docs
mv terraform-docs /usr/local/bin/terraform-docs

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ root).
| <a name="input_organization_variables"></a> [organization\_variables](#input\_organization\_variables) | Org-level shared Actions variables (plaintext value + visibility). | <pre>map(object({<br/> value = string<br/> visibility = optional(string, "private")<br/> repositories = optional(list(string), [])<br/> }))</pre> | `{}` | no |
| <a name="input_owners"></a> [owners](#input\_owners) | Explicit set of owner usernames (mapped to GitHub's `admin` role). Ignored when `owners_team` is set. | `set(string)` | `[]` | no |
| <a name="input_owners_team"></a> [owners\_team](#input\_owners\_team) | Convenience: derive organization owners from the members of this team, by<br/>name. `null` (default) means use the explicit `owners` set instead. There is<br/>no hardcoded owners team — the consumer chooses. | `string` | `null` | no |
| <a name="input_repositories"></a> [repositories](#input\_repositories) | Repositories and which teams may access them. See the repository submodule for the full object schema and validations. | <pre>list(object({<br/> name = string<br/> description = string<br/> visibility = optional(string, "private")<br/> readers = optional(list(string), [])<br/> writers = optional(list(string), [])<br/> admins = optional(list(string), [])<br/> restricted = optional(bool, false)<br/> enable_pages = optional(bool, false)<br/> unsafe_merges = optional(bool, false)<br/> signed_commits = optional(bool, true)<br/> variables = optional(map(string), {})<br/> environments = optional(map(object({<br/> variables = optional(map(string), {})<br/> reviewers = optional(list(string), [])<br/> wait_timer = optional(number, 0)<br/> deployment_branch_policy = optional(object({<br/> protected_branches = optional(bool, false)<br/> custom_branch_policies = optional(list(string), [])<br/> }))<br/> })), {})<br/> }))</pre> | `[]` | no |
| <a name="input_repositories"></a> [repositories](#input\_repositories) | Repositories and which teams may access them. See the repository submodule for the full object schema and validations. | <pre>list(object({<br/> name = string<br/> description = string<br/> visibility = optional(string, "private")<br/> readers = optional(list(string), [])<br/> writers = optional(list(string), [])<br/> admins = optional(list(string), [])<br/> restricted = optional(bool, false)<br/><br/> topics = optional(list(string), [])<br/> homepage_url = optional(string, null)<br/> has_issues = optional(bool, true)<br/> has_wiki = optional(bool, false)<br/> has_projects = optional(bool, false)<br/> has_downloads = optional(bool, true)<br/> is_template = optional(bool, false)<br/> gitignore_template = optional(string, null)<br/> license_template = optional(string, null)<br/> archived = optional(bool, false)<br/> archive_on_destroy = optional(bool, false)<br/> default_branch = optional(string, null)<br/> enable_pages = optional(bool, false)<br/> signed_commits = optional(bool, true)<br/><br/> allow_merge_commit = optional(bool, true)<br/> allow_squash_merge = optional(bool, false)<br/> allow_rebase_merge = optional(bool, false)<br/> allow_auto_merge = optional(bool, true)<br/> delete_branch_on_merge = optional(bool, true)<br/> merge_commit_message = optional(string, "PR_BODY")<br/> merge_commit_title = optional(string, "PR_TITLE")<br/><br/> template = optional(object({<br/> owner = string<br/> repository = string<br/> include_all_branches = optional(bool, false)<br/> }))<br/><br/> variables = optional(map(string), {})<br/> environments = optional(map(object({<br/> variables = optional(map(string), {})<br/> reviewers = optional(list(string), [])<br/> wait_timer = optional(number, 0)<br/> deployment_branch_policy = optional(object({<br/> protected_branches = optional(bool, false)<br/> custom_branch_policies = optional(list(string), [])<br/> }))<br/> })), {})<br/> }))</pre> | `[]` | no |
| <a name="input_require_signed_commits"></a> [require\_signed\_commits](#input\_require\_signed\_commits) | Require signed commits on all branches of all repositories (except repositories with signed\_commits = false). | `bool` | `true` | no |
| <a name="input_secrets"></a> [secrets](#input\_secrets) | Decrypted secret values keyed by scope. Supplied already-decrypted by the caller; this module never performs decryption. | <pre>object({<br/> org = optional(map(string), {})<br/> repos = optional(map(object({<br/> actions = optional(map(string), {})<br/> environments = optional(map(map(string)), {})<br/> })), {})<br/> })</pre> | <pre>{<br/> "org": {},<br/> "repos": {}<br/>}</pre> | no |
| <a name="input_teams"></a> [teams](#input\_teams) | Teams and their membership. A team may hold predefined organization-level<br/>GitHub roles via `org_roles`. Repository access is granted per repository via<br/>readers/writers/admins, not through org roles. | <pre>list(object({<br/> name = string<br/> description = string<br/> members = optional(list(string), [])<br/> org_roles = optional(list(string), [])<br/> }))</pre> | `[]` | no |
Expand Down
9 changes: 9 additions & 0 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,12 @@ repository module (which would create a dependency cycle).
**Out of scope**: classic org/repo Projects (legacy; Projects V2 is not cleanly
manageable in the provider) and the deprecated `branch_protection_v3` resource
(rulesets supersede it).

## Planned default changes

Defaults intended to change in a future major release. They preserve today's
behavior for now, so existing configs see no plan churn until then:

- **Merge strategy** — switch the default from merge commits to squash-only
(`allow_squash_merge = true`, `allow_merge_commit = false`). The module currently
defaults to merge commits.
12 changes: 12 additions & 0 deletions examples/complete/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,24 @@ scope; see the provider docs.
| <a name="requirement_terraform"></a> [terraform](#requirement\_terraform) | >= 1.9 |
| <a name="requirement_github"></a> [github](#requirement\_github) | ~> 6.0 |

## Providers

No providers.

## Modules

| Name | Source | Version |
| ---- | ------ | ------- |
| <a name="module_orgkit"></a> [orgkit](#module\_orgkit) | ../../ | n/a |

## Resources

No resources.

## Inputs

No inputs.

## Outputs

| Name | Description |
Expand Down
13 changes: 7 additions & 6 deletions examples/complete/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,13 @@ module "orgkit" {
admins = ["platform", "owners"]
},
{
name = "sandbox"
description = "Experiments; relaxed rules"
visibility = "private"
admins = ["owners"]
unsafe_merges = true # allow rebase/squash merges
signed_commits = false # opt out of the required-signed-commits ruleset
name = "sandbox"
description = "Experiments; relaxed rules"
visibility = "private"
admins = ["owners"]
allow_squash_merge = true # allow squash merges
allow_rebase_merge = true # allow rebase merges
signed_commits = false # opt out of the required-signed-commits ruleset
},
{
name = "docs-site"
Expand Down
4 changes: 4 additions & 0 deletions examples/repository/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ terraform validate
| ---- | ---- |
| [github_team.developers](https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/team) | data source |

## Inputs

No inputs.

## Outputs

| Name | Description |
Expand Down
4 changes: 4 additions & 0 deletions modules/organization/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ hardcoded.
| ---- | ------- |
| <a name="provider_github"></a> [github](#provider\_github) | ~> 6.0 |

## Modules

No modules.

## Resources

| Name | Type |
Expand Down
7 changes: 6 additions & 1 deletion modules/repository/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Consumes a `name → { id, slug }` team map (e.g. from the teams module, a
| ---- | ------- |
| <a name="provider_github"></a> [github](#provider\_github) | ~> 6.0 |

## Modules

No modules.

## Resources

| Name | Type |
Expand All @@ -29,6 +33,7 @@ Consumes a `name → { id, slug }` team map (e.g. from the teams module, a
| [github_actions_environment_variable.internal](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_environment_variable) | resource |
| [github_actions_secret.repo](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_secret) | resource |
| [github_actions_variable.repo](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/actions_variable) | resource |
| [github_branch_default.internal](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_default) | resource |
| [github_repository.internal](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository) | resource |
| [github_repository_environment.internal](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_environment) | resource |
| [github_repository_environment_deployment_policy.internal](https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_environment_deployment_policy) | resource |
Expand All @@ -41,7 +46,7 @@ Consumes a `name → { id, slug }` team map (e.g. from the teams module, a
| Name | Description | Type | Default | Required |
| ---- | ----------- | ---- | ------- | :------: |
| <a name="input_all_members_team_id"></a> [all\_members\_team\_id](#input\_all\_members\_team\_id) | ID of the all-members team that receives default read access on non-restricted repositories. null disables the default read grant. | `string` | `null` | no |
| <a name="input_repositories"></a> [repositories](#input\_repositories) | Repositories to manage and which teams may access them. `readers`, `writers`<br/>and `admins` reference team names from `var.teams`. A team listed at more than<br/>one level gets the highest permission (admin > write > read). Set<br/>`restricted = true` to withhold the default all-members read grant. | <pre>list(object({<br/> name = string<br/> description = string<br/> visibility = optional(string, "private")<br/> readers = optional(list(string), [])<br/> writers = optional(list(string), [])<br/> admins = optional(list(string), [])<br/> restricted = optional(bool, false)<br/> enable_pages = optional(bool, false)<br/> unsafe_merges = optional(bool, false)<br/> signed_commits = optional(bool, true)<br/> variables = optional(map(string), {})<br/> environments = optional(map(object({<br/> variables = optional(map(string), {})<br/> reviewers = optional(list(string), [])<br/> wait_timer = optional(number, 0)<br/> deployment_branch_policy = optional(object({<br/> protected_branches = optional(bool, false)<br/> custom_branch_policies = optional(list(string), [])<br/> }))<br/> })), {})<br/> }))</pre> | `[]` | no |
| <a name="input_repositories"></a> [repositories](#input\_repositories) | Repositories to manage and which teams may access them. `readers`, `writers`<br/>and `admins` reference team names from `var.teams`. A team listed at more than<br/>one level gets the highest permission (admin > write > read). Set<br/>`restricted = true` to withhold the default all-members read grant. | <pre>list(object({<br/> name = string<br/> description = string<br/> visibility = optional(string, "private")<br/> readers = optional(list(string), [])<br/> writers = optional(list(string), [])<br/> admins = optional(list(string), [])<br/> restricted = optional(bool, false)<br/><br/> topics = optional(list(string), [])<br/> homepage_url = optional(string, null)<br/> has_issues = optional(bool, true)<br/> has_wiki = optional(bool, false)<br/> has_projects = optional(bool, false)<br/> has_downloads = optional(bool, true)<br/> is_template = optional(bool, false)<br/> gitignore_template = optional(string, null)<br/> license_template = optional(string, null)<br/> archived = optional(bool, false)<br/> archive_on_destroy = optional(bool, false)<br/> default_branch = optional(string, null)<br/> enable_pages = optional(bool, false)<br/> signed_commits = optional(bool, true)<br/><br/> allow_merge_commit = optional(bool, true)<br/> allow_squash_merge = optional(bool, false)<br/> allow_rebase_merge = optional(bool, false)<br/> allow_auto_merge = optional(bool, true)<br/> delete_branch_on_merge = optional(bool, true)<br/> merge_commit_message = optional(string, "PR_BODY")<br/> merge_commit_title = optional(string, "PR_TITLE")<br/><br/> template = optional(object({<br/> owner = string<br/> repository = string<br/> include_all_branches = optional(bool, false)<br/> }))<br/><br/> variables = optional(map(string), {})<br/> environments = optional(map(object({<br/> variables = optional(map(string), {})<br/> reviewers = optional(list(string), [])<br/> wait_timer = optional(number, 0)<br/> deployment_branch_policy = optional(object({<br/> protected_branches = optional(bool, false)<br/> custom_branch_policies = optional(list(string), [])<br/> }))<br/> })), {})<br/> }))</pre> | `[]` | no |
| <a name="input_repository_secrets"></a> [repository\_secrets](#input\_repository\_secrets) | Per-repository Actions and environment secret values (plaintext), keyed by<br/>repository name. Supplied already-decrypted by the caller; this module never<br/>performs decryption. | <pre>map(object({<br/> actions = optional(map(string), {})<br/> environments = optional(map(map(string)), {})<br/> }))</pre> | `{}` | no |
| <a name="input_teams"></a> [teams](#input\_teams) | Map of team name => { id, slug } for teams that may be granted repository access or set as environment reviewers. Supplied by the teams module. | <pre>map(object({<br/> id = string<br/> slug = string<br/> }))</pre> | `{}` | no |

Expand Down
54 changes: 44 additions & 10 deletions modules/repository/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,36 @@ resource "github_repository" "internal" {
description = each.value.description
visibility = each.value.visibility

topics = each.value.topics
homepage_url = each.value.homepage_url
has_issues = each.value.has_issues
has_wiki = each.value.has_wiki
has_projects = each.value.has_projects
has_downloads = each.value.has_downloads
is_template = each.value.is_template
gitignore_template = each.value.gitignore_template
license_template = each.value.license_template
archived = each.value.archived
archive_on_destroy = each.value.archive_on_destroy

auto_init = false
has_issues = true
has_projects = false
has_wiki = false
allow_auto_merge = true
allow_merge_commit = true
allow_rebase_merge = each.value.unsafe_merges
allow_squash_merge = each.value.unsafe_merges
delete_branch_on_merge = true
merge_commit_message = "PR_BODY"
merge_commit_title = "PR_TITLE"
allow_auto_merge = each.value.allow_auto_merge
allow_merge_commit = each.value.allow_merge_commit
allow_rebase_merge = each.value.allow_rebase_merge
allow_squash_merge = each.value.allow_squash_merge
delete_branch_on_merge = each.value.delete_branch_on_merge
merge_commit_message = each.value.merge_commit_message
merge_commit_title = each.value.merge_commit_title

dynamic "template" {
for_each = each.value.template != null ? [each.value.template] : []

content {
owner = template.value.owner
repository = template.value.repository
include_all_branches = template.value.include_all_branches
}
}

dynamic "pages" {
for_each = each.value.enable_pages ? [1] : []
Expand Down Expand Up @@ -61,6 +80,21 @@ resource "github_repository_vulnerability_alerts" "internal" {
enabled = true
}

#
# Default branch, managed as a dedicated resource because setting it on the
# repository is deprecated. Only created for repositories that name one.
#

resource "github_branch_default" "internal" {
for_each = {
for name, r in local.repositories : name => r.default_branch
if r.default_branch != null
}

repository = github_repository.internal[each.key].name
branch = each.value
}

#
# One team-repository grant per repository-team pair. A team listed at more than
# one level gets the highest permission (merge order: admins > writers > readers).
Expand Down
Loading
Loading