From c68e90c7bf78f4993931da3ddde67763e927f438 Mon Sep 17 00:00:00 2001 From: Soren Martius Date: Tue, 25 Feb 2020 10:05:29 +0100 Subject: [PATCH 1/4] split up tests and extend examples --- examples/private-repository-with-team/main.tf | 55 +++++---- .../private-repository-with-team/outputs.tf | 9 ++ .../private-repository-with-team/variables.tf | 104 ++++++++++++++++++ .../private-repository-with-team/versions.tf | 11 ++ .../outputs.tf | 0 .../variables.tf | 0 .../outputs.tf | 0 .../variables.tf | 0 examples/public-repository/main.tf | 37 ------- test/complete_example_test.go | 38 +++++++ test/github_repository_test.go | 68 ------------ test/test_helper.gp.go | 1 + 12 files changed, 190 insertions(+), 133 deletions(-) create mode 100644 examples/private-repository-with-team/outputs.tf create mode 100644 examples/private-repository-with-team/variables.tf create mode 100644 examples/private-repository-with-team/versions.tf create mode 100644 examples/public-repository-complete-example/outputs.tf create mode 100644 examples/public-repository-complete-example/variables.tf create mode 100644 examples/public-repository-with-collaborators/outputs.tf create mode 100644 examples/public-repository-with-collaborators/variables.tf delete mode 100644 examples/public-repository/main.tf create mode 100644 test/complete_example_test.go delete mode 100644 test/github_repository_test.go create mode 100644 test/test_helper.gp.go diff --git a/examples/private-repository-with-team/main.tf b/examples/private-repository-with-team/main.tf index 90e8bdae..44952a6f 100644 --- a/examples/private-repository-with-team/main.tf +++ b/examples/private-repository-with-team/main.tf @@ -1,26 +1,25 @@ -terraform { - required_version = "~> 0.12.9" -} - -provider "github" { - version = ">= 2.3.1, < 3.0.0" -} +# --------------------------------------------------------------------------------------------------------------------- +# CREATE A PRIVATE REPOSITORY WITH AN ATTACHED TEAM +# - create a private repository +# - create a team and invite members +# - add the team to the repository and grant admin permissions +# --------------------------------------------------------------------------------------------------------------------- module "repository" { source = "../.." - name = "private-repository-with-teams" - description = "A private repository created with terraform to test the terraform-github-repository module." - homepage_url = "https://github.com/mineiros-io" + name = var.name + description = var.description + homepage_url = var.homepage_url private = true - has_issues = true - has_projects = true - has_wiki = true - allow_merge_commit = true - allow_rebase_merge = true - allow_squash_merge = true - has_downloads = false - auto_init = true + has_issues = var.has_issues + has_projects = var.has_projects + has_wiki = var.has_wiki + allow_merge_commit = var.allow_merge_commit + allow_rebase_merge = var.allow_rebase_merge + allow_squash_merge = var.allow_squash_merge + has_downloads = var.has_downloads + auto_init = var.auto_init gitignore_template = "Terraform" license_template = "mit" archived = false @@ -43,37 +42,37 @@ module "repository" { required_pull_request_reviews = { dismiss_stale_reviews = true - dismissal_users = ["terraform-test-user-1"] + dismissal_users = var.members dismissal_teams = [github_team.team.slug] require_code_owner_reviews = true required_approving_review_count = 1 } restrictions = { - users = ["terraform-test-user-1"] - teams = ["team-1"] + users = var.members + teams = [github_team.team.slug] } } ] } resource "github_team" "team" { - name = "private-repository-with-teams-test-team" - description = "This team is created with terraform to test the terraformn-github-repository module." + name = var.team_name + description = var.team_description privacy = "secret" } # --------------------------------------------------------------------------------------------------------------------- # TEAM MEMBERSHIP -# We are adding two members to this team. terraform-test-user-1 and terraform-test-user-2 which are both existing users -# and already members of the GitHub Organization terraform-test that is an Organization managed by Mineiros.io to run -# integration tests with Terragrunt. +# We are adding two members to this team. terraform-test-user-1 and terraform-test-user-2 that we define as default +# members in our variables.tf are both existing users and already members of the GitHub Organization terraform-test that +# is an Organization managed by Mineiros.io to run integration tests with Terratest. # --------------------------------------------------------------------------------------------------------------------- resource "github_team_membership" "team_membership" { - count = 2 + count = length(var.members) team_id = github_team.team.id - username = "terraform-test-user-${count.index}" + username = var.members[count.index] role = "member" } diff --git a/examples/private-repository-with-team/outputs.tf b/examples/private-repository-with-team/outputs.tf new file mode 100644 index 00000000..5dd0538b --- /dev/null +++ b/examples/private-repository-with-team/outputs.tf @@ -0,0 +1,9 @@ +output "repository" { + description = "All outputs of the repository." + value = module.repository +} + +output "team" { + description = "All outputs of the team." + value = github_team.team +} diff --git a/examples/private-repository-with-team/variables.tf b/examples/private-repository-with-team/variables.tf new file mode 100644 index 00000000..d303c7d1 --- /dev/null +++ b/examples/private-repository-with-team/variables.tf @@ -0,0 +1,104 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables. +# --------------------------------------------------------------------------------------------------------------------- + +# GITHUB_ORGANIZATION +# GITHUB_TOKEN + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL VARIABLES +# These variables have defaults, but may be overridden. +# --------------------------------------------------------------------------------------------------------------------- + +variable "name" { + type = string + description = "The name of the repository." + default = "private-test-repository-with-admin-team" +} + +variable "description" { + type = string + description = "A description of the repository." + default = "A private repository created with terraform to test the terraform-github-repository module." +} + +variable "homepage_url" { + description = "The website of the repository." + type = string + default = "https://github.com/mineiros-io" +} + +variable "has_issues" { + description = "Set to true to enable the GitHub Issues features on the repository. (Default: false)" + type = bool + default = true +} + +variable "has_projects" { + description = "Set to true to enable the GitHub Projects features on the repository. Per the github documentation when in an organization that has disabled repository projects it will default to false and will otherwise default to true. If you specify true when it has been disabled it will return an error. (Default: false)" + type = bool + default = true +} + +variable "has_wiki" { + description = "Set to true to enable the GitHub Wiki features on the repository. (Default: false)" + type = bool + default = true +} + +variable "allow_merge_commit" { + description = "Set to false to disable merge commits on the repository. (Default: true)" + type = bool + default = true +} + +variable "allow_squash_merge" { + description = "Set to true to enable squash merges on the repository. (Default: false)" + type = bool + default = true +} + +variable "allow_rebase_merge" { + description = "Set to true to enable rebase merges on the repository. (Default: false)" + type = bool + default = true +} + +variable "has_downloads" { + description = "Set to true to enable the (deprecated) downloads features on the repository. (Default: false)" + type = bool + default = false +} + +variable "auto_init" { + description = "Wether or not to produce an initial commit in the repository. (Default: true)" + type = bool + default = true +} + +variable "members" { + description = "A list of members to add to the team." + type = list(string) + default = [ + "terraform-test-user-1", + "terraform-test-user-2" + ] +} + +variable "team_name" { + description = "The name of the created team." + type = string + default = "private-repository-with-teams-test-team" +} + +variable "team_description" { + description = "The description of the created team." + type = string + default = "This team is created with terraform to test the terraformn-github-repository module." +} diff --git a/examples/private-repository-with-team/versions.tf b/examples/private-repository-with-team/versions.tf new file mode 100644 index 00000000..068d0598 --- /dev/null +++ b/examples/private-repository-with-team/versions.tf @@ -0,0 +1,11 @@ +# --------------------------------------------------------------------------------------------------------------------- +# SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE +# --------------------------------------------------------------------------------------------------------------------- + +terraform { + required_version = ">= 0.12.9" + + required_providers { + github = ">= 2.3.1, < 3.0.0" + } +} diff --git a/examples/public-repository-complete-example/outputs.tf b/examples/public-repository-complete-example/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/examples/public-repository-complete-example/variables.tf b/examples/public-repository-complete-example/variables.tf new file mode 100644 index 00000000..e69de29b diff --git a/examples/public-repository-with-collaborators/outputs.tf b/examples/public-repository-with-collaborators/outputs.tf new file mode 100644 index 00000000..e69de29b diff --git a/examples/public-repository-with-collaborators/variables.tf b/examples/public-repository-with-collaborators/variables.tf new file mode 100644 index 00000000..e69de29b diff --git a/examples/public-repository/main.tf b/examples/public-repository/main.tf deleted file mode 100644 index 7a019f17..00000000 --- a/examples/public-repository/main.tf +++ /dev/null @@ -1,37 +0,0 @@ -terraform { - required_version = "~> 0.12.9" -} - -provider "github" { - version = ">= 2.3.1, < 3.0.0" -} - -provider "random" { - version = "= 2.2.1" -} - -resource "random_pet" "suffix" { - length = 1 -} - -module "repository" { - source = "../.." - - name = "test-public-repository-${random_pet.suffix.id}" - description = "A public repository created with terraform to test the terraform-github-repository module." - homepage_url = "https://github.com/mineiros-io" - private = false - has_issues = false - has_projects = false - has_wiki = false - allow_merge_commit = false - allow_rebase_merge = false - allow_squash_merge = true - has_downloads = false - auto_init = true - gitignore_template = "Terraform" - license_template = "mit" - archived = false - topics = ["terraform", "integration-test"] - -} diff --git a/test/complete_example_test.go b/test/complete_example_test.go new file mode 100644 index 00000000..86b6e367 --- /dev/null +++ b/test/complete_example_test.go @@ -0,0 +1,38 @@ +package test + +import ( + "github.com/gruntwork-io/terratest/modules/terraform" + "os" + "testing" +) + +func init() { + githubOrganization := os.Getenv("GITHUB_ORGANIZATION") + githubToken := os.Getenv("GITHUB_TOKEN") + + if githubOrganization == "" { + panic("Please set a github organization using the GITHUB_ORGANIZATION environment variable.") + } + + if githubToken == "" { + panic("Please set a github token using the GITHUB_TOKEN environment variable.") + } +} + + + +func TestGithubPublicRepositoryCompleteExample(t *testing.T) { + t.Parallel() + + terraformOptions := &terraform.Options{ + // The path to where your Terraform code is located + TerraformDir: "../examples/public-repository-complete-example", + Upgrade: true, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) +} diff --git a/test/github_repository_test.go b/test/github_repository_test.go deleted file mode 100644 index 91808013..00000000 --- a/test/github_repository_test.go +++ /dev/null @@ -1,68 +0,0 @@ -package test - -import ( - "github.com/gruntwork-io/terratest/modules/terraform" - "os" - "testing" -) - -func init() { - githubOrganization := os.Getenv("GITHUB_ORGANIZATION") - githubToken := os.Getenv("GITHUB_TOKEN") - - if githubOrganization == "" { - panic("Please set a github organization using the GITHUB_ORGANIZATION environment variable.") - } - - if githubToken == "" { - panic("Please set a github token using the GITHUB_TOKEN environment variable.") - } -} - -func TestGithubPublicRepository(t *testing.T) { - t.Parallel() - - terraformOptions := &terraform.Options{ - // The path to where your Terraform code is located - TerraformDir: "../examples/public-repository", - Upgrade: true, - } - - // At the end of the test, run `terraform destroy` to clean up any resources that were created - defer terraform.Destroy(t, terraformOptions) - - // This will run `terraform init` and `terraform apply` and fail the test if there are any errors - terraform.InitAndApply(t, terraformOptions) -} - -func TestGithubPublicRepositoryWithCollaborators(t *testing.T) { - t.Parallel() - - terraformOptions := &terraform.Options{ - // The path to where your Terraform code is located - TerraformDir: "../examples/public-repository-with-collaborators", - Upgrade: true, - } - - // At the end of the test, run `terraform destroy` to clean up any resources that were created - defer terraform.Destroy(t, terraformOptions) - - // This will run `terraform init` and `terraform apply` and fail the test if there are any errors - terraform.InitAndApply(t, terraformOptions) -} - -func TestGithubPublicRepositoryCompleteExample(t *testing.T) { - t.Parallel() - - terraformOptions := &terraform.Options{ - // The path to where your Terraform code is located - TerraformDir: "../examples/public-repository-complete-example", - Upgrade: true, - } - - // At the end of the test, run `terraform destroy` to clean up any resources that were created - defer terraform.Destroy(t, terraformOptions) - - // This will run `terraform init` and `terraform apply` and fail the test if there are any errors - terraform.InitAndApply(t, terraformOptions) -} diff --git a/test/test_helper.gp.go b/test/test_helper.gp.go new file mode 100644 index 00000000..56e54040 --- /dev/null +++ b/test/test_helper.gp.go @@ -0,0 +1 @@ +package test From bcff992cf9e5352065891a37e688cffbbb49e198 Mon Sep 17 00:00:00 2001 From: Soren Martius Date: Tue, 25 Feb 2020 10:20:56 +0100 Subject: [PATCH 2/4] add golang pre-commit hooks --- .pre-commit-config.yaml | 5 ++++- examples/private-repository-with-team/versions.tf | 11 ----------- 2 files changed, 4 insertions(+), 12 deletions(-) delete mode 100644 examples/private-repository-with-team/versions.tf diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5bb15bbc..ff042720 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,10 @@ repos: - repo: https://github.com/mineiros-io/pre-commit-hooks - rev: v0.0.5 + rev: v0.1.0 hooks: - id: terraform-fmt - id: terraform-validate - id: tflint + - id: gofmt + - id: goimports + - id: golint diff --git a/examples/private-repository-with-team/versions.tf b/examples/private-repository-with-team/versions.tf deleted file mode 100644 index 068d0598..00000000 --- a/examples/private-repository-with-team/versions.tf +++ /dev/null @@ -1,11 +0,0 @@ -# --------------------------------------------------------------------------------------------------------------------- -# SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE -# --------------------------------------------------------------------------------------------------------------------- - -terraform { - required_version = ">= 0.12.9" - - required_providers { - github = ">= 2.3.1, < 3.0.0" - } -} From 1b2e8908604963a9c8bbba10ba3077abedeeb576 Mon Sep 17 00:00:00 2001 From: Soren Martius Date: Tue, 25 Feb 2020 10:31:27 +0100 Subject: [PATCH 3/4] use sets instead of lists of unique parameters --- variables.tf | 114 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 68 insertions(+), 46 deletions(-) diff --git a/variables.tf b/variables.tf index 2f91f163..b75f9436 100644 --- a/variables.tf +++ b/variables.tf @@ -1,3 +1,26 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables. +# --------------------------------------------------------------------------------------------------------------------- + +# GITHUB_ORGANIZATION +# GITHUB_TOKEN + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +variable "name" { + type = string + description = "The name of the repository." +} + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL VARIABLES +# These variables have defaults, but may be overridden. +# --------------------------------------------------------------------------------------------------------------------- + variable "defaults" { type = any description = "Overwrite defaults for various repository settings" @@ -22,184 +45,180 @@ variable "defaults" { # } } -variable "name" { - type = string - description = "The name of the repository." -} - variable "description" { - type = string description = "A description of the repository." + type = string default = "" } variable "homepage_url" { + description = "The website of the repository." type = string - description = "homepage_url" default = null } variable "private" { - type = bool description = "Set to false to create a public repository. (Default: true)" + type = bool default = null } variable "has_issues" { - type = bool description = "Set to true to enable the GitHub Issues features on the repository. (Default: false)" + type = bool default = null } variable "has_projects" { - type = bool description = "Set to true to enable the GitHub Projects features on the repository. Per the github documentation when in an organization that has disabled repository projects it will default to false and will otherwise default to true. If you specify true when it has been disabled it will return an error. (Default: false)" + type = bool default = null } variable "has_wiki" { - type = bool description = "Set to true to enable the GitHub Wiki features on the repository. (Default: false)" + type = bool default = null } variable "allow_merge_commit" { - type = bool description = "Set to false to disable merge commits on the repository. (Default: true)" + type = bool default = null } variable "allow_squash_merge" { - type = bool description = "Set to true to enable squash merges on the repository. (Default: false)" + type = bool default = null } variable "allow_rebase_merge" { - type = bool description = "Set to true to enable rebase merges on the repository. (Default: false)" + type = bool default = null } variable "has_downloads" { - type = bool description = "Set to true to enable the (deprecated) downloads features on the repository. (Default: false)" + type = bool default = null } variable "auto_init" { - type = bool description = "Wether or not to produce an initial commit in the repository. (Default: true)" + type = bool default = null } variable "gitignore_template" { - type = string description = "Use the name of the template without the extension. For example, Haskell. Available templates: https://github.com/github/gitignore" + type = string default = null } variable "license_template" { - type = string description = "Use the name of the template without the extension. For example, 'mit' or 'mpl-2.0'. Available licences: https://github.com/github/choosealicense.com/tree/gh-pages/_licenses" + type = string default = null } variable "default_branch" { - type = string description = "The name of the default branch of the repository. NOTE: This can only be set after a repository has already been created, and after a correct reference has been created for the target branch inside the repository. This means a user will have to omit this parameter from the initial repository creation and create the target branch inside of the repository prior to setting this attribute." + type = string default = null } variable "archived" { - type = bool description = "Specifies if the repository should be archived. (Default: false)" + type = bool default = false } variable "topics" { - type = list(string) description = "The list of topics of the repository. (Default: [])" + type = set(string) default = null } variable "extra_topics" { - type = list(string) description = "The list of additional topics of the repository. (Default: [])" + type = set(string) default = [] } variable "template" { + description = "Template repository to use. (Default: {})" type = object({ owner = string repository = string }) - description = "Template repository to use. (Default: {})" - default = null + default = null } variable "admin_collaborators" { - type = list(string) description = "A list of users to add as collaborators granting them admin (full) permission." + type = set(string) default = [] } variable "push_collaborators" { - type = list(string) description = "A list of users to add as collaborators granting them push (read-write) permission." + type = set(string) default = [] } variable "pull_collaborators" { - type = list(string) description = "A list of users to add as collaborators granting them pull (read-only) permission." + type = set(string) default = [] } variable "triage_collaborators" { - type = list(string) description = "A list of users to add as collaborators granting them triage permission." + type = set(string) default = [] } variable "maintain_collaborators" { - type = list(string) description = "A list of users to add as collaborators granting them maintain permission." + type = set(string) default = [] } variable "admin_team_ids" { - type = list(string) description = "A list of teams (by id) to grant admin (full) permission to." + type = set(string) default = [] } variable "push_team_ids" { - type = list(string) description = "A list of teams (by id) to grant push (read-write) permission to." + type = set(string) default = [] } variable "pull_team_ids" { - type = list(string) description = "A list of teams (by id) to grant pull (read-only) permission to." + type = set(string) default = [] } variable "triage_team_ids" { - type = list(string) description = "A list of teams (by id) to grant triage permission to." + type = set(string) default = [] } variable "maintain_team_ids" { - type = list(string) description = "A list of teams (by id) to grant maintain permission to." + type = set(string) default = [] } variable "branch_protections" { - type = any + description = "Configuring protected branches. For details please check: https://www.terraform.io/docs/providers/github/r/branch_protection.html" + type = any # We can't use a detailed type specification due to a terraform limitation. However, this might be changed in a future # Terraform version. See https://github.com/hashicorp/terraform/issues/19898 and https://github.com/hashicorp/terraform/issues/22449 @@ -225,8 +244,7 @@ variable "branch_protections" { # }) # })) - description = "Configuring protected branches. For details please check: https://www.terraform.io/docs/providers/github/r/branch_protection.html" - default = [] + default = [] # Example: # branch_protections = [ @@ -257,19 +275,18 @@ variable "branch_protections" { } variable "issue_labels_merge_with_github_labels" { - type = bool description = "Specify if you want to merge and control githubs default set of issue labels." + type = bool default = null } variable "issue_labels" { + description = "Configure a GitHub issue label resource." type = list(object({ name = string description = string color = string })) - description = "Configure a GitHub issue label resource." - default = [] # Example: # issue_labels = [ @@ -284,12 +301,13 @@ variable "issue_labels" { # color = "1dc34f" # } # ] + + default = [] } variable "deploy_keys" { - type = any description = "Configure a deploy key ( SSH key ) that grants access to a single GitHub repository. This key is attached directly to the repository instead of to a personal user account." - default = [] + type = any # Example: # deploy_keys = [ @@ -304,12 +322,13 @@ variable "deploy_keys" { # read_only = false # } # ] + + default = [] } variable "deploy_keys_computed" { - type = any description = "Configure a deploy key ( SSH key ) that grants access to a single GitHub repository. This key is attached directly to the repository instead of to a personal user account." - default = [] + type = any # Example: # deploy_keys_computed = [ @@ -319,15 +338,16 @@ variable "deploy_keys_computed" { # read_only = true # } # ] + + default = [] } variable "projects" { + description = "Create and manage projects for GitHub repository." type = list(object({ name = string body = string })) - description = "Create and manage projects for GitHub repository." - default = [] # Example: # projects = [ @@ -336,4 +356,6 @@ variable "projects" { # body = "This is a fancy test project for testing" # } # ] + + default = [] } From 325e8117a4018b29db4fe36e163739547871211c Mon Sep 17 00:00:00 2001 From: Soren Martius Date: Tue, 25 Feb 2020 10:34:54 +0100 Subject: [PATCH 4/4] make examples and tests configurable --- Makefile | 9 +- README.md | 4 +- examples/private-repository-with-team/main.tf | 14 +- .../private-repository-with-team/variables.tf | 16 +- .../main.tf | 146 ++++++-------- .../outputs.tf | 46 +++++ .../variables.tf | 184 ++++++++++++++++++ .../main.tf | 54 +++-- .../outputs.tf | 19 ++ .../variables.tf | 108 ++++++++++ go.mod | 5 +- main.tf | 52 +++-- test/complete_example_test.go | 38 ---- ...public_repository_complete_example_test.go | 122 ++++++++++++ ...blic_repository_with_collaborators_test.go | 64 ++++++ test/test_helper.gp.go | 1 - test/test_helpers.go | 18 ++ variables.tf | 31 +-- versions.tf | 6 +- 19 files changed, 735 insertions(+), 202 deletions(-) delete mode 100644 test/complete_example_test.go create mode 100644 test/public_repository_complete_example_test.go create mode 100644 test/public_repository_with_collaborators_test.go delete mode 100644 test/test_helper.gp.go create mode 100644 test/test_helpers.go diff --git a/Makefile b/Makefile index 0e932ad5..80beb664 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,6 @@ +# Set default shell to bash +SHELL := /bin/bash + MOUNT_TARGET_DIRECTORY = /app/src BUILD_TOOLS_DOCKER_REPO = mineiros/build-tools @@ -37,7 +40,7 @@ docker/pre-commit-hooks: @docker run --rm \ -v ${PWD}:${MOUNT_TARGET_DIRECTORY} \ ${BUILD_TOOLS_DOCKER_IMAGE} \ - sh -c "pre-commit install && pre-commit run --all-files" + sh -c "pre-commit run -a" ## Mounts the working directory inside a new container and runs the Go tests. Requires $GITHUB_TOKEN and $GITHUB_ORGANIZATION to be set docker/unit-tests: @@ -47,6 +50,6 @@ docker/unit-tests: -e GITHUB_ORGANIZATION \ -v ${PWD}:${MOUNT_TARGET_DIRECTORY} \ ${BUILD_TOOLS_DOCKER_IMAGE} \ - go test -v -timeout 10m -parallel 128 test/github_repository_test.go + go test -v -timeout 10m -parallel 128 ./test -.PHONY: help docker/pre-commit-hooks docker/run-tests +.PHONY: help docker/pre-commit-hooks docker/unit-tests diff --git a/README.md b/README.md index 8ca88779..e1b29324 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ features like Branch Protection or Collaborator Management. Gitignore Template, Template Repository -- **Extended S3 Features**: +- **Extended Repository Features**: Branch Protection, Issue Labels, Handle Github Default Issue Labels, @@ -424,7 +424,7 @@ Given a version number `MAJOR.MINOR.PATCH`, we increment the: 2) `MINOR` version when we add functionality in a backwards compatible manner, and 3) `PATCH` version when we make backwards compatible bug fixes. -#### Backwards compatibility in `0.0.z` and `0.y.z` version +### Backwards compatibility in `0.0.z` and `0.y.z` version - Backwards compatibility in versions `0.0.z` is **not guaranteed** when `z` is increased. (Initial development) - Backwards compatibility in versions `0.y.z` is **not guaranteed** when `y` is increased. (Pre-release) diff --git a/examples/private-repository-with-team/main.tf b/examples/private-repository-with-team/main.tf index 44952a6f..fa80cbf4 100644 --- a/examples/private-repository-with-team/main.tf +++ b/examples/private-repository-with-team/main.tf @@ -1,9 +1,21 @@ -# --------------------------------------------------------------------------------------------------------------------- +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # CREATE A PRIVATE REPOSITORY WITH AN ATTACHED TEAM # - create a private repository # - create a team and invite members # - add the team to the repository and grant admin permissions +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# --------------------------------------------------------------------------------------------------------------------- +# SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE # --------------------------------------------------------------------------------------------------------------------- +terraform { + required_version = ">= 0.12.9" + + required_providers { + github = ">= 2.3.1, < 3.0.0" + } +} + module "repository" { source = "../.." diff --git a/examples/private-repository-with-team/variables.tf b/examples/private-repository-with-team/variables.tf index d303c7d1..43395a3b 100644 --- a/examples/private-repository-with-team/variables.tf +++ b/examples/private-repository-with-team/variables.tf @@ -35,49 +35,49 @@ variable "homepage_url" { } variable "has_issues" { - description = "Set to true to enable the GitHub Issues features on the repository. (Default: false)" + description = "Set to true to enable the GitHub Issues features on the repository." type = bool default = true } variable "has_projects" { - description = "Set to true to enable the GitHub Projects features on the repository. Per the github documentation when in an organization that has disabled repository projects it will default to false and will otherwise default to true. If you specify true when it has been disabled it will return an error. (Default: false)" + description = "Set to true to enable the GitHub Projects features on the repository." type = bool default = true } variable "has_wiki" { - description = "Set to true to enable the GitHub Wiki features on the repository. (Default: false)" + description = "Set to true to enable the GitHub Wiki features on the repository." type = bool default = true } variable "allow_merge_commit" { - description = "Set to false to disable merge commits on the repository. (Default: true)" + description = "Set to false to disable merge commits on the repository." type = bool default = true } variable "allow_squash_merge" { - description = "Set to true to enable squash merges on the repository. (Default: false)" + description = "Set to true to enable squash merges on the repository." type = bool default = true } variable "allow_rebase_merge" { - description = "Set to true to enable rebase merges on the repository. (Default: false)" + description = "Set to true to enable rebase merges on the repository." type = bool default = true } variable "has_downloads" { - description = "Set to true to enable the (deprecated) downloads features on the repository. (Default: false)" + description = "Set to true to enable the (deprecated) downloads features on the repository." type = bool default = false } variable "auto_init" { - description = "Wether or not to produce an initial commit in the repository. (Default: true)" + description = "Wether or not to produce an initial commit in the repository." type = bool default = true } diff --git a/examples/public-repository-complete-example/main.tf b/examples/public-repository-complete-example/main.tf index 1c71d83a..41695daa 100644 --- a/examples/public-repository-complete-example/main.tf +++ b/examples/public-repository-complete-example/main.tf @@ -1,35 +1,40 @@ -# ----------------------------------------------------------------------------- +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CREATE TWO REPOSITORIES WITH TEAMS AND DEFAULTS +# This example covers the whole functionality of the module. We create two different repositories and attach default +# settings. Also we create a single team and attach it to one of the repositories. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# --------------------------------------------------------------------------------------------------------------------- # TERRAFORM # We need at least version 0.12.9 for full for_each functionality -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- + terraform { - required_version = "~> 0.12.9" + required_version = ">= 0.12.9" } -# ----------------------------------------------------------------------------- -# PROVIDERS -# We are using specific version of different providers for consistant results -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- +# SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE +# --------------------------------------------------------------------------------------------------------------------- + provider "github" { - # we want to be compatible with 2.x series of github provider + # We want to be compatible with 2.x series of github provider version = ">= 2.3.1, < 3.0.0" - # credentials are read from the environment + + # Read GitHub credentials from environment # GITHUB_TOKEN # GITHUB_ORGANIZATION } -provider "random" { - version = "= 2.2.1" -} - provider "tls" { version = "= 2.1.1" } -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- # DEPENDENCIES from other providers # We are creating some resources for easier testing -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- + resource "tls_private_key" "deploy" { count = 2 @@ -37,34 +42,31 @@ resource "tls_private_key" "deploy" { rsa_bits = 4096 } -resource "random_pet" "suffix" { - length = 1 -} - -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- # TEST A # We are creating a repository, adding teams and setting up branch protection, # deploy keys, issue labels and projects -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- + module "repository" { source = "../.." - name = "test-public-repository-complete-example-A-${random_pet.suffix.id}" - description = "A public repository created with terraform to test the terraform-github-repository module." - homepage_url = "https://github.com/mineiros-io" + name = var.name + description = var.description + homepage_url = var.url private = false - has_issues = true - has_projects = true - has_wiki = true - allow_merge_commit = true - allow_rebase_merge = true - allow_squash_merge = true - has_downloads = false - auto_init = true - gitignore_template = "Terraform" - license_template = "mit" + has_issues = var.has_issues + has_projects = var.has_projects + has_wiki = var.has_wiki + allow_merge_commit = var.allow_merge_commit + allow_rebase_merge = var.allow_rebase_merge + allow_squash_merge = var.allow_squash_merge + has_downloads = var.has_downloads + auto_init = var.auto_init + gitignore_template = var.gitignore_template + license_template = var.license_template archived = false - topics = ["terraform", "integration-test"] + topics = var.topics admin_team_ids = [ github_team.team.id @@ -83,31 +85,22 @@ module "repository" { required_pull_request_reviews = { dismiss_stale_reviews = true - dismissal_users = ["terraform-test-user-1"] + dismissal_users = [var.team_user] dismissal_teams = [github_team.team.slug] require_code_owner_reviews = true required_approving_review_count = 1 } restrictions = { - users = ["terraform-test-user"] - teams = ["team-1"] + users = [var.team_user] + teams = [ + github_team.team.slug + ] } } ] - issue_labels = [ - { - name = "WIP" - description = "Work in Progress..." - color = "d6c860" - }, - { - name = "another-label" - description = "This is a lable created by Terraform..." - color = "1dc34f" - } - ] + issue_labels = var.issue_labels deploy_keys_computed = [ { @@ -118,59 +111,42 @@ module "repository" { tls_private_key.deploy[1].public_key_openssh ] - projects = [ - { - name = "Testproject" - body = "This is a fancy test project for testing" - }, - { - name = "Another Testproject" - body = "This is a fancy test project for testing" - } - ] + projects = var.projects } -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- # TEST B -# We are creating a repository using some defaults defined in locals -# ----------------------------------------------------------------------------- -locals { - defaults = { - homepage_url = "https://github.com/mineiros-io" - private = false - allow_merge_commit = true - gitignore_template = "Terraform" - license_template = "mit" - topics = ["terraform", "integration-test"] - } -} +# We are creating a repository using some defaults defined in +# var.repository_defaults +# --------------------------------------------------------------------------------------------------------------------- module "repository-with-defaults" { source = "../.." - name = "test-public-repository-complete-example-B-${random_pet.suffix.id}" - description = "A public repository created with terraform to test the terraform-github-repository module." - defaults = local.defaults + name = var.repository_with_defaults_name + description = var.repository_with_defaults_description + defaults = var.repository_defaults } -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- # GITHUB DEPENDENCIES: TEAM # We are creating a github team to be added to the repository -# ----------------------------------------------------------------------------- +# --------------------------------------------------------------------------------------------------------------------- + resource "github_team" "team" { - name = "test-public-repository-complete-example-${random_pet.suffix.id}" - description = "A secret team created with terraform to test the terraformn-github-repository module." + name = var.team_name + description = var.team_description privacy = "secret" } -# --------------------------------------------------------------------------------------------------------------------- +# ---------------------------------------------------------------------------------------------------------------------- # TEAM MEMBERSHIP -# We are adding one members to this team for testing branch restrictions -# terraform-test-user is permanent normal member of the test organization -# --------------------------------------------------------------------------------------------------------------------- +# We are adding one members to this team for testing branch restrictions. +# The user defined in "var.team_user" should be a permanent normal member of organization you run the tests in. +# ---------------------------------------------------------------------------------------------------------------------- resource "github_team_membership" "team_membership_permanent" { team_id = github_team.team.id - username = "terraform-test-user" + username = var.team_user role = "member" } diff --git a/examples/public-repository-complete-example/outputs.tf b/examples/public-repository-complete-example/outputs.tf index e69de29b..5aa45c0f 100644 --- a/examples/public-repository-complete-example/outputs.tf +++ b/examples/public-repository-complete-example/outputs.tf @@ -0,0 +1,46 @@ +# --------------------------------------------------------------------------------------------------------------------- +# Repository +# --------------------------------------------------------------------------------------------------------------------- + +output "repository" { + description = "All outputs of the created repository." + value = module.repository +} + +output "repository_name" { + description = "The name of the created repository." + value = module.repository.full_name +} + +# --------------------------------------------------------------------------------------------------------------------- +# Repository with defaults +# --------------------------------------------------------------------------------------------------------------------- + +output "repository_defaults" { + description = "A map of default settings that can be attached to a repository." + value = var.repository_defaults +} + +output "repository_with_defaults" { + description = "All outputs of the repository that has default settings attached to it." + value = module.repository-with-defaults +} + +output "repository_with_defaults_name" { + description = "The nam of the created repository that has default settings attached to it." + value = module.repository-with-defaults.full_name +} + +# --------------------------------------------------------------------------------------------------------------------- +# Team +# --------------------------------------------------------------------------------------------------------------------- + +output "team" { + description = "All outputs of the created team." + value = github_team.team +} + +output "team_name" { + description = "The name of the created team." + value = github_team.team.name +} diff --git a/examples/public-repository-complete-example/variables.tf b/examples/public-repository-complete-example/variables.tf index e69de29b..a75e6b34 100644 --- a/examples/public-repository-complete-example/variables.tf +++ b/examples/public-repository-complete-example/variables.tf @@ -0,0 +1,184 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables. +# --------------------------------------------------------------------------------------------------------------------- + +# GITHUB_ORGANIZATION +# GITHUB_TOKEN + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL VARIABLES +# These variables have defaults, but may be overridden. +# --------------------------------------------------------------------------------------------------------------------- + +variable "name" { + description = "The name of the created repository." + type = string + default = "test-public-repository-complete-example-A" +} + +variable "description" { + description = "The description of the created repository." + type = string + default = "A public repository created with terraform to test the terraform-github-repository module." +} + +variable "url" { + description = "The url of the created repository." + type = string + default = "https://github.com/mineiros-io" +} + + +variable "has_issues" { + description = "Set to true to enable the GitHub Issues features on the repository." + type = bool + default = true +} + +variable "has_projects" { + description = "Set to true to enable the GitHub Projects features on the repository." + type = bool + default = true +} + +variable "has_wiki" { + description = "Set to true to enable the GitHub Wiki features on the repository." + type = bool + default = true +} + +variable "allow_merge_commit" { + description = "Set to false to disable merge commits on the repository." + type = bool + default = true +} + +variable "allow_squash_merge" { + description = "Set to true to enable squash merges on the repository." + type = bool + default = true +} + +variable "allow_rebase_merge" { + description = "Set to true to enable rebase merges on the repository." + type = bool + default = true +} + +variable "has_downloads" { + description = "Set to true to enable the (deprecated) downloads features on the repository." + type = bool + default = false +} + +variable "auto_init" { + description = "Wether or not to produce an initial commit in the repository." + type = bool + default = true +} + +variable "gitignore_template" { + description = "Use the name of the template without the extension. For example, Haskell. Available templates: https://github.com/github/gitignore" + type = string + default = "Terraform" +} + +variable "license_template" { + description = "Use the name of the template without the extension. For example, 'mit' or 'mpl-2.0'. Available licences: https://github.com/github/choosealicense.com/tree/gh-pages/_licenses" + type = string + default = "mit" +} + +variable "projects" { + description = "A list of projects to create." + type = list(object({ + name = string, + body = string + })) + default = [ + { + name = "Testproject" + body = "This is a fancy test project for testing" + }, + { + name = "Another Testproject" + body = "This is a fancy test project for testing" + } + ] +} + +variable "issue_labels" { + description = "A list of issue labels to create." + type = list(object({ + name = string, + description = string, + color = string + })) + default = [ + { + name = "WIP" + description = "Work in Progress..." + color = "d6c860" + }, + { + name = "another-label" + description = "This is a lable created by Terraform..." + color = "1dc34f" + } + ] +} + +variable "topics" { + description = "The list of topics of the repository." + type = list(string) + default = ["terraform", "integration-test"] +} + +variable "team_name" { + description = "The name of the created team." + type = string + default = "test-public-repository-complete-example" +} + +variable "team_description" { + description = "The description of the created team." + type = string + default = "A secret team created with terraform to test the terraformn-github-repository module." +} + +variable "team_user" { + description = "The user that should be added to the created team." + type = string + default = "terraform-test-user" +} + +variable "repository_defaults" { + description = "A map of default settings that can be applied to a repository." + type = any + default = { + homepage_url = "https://github.com/mineiros-io" + private = false + allow_merge_commit = true + gitignore_template = "Terraform" + license_template = "mit" + topics = ["terraform", "integration-test"] + } +} + +variable "repository_with_defaults_name" { + description = "The name of the created repository that has default settings attached to it." + type = string + default = "test-public-repository-complete-example-B" +} + +variable "repository_with_defaults_description" { + description = "The description of the created repository that has default settings attached to it." + type = string + default = "A public repository created with terraform to test the terraform-github-repository module." +} diff --git a/examples/public-repository-with-collaborators/main.tf b/examples/public-repository-with-collaborators/main.tf index 12ba00f1..413f0299 100644 --- a/examples/public-repository-with-collaborators/main.tf +++ b/examples/public-repository-with-collaborators/main.tf @@ -1,3 +1,11 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CREATE A REPOSITORY WITH COLLABORATORS +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# --------------------------------------------------------------------------------------------------------------------- +# SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE +# --------------------------------------------------------------------------------------------------------------------- + terraform { required_version = "~> 0.12.9" } @@ -6,36 +14,24 @@ provider "github" { version = ">= 2.3.1, < 3.0.0" } -provider "random" { - version = "= 2.2.1" -} - -resource "random_pet" "suffix" { - length = 1 -} - module "repository" { source = "../.." - name = "test-public-repository-with-collaborators-${random_pet.suffix.id}" - description = "A public repository created with terraform to test the terraform-github-repository module." - homepage_url = "https://github.com/mineiros-io" - private = false - has_issues = false - has_projects = false - has_wiki = false - allow_merge_commit = false - allow_rebase_merge = false - allow_squash_merge = true - has_downloads = false - auto_init = true - gitignore_template = "Terraform" - license_template = "mit" - archived = false - topics = ["terraform", "integration-test"] - - admin_collaborators = [ - "terraform-test-user-1" - ] - + name = var.name + description = var.description + homepage_url = var.url + private = false + has_issues = var.has_issues + has_projects = var.has_projects + has_wiki = var.has_wiki + allow_merge_commit = var.allow_merge_commit + allow_rebase_merge = var.allow_rebase_merge + allow_squash_merge = var.allow_squash_merge + has_downloads = var.has_downloads + auto_init = var.auto_init + gitignore_template = var.gitignore_template + license_template = var.license_template + archived = false + topics = var.topics + admin_collaborators = var.admin_collaborators } diff --git a/examples/public-repository-with-collaborators/outputs.tf b/examples/public-repository-with-collaborators/outputs.tf index e69de29b..9143257b 100644 --- a/examples/public-repository-with-collaborators/outputs.tf +++ b/examples/public-repository-with-collaborators/outputs.tf @@ -0,0 +1,19 @@ +output "repository" { + description = "All outputs of the created repository." + value = module.repository +} + +output "repository_name" { + description = "The full name of the created repository" + value = module.repository.full_name +} + +output "collaborators" { + description = "A list of collaborators that are attached to the repository." + value = module.repository.collaborators +} + +output "repository_url" { + description = "The URL of the created repository." + value = module.repository.html_url +} diff --git a/examples/public-repository-with-collaborators/variables.tf b/examples/public-repository-with-collaborators/variables.tf index e69de29b..70101329 100644 --- a/examples/public-repository-with-collaborators/variables.tf +++ b/examples/public-repository-with-collaborators/variables.tf @@ -0,0 +1,108 @@ +# --------------------------------------------------------------------------------------------------------------------- +# ENVIRONMENT VARIABLES +# Define these secrets as environment variables. +# --------------------------------------------------------------------------------------------------------------------- + +# GITHUB_ORGANIZATION +# GITHUB_TOKEN + +# --------------------------------------------------------------------------------------------------------------------- +# REQUIRED VARIABLES +# These variables must be set when using this module. +# --------------------------------------------------------------------------------------------------------------------- + +# --------------------------------------------------------------------------------------------------------------------- +# OPTIONAL VARIABLES +# These variables have defaults, but may be overridden. +# --------------------------------------------------------------------------------------------------------------------- + +variable "name" { + description = "The name of the created repository." + type = string + default = "test-public-repository-with-collaborators" +} + +variable "description" { + description = "The description of the created repository." + type = string + default = "A public repository created with terraform to test the terraform-github-repository module." +} + +variable "url" { + description = "The url of the created repository." + type = string + default = "https://github.com/mineiros-io" +} + + +variable "has_issues" { + description = "Set to true to enable the GitHub Issues features on the repository." + type = bool + default = false +} + +variable "has_projects" { + description = "Set to true to enable the GitHub Projects features on the repository." + type = bool + default = false +} + +variable "has_wiki" { + description = "Set to true to enable the GitHub Wiki features on the repository." + type = bool + default = false +} + +variable "allow_merge_commit" { + description = "Set to false to disable merge commits on the repository." + type = bool + default = true +} + +variable "allow_squash_merge" { + description = "Set to true to enable squash merges on the repository." + type = bool + default = false +} + +variable "allow_rebase_merge" { + description = "Set to true to enable rebase merges on the repository." + type = bool + default = false +} + +variable "has_downloads" { + description = "Set to true to enable the (deprecated) downloads features on the repository." + type = bool + default = false +} + +variable "auto_init" { + description = "Wether or not to produce an initial commit in the repository." + type = bool + default = true +} + +variable "gitignore_template" { + description = "Use the name of the template without the extension. For example, Haskell. Available templates: https://github.com/github/gitignore" + type = string + default = "Terraform" +} + +variable "license_template" { + description = "Use the name of the template without the extension. For example, 'mit' or 'mpl-2.0'. Available licences: https://github.com/github/choosealicense.com/tree/gh-pages/_licenses" + type = string + default = "mit" +} + +variable "topics" { + description = "The list of topics of the repository." + type = list(string) + default = ["terraform", "integration-test"] +} + +variable "admin_collaborators" { + description = "A list of GitHub usernames that should be added as admin collaborators to the created repository." + type = list(string) + default = ["terraform-test-user-1"] +} diff --git a/go.mod b/go.mod index 2599bb51..7463504c 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module github.com/mineiros-io/terraform-github-repository/v2 go 1.13 -require github.com/gruntwork-io/terratest v0.23.0 // indirect +require ( + github.com/gruntwork-io/terratest v0.23.0 + github.com/stretchr/testify v1.4.0 +) diff --git a/main.tf b/main.tf index addb36aa..55b9dbd0 100644 --- a/main.tf +++ b/main.tf @@ -1,3 +1,9 @@ +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# CREATE A GITHUB REPOSITORY +# This module creates a GitHub repository with opinionated default settings. +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +# Set some opinionated default settings through var.defaults and locals locals { homepage_url = var.homepage_url == null ? lookup(var.defaults, "homepage_url", "") : var.homepage_url private = var.private == null ? lookup(var.defaults, "private", true) : var.private @@ -66,6 +72,10 @@ locals { ] } +# --------------------------------------------------------------------------------------------------------------------- +# Create the repository +# --------------------------------------------------------------------------------------------------------------------- + resource "github_repository" "repository" { name = var.name description = var.description @@ -104,10 +114,11 @@ resource "github_repository" "repository" { } } -# -# Repository branch protection -# +# --------------------------------------------------------------------------------------------------------------------- +# Branch Protection # https://www.terraform.io/docs/providers/github/r/branch_protection.html +# --------------------------------------------------------------------------------------------------------------------- + resource "github_branch_protection" "branch_protection" { count = length(local.branch_protections) @@ -155,9 +166,10 @@ resource "github_branch_protection" "branch_protection" { } } -# -# Repository issue labels -# +# --------------------------------------------------------------------------------------------------------------------- +# Issue Labels +# --------------------------------------------------------------------------------------------------------------------- + locals { # only add to the list of labels even if github removes labels as changing this will affect # all deployed repositories. @@ -229,9 +241,10 @@ resource "github_issue_label" "label" { color = each.value.color } -# -# Repository collaborators -# +# --------------------------------------------------------------------------------------------------------------------- +# Collaborators +# --------------------------------------------------------------------------------------------------------------------- + locals { collab_admin = { for i in var.admin_collaborators : i => "admin" } collab_push = { for i in var.push_collaborators : i => "push" } @@ -256,9 +269,10 @@ resource "github_repository_collaborator" "collaborator" { permission = each.value } -# -# Repository teams -# +# --------------------------------------------------------------------------------------------------------------------- +# Teams +# --------------------------------------------------------------------------------------------------------------------- + locals { team_admin = [for i in var.admin_team_ids : { team_id = i, permission = "admin" }] team_push = [for i in var.push_team_ids : { team_id = i, permission = "push" }] @@ -283,9 +297,10 @@ resource "github_team_repository" "team_repository" { permission = local.teams[count.index].permission } -# -# Repository deploy keys -# +# --------------------------------------------------------------------------------------------------------------------- +# Deploy Keys +# --------------------------------------------------------------------------------------------------------------------- + locals { deploy_keys_computed_temp = [ for d in var.deploy_keys_computed : try({ key = tostring(d) }, d) @@ -330,9 +345,10 @@ resource "github_repository_deploy_key" "deploy_key" { read_only = each.value.read_only } -# -# Repository projects -# +# --------------------------------------------------------------------------------------------------------------------- +# Projects +# --------------------------------------------------------------------------------------------------------------------- + locals { projects = { for i in var.projects : lookup(i, "id", lower(i.name)) => merge({ body = null diff --git a/test/complete_example_test.go b/test/complete_example_test.go deleted file mode 100644 index 86b6e367..00000000 --- a/test/complete_example_test.go +++ /dev/null @@ -1,38 +0,0 @@ -package test - -import ( - "github.com/gruntwork-io/terratest/modules/terraform" - "os" - "testing" -) - -func init() { - githubOrganization := os.Getenv("GITHUB_ORGANIZATION") - githubToken := os.Getenv("GITHUB_TOKEN") - - if githubOrganization == "" { - panic("Please set a github organization using the GITHUB_ORGANIZATION environment variable.") - } - - if githubToken == "" { - panic("Please set a github token using the GITHUB_TOKEN environment variable.") - } -} - - - -func TestGithubPublicRepositoryCompleteExample(t *testing.T) { - t.Parallel() - - terraformOptions := &terraform.Options{ - // The path to where your Terraform code is located - TerraformDir: "../examples/public-repository-complete-example", - Upgrade: true, - } - - // At the end of the test, run `terraform destroy` to clean up any resources that were created - defer terraform.Destroy(t, terraformOptions) - - // This will run `terraform init` and `terraform apply` and fail the test if there are any errors - terraform.InitAndApply(t, terraformOptions) -} diff --git a/test/public_repository_complete_example_test.go b/test/public_repository_complete_example_test.go new file mode 100644 index 00000000..698bd977 --- /dev/null +++ b/test/public_repository_complete_example_test.go @@ -0,0 +1,122 @@ +package test + +import ( + "fmt" + "testing" + + "github.com/gruntwork-io/terratest/modules/random" + + "github.com/gruntwork-io/terratest/modules/terraform" + "github.com/stretchr/testify/require" +) + +func TestGithubPublicRepositoryCompleteExample(t *testing.T) { + t.Parallel() + + const OutputTeamName = "team_name" + const OutputRepositoryDefaults = "repository_defaults" + const OutputRepositoryName = "repository_name" + const OutputRepositoryWithDefaultsName = "repository_with_defaults_name" + + githubOrganization := checkIfEnvironmentVariablesAreSet() + + // Set the names for the repositories this test should create + expectedRepositoryNameA := fmt.Sprintf("test-public-repository-complete-example-A-%s", random.UniqueId()) + expectedRepositoryNameB := fmt.Sprintf("test-public-repository-complete-example-B-%s", random.UniqueId()) + + expectedTeamName := fmt.Sprintf("test-public-repository-complete-example-%s", random.UniqueId()) + + // We pass this map of default repository settings as a variable to Terraform + expectedRepositoryDefaults := map[string]interface{}{ + "homepage_url": "https://github.com/mineiros-io", + "private": "false", + "allow_merge_commit": "true", + "gitignore_template": "Terraform", + "license_template": "mit", + "topics": []interface{}{"terraform", "integration-test"}, + } + + // Define some issue labels we pass as variables to Terraform + issueLabelNameA := random.UniqueId() + issueLabelNameB := random.UniqueId() + + issueLabels := []interface{}{ + map[string]interface{}{ + "name": issueLabelNameA, + "description": "Work in Progress...", + "color": "d6c860", + }, + map[string]interface{}{ + "name": issueLabelNameB, + "description": "This is a label created by Terraform...", + "color": "1dc34f", + }, + } + + // Set Terraform options + terraformOptions := &terraform.Options{ + // The path to where your Terraform code is located + TerraformDir: "../examples/public-repository-complete-example", + Upgrade: true, + Vars: map[string]interface{}{ + // Repositories + "name": expectedRepositoryNameA, + "repository_with_defaults_name": expectedRepositoryNameB, + "issue_labels": issueLabels, + "repository_defaults": expectedRepositoryDefaults, + + //Team + "team_name": expectedTeamName, + }, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) + + // Retrieve all outputs from Terraform + out := terraform.OutputAll(t, terraformOptions) + + // Validate that the name of the created team matches the one we defined as a variable + teamName, ok := out[OutputTeamName].(string) + require.True(t, ok, fmt.Sprintf( + "Wrong data type for '%s', expected string, got %T", + OutputTeamName, + out[OutputTeamName])) + + require.Equal(t, expectedTeamName, teamName, "String %q should match %q", + expectedTeamName, teamName) + + // Validate that the type of the outputs for the defaults is correct + repositoryDefaults, ok := out[OutputRepositoryDefaults].(map[string]interface{}) + require.True(t, ok, fmt.Sprintf( + "Wrong data type for '%s', expected map[string], got %T", + OutputRepositoryDefaults, + out[OutputRepositoryDefaults])) + + // Validate that the returned map of repository defaults + require.Equal(t, expectedRepositoryDefaults, repositoryDefaults, "Map item %q should match %q", + expectedRepositoryDefaults, repositoryDefaults) + + // Validate that the names of the created repositories match the ones we passed as variables + repositoryNameA, ok := out[OutputRepositoryName].(string) + require.True(t, ok, fmt.Sprintf("Wrong data type for '%s', expected string, got %T", + OutputRepositoryName, + out[OutputRepositoryName])) + + expectedFullRepositoryNameA := fmt.Sprintf("%s/%s", githubOrganization, expectedRepositoryNameA) + require.Equal(t, expectedFullRepositoryNameA, repositoryNameA, "String %q should match %q", + expectedFullRepositoryNameA, repositoryNameA) + + repositoryNameB, ok := out[OutputRepositoryWithDefaultsName].(string) + require.True(t, ok, fmt.Sprintf( + "Wrong data type for '%s', expected string, got %T", + OutputRepositoryWithDefaultsName, + out[OutputRepositoryWithDefaultsName])) + + expectedFullRepositoryNameB := fmt.Sprintf("%s/%s", githubOrganization, expectedRepositoryNameB) + require.Equal(t, expectedFullRepositoryNameB, repositoryNameB, "String %q should match %q", + expectedFullRepositoryNameB, repositoryNameB) +} diff --git a/test/public_repository_with_collaborators_test.go b/test/public_repository_with_collaborators_test.go new file mode 100644 index 00000000..8467a42f --- /dev/null +++ b/test/public_repository_with_collaborators_test.go @@ -0,0 +1,64 @@ +package test + +import ( + "crypto/tls" + "fmt" + "testing" + "time" + + http_helper "github.com/gruntwork-io/terratest/modules/http-helper" + + "github.com/gruntwork-io/terratest/modules/random" + "github.com/stretchr/testify/require" + + "github.com/gruntwork-io/terratest/modules/terraform" +) + +func TestGithubPublicRepositoryWithCollaborators(t *testing.T) { + t.Parallel() + + const OutputRepositoryName = "repository_name" + const OutputRepositoryURL = "repository_url" + + GithubOrganization := checkIfEnvironmentVariablesAreSet() + + expectedRepositoryName := fmt.Sprintf("test-public-repository-with-collaborators-%s", random.UniqueId()) + + terraformOptions := &terraform.Options{ + // The path to where your Terraform code is located + TerraformDir: "../examples/public-repository-with-collaborators", + Upgrade: true, + Vars: map[string]interface{}{ + "name": expectedRepositoryName, + }, + } + + // At the end of the test, run `terraform destroy` to clean up any resources that were created + defer terraform.Destroy(t, terraformOptions) + + // This will run `terraform init` and `terraform apply` and fail the test if there are any errors + terraform.InitAndApply(t, terraformOptions) + + repositoryName := terraform.OutputRequired(t, terraformOptions, OutputRepositoryName) + require.Equal(t, fmt.Sprintf("%s/%s", GithubOrganization, expectedRepositoryName), + repositoryName, "Name of repository %q should match %q", + fmt.Sprintf("%s/%s", GithubOrganization, expectedRepositoryName), repositoryName) + + // Retrieve the repository URL from the outputs + repositoryURL := terraform.OutputRequired(t, terraformOptions, OutputRepositoryURL) + + // Check if the created repository is available through HTTP + status := 200 + retries := 15 + sleep := 5 * time.Second + tlsConfig := tls.Config{} + http_helper.HttpGetWithRetryWithCustomValidation( + t, + repositoryURL, + &tlsConfig, + retries, + sleep, + func(statusCode int, body string) bool { + return statusCode == status + }) +} diff --git a/test/test_helper.gp.go b/test/test_helper.gp.go deleted file mode 100644 index 56e54040..00000000 --- a/test/test_helper.gp.go +++ /dev/null @@ -1 +0,0 @@ -package test diff --git a/test/test_helpers.go b/test/test_helpers.go new file mode 100644 index 00000000..5e0fcd00 --- /dev/null +++ b/test/test_helpers.go @@ -0,0 +1,18 @@ +package test + +import "os" + +func checkIfEnvironmentVariablesAreSet() string { + githubOrganization := os.Getenv("GITHUB_ORGANIZATION") + githubToken := os.Getenv("GITHUB_TOKEN") + + if githubOrganization == "" { + panic("Please set a github organization using the GITHUB_ORGANIZATION environment variable.") + } + + if githubToken == "" { + panic("Please set a github token using the GITHUB_TOKEN environment variable.") + } + + return githubOrganization +} diff --git a/variables.tf b/variables.tf index b75f9436..92ce7e49 100644 --- a/variables.tf +++ b/variables.tf @@ -12,8 +12,8 @@ # --------------------------------------------------------------------------------------------------------------------- variable "name" { - type = string description = "The name of the repository." + type = string } # --------------------------------------------------------------------------------------------------------------------- @@ -22,9 +22,8 @@ variable "name" { # --------------------------------------------------------------------------------------------------------------------- variable "defaults" { - type = any description = "Overwrite defaults for various repository settings" - default = {} + type = any # Example: # defaults = { @@ -43,6 +42,8 @@ variable "defaults" { # default_branch = "master" # topics = ["topic-1", "topic-2"] # } + + default = {} } variable "description" { @@ -137,13 +138,13 @@ variable "archived" { variable "topics" { description = "The list of topics of the repository. (Default: [])" - type = set(string) + type = list(string) default = null } variable "extra_topics" { description = "The list of additional topics of the repository. (Default: [])" - type = set(string) + type = list(string) default = [] } @@ -158,61 +159,61 @@ variable "template" { variable "admin_collaborators" { description = "A list of users to add as collaborators granting them admin (full) permission." - type = set(string) + type = list(string) default = [] } variable "push_collaborators" { description = "A list of users to add as collaborators granting them push (read-write) permission." - type = set(string) + type = list(string) default = [] } variable "pull_collaborators" { description = "A list of users to add as collaborators granting them pull (read-only) permission." - type = set(string) + type = list(string) default = [] } variable "triage_collaborators" { description = "A list of users to add as collaborators granting them triage permission." - type = set(string) + type = list(string) default = [] } variable "maintain_collaborators" { description = "A list of users to add as collaborators granting them maintain permission." - type = set(string) + type = list(string) default = [] } variable "admin_team_ids" { description = "A list of teams (by id) to grant admin (full) permission to." - type = set(string) + type = list(string) default = [] } variable "push_team_ids" { description = "A list of teams (by id) to grant push (read-write) permission to." - type = set(string) + type = list(string) default = [] } variable "pull_team_ids" { description = "A list of teams (by id) to grant pull (read-only) permission to." - type = set(string) + type = list(string) default = [] } variable "triage_team_ids" { description = "A list of teams (by id) to grant triage permission to." - type = set(string) + type = list(string) default = [] } variable "maintain_team_ids" { description = "A list of teams (by id) to grant maintain permission to." - type = set(string) + type = list(string) default = [] } diff --git a/versions.tf b/versions.tf index 7d5e5225..068d0598 100644 --- a/versions.tf +++ b/versions.tf @@ -1,5 +1,9 @@ +# --------------------------------------------------------------------------------------------------------------------- +# SET TERRAFORM AND PROVIDER REQUIREMENTS FOR RUNNING THIS MODULE +# --------------------------------------------------------------------------------------------------------------------- + terraform { - required_version = "~> 0.12.9" + required_version = ">= 0.12.9" required_providers { github = ">= 2.3.1, < 3.0.0"