Skip to content

feat: initial terraform configuration for GitHub org management - #1

Merged
xnoto merged 6 commits into
mainfrom
initial-commit
Dec 21, 2025
Merged

feat: initial terraform configuration for GitHub org management#1
xnoto merged 6 commits into
mainfrom
initial-commit

Conversation

@xnoto

@xnoto xnoto commented Dec 21, 2025

Copy link
Copy Markdown
Contributor

Summary

OpenTofu configuration to manage GitHub organization resources as code.

What's Included

Component Purpose
gh-repositories.tf Repository creation and settings
gh-protections.tf Branch protection rules
gh-secrets.tf GitHub Actions secrets (via SOPS)
gh-iam.tf Organization membership

CI/CD

  • Runs on ghcr.io/makeitworkcloud/runner:latest container
  • Pre-commit: validate, tflint, checkov, fmt, terraform-docs
  • PR: plan output commented on PR
  • Push to main: auto-apply (requires production environment approval)

Secrets Management

  • SOPS + age encryption
  • Secrets stored in secrets/secrets.yaml
  • Requires SOPS_AGE_KEY in GitHub Actions

Notable Decisions

  • No provider version pinning (uses lock file)
  • S3 backend (credentials from SOPS at runtime)
  • Branch protection enforces: linear history, PR reviews, conversation resolution

@github-actions

Copy link
Copy Markdown
Contributor

OpenTofu Plan 📋

�[0m�[1m�[32mNo changes.�[0m�[1m Your infrastructure matches the configuration.�[0m

�[0mOpenTofu has compared your real infrastructure against your configuration and

@github-actions

Copy link
Copy Markdown
Contributor

OpenTofu Plan 📋

No changes. Your infrastructure matches the configuration.

OpenTofu has compared your real infrastructure against your configuration and

@github-actions

Copy link
Copy Markdown
Contributor

OpenTofu Plan

OpenTofu will perform the following actions:

  # github_branch_protection.protections["shared-workflows"] will be destroyed
  # (because key ["shared-workflows"] is not in for_each map)
  - resource "github_branch_protection" "protections" {
      - allows_deletions                = false -> null
      - allows_force_pushes             = false -> null
      - enforce_admins                  = true -> null
      - force_push_bypassers            = [] -> null
      - id                              = "BPR_kwDOQsfaHs4EO2Q7" -> null
      - lock_branch                     = false -> null
      - pattern                         = "main" -> null
      - repository_id                   = "R_kgDOQsfaHg" -> null
      - require_conversation_resolution = true -> null
      - require_signed_commits          = false -> null
      - required_linear_history         = true -> null

      - required_pull_request_reviews {
          - dismiss_stale_reviews           = true -> null
          - dismissal_restrictions          = [
              - "/xnoto",
            ] -> null
          - pull_request_bypassers          = [
              - "/xnoto",
            ] -> null
          - require_code_owner_reviews      = true -> null
          - require_last_push_approval      = true -> null
          - required_approving_review_count = 1 -> null
          - restrict_dismissals             = true -> null
        }

      - required_status_checks {
          - contexts = [] -> null
          - strict   = true -> null
        }

      - restrict_pushes {
          - blocks_creations = true -> null
          - push_allowances  = [
              - "/xnoto",
            ] -> null
        }
    }

  # github_repository.repositories["shared-workflows"] will be destroyed
  # (because key ["shared-workflows"] is not in for_each map)
  - resource "github_repository" "repositories" {
      - allow_auto_merge            = false -> null
      - allow_merge_commit          = true -> null
      - allow_rebase_merge          = true -> null
      - allow_squash_merge          = true -> null
      - allow_update_branch         = false -> null
      - archived                    = false -> null
      - default_branch              = "main" -> null
      - delete_branch_on_merge      = false -> null
      - etag                        = "W/\"12967aad3796cab07e03e26a2ed5210df90a102587f6068d4dc721127be39517\"" -> null
      - fork                        = "false" -> null
      - full_name                   = "makeitworkcloud/shared-workflows" -> null
      - git_clone_url               = "git://github.com/makeitworkcloud/shared-workflows.git" -> null
      - has_discussions             = false -> null
      - has_downloads               = false -> null
      - has_issues                  = false -> null
      - has_projects                = false -> null
      - has_wiki                    = false -> null
      - html_url                    = "https://github.com/makeitworkcloud/shared-workflows" -> null
      - http_clone_url              = "https://github.com/makeitworkcloud/shared-workflows.git" -> null
      - id                          = "shared-workflows" -> null
      - is_template                 = false -> null
      - merge_commit_message        = "PR_TITLE" -> null
      - merge_commit_title          = "MERGE_MESSAGE" -> null
      - name                        = "shared-workflows" -> null
      - node_id                     = "R_kgDOQsfaHg" -> null
      - private                     = false -> null
      - repo_id                     = 1120393758 -> null
      - squash_merge_commit_message = "COMMIT_MESSAGES" -> null
      - squash_merge_commit_title   = "COMMIT_OR_PR_TITLE" -> null
      - ssh_clone_url               = "git@github.com:makeitworkcloud/shared-workflows.git" -> null
      - svn_url                     = "https://github.com/makeitworkcloud/shared-workflows" -> null
      - topics                      = [] -> null
      - visibility                  = "public" -> null
      - vulnerability_alerts        = false -> null
      - web_commit_signoff_required = false -> null

      - security_and_analysis {
          - secret_scanning {
              - status = "disabled" -> null
            }
          - secret_scanning_push_protection {
              - status = "disabled" -> null
            }
        }
    }

Plan: 0 to add, 0 to change, 2 to destroy.

@github-actions

Copy link
Copy Markdown
Contributor

OpenTofu Plan

No changes. Your infrastructure matches the configuration.

OpenTofu has compared your real infrastructure against your configuration and

@xnoto
xnoto merged commit 26c67ed into main Dec 21, 2025
3 checks passed
xnoto added a commit that referenced this pull request Dec 28, 2025
* feat: initial terraform configuration for GitHub org management

* fix: add pull-requests write permission for plan comments

* fix: add no-color to plan output for CI readability

* refactor: use shared OpenTofu workflow

* fix: add permissions to caller workflow

* shared-workflows
xnoto added a commit that referenced this pull request Sep 4, 2026
## Summary

Import the two Dependabot files that [`tfroot-twilio` PR
#1](makeitworkcloud/tfroot-twilio#1) seeded
through the required pull-request path. This lets their canonical
`tfroot-github` resources adopt existing files instead of attempting
protected direct creation.

The import reports inherited commit metadata and a create-only setting
that would otherwise cause a protected-branch file update. The two
resource definitions therefore ignore only `commit_message` and
`overwrite_on_create`; their centrally managed file content remains
enforced.

Fixes # N/A — repair the failed central Dependabot adoption path.

## Type of change

- [x] Bug fix
- [ ] Feature / enhancement
- [ ] Documentation
- [x] Infrastructure (OpenTofu root or module)
- [ ] GitOps desired state (manifests, kustomize, charts, SOPS/KSOPS
secrets)
- [ ] Container image
- [ ] CI / reusable workflow
- [ ] Refactor / cleanup
- [ ] Breaking change

## Validation

- [x] Required pull-request checks pass — OpenTofu test and plan
succeeded in [run
33819976668](https://github.com/makeitworkcloud/tfroot-github/actions/runs/33819976668).
- [x] Plan is exactly `2 to import, 0 to add, 0 to change, 0 to
destroy`.
- [x] Generated or centrally distributed files were regenerated by their
owning automation, not hand-edited — the files were exact PR seeds and
retain `tfroot-github` as their canonical owner.

The provider's documented import IDs use `repository:file-path:branch`,
with an empty branch for the default branch. No local OpenTofu, SOPS,
state, import, plan, or apply operations were run.

## Impact and rollout

Producer: `tfroot-github` owns both generated files and their resource
state. Consumer: `tfroot-twilio` now contains the exact seeded files on
`main` at
[`315acbf8`](makeitworkcloud/tfroot-twilio@315acbf).

The previous main apply attempted direct creation before the files
existed and failed on repository protection. This PR imports only
`.github/dependabot.yml` and `.github/workflows/dependabot-notify.yml`
into their existing central resources. Its validated plan neither writes
a file nor changes repository protection, Actions secrets, Twilio
configuration, or any GitOps/runtime system. After a confirmed merge,
verify the environment-gated apply succeeds and records the two imports.

Rollback is a reviewed revert of these import declarations. Do not
manually edit the managed target files.

## Safety and secrets

- [x] Contains no plaintext secrets, decrypted SOPS values, state files,
kubeconfigs, tokens, or private endpoints.
- [x] No local OpenTofu init/plan/apply/destroy/import/state operations
were run or claimed — plans come from pull-request checks.
- [x] Breaking or irreversible effects are described above with rollback
notes.

Repository-side secret scanning is unavailable because GitHub Advanced
Security is not enabled; the diff was manually inspected before
publication.

AI agent materially produced this change; reviewers should confirm the
documented import IDs, exact resource addresses, metadata-only lifecycle
exclusions, and retained central ownership.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant