Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README-ja.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@

- Environment、AWS region、IAM role は `workflow-config.yaml` で定義する。環境の追加・削除は同ファイルの編集で行う。
- 認証は GitHub OIDC。`aws/github-oidc-auth/` が environment ごとの plan / apply role を発行し、executor がそれを引き受ける。
- GitHub environment `production` は tag pattern `*-v*` に一致する ref からの deployment だけを受け付ける。この設定は `github/repository/` で管理する。
- Terragrunt の remote state は S3 + DynamoDB に保存される。bucket / lock table 名は各 `aws/{service}/root.hcl`(および `github/` 配下の同等ファイル)で定義される。

### Pipeline Flow
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ A PR labeled by `panicboat/deploy-actions` is resolved against `workflow-config.

- Environments, AWS regions, and IAM roles are defined in `workflow-config.yaml`. Adding or removing an environment means editing that file.
- Authentication uses GitHub OIDC. `aws/github-oidc-auth/` issues per-environment plan / apply roles that the executors assume.
- The GitHub environment `production` accepts deployments only from refs that match the tag pattern `*-v*`. The setting is managed in `github/repository/`.
- Terragrunt remote state lives in S3 + DynamoDB; bucket and lock-table names are defined in each `aws/{service}/root.hcl` (and the equivalent under `github/`).

### Pipeline Flow
Expand Down
1 change: 1 addition & 0 deletions github/repository/master/platform.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ locals {
wiki = false
projects = true
}
environments = { production = { deployment_tag_patterns = ["*-v*"] } }
}
}
33 changes: 33 additions & 0 deletions github/repository/modules/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,36 @@ resource "github_workflow_repository_permissions" "repository" {
default_workflow_permissions = "read"
can_approve_pull_request_reviews = false
}

resource "github_repository_environment" "repository" {
for_each = merge([
for repo_key, repo in var.repositories : {
for env_name, env in repo.environments :
"${repo_key}/${env_name}" => { repo_key = repo_key, name = env_name }
}
]...)

repository = github_repository.repository[each.value.repo_key].name
environment = each.value.name
can_admins_bypass = false

deployment_branch_policy {
protected_branches = false
custom_branch_policies = true
}
}

resource "github_repository_environment_deployment_policy" "repository" {
for_each = merge([
for repo_key, repo in var.repositories : merge([
for env_name, env in repo.environments : {
for pattern in env.deployment_tag_patterns :
"${repo_key}/${env_name}/${pattern}" => { env_key = "${repo_key}/${env_name}", pattern = pattern }
}
]...)
]...)

repository = github_repository_environment.repository[each.value.env_key].repository
environment = github_repository_environment.repository[each.value.env_key].environment
tag_pattern = each.value.pattern
}
106 changes: 106 additions & 0 deletions github/repository/modules/tests/environment.tftest.hcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
mock_provider "aws" {}

mock_provider "github" {}

variables {
project_name = "repository"
environment = "master"
github_org = "panicboat"
github_token = "dummy"
}

run "creates_tag_policy_for_declared_environment" {
command = plan

variables {
repositories = {
platform = {
name = "platform"
description = "Platform"
visibility = "public"
features = {
issues = true
wiki = false
projects = true
}
environments = {
production = { deployment_tag_patterns = ["*-v*"] }
}
}
}
}

assert {
condition = keys(github_repository_environment.repository) == ["platform/production"]
error_message = "One environment must exist per declared repository and environment."
}

assert {
condition = github_repository_environment.repository["platform/production"].environment == "production"
error_message = "The environment must use the declared name."
}

assert {
condition = github_repository_environment.repository["platform/production"].can_admins_bypass == false
error_message = "Admins must not bypass the deployment policy."
}

assert {
condition = github_repository_environment.repository["platform/production"].deployment_branch_policy[0].custom_branch_policies == true
error_message = "The environment must restrict deployments with custom policies."
}

assert {
condition = github_repository_environment.repository["platform/production"].deployment_branch_policy[0].protected_branches == false
error_message = "The environment must not rely on protected branches."
}

assert {
condition = keys(github_repository_environment_deployment_policy.repository) == ["platform/production/*-v*"]
error_message = "One deployment policy must exist per declared tag pattern."
}

assert {
condition = github_repository_environment_deployment_policy.repository["platform/production/*-v*"].tag_pattern == "*-v*"
error_message = "The deployment policy must match tags, not branches."
}

assert {
condition = github_repository_environment_deployment_policy.repository["platform/production/*-v*"].environment == "production"
error_message = "The deployment policy must target the declared environment."
}

assert {
condition = github_repository_environment_deployment_policy.repository["platform/production/*-v*"].repository == "platform"
error_message = "The deployment policy must target the declared repository."
}
}

run "creates_no_environment_by_default" {
command = plan

variables {
repositories = {
platform = {
name = "platform"
description = "Platform"
visibility = "public"
features = {
issues = true
wiki = false
projects = true
}
}
}
}

assert {
condition = length(github_repository_environment.repository) == 0
error_message = "No environment must exist when environments is not declared."
}

assert {
condition = length(github_repository_environment_deployment_policy.repository) == 0
error_message = "No deployment policy must exist when environments is not declared."
}
}
1 change: 1 addition & 0 deletions github/repository/modules/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ variable "repositories" {
wiki = bool
projects = bool
})
environments = optional(map(object({ deployment_tag_patterns = list(string) })), {})
}))
}

Expand Down
Loading