Skip to content

Commit

Permalink
Conditionally add the image build project
Browse files Browse the repository at this point in the history
  • Loading branch information
JohnStainsby committed Jan 16, 2025
1 parent e3cdc1e commit 557b73b
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 48 deletions.
14 changes: 9 additions & 5 deletions codebase-pipelines/codebuild.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,11 @@ data "aws_codestarconnections_connection" "github_codestar_connection" {
}

resource "aws_codebuild_project" "codebase_image_build" {
for_each = toset(var.image_build ? [""] : [])
name = "${var.application}-${var.codebase}-codebase-pipeline-image-build"
description = "Publish images on push to ${var.repository}"
build_timeout = 30
service_role = aws_iam_role.codebase_image_build.arn
service_role = aws_iam_role.codebase_image_build[""].arn
badge_enabled = true

artifacts {
Expand Down Expand Up @@ -49,8 +50,8 @@ resource "aws_codebuild_project" "codebase_image_build" {

logs_config {
cloudwatch_logs {
group_name = aws_cloudwatch_log_group.codebase_image_build.name
stream_name = aws_cloudwatch_log_stream.codebase_image_build.name
group_name = aws_cloudwatch_log_group.codebase_image_build[""].name
stream_name = aws_cloudwatch_log_stream.codebase_image_build[""].name
}
}

Expand All @@ -70,17 +71,20 @@ resource "aws_codebuild_project" "codebase_image_build" {
resource "aws_cloudwatch_log_group" "codebase_image_build" {
# checkov:skip=CKV_AWS_338:Retains logs for 3 months instead of 1 year
# checkov:skip=CKV_AWS_158:Log groups encrypted using default encryption key instead of KMS CMK
for_each = toset(var.image_build ? [""] : [])
name = "codebuild/${var.application}-${var.codebase}-codebase-image-build/log-group"
retention_in_days = 90
}

resource "aws_cloudwatch_log_stream" "codebase_image_build" {
for_each = toset(var.image_build ? [""] : [])
name = "codebuild/${var.application}-${var.codebase}-codebase-image-build/log-stream"
log_group_name = aws_cloudwatch_log_group.codebase_image_build.name
log_group_name = aws_cloudwatch_log_group.codebase_image_build[""].name
}

resource "aws_codebuild_webhook" "codebuild_webhook" {
project_name = aws_codebuild_project.codebase_image_build.name
for_each = toset(var.image_build ? [""] : [])
project_name = aws_codebuild_project.codebase_image_build[""].name
build_type = "BUILD"

dynamic "filter_group" {
Expand Down
13 changes: 9 additions & 4 deletions codebase-pipelines/iam.tf
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ data "aws_caller_identity" "current" {}
data "aws_region" "current" {}

resource "aws_iam_role" "codebase_image_build" {
for_each = toset(var.image_build ? [""] : [])
name = "${var.application}-${var.codebase}-codebase-pipeline-image-build"
assume_role_policy = data.aws_iam_policy_document.assume_codebuild_role.json
tags = local.tags
Expand All @@ -21,13 +22,15 @@ data "aws_iam_policy_document" "assume_codebuild_role" {
}

resource "aws_iam_role_policy_attachment" "ssm_access" {
role = aws_iam_role.codebase_image_build.name
for_each = toset(var.image_build ? [""] : [])
role = aws_iam_role.codebase_image_build[""].name
policy_arn = "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
}

resource "aws_iam_role_policy" "log_access_for_codebuild_images" {
for_each = toset(var.image_build ? [""] : [])
name = "log-access"
role = aws_iam_role.codebase_image_build.name
role = aws_iam_role.codebase_image_build[""].name
policy = data.aws_iam_policy_document.log_access.json
}

Expand All @@ -50,8 +53,9 @@ data "aws_iam_policy_document" "log_access" {
}

resource "aws_iam_role_policy" "ecr_access_for_codebuild_images" {
for_each = toset(var.image_build ? [""] : [])
name = "ecr-access"
role = aws_iam_role.codebase_image_build.name
role = aws_iam_role.codebase_image_build[""].name
policy = data.aws_iam_policy_document.ecr_access_for_codebuild_images.json
}

Expand Down Expand Up @@ -122,8 +126,9 @@ data "aws_iam_policy_document" "ecr_access_for_codebuild_images" {
}

resource "aws_iam_role_policy" "codestar_connection_access_for_codebuild_images" {
for_each = toset(var.image_build ? [""] : [])
name = "codestar-connection-policy"
role = aws_iam_role.codebase_image_build.name
role = aws_iam_role.codebase_image_build[""].name
policy = data.aws_iam_policy_document.codestar_connection_access.json
}

Expand Down
91 changes: 52 additions & 39 deletions codebase-pipelines/tests/unit.tftest.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -175,117 +175,117 @@ run "test_codebuild_images" {
command = plan

assert {
condition = aws_codebuild_project.codebase_image_build.name == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_codebuild_project.codebase_image_build[""].name == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: my-app-my-codebase-codebase-pipeline-image-build"
}
assert {
condition = aws_codebuild_project.codebase_image_build.description == "Publish images on push to my-repository"
condition = aws_codebuild_project.codebase_image_build[""].description == "Publish images on push to my-repository"
error_message = "Should be: 'Publish images on push to my-repository'"
}
assert {
condition = aws_codebuild_project.codebase_image_build.build_timeout == 30
condition = aws_codebuild_project.codebase_image_build[""].build_timeout == 30
error_message = "Should be: 30"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.artifacts).type == "NO_ARTIFACTS"
condition = one(aws_codebuild_project.codebase_image_build[""].artifacts).type == "NO_ARTIFACTS"
error_message = "Should be: 'NO_ARTIFACTS'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.cache).type == "LOCAL"
condition = one(aws_codebuild_project.codebase_image_build[""].cache).type == "LOCAL"
error_message = "Should be: 'LOCAL'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.cache).modes[0] == "LOCAL_DOCKER_LAYER_CACHE"
condition = one(aws_codebuild_project.codebase_image_build[""].cache).modes[0] == "LOCAL_DOCKER_LAYER_CACHE"
error_message = "Should be: 'LOCAL_DOCKER_LAYER_CACHE'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.environment).compute_type == "BUILD_GENERAL1_SMALL"
condition = one(aws_codebuild_project.codebase_image_build[""].environment).compute_type == "BUILD_GENERAL1_SMALL"
error_message = "Should be: 'BUILD_GENERAL1_SMALL'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.environment).image == "public.ecr.aws/uktrade/ci-image-builder:tag-latest"
condition = one(aws_codebuild_project.codebase_image_build[""].environment).image == "public.ecr.aws/uktrade/ci-image-builder:tag-latest"
error_message = "Should be: 'public.ecr.aws/uktrade/ci-image-builder:tag-latest'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.environment).environment_variable[1].name == "ECR_REPOSITORY"
condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[1].name == "ECR_REPOSITORY"
error_message = "Should be: 'ECR_REPOSITORY'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.environment).environment_variable[1].value == "my-app/my-codebase"
condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[1].value == "my-app/my-codebase"
error_message = "Should be: 'my-app/my-codebase'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.environment).environment_variable[3].name == "ADDITIONAL_ECR_REPOSITORY"
condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[3].name == "ADDITIONAL_ECR_REPOSITORY"
error_message = "Should be: 'ADDITIONAL_ECR_REPOSITORY'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.environment).environment_variable[3].value == "my-additional-repository"
condition = one(aws_codebuild_project.codebase_image_build[""].environment).environment_variable[3].value == "my-additional-repository"
error_message = "Should be: 'my-additional-repository'"
}
assert {
condition = aws_codebuild_project.codebase_image_build.logs_config[0].cloudwatch_logs[
condition = aws_codebuild_project.codebase_image_build[""].logs_config[0].cloudwatch_logs[
0
].group_name == "codebuild/my-app-my-codebase-codebase-image-build/log-group"
error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-group'"
}
assert {
condition = aws_codebuild_project.codebase_image_build.logs_config[0].cloudwatch_logs[
condition = aws_codebuild_project.codebase_image_build[""].logs_config[0].cloudwatch_logs[
0
].stream_name == "codebuild/my-app-my-codebase-codebase-image-build/log-stream"
error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-stream'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.source).type == "GITHUB"
condition = one(aws_codebuild_project.codebase_image_build[""].source).type == "GITHUB"
error_message = "Should be: 'GITHUB'"
}
assert {
condition = one(aws_codebuild_project.codebase_image_build.source).location == "https://github.com/my-repository.git"
condition = one(aws_codebuild_project.codebase_image_build[""].source).location == "https://github.com/my-repository.git"
error_message = "Should be: 'https://github.com/my-repository.git'"
}
assert {
condition = length(regexall(".*/work/cli build.*", aws_codebuild_project.codebase_image_build.source[0].buildspec)) > 0
condition = length(regexall(".*/work/cli build.*", aws_codebuild_project.codebase_image_build[""].source[0].buildspec)) > 0
error_message = "Should contain: '/work/cli build'"
}
assert {
condition = jsonencode(aws_codebuild_project.codebase_image_build.tags) == jsonencode(var.expected_tags)
condition = jsonencode(aws_codebuild_project.codebase_image_build[""].tags) == jsonencode(var.expected_tags)
error_message = "Should be: ${jsonencode(var.expected_tags)}"
}

# Cloudwatch config:
assert {
condition = aws_cloudwatch_log_group.codebase_image_build.name == "codebuild/my-app-my-codebase-codebase-image-build/log-group"
condition = aws_cloudwatch_log_group.codebase_image_build[""].name == "codebuild/my-app-my-codebase-codebase-image-build/log-group"
error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-group'"
}
assert {
condition = aws_cloudwatch_log_group.codebase_image_build.retention_in_days == 90
condition = aws_cloudwatch_log_group.codebase_image_build[""].retention_in_days == 90
error_message = "Should be: 90"
}
assert {
condition = aws_cloudwatch_log_stream.codebase_image_build.name == "codebuild/my-app-my-codebase-codebase-image-build/log-stream"
condition = aws_cloudwatch_log_stream.codebase_image_build[""].name == "codebuild/my-app-my-codebase-codebase-image-build/log-stream"
error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-stream'"
}
assert {
condition = aws_cloudwatch_log_stream.codebase_image_build.log_group_name == "codebuild/my-app-my-codebase-codebase-image-build/log-group"
condition = aws_cloudwatch_log_stream.codebase_image_build[""].log_group_name == "codebuild/my-app-my-codebase-codebase-image-build/log-group"
error_message = "Should be: 'codebuild/my-app-my-codebase-codebase-image-build/log-group'"
}

# Webhook config:
assert {
condition = aws_codebuild_webhook.codebuild_webhook.project_name == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_codebuild_webhook.codebuild_webhook[""].project_name == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'"
}
assert {
condition = aws_codebuild_webhook.codebuild_webhook.build_type == "BUILD"
condition = aws_codebuild_webhook.codebuild_webhook[""].build_type == "BUILD"
error_message = "Should be: 'BUILD'"
}

assert {
condition = length(aws_codebuild_webhook.codebuild_webhook.filter_group) == 2
condition = length(aws_codebuild_webhook.codebuild_webhook[""].filter_group) == 2
error_message = "Should be: 2"
}
assert {
condition = [
for el in aws_codebuild_webhook.codebuild_webhook.filter_group : true
for el in aws_codebuild_webhook.codebuild_webhook[""].filter_group : true
if[for filter in el.filter : true if filter.type == "EVENT" && filter.pattern == "PUSH"][0] == true
][
0
Expand All @@ -294,6 +294,19 @@ run "test_codebuild_images" {
}
}

run "test_codebuild_images_disabled" {
command = plan

variables {
image_build = false
}
# TODO testing when image_build is false, all of the image build stuff isn't created
assert {
condition = length(terraform_data.update_pipeline.triggers_replace) == 3
error_message = "Should be: 3"
}
}

run "test_main_branch_filter" {
command = plan

Expand All @@ -312,7 +325,7 @@ run "test_main_branch_filter" {

assert {
condition = [
for el in aws_codebuild_webhook.codebuild_webhook.filter_group : true
for el in aws_codebuild_webhook.codebuild_webhook[""].filter_group : true
if[
for filter in el.filter : true
if filter.type == "HEAD_REF" && filter.pattern == "^refs/heads/main$"
Expand Down Expand Up @@ -344,7 +357,7 @@ run "test_tagged_branch_filter" {

assert {
condition = [
for el in aws_codebuild_webhook.codebuild_webhook.filter_group : true
for el in aws_codebuild_webhook.codebuild_webhook[""].filter_group : true
if[
for filter in el.filter : true
if filter.type == "HEAD_REF" && filter.pattern == "^refs/tags/.*"
Expand All @@ -363,47 +376,47 @@ run "test_iam" {

# CodeBuild image build
assert {
condition = aws_iam_role.codebase_image_build.name == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_iam_role.codebase_image_build[""].name == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'"
}
assert {
condition = aws_iam_role.codebase_image_build.assume_role_policy == "{\"Sid\": \"AssumeCodebuildRole\"}"
condition = aws_iam_role.codebase_image_build[""].assume_role_policy == "{\"Sid\": \"AssumeCodebuildRole\"}"
error_message = "Should be: {\"Sid\": \"AssumeCodebuildRole\"}"
}
assert {
condition = jsonencode(aws_iam_role.codebase_image_build.tags) == jsonencode(var.expected_tags)
condition = jsonencode(aws_iam_role.codebase_image_build[""].tags) == jsonencode(var.expected_tags)
error_message = "Should be: ${jsonencode(var.expected_tags)}"
}
assert {
condition = aws_iam_role_policy.log_access_for_codebuild_images.name == "log-access"
condition = aws_iam_role_policy.log_access_for_codebuild_images[""].name == "log-access"
error_message = "Should be: 'log-access'"
}
assert {
condition = aws_iam_role_policy.log_access_for_codebuild_images.role == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_iam_role_policy.log_access_for_codebuild_images[""].role == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'"
}
assert {
condition = aws_iam_role_policy.ecr_access_for_codebuild_images.name == "ecr-access"
condition = aws_iam_role_policy.ecr_access_for_codebuild_images[""].name == "ecr-access"
error_message = "Should be: 'ecr-access'"
}
assert {
condition = aws_iam_role_policy.ecr_access_for_codebuild_images.role == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_iam_role_policy.ecr_access_for_codebuild_images[""].role == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'"
}
assert {
condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images.name == "codestar-connection-policy"
condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images[""].name == "codestar-connection-policy"
error_message = "Should be: 'codestar-connection-policy'"
}
assert {
condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images.role == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_iam_role_policy.codestar_connection_access_for_codebuild_images[""].role == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'"
}
assert {
condition = aws_iam_role_policy_attachment.ssm_access.role == "my-app-my-codebase-codebase-pipeline-image-build"
condition = aws_iam_role_policy_attachment.ssm_access[""].role == "my-app-my-codebase-codebase-pipeline-image-build"
error_message = "Should be: 'my-app-my-codebase-codebase-pipeline-image-build'"
}
assert {
condition = aws_iam_role_policy_attachment.ssm_access.policy_arn == "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
condition = aws_iam_role_policy_attachment.ssm_access[""].policy_arn == "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess"
error_message = "Should be: 'arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess'"
}

Expand Down
5 changes: 5 additions & 0 deletions codebase-pipelines/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ variable "services" {
variable "env_config" {
type = any
}

variable "image_build" {
type = bool
default = true
}

0 comments on commit 557b73b

Please sign in to comment.