Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

11 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

terraform-github-orgkit

Terraform Registry Release Tests License

A composable Terraform module suite for managing a whole GitHub organization as code — members, teams, repositories, GitHub Actions (variables, secrets and environments), organization rulesets, and organization roles.

Use the whole thing, or just one piece:

# Everything — the root module manages the entire organization.
module "github" {
  source  = "pelotech/orgkit/github"
  version = "~> 0.3"

  users        = [/* ... */]
  teams        = [/* ... */]
  repositories = [/* ... */]
}

# Or adopt a single submodule.
module "repos" {
  source  = "pelotech/orgkit/github//modules/repository"
  version = "~> 0.2"

  teams        = { developers = { id = "123", slug = "developers" } }
  repositories = [/* ... */]
}

Why orgkit

The well-known community modules for GitHub-as-code are all years-stale. orgkit is a maintained, modern alternative that also does more than any of them on the organization and Actions axes:

  • GitHub Actions — repository and environment variables, repository and environment secrets, and organization-level secrets/variables with all/private/selected visibility.
  • Environments — reviewers, wait timers, and deployment branch policies.
  • Organization & repository rulesets — a generic ruleset interface with opt-in presets (PR reviews, signed commits, deletion protection, force-push and linear-history), the modern replacement for per-repo branch protection.
  • Organization roles — assign predefined org roles (e.g. security_manager) to teams.
  • Opinionated defaults, no hardcoded policy — every organization-specific choice (who is an owner, the all-members team, ruleset tuning) is an input, not a baked-in constant.

See docs/DESIGN.md for the design rationale, a comparison with the existing ecosystem modules, and the feature roadmap.

Architecture

Three submodules composed by the root as a one-directional pipeline (no cycles):

modules/organization  →  modules/teams  →  modules/repository
Submodule Manages
organization Org membership, owner/admin assignment, org rulesets (generic interface + presets).
teams Teams, team memberships, the optional all-members team, org-role assignments.
repository Repositories, team↔repo grants, per-repo rulesets, repo/environment Actions variables & secrets, environments.

The root additionally manages organization-level Actions secrets and variables (they need both secret values and repository ids, so they live at the composition root).

Examples

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.

Requirements

Name Version
terraform >= 1.9
github ~> 6.0

Providers

Name Version
github ~> 6.0

Modules

Name Source Version
organization ./modules/organization n/a
repository ./modules/repository n/a
teams ./modules/teams n/a

Resources

Name Type
github_actions_organization_secret.internal resource
github_actions_organization_variable.internal resource

Inputs

Name Description Type Default Required
all_members_team_name Name of the all-members team. string "everyone" no
create_all_members_team Create an all-members team that grants default read access to non-restricted repositories. bool true no
enabled_presets Names of built-in ruleset presets to enable. See modules/organization/main.tf local.presets. list(string)
[
"require_pull_request_reviews",
"restrict_deletions",
"require_signed_commits"
]
no
organization_rulesets Organization rulesets, keyed by name. Merged with (and overridden by name by)
the presets selected via enabled_presets. bypass_actors uses raw numeric
actor_id (OrganizationAdmin needs none); team-name bypass is per-repo only.
map(object({
enforcement = optional(string, "active")
target = optional(string, "branch")
include_refs = optional(list(string), ["~ALL"])
exclude_refs = optional(list(string), [])
include_repositories = optional(list(string), ["~ALL"])
exclude_repositories = optional(list(string), [])
bypass_actors = optional(list(object({
actor_type = string
actor_id = optional(number, 0)
bypass_mode = optional(string, "always")
})), [])
rules = object({
creation = optional(bool, false)
update = optional(bool, false)
deletion = optional(bool, false)
non_fast_forward = optional(bool, false)
required_signatures = optional(bool, false)
required_linear_history = optional(bool, false)
pull_request = optional(object({
required_approving_review_count = optional(number, 0)
require_code_owner_review = optional(bool, false)
require_last_push_approval = optional(bool, false)
dismiss_stale_reviews_on_push = optional(bool, false)
required_review_thread_resolution = optional(bool, false)
}))
})
}))
{} no
organization_secrets Visibility config for org-level shared secrets. Values come from var.secrets.org.
map(object({
visibility = optional(string, "private")
repositories = optional(list(string), [])
}))
{} no
organization_variables Org-level shared Actions variables (plaintext value + visibility).
map(object({
value = string
visibility = optional(string, "private")
repositories = optional(list(string), [])
}))
{} no
owners Explicit set of owner usernames (mapped to GitHub's admin role). Ignored when owners_team is set. set(string) [] no
owners_team Convenience: derive organization owners from the members of this team, by
name. null (default) means use the explicit owners set instead. There is
no hardcoded owners team — the consumer chooses.
string null no
repositories Repositories and which teams may access them. See the repository submodule for the full object schema and validations.
list(object({
name = string
description = string
visibility = optional(string, "private")
readers = optional(list(string), [])
writers = optional(list(string), [])
admins = optional(list(string), [])
restricted = optional(bool, false)

topics = optional(list(string), [])
homepage_url = optional(string, null)
has_issues = optional(bool, true)
has_wiki = optional(bool, false)
has_projects = optional(bool, false)
has_downloads = optional(bool, false)
is_template = optional(bool, false)
gitignore_template = optional(string, null)
license_template = optional(string, null)
archived = optional(bool, false)
archive_on_destroy = optional(bool, true)
default_branch = optional(string, null)
enable_pages = optional(bool, false)
signed_commits = optional(bool, true)

allow_merge_commit = optional(bool, false)
allow_squash_merge = optional(bool, true)
allow_rebase_merge = optional(bool, false)
allow_auto_merge = optional(bool, true)
delete_branch_on_merge = optional(bool, true)
merge_commit_message = optional(string, "PR_BODY")
merge_commit_title = optional(string, "PR_TITLE")

template = optional(object({
owner = string
repository = string
include_all_branches = optional(bool, false)
}))

rulesets = optional(map(object({
enforcement = optional(string, "active")
target = optional(string, "branch")
include_refs = optional(list(string), ["~ALL"])
exclude_refs = optional(list(string), [])
bypass_actors = optional(list(object({
actor_type = string
actor_id = optional(number, 0)
team = optional(string)
bypass_mode = optional(string, "always")
})), [])
rules = object({
creation = optional(bool, false)
update = optional(bool, false)
deletion = optional(bool, false)
non_fast_forward = optional(bool, false)
required_signatures = optional(bool, false)
required_linear_history = optional(bool, false)
pull_request = optional(object({
required_approving_review_count = optional(number, 0)
require_code_owner_review = optional(bool, false)
require_last_push_approval = optional(bool, false)
dismiss_stale_reviews_on_push = optional(bool, false)
required_review_thread_resolution = optional(bool, false)
}))
})
})), {})

variables = optional(map(string), {})
environments = optional(map(object({
variables = optional(map(string), {})
reviewers = optional(list(string), [])
wait_timer = optional(number, 0)
deployment_branch_policy = optional(object({
protected_branches = optional(bool, false)
custom_branch_policies = optional(list(string), [])
}))
})), {})
}))
[] no
secrets Decrypted secret values keyed by scope. Supplied already-decrypted by the caller; this module never performs decryption.
object({
org = optional(map(string), {})
repos = optional(map(object({
actions = optional(map(string), {})
environments = optional(map(map(string)), {})
})), {})
})
{
"org": {},
"repos": {}
}
no
teams Teams and their membership. A team may hold predefined organization-level
GitHub roles via org_roles. Repository access is granted per repository via
readers/writers/admins, not through org roles.
list(object({
name = string
description = string
members = optional(list(string), [])
org_roles = optional(list(string), [])
}))
[] no
users Organization members. fullname/email are informational; membership is keyed on username.
list(object({
username = string
fullname = optional(string, "")
email = optional(string, "")
}))
[] no

Outputs

Name Description
all_members_team_id ID of the all-members team, or null when create_all_members_team = false.
members Map of organization member username => managed membership username.
repository_ids Map of repository name => numeric repo_id.
teams Map of team name => { id, slug }.

About

A composable Terraform module suite to manage an entire GitHub organization as code — members, teams, repositories, Actions, rulesets, and org roles.

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages