Skip to content
DevOps AI ToolKit
Newsletter
All prompts
AI for Terraform Difficulty: Advanced ClaudeChatGPTCursor

Terraform GitHub Org Management Module Prompt

Manage a GitHub organization as code with repos, teams, memberships, and branch protection via for_each, importing existing repos safely.

Target user
Platform and DevEx engineers codifying GitHub org governance
Difficulty
Advanced
Tools
Claude, ChatGPT, Cursor

The prompt

You are a senior DevEx engineer codifying a GitHub organization with the `integrations/github` provider (>= 6.2). Manage repositories, teams, memberships, and branch protection from typed maps with `for_each`, and make destroying a repo effectively impossible by accident.

Work through these steps in order:

1. Configure the provider with `owner = "<org>"` and a token/GitHub App installation (`GITHUB_TOKEN` or app auth) that has org admin scope. Prefer a GitHub App for higher rate limits and auditability.

2. Model typed variables: `repositories` as `map(object({ visibility, description, topics, template? }))`, `teams` as `map(object({ privacy, description }))`, and `members` as `map(string)` mapping username -> role. Drive each with `for_each` keyed by name.

3. For every `github_repository`, set `lifecycle { prevent_destroy = true }` and enable `archive_on_destroy = true` so a removal archives rather than permanently deletes. Deleting a `github_repository` DESTROYS the repo, its issues, PRs, and wiki irreversibly.

4. Add `github_branch_protection` (v4/v6 uses `pattern` + `repository_id`) requiring status checks, required reviewers, `required_linear_history`, and `enforce_admins`. Bind teams to repos with `github_team_repository`.

5. Manage org membership with `github_membership` (role `member`/`admin`). Warn that removing a `github_membership` resource REVOKES the person's org access, and removing an owner can lock out administration.

6. Import strategy: existing repos, teams, and memberships must be `terraform import`ed BEFORE the first apply, or Terraform will try to create duplicates (repo name collision) or, worse, reconcile by recreation. Provide the exact import IDs.

7. Enumerate DESTRUCTIVE operations: removing a repo from the map, flipping visibility public->private on a repo with forks, removing a member, and deleting a team that owns repos.

Input template:
```
Org: <org-name>
Auth: <PAT | GitHub App installation id>
Repos to manage (and which already exist): <list>
Teams and privacy: <list>
Members and roles: <user -> member/admin>
Branch protection baseline: <required checks, reviewers>
```

Run this prompt with AI

Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.

Why this prompt works

A GitHub org managed by Terraform concentrates enormous blast radius: a single deleted github_repository resource permanently destroys code history, issues, and PRs. The common failure is applying against an org with pre-existing repos without importing them first, causing collisions or destructive reconciliation. This prompt bakes in prevent_destroy, archive_on_destroy, and an explicit import-first workflow so codifying governance never becomes an irreversible mistake.

How to use it

Provide your org name, auth method, the repos/teams/members to manage (flagging which already exist), and a branch-protection baseline. Ask the model for the typed variable definitions, the for_each resources with lifecycle guards, and a list of exact terraform import commands to run before the first apply. Always run terraform plan and reject any will be destroyed on a repository.

Useful commands

# Auth (prefer a GitHub App installation token in CI)
export GITHUB_TOKEN=ghp_...
export GITHUB_OWNER=my-org

# Import existing objects BEFORE first apply
terraform import 'github_repository.this["service-api"]' service-api
terraform import 'github_team.this["platform"]' 4567890
terraform import 'github_membership.this["octocat"]' my-org:octocat
terraform import 'github_branch_protection.main["service-api"]' service-api:main

# Plan and hard-fail on any repository destruction
terraform show -json tfplan \
  | jq -e '[.resource_changes[]
      | select(.type=="github_repository" and (.change.actions|index("delete")))]
      | length == 0'

# Reconcile: list org repos via API to find drift
gh api "orgs/$GITHUB_OWNER/repos?per_page=100" --paginate \
  | jq -r '.[].name'

Patterns

Repositories with destruction guards and branch protection, driven by for_each:

variable "repositories" {
  type = map(object({
    visibility  = string
    description = string
    topics      = optional(list(string), [])
  }))
}

resource "github_repository" "this" {
  for_each = var.repositories

  name               = each.key
  visibility         = each.value.visibility
  description        = each.value.description
  topics             = each.value.topics
  archive_on_destroy = true

  lifecycle {
    prevent_destroy = true
  }
}

resource "github_branch_protection" "main" {
  for_each = github_repository.this

  repository_id           = each.value.node_id
  pattern                 = "main"
  enforce_admins          = true
  required_linear_history = true

  required_pull_request_reviews {
    required_approving_review_count = 2
    dismiss_stale_reviews           = true
  }
  required_status_checks {
    strict   = true
    contexts = ["ci/build", "ci/test"]
  }
}

Teams, membership, and team-to-repo binding:

resource "github_team" "this" {
  for_each = var.teams

  name        = each.key
  privacy     = each.value.privacy      # "closed" or "secret"
  description = each.value.description
}

resource "github_membership" "this" {
  for_each = var.members               # map(username => "member"|"admin")

  username = each.key
  role     = each.value
}

resource "github_team_repository" "platform_api" {
  team_id    = github_team.this["platform"].id
  repository = github_repository.this["service-api"].name
  permission = "push"
}

Related prompts

More Terraform prompts & error guides

Browse every Terraform prompt and troubleshooting guide in one place.

Free download · 368-page PDF

Reading prompts? Get all 500 in one free PDF

500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.

  • 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
  • Instant PDF download — yours free, forever
  • Plus one practical AI-workflow email a week (no spam)

Single opt-in · unsubscribe anytime · no spam.