Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DEV-1939] - Use self hosted runner #1174

Merged
merged 12 commits into from
Oct 3, 2024
5 changes: 5 additions & 0 deletions .changeset/new-birds-joke.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"infrastructure": minor
---

Using codebuild for actions demanding high disk usage and private AWS networking
2 changes: 1 addition & 1 deletion .github/workflows/code_review.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,4 @@ jobs:
uses: ./.github/actions/check-nextjs-bundle-size
with:
path_to_nextjs_folder: ./apps/nextjs-website
upload_path: apps/nextjs-website/.next/analyze/__bundle_analysis.json
upload_path: apps/nextjs-website/.next/analyze/__bundle_analysis.json
christian-calabrese marked this conversation as resolved.
Show resolved Hide resolved
18 changes: 17 additions & 1 deletion apps/infrastructure/src/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,27 @@ module "chatbot" {
environment = var.environment
tags = var.tags

website_bucket_name = module.website.website_bucket_name
website_bucket_name = module.website.website_bucket.name
dns_chatbot_hosted_zone = module.core.dns_chatbot_hosted_zone
cognito_user_pool = module.website.cognito_user_pool
vpc = module.cms.vpc
security_groups = module.cms.security_groups
dns_domain_name = var.dns_domain_name
ecs_redis = var.chatbot_ecs_redis
}

module "cicd" {
source = "./modules/cicd"

environment = var.environment
tags = var.tags

create_chatbot = var.create_chatbot
vpc = module.cms.vpc
security_groups = var.create_chatbot ? merge(module.cms.security_groups, module.chatbot[0].security_groups) : module.cms.security_groups
redis_port = var.chatbot_ecs_redis.port
github_repository = var.github_repository

website_bucket = module.website.website_bucket
website_cdn = module.website.website_cdn
}
2 changes: 2 additions & 0 deletions apps/infrastructure/src/modules/chatbot/efs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ resource "aws_efs_file_system" "this" {

performance_mode = "generalPurpose"
throughput_mode = "bursting"

tags = merge(var.tags, { Name = "${local.prefix}-efs" })
}

resource "aws_efs_access_point" "this" {
Expand Down
5 changes: 5 additions & 0 deletions apps/infrastructure/src/modules/chatbot/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,8 @@ output "lambda_cloudwatch_log_group_arn" {
value = module.lambda_function.lambda_cloudwatch_log_group_arn
}

output "security_groups" {
value = {
redis = aws_security_group.redis.id
}
}
51 changes: 51 additions & 0 deletions apps/infrastructure/src/modules/cicd/codebuild.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
resource "aws_codebuild_project" "github_runner" {
name = "${var.environment}-github-runner"
description = "CodeBuild project for self-hosted GitHub runner"
service_role = aws_iam_role.codebuild_role.arn
build_timeout = var.build_timeout
artifacts {
type = "NO_ARTIFACTS"
}

environment {
compute_type = "BUILD_GENERAL1_MEDIUM"
image = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
type = "LINUX_CONTAINER"
image_pull_credentials_type = "CODEBUILD"
privileged_mode = true
}

source {
type = "GITHUB"
location = "https://github.com/${var.github_repository}.git"
git_clone_depth = 1
}

vpc_config {
vpc_id = var.vpc.id
subnets = var.vpc.private_subnets
security_group_ids = [aws_security_group.codebuild.id]
}

logs_config {
cloudwatch_logs {
group_name = "/aws/codebuild/${var.environment}-github-runner"
stream_name = "log-stream"
}
}

tags = var.tags
}

resource "aws_codebuild_webhook" "github_webhook" {
project_name = aws_codebuild_project.github_runner.name

filter_group {
filter {
type = "EVENT"
pattern = "WORKFLOW_JOB_QUEUED"
}
}

depends_on = [aws_iam_role_policy_attachment.github_connection]
}
1 change: 1 addition & 0 deletions apps/infrastructure/src/modules/cicd/data.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
data "aws_caller_identity" "current" {}
170 changes: 170 additions & 0 deletions apps/infrastructure/src/modules/cicd/iam.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
resource "aws_iam_role" "codebuild_role" {
name = "codebuild-${var.environment}-github-runner-service-role"

assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "codebuild.amazonaws.com"
}
}
]
})
}

resource "aws_iam_role_policy_attachment" "codebuild_policy" {
role = aws_iam_role.codebuild_role.name
policy_arn = "arn:aws:iam::aws:policy/AWSCodeBuildAdminAccess"
}

resource "aws_iam_policy" "deploy_website" {
name = "${local.prefix}-deploy-website"
description = "Policy to allow to deploy the website"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"s3:PutObject",
"s3:GetObject",
"s3:PutObjectAcl",
"s3:DeleteObject"
]
Effect = "Allow"
Resource = [
format("%s/*", var.website_bucket.arn)
]
},
{
Action = [
"s3:ListBucket"
]
Effect = "Allow"
Resource = [
var.website_bucket.arn
]
},
{
Action = [
"cloudfront:CreateInvalidation"
]
Effect = "Allow"
Resource = [
var.website_cdn.arn
]
}
]
})
}

resource "aws_iam_role_policy_attachment" "deploy_website" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.deploy_website.arn
}

resource "aws_iam_policy" "github_connection" {
name = "${local.prefix}-github-connection"
description = "Policy to allow to use the github connection"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"codeconnections:*",
"codestar-connections:*"
]
Effect = "Allow"
Resource = [
"*"
]
}
]
})
}

resource "aws_iam_role_policy_attachment" "github_connection" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.github_connection.arn
}

resource "aws_iam_policy" "vpc_connection" {
name = "${local.prefix}-vpc-connection"
description = "Policy to allow to use the vpc connection"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"ec2:CreateNetworkInterface",
"ec2:DescribeDhcpOptions",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeVpcs"
]
Effect = "Allow"
Resource = [
"*"
]
},
{
Action = [
"ec2:CreateNetworkInterfacePermission"
]
Effect = "Allow"
Resource = [
"arn:aws:ec2:${var.aws_region}:${data.aws_caller_identity.current.account_id}:network-interface/*"
]
Condition = {
StringEquals = {
"ec2:AuthorizedService" = "codebuild.amazonaws.com"
}
}
}
]
})
}

resource "aws_iam_role_policy_attachment" "vpc_connection" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.vpc_connection.arn
}

resource "aws_iam_policy" "cloudwatch" {
name = "${local.prefix}-cloudwatch"
description = "Policy to allow to log in cloudwatch"

policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:DescribeLogGroups",
"logs:DescribeLogStreams",
"logs:PutLogEvents",
"logs:GetLogEvents",
"logs:FilterLogEvents",
]
Effect = "Allow"
Resource = [
"arn:aws:logs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/codebuild/${var.environment}-github-runner:*",
"arn:aws:logs:${var.aws_region}:${data.aws_caller_identity.current.account_id}:log-group:/aws/codebuild/${var.environment}-github-runner:log-stream:log-stream/*"
]
}
]
})
}

resource "aws_iam_role_policy_attachment" "cloudwatch" {
role = aws_iam_role.codebuild_role.name
policy_arn = aws_iam_policy.cloudwatch.arn
}
3 changes: 3 additions & 0 deletions apps/infrastructure/src/modules/cicd/locals.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
locals {
prefix = "${var.module}-${var.environment}"
}
30 changes: 30 additions & 0 deletions apps/infrastructure/src/modules/cicd/networking.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
resource "aws_security_group" "codebuild" {
name = "${local.prefix}-codebuild"
description = "Security group for Codebuild container"
vpc_id = var.vpc.id

# https://registry.terraform.io/providers/hashicorp/aws/5.35.0/docs/resources/security_group#recreating-a-security-group
lifecycle {
create_before_destroy = true
}
}

resource "aws_security_group_rule" "codebuild_redis_ingress" {
count = var.create_chatbot ? 1 : 0
type = "ingress"
from_port = var.redis_port
to_port = var.redis_port
protocol = "tcp"
security_group_id = var.security_groups.redis
source_security_group_id = aws_security_group.codebuild.id
}


resource "aws_security_group_rule" "codebuild_egress" {
type = "egress"
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
security_group_id = aws_security_group.codebuild.id
}
8 changes: 8 additions & 0 deletions apps/infrastructure/src/modules/cicd/providers.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 5.33.0"
}
}
}
Loading
Loading