diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..2c909c5 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,15 @@ +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true +quote_type = double + +[*.md] +max_line_length = 0 +trim_trailing_whitespace = false diff --git a/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md new file mode 100644 index 0000000..b462ac0 --- /dev/null +++ b/.github/PULL_REQUEST_TEMPLATE/pull_request_template.md @@ -0,0 +1,8 @@ +## Info + +- Describe high-level what changed as a result of these commits and why you made these changes. Be descriptive as pull requests are a common source of historical information when looking at past changes to the code. +- Use bullet points to be concise and to the point. + +## References + +- Include any links to tickets, Teams or Slack threads, documentation, or online articles that help understand these changes and why they were made. diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml new file mode 100644 index 0000000..9ec010e --- /dev/null +++ b/.github/workflows/lint.yaml @@ -0,0 +1,21 @@ +name: Lint + +on: pull_request + +permissions: + actions: read + checks: write + contents: read + pull-requests: read + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Check out Git repository + uses: actions/checkout@v4 + - name: Trunk Check + uses: trunk-io/trunk-action@v1 + - name: Set up Terraform CLI + uses: hashicorp/setup-terraform@v2 + - run: terraform fmt -check -recursive diff --git a/.gitignore b/.gitignore index 7a3e2fd..b381aea 100644 --- a/.gitignore +++ b/.gitignore @@ -5,14 +5,16 @@ *.tfstate *.tfstate.* +# Terraform lock files +.terraform.lock.hcl + # 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 +*.tfvars # Ignore override files as they are usually used to override resources locally and so # are not checked in diff --git a/.markdownlint.yaml b/.markdownlint.yaml new file mode 100644 index 0000000..81f8cd2 --- /dev/null +++ b/.markdownlint.yaml @@ -0,0 +1,4 @@ +# This is a Markdownlint configuration file to ignore the acceptable issues for all files. +MD041: false # First line in file should be a top level header. +MD013: false # Line length. +MD033: false # Inline HTML. diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d6fcd35 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,6 @@ +repos: + - repo: https://github.com/antonbabenko/pre-commit-terraform + rev: v1.83.5 # Get the latest from: https://github.com/antonbabenko/pre-commit-terraform/releases + hooks: + - id: terraform_fmt + - id: terraform_docs diff --git a/.trunk/.gitignore b/.trunk/.gitignore new file mode 100644 index 0000000..1e24652 --- /dev/null +++ b/.trunk/.gitignore @@ -0,0 +1,8 @@ +*out +*logs +*actions +*notifications +*tools +plugins +user_trunk.yaml +user.yaml diff --git a/.trunk/configs/.markdownlint.yaml b/.trunk/configs/.markdownlint.yaml new file mode 100644 index 0000000..fb94039 --- /dev/null +++ b/.trunk/configs/.markdownlint.yaml @@ -0,0 +1,10 @@ +# Autoformatter friendly markdownlint config (all formatting rules disabled) +default: true +blank_lines: false +bullet: false +html: false +indentation: false +line_length: false +spaces: false +url: false +whitespace: false diff --git a/.trunk/configs/.yamllint.yaml b/.trunk/configs/.yamllint.yaml new file mode 100644 index 0000000..4d44466 --- /dev/null +++ b/.trunk/configs/.yamllint.yaml @@ -0,0 +1,10 @@ +rules: + quoted-strings: + required: only-when-needed + extra-allowed: ["{|}"] + empty-values: + forbid-in-block-mappings: true + forbid-in-flow-mappings: true + key-duplicates: {} + octal-values: + forbid-implicit-octal: true diff --git a/.trunk/trunk.yaml b/.trunk/trunk.yaml new file mode 100644 index 0000000..474a484 --- /dev/null +++ b/.trunk/trunk.yaml @@ -0,0 +1,30 @@ +# This file controls the behavior of Trunk: https://docs.trunk.io/cli +# To learn more about the format of this file, see https://docs.trunk.io/reference/trunk-yaml +version: 0.1 +cli: + version: 1.17.0 +plugins: + sources: + - id: trunk + ref: v1.2.5 + uri: https://github.com/trunk-io/plugins +runtimes: + enabled: + - node@18.12.1 + - python@3.10.8 +lint: + enabled: + - checkov@2.5.9 + - git-diff-check + - markdownlint@0.37.0 + - prettier@3.0.3 + - tflint@0.48.0 + - trivy@0.46.0 + - trufflehog@3.60.0 + - yamllint@1.32.0 +actions: + enabled: + - trunk-announce + - trunk-check-pre-push + - trunk-fmt-pre-commit + - trunk-upgrade-available diff --git a/README.md b/README.md index 5bbde1d..832a95e 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,29 @@ -# terraform-components -The Masterpoint reusable and sharable Terraform Root Modules (Components) +[![Masterpoint Logo](https://i.imgur.com/RDLnuQO.png)](https://masterpoint.io) + +# terraform-components [![Latest Release](https://img.shields.io/github/release/masterpointio/terraform-components.svg)](https://github.com/masterpointio/terraform-components/releases/latest) + +This is a Masterpoint's reusable and sharable collection of Terraform Root Modules (Components). Each Component is a set of Terraform modules, resources, data sources and local expressions that represent an higher abstraction layer of infrastructure comparing to an average community child module. It can be easily integrated into the architecture and removed if needed. + +It's Open Source and licensed under the [APACHE2](LICENSE). + +## Components + +- [GitHub Repositories](./github-repositories/README.md): responsible for managing GitHub repositories, including permissions, webhooks, pages, etc. + +## Trunk Linter + +To maintain code quality we use a collection of linters, all managed by [Trunk](https://trunk.io). + +To install trunk on your machine you can use brew: `brew install trunk-io`. You can also install trunk via the [official instructions](https://docs.trunk.io/docs/install). + +### Usage + +To run the linters, simply run `trunk check` from the root of the project. This will check any files that you have changed in your current branch. + +To automatically apply formatting changes, run `trunk fmt`. + +## Automating Trunk + +Trunk can manage git hooks, and is configured to run `fmt` on pre-commit and `check` on pre-push. This should help to prevent code being kicked-back by CI. + +Trunk is automated in CI using GitHub Actions, and PRs will be blocked if the linters fail. diff --git a/github-repositories/README.md b/github-repositories/README.md new file mode 100644 index 0000000..8a4da73 --- /dev/null +++ b/github-repositories/README.md @@ -0,0 +1,99 @@ +# GitHub Repositories Component + +This repository contains a collection of Terraform configurations tailored for managing GitHub repositories, including permissions, webhooks, pages, and more. + +## Usage + +### Prerequsites + +This Terraform module makes extensive use of the [integrations/github](https://registry.terraform.io/providers/integrations/github/latest/docs#pem_file) Terraform Provider to manage resources within a GitHub organization or user account. This requires setting up the GitHub provider with appropriate credentials to interact with the GitHub API. + +The following ways to authenticate with GitHub API are supported: + +- OAuth / Personal Access Token +- GitHub App Installation + +We use [terraform-secrets-helper](https://github.com/masterpointio/terraform-secrets-helper/tree/main) to retrieve sensitive data, such as tokens or pem file content. At the moment, we support SOPS encrypted files as a source, so before using this component: + +- Create a [GitHub Token](https://github.com/settings/tokens) or [GitHub App Installation](https://docs.github.com/en/rest/apps/installations?apiVersion=2022-11-28). +- Add the secret to SOPS file, see [SOPS Usage](https://github.com/getsops/sops#usage) for detailed instructions. +- Provide the secrets name and path to your SOPS file as inputs. + +### Example + +You can start with the configuration below to use the GitHub component module. + +:warning: the key of each item in the `repos` map matches the repository's name. This is to ensure consistent naming and referencing throughout your Terraform configuration. + +```hcl +module "gh_repos" { + source = "git::https://github.com/masterpointio/terraform-components.git//github-repositories?ref=" + + # GitHub provider + gh_owner = "myorg" + gh_token_secret_name = "gh_token" + + # SOPS secrets + secret_mapping = [{ + name = "gh_token" + file = "./config/secrets/global.yaml" + type = "sops" + }] + + # GitHub repositories + repos = { + "best-pet-project" = { + description = "This is a private repo for the Best Pet Project." + # ... other configurations + }, + "demo" = { + visibility = public + # ... other configurations + } + } +} +``` + + + +## Requirements + +| Name | Version | +| ------------------------------------------------------------------------ | ------- | +| [terraform](#requirement_terraform) | >= 1.0 | +| [github](#requirement_github) | >= 5.0 | +| [sops](#requirement_sops) | >= 0.7 | + +## Providers + +No providers. + +## Modules + +| Name | Source | Version | +| -------------------------------------------------------- | ----------------------------- | ------- | +| [repos](#module_repos) | mineiros-io/repository/github | 0.18.0 | +| [secrets](#module_secrets) | masterpointio/helper/secrets | 0.2.0 | + +## Resources + +No resources. + +## Inputs + +| Name | Description | Type | Default | Required | +| --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- | :------: | +| [gh_app_auth_id](#input_gh_app_auth_id) | The ID of the GitHub App. | `string` | `""` | no | +| [gh_app_auth_installation_id](#input_gh_app_auth_installation_id) | The ID of the GitHub App installation | `string` | `""` | no | +| [gh_app_auth_pem_file_secret_name](#input_gh_app_auth_pem_file_secret_name) | The name of the secret retrieved by secrets mixin that contains
the contents of the GitHub App private key PEM file. | `string` | `null` | no | +| [gh_base_url](#input_gh_base_url) | (Optional) This is the target GitHub base API endpoint.
Providing a value is a requirement when working with GitHub Enterprise.
It is optional to provide this value and it can also be sourced from the GITHUB_BASE_URL environment variable.
The value must end with a slash. | `string` | `null` | no | +| [gh_owner](#input_gh_owner) | (Optional) This is the target GitHub organization or individual user account to manage.
For example, `torvalds` and `github` are valid owners. It is optional to provide this value
and it can also be sourced from the GITHUB_OWNER environment variable.
When not provided and a token is available, the individual user account owning the token will be used.
When not provided and no token is available, the provider may not function correctly. | `string` | `null` | no | +| [gh_token_secret_name](#input_gh_token_secret_name) | The name of the secret retrieved by secrets mixin that contains the GitHub personal access token. | `string` | `null` | no | +| [repos](#input_repos) | The GitHub repositories for this organization. |
map(object({
# Main Resource Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#main-resource-configuration
allow_auto_merge = optional(bool, false)
allow_merge_commit = optional(bool, true)
allow_rebase_merge = optional(bool, false)
allow_squash_merge = optional(bool, false)
archive_on_destroy = optional(bool, true)
archived = optional(bool, false)
default_branch = optional(string, null)
description = optional(string, "")
extra_topics = optional(list(string), [])
has_downloads = optional(bool, false)
has_issues = optional(bool, false)
has_projects = optional(bool, false)
has_wiki = optional(bool, false)
homepage_url = optional(string, "")
is_template = optional(bool, false)
pages = optional(object({
branch = string
cname = optional(string, null)
path = optional(string, "/")
}))
topics = optional(list(string), [])
visibility = optional(string, "private")
vulnerability_alerts = optional(bool, false)

# Extended Resource Configuration

## Repository Creation Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#repository-creation-configuration
auto_init = optional(bool, true)
gitignore_template = optional(string, "")
license_template = optional(string, "")
template = optional(object({
owner = string
repository = string
}))

## Teams Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#teams-configuration
admin_teams = optional(list(string), [])
maintain_teams = optional(list(string), [])
pull_teams = optional(list(string), [])
push_teams = optional(list(string), [])
triage_teams = optional(list(string), [])

## Collaborator Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#collaborator-configuration
admin_collaborators = optional(list(string), [])
maintain_collaborators = optional(list(string), [])
pull_collaborators = optional(list(string), [])
push_collaborators = optional(list(string), [])
triage_collaborators = optional(list(string), [])

## Branches Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#branches-configuration
branches = optional(list(object({
name = string
source_branch = optional(string, null)
source_sha = optional(bool, null)
})), [])

## Deploy Keys Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#deploy-keys-configuration
deploy_keys = optional(list(object({
id = optional(string, "md5(key)")
key = string
read_only = optional(bool, true)
title = optional(string, null)
})), [])
deploy_keys_computed = optional(list(object({
id = optional(string, "md5(key)")
key = string
read_only = optional(bool, true)
title = optional(string, null)
})), [])

## Branch Protections v4 Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#branch-protections-v4-configuration
branch_protections_v4 = optional(list(object({
pattern = string
\_key = optional(string)
allows_deletions = optional(bool, false)
allows_force_pushes = optional(bool, false)
blocks_creations = optional(bool, false)
enforce_admins = optional(bool, true)
push_restrictions = optional(list(string), [])
require_conversation_resolution = optional(bool, false)
require_signed_commits = optional(bool, false)
required_linear_history = optional(bool, false)
required_pull_request_reviews = optional(list(object({
dismiss_stale_reviews = optional(bool, true)
restrict_dismissals = optional(bool, false)
dismissal_restrictions = optional(list(string), [])
pull_request_bypassers = optional(list(string), [])
require_code_owner_reviews = optional(bool, true)
required_approving_review_count = optional(number, 1)
})), [])
required_status_checks = optional(list(object({
strict = optional(bool, false)
contexts = optional(list(string), [])
})), [])
})), [])

## Issue Labels Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#issue-labels-configuration
issue_labels = optional(list(object({
color = string
description = optional(string, null)
id = optional(string, "name")
name = string
})), [])

issue_labels_merge_with_github_labels = optional(bool)
issue_labels_create = optional(bool)

## Projects Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#projects-configuration
projects = optional(list(object({
body = optional(string, "")
id = optional(string, "name")
name = string
})), [])

## Webhooks Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#webhooks-configuration
webhooks = optional(list(object({
active = optional(bool, true)
content_type = optional(string, "form")
insecure_ssl = optional(bool, false)
events = list(string)
name = optional(string)
secret = optional(string)
url = string
})), [])

## Secrets Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#secrets-configuration
plaintext_secrets = optional(map(string), {})
encrypted_secrets = optional(map(string), {})

## Autolink References Configuration
# https://github.com/mineiros-io/terraform-github-repository/tree/main#autolink-references-configuration
autolink_references = optional(list(object({
key_prefix = string
target_url_template = string
})), [])

## App Installations
# https://github.com/mineiros-io/terraform-github-repository/tree/main#app-installations
app_installations = optional(set(string), [])
}))
| `{}` | no | +| [secret_mapping](#input_secret_mapping) | The list of secret mappings the application will need.
This creates secret values for the component to consume at `local.secrets[name]`. |
list(object({
name = string
type = string
path = optional(string, null)
file = string
}))
| `[]` | no | + +## Outputs + +No outputs. + + diff --git a/github-repositories/main.tf b/github-repositories/main.tf new file mode 100644 index 0000000..9162ccd --- /dev/null +++ b/github-repositories/main.tf @@ -0,0 +1,84 @@ +module "repos" { + # checkov:skip=CKV_TF_1: For now we use Terraform registry source, not git. If switching to git, we should use a commit hash. + source = "mineiros-io/repository/github" + version = "0.18.0" + + for_each = var.repos + + # Main Resource Configuration + allow_auto_merge = each.value.allow_auto_merge + allow_merge_commit = each.value.allow_merge_commit + allow_rebase_merge = each.value.allow_rebase_merge + allow_squash_merge = each.value.allow_squash_merge + archive_on_destroy = each.value.archive_on_destroy + archived = each.value.archived + # NOTE: The configured branch must exist in the repository. + # If the branch doesn't exist yet, or if you are creating a new repository, + # please add the desired default branch to the `branches` variable, which will cause Terraform to create it for you. + default_branch = each.value.default_branch + description = each.value.description + extra_topics = each.value.extra_topics + has_downloads = each.value.has_downloads + has_issues = each.value.has_issues + has_projects = each.value.has_projects + has_wiki = each.value.has_wiki + homepage_url = each.value.homepage_url + is_template = each.value.is_template + name = each.key + pages = each.value.pages + topics = each.value.topics + visibility = each.value.visibility + vulnerability_alerts = each.value.vulnerability_alerts + + # Extended Resource Configuration + auto_init = each.value.auto_init + gitignore_template = each.value.gitignore_template + license_template = each.value.license_template + template = each.value.template + + # Teams Configuration + admin_teams = each.value.admin_teams + maintain_teams = each.value.maintain_teams + pull_teams = each.value.pull_teams + push_teams = each.value.push_teams + triage_teams = each.value.triage_teams + + # Collaborator Configuration + admin_collaborators = each.value.admin_collaborators + maintain_collaborators = each.value.maintain_collaborators + pull_collaborators = each.value.pull_collaborators + push_collaborators = each.value.push_collaborators + triage_collaborators = each.value.triage_collaborators + + # Branches Configuration + branches = each.value.branches + + # Deploy Keys Configuration + deploy_keys = each.value.deploy_keys + deploy_keys_computed = each.value.deploy_keys_computed + + # Branch Protections v4 Configuration + branch_protections_v4 = each.value.branch_protections_v4 + + # Issue Labels Configuration + issue_labels = each.value.issue_labels + issue_labels_create = each.value.issue_labels_create + + issue_labels_merge_with_github_labels = each.value.issue_labels_merge_with_github_labels + + # Projects Configuration + projects = each.value.projects + + # Webhooks Configuration + webhooks = each.value.webhooks + + # Secrets Configuration + plaintext_secrets = each.value.plaintext_secrets + encrypted_secrets = each.value.encrypted_secrets + + # Autolink References Configuration + autolink_references = each.value.autolink_references + + # App Installations + app_installations = each.value.app_installations +} diff --git a/github-repositories/providers.tf b/github-repositories/providers.tf new file mode 100644 index 0000000..6ba598c --- /dev/null +++ b/github-repositories/providers.tf @@ -0,0 +1,32 @@ +locals { + gh_token = try(local.secrets[var.gh_token_secret_name], "") + gh_token_enabled = length(local.gh_token) > 0 ? true : false + + gh_app_auth_id_enabled = length(var.gh_app_auth_id) > 0 ? true : false + gh_app_auth_installation_id_enabled = length(var.gh_app_auth_installation_id) > 0 ? true : false + gh_app_auth_pem_file = try(local.secrets[var.gh_app_auth_pem_file_secret_name], "") + gh_app_auth_pem_file_enabled = length(local.gh_app_auth_pem_file) > 0 ? true : false + gh_app_auth_enabled = alltrue([local.gh_app_auth_id_enabled, local.gh_app_auth_installation_id_enabled, local.gh_app_auth_pem_file_enabled]) +} + +# The GitHub provider offers multiple ways to authenticate with GitHub API: +# - GitHub CLI +# - OAuth / Personal Access Token +# - GitHub App Installation +# +# When none configuration is provided, the provider can only access resources available anonymously. +provider "github" { + base_url = var.gh_base_url + owner = var.gh_owner + + token = local.gh_token_enabled ? local.gh_token : null + + dynamic "app_auth" { + for_each = local.gh_app_auth_enabled ? ["app_auth"] : [] + content { + id = var.gh_app_auth_id + installation_id = var.gh_app_auth_installation_id + pem_file = local.gh_app_auth_pem_file + } + } +} diff --git a/github-repositories/secrets.sops.tf b/github-repositories/secrets.sops.tf new file mode 100644 index 0000000..c9b528b --- /dev/null +++ b/github-repositories/secrets.sops.tf @@ -0,0 +1,26 @@ +module "secrets" { + # checkov:skip=CKV_TF_1: For now we use Terraform registry source, not git. If switching to git, we should use a commit hash. + source = "masterpointio/helper/secrets" + version = "0.2.0" + secret_mapping = var.secret_mapping +} + +variable "secret_mapping" { + type = list(object({ + name = string + type = string + path = optional(string, null) + file = string + })) + default = [] + description = <<-EOT + The list of secret mappings the application will need. + This creates secret values for the component to consume at `local.secrets[name]`. + EOT +} + +# Reference your secrets using the module output +locals { + # tflint-ignore: terraform_unused_declarations + secrets = module.secrets.all +} diff --git a/github-repositories/variables.tf b/github-repositories/variables.tf new file mode 100644 index 0000000..fc4e6e0 --- /dev/null +++ b/github-repositories/variables.tf @@ -0,0 +1,213 @@ +####################### +# GitHub repositories # +####################### +variable "repos" { + description = "The GitHub repositories for this organization." + default = {} + type = map(object({ + # Main Resource Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#main-resource-configuration + allow_auto_merge = optional(bool, false) + allow_merge_commit = optional(bool, true) + allow_rebase_merge = optional(bool, false) + allow_squash_merge = optional(bool, false) + archive_on_destroy = optional(bool, true) + archived = optional(bool, false) + default_branch = optional(string, null) + description = optional(string, "") + extra_topics = optional(list(string), []) + has_downloads = optional(bool, false) + has_issues = optional(bool, false) + has_projects = optional(bool, false) + has_wiki = optional(bool, false) + homepage_url = optional(string, "") + is_template = optional(bool, false) + pages = optional(object({ + branch = string + cname = optional(string, null) + path = optional(string, "/") + })) + topics = optional(list(string), []) + visibility = optional(string, "private") + vulnerability_alerts = optional(bool, false) + + # Extended Resource Configuration + + ## Repository Creation Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#repository-creation-configuration + auto_init = optional(bool, true) + gitignore_template = optional(string, "") + license_template = optional(string, "") + template = optional(object({ + owner = string + repository = string + })) + + ## Teams Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#teams-configuration + admin_teams = optional(list(string), []) + maintain_teams = optional(list(string), []) + pull_teams = optional(list(string), []) + push_teams = optional(list(string), []) + triage_teams = optional(list(string), []) + + ## Collaborator Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#collaborator-configuration + admin_collaborators = optional(list(string), []) + maintain_collaborators = optional(list(string), []) + pull_collaborators = optional(list(string), []) + push_collaborators = optional(list(string), []) + triage_collaborators = optional(list(string), []) + + ## Branches Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#branches-configuration + branches = optional(list(object({ + name = string + source_branch = optional(string, null) + source_sha = optional(bool, null) + })), []) + + ## Deploy Keys Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#deploy-keys-configuration + deploy_keys = optional(list(object({ + id = optional(string, "md5(key)") + key = string + read_only = optional(bool, true) + title = optional(string, null) + })), []) + deploy_keys_computed = optional(list(object({ + id = optional(string, "md5(key)") + key = string + read_only = optional(bool, true) + title = optional(string, null) + })), []) + + ## Branch Protections v4 Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#branch-protections-v4-configuration + branch_protections_v4 = optional(list(object({ + pattern = string + _key = optional(string) + allows_deletions = optional(bool, false) + allows_force_pushes = optional(bool, false) + blocks_creations = optional(bool, false) + enforce_admins = optional(bool, true) + push_restrictions = optional(list(string), []) + require_conversation_resolution = optional(bool, false) + require_signed_commits = optional(bool, false) + required_linear_history = optional(bool, false) + required_pull_request_reviews = optional(list(object({ + dismiss_stale_reviews = optional(bool, true) + restrict_dismissals = optional(bool, false) + dismissal_restrictions = optional(list(string), []) + pull_request_bypassers = optional(list(string), []) + require_code_owner_reviews = optional(bool, true) + required_approving_review_count = optional(number, 1) + })), []) + required_status_checks = optional(list(object({ + strict = optional(bool, false) + contexts = optional(list(string), []) + })), []) + })), []) + + ## Issue Labels Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#issue-labels-configuration + issue_labels = optional(list(object({ + color = string + description = optional(string, null) + id = optional(string, "name") + name = string + })), []) + + issue_labels_merge_with_github_labels = optional(bool) + issue_labels_create = optional(bool) + + ## Projects Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#projects-configuration + projects = optional(list(object({ + body = optional(string, "") + id = optional(string, "name") + name = string + })), []) + + ## Webhooks Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#webhooks-configuration + webhooks = optional(list(object({ + active = optional(bool, true) + content_type = optional(string, "form") + insecure_ssl = optional(bool, false) + events = list(string) + name = optional(string) + secret = optional(string) + url = string + })), []) + + ## Secrets Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#secrets-configuration + plaintext_secrets = optional(map(string), {}) + encrypted_secrets = optional(map(string), {}) + + ## Autolink References Configuration + # https://github.com/mineiros-io/terraform-github-repository/tree/main#autolink-references-configuration + autolink_references = optional(list(object({ + key_prefix = string + target_url_template = string + })), []) + + ## App Installations + # https://github.com/mineiros-io/terraform-github-repository/tree/main#app-installations + app_installations = optional(set(string), []) + })) +} + +################### +# GitHub Provider # +################### +variable "gh_app_auth_id" { + type = string + description = "The ID of the GitHub App." + default = "" +} + +variable "gh_app_auth_installation_id" { + type = string + description = "The ID of the GitHub App installation" + default = "" +} + +variable "gh_app_auth_pem_file_secret_name" { + type = string + description = <<-EOF + The name of the secret retrieved by secrets mixin that contains + the contents of the GitHub App private key PEM file. + EOF + default = null +} + +variable "gh_base_url" { + type = string + description = <<-EOF + (Optional) This is the target GitHub base API endpoint. + Providing a value is a requirement when working with GitHub Enterprise. + It is optional to provide this value and it can also be sourced from the GITHUB_BASE_URL environment variable. + The value must end with a slash. + EOF + default = null +} + +variable "gh_owner" { + type = string + description = <<-EOF + (Optional) This is the target GitHub organization or individual user account to manage. + For example, `torvalds` and `github` are valid owners. It is optional to provide this value + and it can also be sourced from the GITHUB_OWNER environment variable. + When not provided and a token is available, the individual user account owning the token will be used. + When not provided and no token is available, the provider may not function correctly. + EOF + default = null +} + +variable "gh_token_secret_name" { + type = string + description = "The name of the secret retrieved by secrets mixin that contains the GitHub personal access token." + default = null +} diff --git a/github-repositories/versions.tf b/github-repositories/versions.tf new file mode 100644 index 0000000..c820fc8 --- /dev/null +++ b/github-repositories/versions.tf @@ -0,0 +1,14 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + github = { + source = "integrations/github" + version = ">= 5.0" + } + sops = { + source = "carlpett/sops" + version = ">= 0.7" + } + } +}