Skip to content

Commit

Permalink
initial add
Browse files Browse the repository at this point in the history
  • Loading branch information
Dave Arnold committed Apr 17, 2024
0 parents commit ada3691
Show file tree
Hide file tree
Showing 12 changed files with 377 additions and 0 deletions.
30 changes: 30 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Local .terraform directories
**/.terraform/*

# .tfstate files
*.tfstate
*.tfstate.*

# 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

# Ignore override files as they are usually used to override resources locally and so
# are not checked in
override.tf
override.tf.json
*_override.tf
*_override.tf.json

# Include override files you do wish to add to version control using negated pattern
#
# !example_override.tf

# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan
# example: *tfplan*
.terraform.lock.hcl
1 change: 1 addition & 0 deletions CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# These owners will be the default owners for everything in the repo. Unless a later match takes precedence
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# terraform-tfe-module
Module to automate creation of
* terraform workspace
* github related resources
* repo
* default branch
* branch protection rule for main branch
* default codeowners and backend.tf file
* team access
13 changes: 13 additions & 0 deletions action_secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
resource "github_actions_secret" "secret" {
for_each = tomap({ for secret in var.secrets : secret.name => secret.value })
secret_name = each.key
plaintext_value = each.value
repository = github_repository.repo.name
}

resource "github_actions_variable" "variable" {
for_each = tomap({ for _var in var.vars : _var.name => _var.value })
repository = github_repository.repo.name
variable_name = each.key
value = each.value
}
3 changes: 3 additions & 0 deletions data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
codeowners = length(var.additional_codeowners) > 0 ? flatten(["${var.repo_org}/${var.github_codeowners_team}", formatlist("${var.repo_org}/%s", var.additional_codeowners)]) : ["${var.repo_org}/${var.github_codeowners_team}"]
}
68 changes: 68 additions & 0 deletions github_branch.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@

# https://registry.terraform.io/providers/integrations/github/latest/docs/data-sources/team
# data "github_team" "github_codeowners_team" {
# slug = var.github_codeowners_team
# }

# not creating main branch because its created by default when repo is created
resource "github_branch" "branch" {
count = var.github_default_branch == "main" ? 0 : 1
repository = github_repository.repo.name
branch = var.github_default_branch
}


# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_default
resource "github_branch_default" "default_main_branch" {
count = var.github_default_branch == "main" ? 0 : 1
repository = github_repository.repo.name
branch = var.github_default_branch
depends_on = [
github_branch.branch
]
}


data "github_user" "pull_request_bypassers" {
for_each = toset(var.pull_request_bypassers)
username = each.value
}

locals {
pull_request_bypassers = [for user in data.github_user.pull_request_bypassers : user.node_id]
}

# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/branch_protection
resource "github_branch_protection" "main" {
enforce_admins = var.github_enforce_admins_branch_protection
pattern = var.github_default_branch
push_restrictions = var.github_push_restrictions
repository_id = github_repository.repo.node_id
required_pull_request_reviews {
dismiss_stale_reviews = var.github_dismiss_stale_reviews
require_code_owner_reviews = var.github_require_code_owner_reviews
required_approving_review_count = var.github_required_approving_review_count
pull_request_bypassers = local.pull_request_bypassers
}
lifecycle {
ignore_changes = [
required_status_checks[0].contexts
]
}

dynamic "required_status_checks" {
# A bogus map for a conditional block
for_each = length(var.required_status_checks) > 0 ? ["*"] : []
content {
contexts = var.required_status_checks
strict = true
}
}

depends_on = [
# first let the automation create the codeowners and backend file then only create branch protection rule
# if branch protection rule is created first, codeowners will fail
github_repository_file.codeowners,
github_repository_file.extra_files
]
}
29 changes: 29 additions & 0 deletions github_files.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository_file
resource "github_repository_file" "codeowners" {
repository = github_repository.repo.name
branch = var.github_default_branch
file = "CODEOWNERS"
content = templatefile("${path.module}/templates/CODEOWNERS", { codeowners = local.codeowners })
overwrite_on_create = true
lifecycle {
ignore_changes = [
content,
branch
]
}
}

resource "github_repository_file" "extra_files" {
for_each = tomap({ for file in var.extra_files : "${element(split("/", file.path), length(split("/", file.path)) - 1)}" => file })
repository = github_repository.repo.name
branch = var.github_default_branch
file = each.value.path
content = each.value.content
overwrite_on_create = true
lifecycle {
ignore_changes = [
content,
branch
]
}
}
36 changes: 36 additions & 0 deletions github_repo.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
locals {
repo_name = var.force_name ? var.name : "${var.name}-${formatdate("YYYYMMDD", timestamp())}"
}
resource "github_repository" "repo" {
name = local.repo_name
description = var.github_repo_description
visibility = var.github_is_private ? "private" : "public"
auto_init = var.github_auto_init
allow_merge_commit = var.github_allow_merge_commit
allow_squash_merge = var.github_allow_squash_merge
allow_rebase_merge = var.github_allow_rebase_merge
archive_on_destroy = true
delete_branch_on_merge = var.github_delete_branch_on_merge
has_projects = var.github_has_projects
has_issues = var.github_has_issues
has_wiki = var.github_has_wiki
topics = var.github_repo_topics
gitignore_template = "Terraform"
is_template = var.is_template
archived = var.archived
lifecycle {
ignore_changes = [
name
]
}
dynamic "template" {
# A bogus map for a conditional block
for_each = var.template_repo == null ? [] : ["*"]
content {
owner = var.template_repo_org
repository = var.template_repo
# include_all_branches = var.template_include_all_branches
}
}
}
27 changes: 27 additions & 0 deletions github_team_access.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/repository
data "github_organization_teams" "root_teams" {
count = var.github_org_teams == null ? 1 : 0
root_teams_only = false
}

locals {
github_org_teams = var.github_org_teams == null ? data.github_organization_teams.root_teams[0].teams : var.github_org_teams
github_teams = { for obj in local.github_org_teams : "${obj.slug}" => obj.id }
}

# data "github_team" "nit_admin" {
# slug = "nit"
# }

# https://registry.terraform.io/providers/integrations/github/latest/docs/resources/team_repository
resource "github_team_repository" "admin" {
for_each = toset(var.admin_teams)
team_id = lookup(local.github_teams, each.value)
repository = github_repository.repo.name
permission = "admin"
lifecycle {
ignore_changes = [
team_id
]
}
}
3 changes: 3 additions & 0 deletions outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
output "github_repo" {
value = github_repository.repo
}
4 changes: 4 additions & 0 deletions templates/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# These owners will be the default owners for everything in the repo. Unless a later match takes precedence
%{ for codeowner in codeowners ~}
* @${codeowner}
%{ endfor ~}
154 changes: 154 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
variable "name" {
description = "Name of the terraform workspace and optionally github repo"
}

variable "repo_org" {
default = null
}

variable "github_codeowners_team" {
default = "terraform-reviewers"
}

variable "github_repo_description" {
default = "Terraform Workspace"
}

variable "github_repo_topics" {
description = "Github Repo Topics"
type = list(any)
default = []
}

variable "github_push_restrictions" {
description = "Github Push Restrictions"
type = list(any)
default = []
}
variable "github_is_private" {
default = true
}
variable "github_auto_init" {
default = true
}
variable "github_allow_merge_commit" {
default = false
}
variable "github_allow_squash_merge" {
default = true
}
variable "github_allow_rebase_merge" {
default = false
}
variable "github_delete_branch_on_merge" {
default = true
}
variable "github_has_projects" {
default = true
}
variable "github_has_issues" {
default = false
}
variable "github_has_wiki" {
default = true
}
variable "github_default_branch" {
default = "main"
}
variable "github_required_approving_review_count" {
default = 1
}
variable "github_require_code_owner_reviews" {
default = true
}
variable "github_dismiss_stale_reviews" {
default = true
}
variable "github_enforce_admins_branch_protection" {
default = true
}

variable "additional_codeowners" {
description = "Enable adding of Codeowner Teams"
type = list(any)
default = []
}

variable "prefix" {
default = null
}

variable "force_name" {
description = "Force Naming of Repo. If forced, archive management will not operate on this repo"
default = false
}

variable "github_org_teams" {
type = list(any)
description = "provide module with list of teams so that module does not need to look them up"
default = null
}

variable "template_repo_org" {
default = null
}

variable "template_repo" {
default = null
}

variable "is_template" {
default = false
}


variable "admin_teams" {
description = "Admin Teams"
type = list(any)
default = []
}


variable "required_status_checks" {
description = "Required Status Checks"
type = list(any)
default = []
}

variable "archived" {
default = false
}

variable "secrets" {
type = list(object({
name = string,
value = string
}))
default = []
description = "Github Action Secrets"
}

variable "vars" {
type = list(object({
name = string,
value = string
}))
default = []
description = "Github Action Vars"
}

variable "extra_files" {
type = list(object({
path = string,
content = string
}))
default = []
description = "Extra Files"
}


variable "pull_request_bypassers" {
default = []
type = list(any)
}

0 comments on commit ada3691

Please sign in to comment.