
CodeBuild-hosted GitHub Actions Runnerの設定例とTips
note株式会社のSREチームのショウゴです。
本記事は、note株式会社 Advent Calendar 2024の10日目の記事です。
noteのSREチームでは、今年サポートが発表されたCodeBuild-hosted GitHub Actions Runnerを検証・一部導入を行いました。導入したことにより、低コストでスケーラブルなGitHub Actionsの実行環境を確保することができました。
本記事では、CodeBuild-hosted GitHub Actions RunnerのTerraformとCloudFormationによる設定例と検証した際に得られたTipsを紹介します。
CodeBuild-hosted GitHub Actions Runnerとは
CodeBuild-hosted GitHub Actions Runner は、AWS CodeBuildをGitHubのself-hosted runnerとして利用することができ、AWS CodeBuild上でGitHub Actionsを動かすことができる仕組みです。
アップデートの変遷
今年の4月にAWS CodeBuildがGitHub Actions Runnerをサポート開始するというアップデートが発表されました。
また、初期のサポートではGitHubのリポジトリ単位のwebhookのみに対応していましたが、今年の6月にGitHubのOrganization単位のwebhookが作成できるようになったというアップデートが発表されました。
AWS CodeBuildを使う利点
AWS CodeBuildを使う利点としては、コンピューティングにLambdaが使えることが挙げられます。厳密な比較ではありませんが、おおよそのコスト比較は以下となります。armのLambdaを利用した場合が最も低価格で利用できます。
GitHubの場合
Linux 2コア:0.008[ドル/分]
CodeBuildの場合
EC2
x86_64, 3GB, 2vCPU:0.005[ドル/分]
arm, 3GB, 2vCPU:0.00425[ドル/分]
Lambda
x86_64, 1GB:0.00002[ドル/秒] = 0.0012[ドル/分]
arm, 1GB:0.00001[ドル/秒] = 0.0006[ドル/分]
設定例
次にAWS側のリポジトリ単位とOrganization単位の2種類の設定例とGithubのワークフローの設定例を紹介します。
AWS側の設定(リポジトリ単位)
リポジトリ単位のCodeBuildプロジェクトを作成するTerraformのコードの例が以下となります。
# main.tf
# ---------------------------------
# CodeBuild Project
resource "aws_codebuild_project" "app_project" {
name = "sample-repository-codebuild-project"
description = "GitHub Actions Runner in CodeBuild for sample repository"
service_role = aws_iam_role.app_role.arn
artifacts {
type = "NO_ARTIFACTS"
}
source {
buildspec = file("${path.module}/buildspec.yaml")
git_clone_depth = 1
location = "https://github.com/org/sample_repository.git"
type = "GITHUB"
git_submodules_config {
fetch_submodules = false
}
}
environment {
compute_type = "BUILD_GENERAL1_SMALL"
image = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
type = "LINUX_CONTAINER"
}
logs_config {
cloudwatch_logs {
status = "ENABLED"
group_name = "/aws/codebuild/github-actions-runner-sample-repository-logs"
}
}
# VPCに配置する場合
vpc_config {
vpc_id = "vpc_id"
subnets = ["subnet_id"]
security_group_ids = ["security_group_id"]
}
}
# ---------------------------------
# CodeBuild Webhook
resource "aws_codebuild_webhook" "app_webhook" {
project_name = "sample-repository-codebuild-project"
filter_group {
filter {
pattern = "WORKFLOW_JOB_QUEUED"
type = "EVENT"
}
}
}
# ---------------------------------
# Data: IAM Policy Document
data "aws_iam_policy_document" "codebuild_role" {
statement {
effect = "Allow"
actions = ["sts:AssumeRole"]
principals {
type = "Service"
identifiers = ["codebuild.amazonaws.com"]
}
}
}
data "aws_iam_policy_document" "codebuild_role_policy" {
statement {
sid = "CodeBuildPolicy"
effect = "Allow"
actions = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents",
"s3:GetObject",
"s3:GetObjectVersion",
"s3:PutObject"
]
resources = ["*"]
}
}
# ---------------------------------
# IAM
resource "aws_iam_role" "app_role" {
name = "github-actions-runner-sample-repository-role"
assume_role_policy = data.aws_iam_policy_document.codebuild_role.json
}
resource "aws_iam_role_policy" "app_role_policy" {
name = "github-actions-runner-sample-repository-role-policy"
role = aws_iam_role.app_role.id
policy = data.aws_iam_policy_document.codebuild_role_policy.json
}
buildspec.ymlはデフォルトだと上書きされるため、以下の内容のように書きます。
# buildspec.yml
# このbuildspec.yamlはCodeBuildで上書きされる。
version: 0.2
phase:
build:
commands:
- echo "Hello, CodeBuild!"
AWS側の設定(Organization単位)
Organization単位のCodeBuildプロジェクトを作成するTerraformとCloudFormationのコードの例が以下となります。
# main.tf
resource "aws_cloudformation_stack" "app_project" {
name = "sample-organization-codebuild-project"
template_body = file("${path.module}/cfn_template.yaml")
disable_rollback = false
parameters = {
ProjectName = "sample-organization-codebuild-project"
Description = "GitHub Actions Runner in CodeBuild for sample organization"
ServiceRole = aws_iam_role.app_role.arn
EnvironmentType = "LINUX_CONTAINER"
EnvironmentComputeType = "BUILD_GENERAL1_SMALL"
EnvironmentImage = "aws/codebuild/amazonlinux2-x86_64-standard:5.0"
ExcludeReposPattern = "^(?!${local.exclude_repos_pattern}).*$" # 特定のリポジトリを除外したい場合
}
}
# IAMはリポジトリ単位の場合と同様に設定します。
# cfn_template.yml
AWSTemplateFormatVersion: "2010-09-09"
Description: "GitHub Actions Runner in CodeBuild"
Parameters:
ProjectName:
Description: Project Name
Type: String
Description:
Description: Description
Type: String
ServiceRole:
Description: Service Role
Type: String
EnvironmentType:
Description: Environment Type
Type: String
EnvironmentComputeType:
Description: Environment Compute Type
Type: String
EnvironmentImage:
Description: Environment Image
Type: String
ExcludeReposPattern:
Description: Exclude Repos Pattern
Type: String
Resources:
CodeBuildProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref ProjectName
Description: !Ref Description
ServiceRole: !Ref ServiceRole
Artifacts:
Type: NO_ARTIFACTS
Environment:
Type: !Ref EnvironmentType
ComputeType: !Ref EnvironmentComputeType
Image: !Ref EnvironmentImage
Source:
Type: GITHUB
Location: CODEBUILD_DEFAULT_WEBHOOK_SOURCE_LOCATION
BuildSpec: buildspec.yml
Triggers:
Webhook: true
ScopeConfiguration:
Name: sample-organization
FilterGroups:
- - Type: EVENT
Pattern: WORKFLOW_JOB_QUEUED
- Type: REPOSITORY_NAME
Pattern: !Ref ExcludeReposPattern
LogsConfig:
CloudWatchLogs:
Status: ENABLED
GroupName: !Sub /aws/codebuild/${ProjectName}
S3Logs:
Status: DISABLED
Tags:
- Key: Name
Value: !Ref ProjectName
検証を行った2024年6月当時は、terraform-provider-awsの公式ドキュメントにOrganization単位での設定の仕方が明確に言及されていなかったため、CloudFormationで設定を行いましたが、v5.59.0でドキュメントが更新されているため、現在はTerraformでも定義が可能です。

GitHub側の設定
runs-onの箇所を以下のように設定します。ビルドプロジェクト名に「codebuild-」というprefixを付ける必要があります。このprefixをつけ忘れることがよくあるため注意が必要です。
リポジトリ単位
# org/repository/.github/workflows/sample.yml
name: Test
on: [push]
jobs:
test:
runs-on:
- codebuild-sample-repository-codebuild-project-${{ github.run_id }}-${{ github.run_attempt }}
steps:
- run: echo "Hello World!"
Organization単位
# org/repository/.github/workflows/sample.yml
name: Test
on: [push]
jobs:
test:
runs-on:
- codebuild-sample-organization-codebuild-project-${{ github.run_id }}-${{ github.run_attempt }}
steps:
- run: echo "Hello World!"
また、以下のようにimageの種類やインスタンスサイズを上書きすることができます。
# org/repository/.github/workflows/samlple.yml
name: Test
on: [push]
jobs:
Test:
runs-on:
- codebuild-sample-repository-codebuild-project-${{ github.run_id }}-${{ github.run_attempt }}
- image:arm-3.0 # 👈️ image指定の上書き
- instance-size:large # 👈️ インスタンスタイズの指定の上書き
steps:
- run: echo "Hello World!"
アップデート発表直後は下記のように1行のラベルで書く方法が公式の書き方でしたが、現在はこの書き方はレガシーとなっているため上記の書き方が推奨されています。またFleetの指定や、buildspecを使えるようにするフラグの設定なども追加されています。
# org/repository/.github/workflows/legacy-sample.yml
name: Test
on: [push]
jobs:
Test:
// 1行のラベルで書く方法は非推奨の書き方です
runs-on: codebuild-sample-repository-codebuild-project-${{ github.run_id }}-${{ github.run_attempt }}-arm-3.0-large
steps:
- run: echo "Hello World!"
Tipsの紹介
次に検証の過程で得られたTipsを紹介します。
1. GitHubの環境変数の活用
例えば、「aws/codebuild/amazonlinux2-aarch64-standard:3.0」のイメージを利用したい場合、ラベルの値として「arm-3.0」を使用します。Organization単位で利用し、今後新しいバージョンのイメージが出た場合に、複数のリポジトリのラベルを全て修正するのはかなり苦労する可能性があるため、GitHubのOrganizationの変数に最新版のイメージのラベル名を「GHA_ARM」のように設定しておくと一斉置換できるので良いのではないかと考えています。
# EC2利用の場合
GHA_ARM = arm-3.0
name: Test
on: [push]
jobs:
Test:
runs-on:
- codebuild-sample-org-codebuild-project-${{ github.run_id }}-${{ github.run_attempt }}
- image:${{ vars.GHA_ARM }}
- instance-size:large
steps:
- run: echo "Hello World!"
# Lambda利用の場合
GHA_LINUX_LAMBDA_NODE = linux-lambda-nodejs20
name: Test
on: [push]
jobs:
Test:
runs-on:
- codebuild-sample-org-codebuild-project-${{ github.run_id }}-${{ github.run_attempt }}
- image:${{ vars.GHA_LINUX_LAMBDA_NODE }}
- instance-size:large
steps:
- run: echo "Hello World!"
2. Webhook作成時の注意点
TerraformでWebhookを作成する際に以下のようなエラーが出ることがあります。この場合は、AWSのマネージメントコンソール上で、GitHubへの接続を行ってから再実行すると解消されます。
│ Error: creating CodeBuild Webhook (sample-repository-codebuild-project): operation error CodeBuild: CreateWebhook, https response error StatusCode: 400, RequestID: xxxxxx-xxxx-xxxx-xxxxx, ResourceNotFoundException: Access token not found in CodeBuild project for server type github
│
│ with aws_codebuild_webhook.app_webhook,
│ on config_codebuild.tf line XX, in resource "aws_codebuild_webhook" "app_webhook":
│ XX: resource "aws_codebuild_webhook" "app_webhook" {

3. 構築時のデバッグ
ラベルを指定してワークフローを動かしてもCodeBuild側でビルドが開始されないことがあります。その場合は、GitHub側のWebhooksのRecent Deliveriesのページの実行履歴で、エラーなどの発生有無が確認できます。


4. Lambdaコンピューティングの制約
Lambdaコンピューティングには以下の制約などがあります。
root権限が必要なツール(yum, rpm)などが使えない。
docker build/runが非対応
15分以上の処理実行ができない。
noteのSREチームでは、PRのAuthorの自動設定や、AWS CLIなどを実行する定期実行ワークフローなど短い処理時間で実行頻度の多いワークフローなどでLambdaコンピューティングを利用しています。
5. actions/setup-python利用時のイメージの制約
actions/setup-pythonを利用する場合は、以下のIssueに記載されているUbuntuのイメージを使用する必要があります。
I think it is an expected behaviour because Python versions 3.x was built for Ubuntu 18.04 - 22.04 that is why the action can't find the proper version.
なお、Amazon Linux 2とAmazon Linux 2023をサポートしているOSSのActionも公開されています。
Since this setup-python github action is not supporting amazon linux and has no foreseeable plans of doing so, i have created an open source action to support the same
https://github.com/kishaningithub/setup-python-amazon-linux
6. GitHub CLIのセルフインストール
CodeBuildで動かす場合にGitHub CLIを使う場合は、GitHub CLIをセルフインストールする必要があります。検証当時、arm64とx86_64の両方に対応している良さそうなカスタムアクションがなかったため、自作しました。
以上がCodeBuild-hosted GitHub Actions Runnerの設定例と検証時に得られたTipsの紹介となります。利用を検討している方の参考になると嬉しいです。
▼ noteエンジニアアドベントカレンダーはこちら
▼さらにnoteの技術記事が読みたい方はこちら