diff --git a/terraform/main.tf b/terraform/main.tf index 9170792..9a6bd07 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -4,43 +4,30 @@ locals { allowed_top_level_keys = ["repositories"] allowed_repository_keys = ["name", "description", "homepage_url", "topics", "is_template", "template"] - repository_defaults = { - description = null - homepage_url = null - topics = null - is_template = null - template = null - } - repositories = try({ for repository in local.config.repositories : - repository.name => merge(local.repository_defaults, repository) + repository.name => repository }, {}) } -resource "github_repository" "this" { +module "repository" { + source = "./modules/repository" for_each = local.repositories - name = each.key - - # Metadata - description = each.value.description - homepage_url = each.value.homepage_url - topics = each.value.topics - - # Properties - archive_on_destroy = true - delete_branch_on_merge = true - is_template = each.value.is_template + repository = each.value +} - # Contents - dynamic "template" { - for_each = each.value.template == null ? [] : [each.value.template] +# Keep until every workspace has applied this. +removed { + from = github_repository.this - content { - owner = template.value.owner - repository = template.value.repository - include_all_branches = try(template.value.include_all_branches, false) - } + lifecycle { + destroy = false } } + +import { + for_each = local.repositories + to = module.repository[each.key].github_repository.this + id = each.key +} diff --git a/terraform/modules/repository/config.tf b/terraform/modules/repository/config.tf new file mode 100644 index 0000000..342e8c6 --- /dev/null +++ b/terraform/modules/repository/config.tf @@ -0,0 +1,10 @@ +terraform { + required_version = "~> 1.14" + + required_providers { + github = { + source = "integrations/github" + version = "~> 6.0" + } + } +} diff --git a/terraform/modules/repository/main.tf b/terraform/modules/repository/main.tf new file mode 100644 index 0000000..1e1eb9c --- /dev/null +++ b/terraform/modules/repository/main.tf @@ -0,0 +1,24 @@ +resource "github_repository" "this" { + name = var.repository.name + + # Metadata + description = var.repository.description + homepage_url = var.repository.homepage_url + topics = var.repository.topics + + # Properties + archive_on_destroy = true + delete_branch_on_merge = true + is_template = var.repository.is_template + + # Contents + dynamic "template" { + for_each = var.repository.template == null ? [] : [var.repository.template] + + content { + owner = template.value.owner + repository = template.value.repository + include_all_branches = template.value.include_all_branches + } + } +} diff --git a/terraform/modules/repository/outputs.tf b/terraform/modules/repository/outputs.tf new file mode 100644 index 0000000..ec58353 --- /dev/null +++ b/terraform/modules/repository/outputs.tf @@ -0,0 +1,4 @@ +output "repository" { + value = github_repository.this + description = "Repository resource" +} diff --git a/terraform/modules/repository/variables.tf b/terraform/modules/repository/variables.tf new file mode 100644 index 0000000..0c7c86d --- /dev/null +++ b/terraform/modules/repository/variables.tf @@ -0,0 +1,15 @@ +variable "repository" { + type = object({ + name = string + description = optional(string) + homepage_url = optional(string) + topics = optional(list(string)) + is_template = optional(bool) + template = optional(object({ + owner = string + repository = string + include_all_branches = optional(bool, false) + })) + }) + description = "Repository configuration" +} diff --git a/terraform/tests/repositories.tftest.hcl b/terraform/tests/repositories.tftest.hcl index 9526d05..2e1c4a9 100644 --- a/terraform/tests/repositories.tftest.hcl +++ b/terraform/tests/repositories.tftest.hcl @@ -1,5 +1,26 @@ mock_provider "github" {} +override_resource { + target = module.repository["bar"].github_repository.this + values = { + id = "bar" + } +} + +override_resource { + target = module.repository["baz"].github_repository.this + values = { + id = "baz" + } +} + +override_resource { + target = module.repository["foo"].github_repository.this + values = { + id = "foo" + } +} + run "repositories_missing" { command = plan @@ -108,7 +129,7 @@ run "one_repository" { } assert { - condition = keys(github_repository.this) == ["foo"] + condition = keys(module.repository) == ["foo"] error_message = "Expected repository foo." } } @@ -121,7 +142,7 @@ run "several_repositories" { } assert { - condition = keys(github_repository.this) == ["bar", "baz", "foo"] + condition = keys(module.repository) == ["bar", "baz", "foo"] error_message = "Expected repositories bar, baz, foo." } } diff --git a/terraform/tests/test-yaml.tftest.hcl b/terraform/tests/test-yaml.tftest.hcl index f3b8054..4778316 100644 --- a/terraform/tests/test-yaml.tftest.hcl +++ b/terraform/tests/test-yaml.tftest.hcl @@ -1,5 +1,26 @@ mock_provider "github" {} +override_resource { + target = module.repository[".github"].github_repository.this + values = { + id = ".github" + } +} + +override_resource { + target = module.repository["template"].github_repository.this + values = { + id = "template" + } +} + +override_resource { + target = module.repository["template-use"].github_repository.this + values = { + id = "template-use" + } +} + run "test_yaml" { command = plan @@ -8,32 +29,45 @@ run "test_yaml" { } assert { - condition = keys(github_repository.this) == [".github", "template", "template-use"] + condition = keys(module.repository) == [".github", "template", "template-use"] error_message = "Expected repositories .github, template, template-use." } assert { - condition = startswith(github_repository.this[".github"].description, "BruzIT Test organization profile") + condition = startswith(module.repository[".github"].repository.description, "BruzIT Test organization profile") error_message = "Unexpected .github description." } assert { - condition = contains(github_repository.this[".github"].topics, "terraform") && length(github_repository.this[".github"].topics) == 10 + condition = contains(module.repository[".github"].repository.topics, "terraform") && length(module.repository[".github"].repository.topics) == 10 error_message = "Unexpected .github topics." } assert { - condition = github_repository.this["template"].is_template && github_repository.this["template"].topics == toset(["repository-template"]) + condition = module.repository["template"].repository.is_template && module.repository["template"].repository.topics == toset(["repository-template"]) error_message = "Unexpected template is_template or topics." } assert { - condition = github_repository.this["template-use"].template[0].owner == "bruzit-test" && github_repository.this["template-use"].template[0].repository == "template" && !github_repository.this["template-use"].template[0].include_all_branches + condition = module.repository["template-use"].repository.template[0].owner == "bruzit-test" && module.repository["template-use"].repository.template[0].repository == "template" && !module.repository["template-use"].repository.template[0].include_all_branches error_message = "Unexpected template-use template." } assert { - condition = alltrue([for r in github_repository.this : r.archive_on_destroy && r.delete_branch_on_merge]) + condition = alltrue([for m in module.repository : m.repository.archive_on_destroy && m.repository.delete_branch_on_merge]) error_message = "Every repository must archive on destroy and delete branches on merge." } } + +run "test_yaml_import" { + command = plan + + variables { + config = "../test.yaml" + } + + assert { + condition = alltrue([for k, m in module.repository : m.repository.id == k]) + error_message = "Every repository must be imported, not created." + } +}