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
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ root).
- [`examples/complete`](examples/complete) — manage an entire organization.
- [`examples/repository`](examples/repository) — use only the repository submodule.

## Stability

orgkit is **pre-1.0** and the input interface may still change between minor
releases. Pin a version (`version = "~> 0.2"`) and review the changelog before
upgrading. Breaking input changes so far, since the initial release:

- **`unsafe_merges` removed** — use `allow_squash_merge` / `allow_rebase_merge`
(and the other granular merge controls) instead.
- **`baseline_ruleset` and `require_signed_commits` removed** — use
`enabled_presets` (defaults reproduce the previous behavior) and
`organization_rulesets`; per-repo rules via `repositories[].rulesets`.
- **Default merge strategy is now squash-only** (`allow_squash_merge = true`,
`allow_merge_commit = false`). Set the `allow_*` fields per repository to
change it.

<!-- BEGIN_TF_DOCS -->
## Requirements

Expand Down Expand Up @@ -113,7 +128,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/><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/> rulesets = optional(map(object({<br/> enforcement = optional(string, "active")<br/> target = optional(string, "branch")<br/> include_refs = optional(list(string), ["~ALL"])<br/> exclude_refs = optional(list(string), [])<br/> bypass_actors = optional(list(object({<br/> actor_type = string<br/> actor_id = optional(number, 0)<br/> team = optional(string)<br/> bypass_mode = optional(string, "always")<br/> })), [])<br/> rules = object({<br/> creation = optional(bool, false)<br/> update = optional(bool, false)<br/> deletion = optional(bool, false)<br/> non_fast_forward = optional(bool, false)<br/> required_signatures = optional(bool, false)<br/> required_linear_history = optional(bool, false)<br/> pull_request = optional(object({<br/> required_approving_review_count = optional(number, 0)<br/> require_code_owner_review = optional(bool, false)<br/> require_last_push_approval = optional(bool, false)<br/> dismiss_stale_reviews_on_push = optional(bool, false)<br/> required_review_thread_resolution = optional(bool, false)<br/> }))<br/> })<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_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, false)<br/> allow_squash_merge = optional(bool, true)<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/> rulesets = optional(map(object({<br/> enforcement = optional(string, "active")<br/> target = optional(string, "branch")<br/> include_refs = optional(list(string), ["~ALL"])<br/> exclude_refs = optional(list(string), [])<br/> bypass_actors = optional(list(object({<br/> actor_type = string<br/> actor_id = optional(number, 0)<br/> team = optional(string)<br/> bypass_mode = optional(string, "always")<br/> })), [])<br/> rules = object({<br/> creation = optional(bool, false)<br/> update = optional(bool, false)<br/> deletion = optional(bool, false)<br/> non_fast_forward = optional(bool, false)<br/> required_signatures = optional(bool, false)<br/> required_linear_history = optional(bool, false)<br/> pull_request = optional(object({<br/> required_approving_review_count = optional(number, 0)<br/> require_code_owner_review = optional(bool, false)<br/> require_last_push_approval = optional(bool, false)<br/> dismiss_stale_reviews_on_push = optional(bool, false)<br/> required_review_thread_resolution = optional(bool, false)<br/> }))<br/> })<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_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 |
| <a name="input_users"></a> [users](#input\_users) | Organization members. `fullname`/`email` are informational; membership is keyed on `username`. | <pre>list(object({<br/> username = string<br/> fullname = optional(string, "")<br/> email = optional(string, "")<br/> }))</pre> | `[]` | no |
Expand Down
12 changes: 5 additions & 7 deletions docs/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,9 @@ repository module (which would create a dependency cycle).
manageable in the provider) and the deprecated `branch_protection_v3` resource
(rulesets supersede it).

## Planned default changes
## Merge strategy default

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.
Repositories default to **squash-only** merges (`allow_squash_merge = true`,
`allow_merge_commit = false`, `allow_rebase_merge = false`). Override per
repository via the `allow_merge_commit` / `allow_squash_merge` /
`allow_rebase_merge` fields (at least one must be enabled).
2 changes: 1 addition & 1 deletion modules/repository/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ No modules.
| 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/><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/> rulesets = optional(map(object({<br/> enforcement = optional(string, "active")<br/> target = optional(string, "branch")<br/> include_refs = optional(list(string), ["~ALL"])<br/> exclude_refs = optional(list(string), [])<br/> bypass_actors = optional(list(object({<br/> actor_type = string<br/> actor_id = optional(number, 0)<br/> team = optional(string)<br/> bypass_mode = optional(string, "always")<br/> })), [])<br/> rules = object({<br/> creation = optional(bool, false)<br/> update = optional(bool, false)<br/> deletion = optional(bool, false)<br/> non_fast_forward = optional(bool, false)<br/> required_signatures = optional(bool, false)<br/> required_linear_history = optional(bool, false)<br/> pull_request = optional(object({<br/> required_approving_review_count = optional(number, 0)<br/> require_code_owner_review = optional(bool, false)<br/> require_last_push_approval = optional(bool, false)<br/> dismiss_stale_reviews_on_push = optional(bool, false)<br/> required_review_thread_resolution = optional(bool, false)<br/> }))<br/> })<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_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, false)<br/> allow_squash_merge = optional(bool, true)<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/> rulesets = optional(map(object({<br/> enforcement = optional(string, "active")<br/> target = optional(string, "branch")<br/> include_refs = optional(list(string), ["~ALL"])<br/> exclude_refs = optional(list(string), [])<br/> bypass_actors = optional(list(object({<br/> actor_type = string<br/> actor_id = optional(number, 0)<br/> team = optional(string)<br/> bypass_mode = optional(string, "always")<br/> })), [])<br/> rules = object({<br/> creation = optional(bool, false)<br/> update = optional(bool, false)<br/> deletion = optional(bool, false)<br/> non_fast_forward = optional(bool, false)<br/> required_signatures = optional(bool, false)<br/> required_linear_history = optional(bool, false)<br/> pull_request = optional(object({<br/> required_approving_review_count = optional(number, 0)<br/> require_code_owner_review = optional(bool, false)<br/> require_last_push_approval = optional(bool, false)<br/> dismiss_stale_reviews_on_push = optional(bool, false)<br/> required_review_thread_resolution = optional(bool, false)<br/> }))<br/> })<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
Loading
Loading