From 99a1ca482b2da32cf9228af743db8e3febefface Mon Sep 17 00:00:00 2001 From: wanis-fahmy Date: Wed, 30 Jul 2025 09:53:13 +0200 Subject: [PATCH 1/3] feat: adds support for GitHub App CodeConnection --- .gitignore | 2 ++ README.md | 6 +++++- iam.tf | 24 ++++++++++++++++++++++++ locals.tf | 2 ++ main.tf | 15 ++++++++++++++- variables.tf | 6 ++++++ 6 files changed, 53 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 19a06e3..8e5f02c 100644 --- a/.gitignore +++ b/.gitignore @@ -48,3 +48,5 @@ test.auto.tfvars.json # Apple .DS_Store + +.idea \ No newline at end of file diff --git a/README.md b/README.md index e46d9a0..cd2c185 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,7 @@ module "github_runner" { | [environment\_compute\_type](#input\_environment\_compute\_type) | Information about the compute resources the build project will use. Valid values: `BUILD_GENERAL1_SMALL`, `BUILD_GENERAL1_MEDIUM`, `BUILD_GENERAL1_LARGE`, `BUILD_GENERAL1_2XLARGE`, `BUILD_LAMBDA_1GB`, `BUILD_LAMBDA_2GB`, `BUILD_LAMBDA_4GB`, `BUILD_LAMBDA_8GB`, `BUILD_LAMBDA_10GB`. `BUILD_GENERAL1_SMALL` is only valid if type is set to `LINUX_CONTAINER`. When type is set to `LINUX_GPU_CONTAINER`, compute\_type must be `BUILD_GENERAL1_LARGE`. When type is set to `LINUX_LAMBDA_CONTAINER` or `ARM_LAMBDA_CONTAINER`, compute\_type must be `BUILD_LAMBDA_XGB` | `string` | `"BUILD_GENERAL1_SMALL"` | no | | [environment\_image](#input\_environment\_image) | Docker image to use for this build project. Valid values include Docker images provided by CodeBuild (e.g `aws/codebuild/amazonlinux2-x86_64-standard:4.0`), Docker Hub images (e.g., `hashicorp/terraform:latest`) and full Docker repository URIs such as those for ECR (e.g., `137112412989.dkr.ecr.us-west-2.amazonaws.com/amazonlinux:latest`). If not specified and not using ECR, then a default CodeBuild image is used, or if using ECR then an ECR image with a `latest` tag is used. | `string` | `null` | no | | [environment\_type](#input\_environment\_type) | Type of build environment to use for related builds. Valid values: `LINUX_CONTAINER`, `LINUX_GPU_CONTAINER`, `WINDOWS_CONTAINER` (deprecated), `WINDOWS_SERVER_2019_CONTAINER`, `ARM_CONTAINER`, `LINUX_LAMBDA_CONTAINER`, `ARM_LAMBDA_CONTAINER` | `string` | `"LINUX_CONTAINER"` | no | +| [github\_codeconnection\_arn](#input\_github\_codeconnection\_arn) | ARN of an active GitHub app CodeConnection. If not specified then GitHub auth must be configured separately. | `string` | `null` | no | | [github\_personal\_access\_token](#input\_github\_personal\_access\_token) | The GitHub personal access token to use for accessing the repository. If not specified then GitHub auth must be configured separately. | `string` | `null` | no | | [github\_personal\_access\_token\_ssm\_parameter](#input\_github\_personal\_access\_token\_ssm\_parameter) | The GitHub personal access token to use for accessing the repository. If not specified then GitHub auth must be configured separately. | `string` | `null` | no | | [iam\_role\_assume\_role\_policy](#input\_iam\_role\_assume\_role\_policy) | The IAM role assume role policy document to use. If not specified then a default is used. | `string` | `null` | no | @@ -270,6 +271,7 @@ No modules. |------|------| | [aws_cloudwatch_log_group.codebuild](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/cloudwatch_log_group) | resource | | [aws_codebuild_project.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_project) | resource | +| [aws_codebuild_source_credential.codeconnection](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_source_credential) | resource | | [aws_codebuild_source_credential.ssm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_source_credential) | resource | | [aws_codebuild_source_credential.string](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_source_credential) | resource | | [aws_codebuild_webhook.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/codebuild_webhook) | resource | @@ -277,6 +279,7 @@ No modules. | [aws_ecr_repository.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/ecr_repository) | resource | | [aws_iam_role.this](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role) | resource | | [aws_iam_role_policy.cloudwatch_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | +| [aws_iam_role_policy.codeconnection_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.ecr_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.networking_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_role_policy.s3_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | @@ -288,6 +291,7 @@ No modules. | [aws_cloudwatch_log_group.codebuild](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/cloudwatch_log_group) | data source | | [aws_iam_policy_document.assume_role](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.cloudwatch_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | +| [aws_iam_policy_document.codeconnection_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.ecr_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.networking_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | | [aws_iam_policy_document.s3_required](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document) | data source | @@ -297,4 +301,4 @@ No modules. ---- ``` - + \ No newline at end of file diff --git a/iam.tf b/iam.tf index 32b5914..93f4f2b 100644 --- a/iam.tf +++ b/iam.tf @@ -134,6 +134,30 @@ resource "aws_iam_role_policy" "ecr_required" { policy = data.aws_iam_policy_document.ecr_required[count.index].json } +data "aws_iam_policy_document" "codeconnection_required" { + count = local.has_github_codeconnection_arn ? 1 : 0 + statement { + effect = "Allow" + # https://docs.aws.amazon.com/dtconsole/latest/userguide/rename.html + actions = length(regexall("^arn:aws:codestar-connections:.*", var.github_codeconnection_arn)) > 0 ? [ + "codestar-connections:GetConnection", + "codestar-connections:GetConnectionToken" + ] : [ + "codeconnections:GetConnection", + "codeconnections:GetConnectionToken", + "codeconnections:UseConnection" + ] + resources = [var.github_codeconnection_arn] + } +} + +resource "aws_iam_role_policy" "codeconnection_required" { + count = local.has_github_codeconnection_arn ? 1 : 0 + name = "${var.name}-codeconnection" + role = local.create_iam_role ? aws_iam_role.this[0].name : var.iam_role_name + policy = data.aws_iam_policy_document.codeconnection_required[count.index].json +} + data "aws_iam_policy_document" "assume_role" { statement { effect = "Allow" diff --git a/locals.tf b/locals.tf index e3dc2c1..a909c50 100644 --- a/locals.tf +++ b/locals.tf @@ -11,6 +11,8 @@ locals { has_github_personal_access_token_ssm_parameter = var.github_personal_access_token_ssm_parameter != null + has_github_codeconnection_arn = var.github_codeconnection_arn != null + subnet_arns = [for subnet_id in var.subnet_ids : "arn:aws:ec2:${local.aws_region}:${local.aws_account_id}:subnet/${subnet_id}"] create_iam_role = var.iam_role_name == null diff --git a/main.tf b/main.tf index 427b04d..73868f7 100644 --- a/main.tf +++ b/main.tf @@ -18,6 +18,7 @@ locals { } resource "aws_codebuild_project" "this" { + depends_on = [aws_iam_role_policy.codeconnection_required] name = var.name description = var.description build_timeout = var.build_timeout @@ -98,8 +99,20 @@ resource "aws_codebuild_source_credential" "ssm" { token = data.aws_ssm_parameter.github_personal_access_token[0].value } +resource "aws_codebuild_source_credential" "codeconnection" { + count = local.has_github_codeconnection_arn ? 1 : 0 + auth_type = "CODECONNECTIONS" + server_type = "GITHUB" + token = var.github_codeconnection_arn +} + resource "aws_codebuild_webhook" "this" { - depends_on = [aws_codebuild_source_credential.string, aws_codebuild_source_credential.ssm] + depends_on = [ + aws_codebuild_source_credential.string, + aws_codebuild_source_credential.ssm, + aws_codebuild_source_credential.codeconnection, + aws_iam_role_policy.codeconnection_required + ] project_name = aws_codebuild_project.this.name build_type = "BUILD" filter_group { diff --git a/variables.tf b/variables.tf index c909153..8f3b1fb 100644 --- a/variables.tf +++ b/variables.tf @@ -151,6 +151,12 @@ variable "github_personal_access_token_ssm_parameter" { default = null } +variable "github_codeconnection_arn" { + description = "ARN of an active GitHub app CodeConnection. If not specified then GitHub auth must be configured separately." + type = string + default = null +} + # Encryption variable "kms_key_id" { description = "The AWS KMS key to be used" From 3b9f9bbba0929b515ec4bae73487160cfefd0ac0 Mon Sep 17 00:00:00 2001 From: wanis-fahmy Date: Wed, 30 Jul 2025 14:00:29 +0200 Subject: [PATCH 2/3] chore: runs pre-commit --- .gitignore | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 8e5f02c..a1a34b0 100644 --- a/.gitignore +++ b/.gitignore @@ -49,4 +49,4 @@ test.auto.tfvars.json # Apple .DS_Store -.idea \ No newline at end of file +.idea diff --git a/README.md b/README.md index cd2c185..4e751fa 100644 --- a/README.md +++ b/README.md @@ -301,4 +301,4 @@ No modules. ---- ``` - \ No newline at end of file + From 1943b8834fd1511e225b8b6a080a79a8e6d8eaf8 Mon Sep 17 00:00:00 2001 From: wanis-fahmy Date: Thu, 18 Dec 2025 14:22:01 +0100 Subject: [PATCH 3/3] improvement: Add Cloudwatch group name to outputs --- README.md | 1 + examples/multiple-runners/README.md | 2 +- outputs.tf | 5 +++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 823c198..6b285a6 100644 --- a/README.md +++ b/README.md @@ -241,6 +241,7 @@ No modules. | Name | Description | |------|-------------| | [aws\_security\_group\_id](#output\_aws\_security\_group\_id) | ID of the security group created for the CodeBuild project | +| [cloudwatch\_log\_group\_name](#output\_cloudwatch\_log\_group\_name) | Name of the CloudWatch log group for the CodeBuild project | | [codebuild\_project\_arn](#output\_codebuild\_project\_arn) | ARN of the CodeBuild project, to be used when running GitHub Actions | | [codebuild\_project\_name](#output\_codebuild\_project\_name) | Name of the CodeBuild project, to be used when running GitHub Actions | | [codebuild\_role\_name](#output\_codebuild\_role\_name) | Name of the CodeBuild role, to be used when running GitHub Actions | diff --git a/examples/multiple-runners/README.md b/examples/multiple-runners/README.md index 1471b8c..c8ab412 100644 --- a/examples/multiple-runners/README.md +++ b/examples/multiple-runners/README.md @@ -29,7 +29,7 @@ module "runners" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [github\_personal\_access\_token\_ssm\_parameter](#input\_github\_personal\_access\_token\_ssm\_parameter) | The GitHub personal access token to use for accessing the repository | `string` | n/a | yes | -| [source\_locations](#input\_source\_locations) | Map of source locations to use when creating runners |
map(object({
source_location = string
source_name = string
}))
|
{
"example-1": {
"source_location": "https://github.com/my-org/example-1.git",
"source_name": "example-1"
},
"example-2": {
"source_location": "https://github.com/my-org/example-2.git",
"source_name": "example-2"
}
}
| no | +| [source\_locations](#input\_source\_locations) | Map of source locations to use when creating runners |
map(object({
source_location = string
source_name = string
}))
|
{
"example-1": {
"source_location": "https://github.com/my-org/example-1.git",
"source_name": "example-1"
},
"example-2": {
"source_location": "https://github.com/my-org/example-2.git",
"source_name": "example-2"
}
}
| no | | [subnet\_ids](#input\_subnet\_ids) | The list of Subnet IDs for AWS Codebuild to launch ephemeral EC2 instances in. | `list(string)` | n/a | yes | | [vpc\_id](#input\_vpc\_id) | The VPC ID for AWS Codebuild to launch ephemeral instances in. | `string` | n/a | yes | diff --git a/outputs.tf b/outputs.tf index 6980435..e006f77 100644 --- a/outputs.tf +++ b/outputs.tf @@ -27,3 +27,8 @@ output "environment_image" { value = local.environment_image description = "Docker image used for this CodeBuild project" } + +output "cloudwatch_log_group_name" { + value = try(aws_cloudwatch_log_group.codebuild[0].name, null) + description = "Name of the CloudWatch log group for the CodeBuild project" +}