Skip to content
This repository was archived by the owner on May 16, 2026. It is now read-only.
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
2 changes: 1 addition & 1 deletion .github/workflows/terraform-CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
apply:
name: 'Terraform Apply'
if: github.event.pull_request.merged
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
environment: production
timeout-minutes: 60
env:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/terraform-CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ permissions:
jobs:
terraform:
name: 'Terraform Plan'
runs-on: ubuntu-latest
runs-on: ubuntu-24.04
environment: production
timeout-minutes: 60
env:
Expand Down
8 changes: 3 additions & 5 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,8 @@
# Crash log files
crash.log

# Ignore any .tfvars files that are generated automatically for each Terraform run. Most
# .tfvars files are managed as part of configuration and so should be included in
# version control.
#
# example.tfvars
# Local environment
/.env/

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
Expand All @@ -36,4 +33,5 @@ tf.plan
# Claude Code local settings
.claude/*.local.json
.claude/reviews/
.claude/plans/*.local.md
nul
56 changes: 37 additions & 19 deletions .terraform.lock.hcl

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion .yamllint
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ rules:
line-length:
max: 120
level: warning
...
...
10 changes: 0 additions & 10 deletions data_sources.tf
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,6 @@ data "aws_ssm_parameter" "github_control_lock_table" {
name = "/terraform/github-control/backend/lock_table"
}


data "aws_secretsmanager_secrets" "gh_secrets" {
provider = aws.aws-303467602807-uw1
filter {
name = "name"
values = []
}
}


data "aws_secretsmanager_secret_version" "pypi_api_token" {
provider = aws.aws-303467602807-uw1
secret_id = aws_secretsmanager_secret.pypi_api_token.id
Expand Down
6 changes: 3 additions & 3 deletions locals.tf
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
locals {
aws_account_id = "990466748045"
aws_default_region = "us-west-1"
environment = "production"

gh_org_name = "infrahouse"

s_prefix = "${data.aws_ssm_parameter.gh_secrets_namespace.value}tf_admin"
environment = "production"
team_members = {
"akuzminsky" : [
github_team.dev.name,
Expand Down
11 changes: 11 additions & 0 deletions modules/service-repo/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# service-repo

Terraform module that creates and configures a GitHub repository for deploying
Terraform infrastructure to one or more AWS environments.

The module is a pure GitHub module — it has no AWS provider dependency. IAM roles
and the state bucket are created by the caller and passed in via `var.environments`
and `var.state_bucket`.

<!-- BEGIN_TF_DOCS -->
<!-- END_TF_DOCS -->
35 changes: 35 additions & 0 deletions modules/service-repo/codeowners.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
locals {
# Order matters: last match wins in CODEOWNERS.
# Catch-all first, then increasingly specific patterns.
standard_codeowners_lines = [
"* @${var.gh_org_name}/${var.infrastructure_approvers}",
"environments/*/releases.auto.tfvars @${var.gh_org_name}/${var.release_managers}",
".github/workflows/** @${var.gh_org_name}/${var.pipeline_guardians}",
]

extra_codeowners_lines = [
for path, slug in var.extra_codeowners :
"${path} @${var.gh_org_name}/${slug}"
]

codeowners_content = join("\n", concat(
local.standard_codeowners_lines,
local.extra_codeowners_lines,
))
}

resource "github_repository_file" "codeowners" {
count = var.archived ? 0 : 1
repository = github_repository.this.name
file = ".github/CODEOWNERS"
overwrite_on_create = true
content = join("\n", [
"# This file is managed by Terraform in github-control repository",
"# Do not edit this file, all changes will be overwritten",
"",
local.codeowners_content,
"",
])
commit_message = "Update CODEOWNERS"
branch = local.default_branch
}
7 changes: 7 additions & 0 deletions modules/service-repo/custom_properties.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
resource "github_repository_custom_property" "this" {
for_each = var.custom_properties
repository = github_repository.this.name
property_name = each.key
property_type = each.value.type
property_value = each.value.value
}
18 changes: 18 additions & 0 deletions modules/service-repo/environments.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
resource "github_repository_environment" "ci" {
for_each = var.environments
environment = "continuous-integration-${each.key}"
repository = github_repository.this.name
}

resource "github_repository_environment" "cd" {
for_each = var.environments
environment = "live-${each.key}"
repository = github_repository.this.name

dynamic "reviewers" {
for_each = each.value.deploy_order > 0 ? [1] : []
content {
teams = [data.github_team.release_managers.id]
}
}
}
49 changes: 49 additions & 0 deletions modules/service-repo/files.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
resource "github_repository_file" "terraform_tf" {
for_each = var.environments
repository = github_repository.this.name
file = "environments/${each.key}/terraform.tf"
overwrite_on_create = true
content = templatefile("${path.module}/templates/terraform.tf.tftpl", {
state_bucket = var.state_bucket
environment = each.key
region = each.value.region
state_manager_role_arn = each.value.state_manager_role_arn
aws_provider_constraint = var.aws_provider_constraint
extra_required_providers = var.extra_required_providers
})
commit_message = "Add terraform.tf for ${each.key} environment"
branch = local.default_branch
}

resource "github_repository_file" "terraform_tfvars" {
for_each = var.environments
repository = github_repository.this.name
file = "environments/${each.key}/terraform.tfvars"
overwrite_on_create = true
content = templatefile("${path.module}/templates/terraform.tfvars.tftpl", {
state_manager_role_arn = each.value.state_manager_role_arn
admin_role_arn = each.value.admin_role_arn
github_role_arn = each.value.github_role_arn
gh_org_name = var.gh_org_name
repo_name = var.repo_name
region = each.value.region
})
commit_message = "Add terraform.tfvars for ${each.key} environment"
branch = local.default_branch
lifecycle {
ignore_changes = [content]
}
}

resource "github_repository_file" "releases_auto_tfvars" {
for_each = var.environments
repository = github_repository.this.name
file = "environments/${each.key}/releases.auto.tfvars"
overwrite_on_create = true
content = file("${path.module}/templates/releases.auto.tfvars.tftpl")
commit_message = "Add releases.auto.tfvars for ${each.key} environment"
branch = local.default_branch
lifecycle {
ignore_changes = [content]
}
}
41 changes: 41 additions & 0 deletions modules/service-repo/github_actions_variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
resource "github_actions_variable" "role_github" {
repository = github_repository.this.name
variable_name = "ROLE_GITHUB"
value = jsonencode({
for env, config in var.environments :
env => config.github_role_arn
})
}

resource "github_actions_variable" "role_admin" {
repository = github_repository.this.name
variable_name = "ROLE_ADMIN"
value = jsonencode({
for env, config in var.environments :
env => config.admin_role_arn
})
}

resource "github_actions_variable" "role_state_manager" {
repository = github_repository.this.name
variable_name = "ROLE_STATE_MANAGER"
value = jsonencode({
for env, config in var.environments :
env => config.state_manager_role_arn
})
}

resource "github_actions_variable" "state_bucket" {
repository = github_repository.this.name
variable_name = "STATE_BUCKET"
value = var.state_bucket
}

resource "github_actions_variable" "aws_default_region" {
repository = github_repository.this.name
variable_name = "AWS_DEFAULT_REGION"
value = jsonencode({
for env, config in var.environments :
env => config.region
})
}
9 changes: 9 additions & 0 deletions modules/service-repo/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
locals {
default_branch = "main"

required_checks = concat(
[for env in keys(var.environments) : "Terraform Plan ${env}"],
["TruffleHog", "vulnerability-check"],
var.checks,
)
}
60 changes: 60 additions & 0 deletions modules/service-repo/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
data "github_app" "terraform" {
slug = var.github_app_slug
}

data "github_team" "release_managers" {
slug = var.release_managers
}

resource "github_repository" "this" {
name = var.repo_name
description = var.repo_description
has_downloads = true
has_issues = true
has_projects = true
has_wiki = true
vulnerability_alerts = var.archived ? false : true
allow_update_branch = true
allow_merge_commit = true
allow_rebase_merge = true
allow_squash_merge = true
delete_branch_on_merge = true
squash_merge_commit_title = "COMMIT_OR_PR_TITLE"
squash_merge_commit_message = "COMMIT_MESSAGES"
merge_commit_title = "MERGE_MESSAGE"
merge_commit_message = "PR_TITLE"
archived = var.archived
visibility = var.repo_private ? "private" : "public"
web_commit_signoff_required = false

template {
owner = var.gh_org_name
repository = var.template_repo
}
}

resource "github_branch_default" "main" {
branch = local.default_branch
repository = github_repository.this.name
}

resource "github_team_repository" "committers" {
for_each = var.committers
repository = github_repository.this.name
team_id = each.value
permission = "push"
}

resource "github_team_repository" "admins" {
for_each = var.admins
repository = github_repository.this.name
team_id = each.value
permission = "admin"
}

resource "github_actions_secret" "secret" {
for_each = var.secrets
repository = github_repository.this.name
secret_name = each.key
plaintext_value = each.value
}
9 changes: 9 additions & 0 deletions modules/service-repo/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
output "repository_name" {
description = "The created repository name."
value = github_repository.this.name
}

output "repository_node_id" {
description = "The GraphQL node ID of the repository."
value = github_repository.this.node_id
}
Loading
Loading