はじめに
CodeBuildを触ってみたいと思い、ハンズオンなど探してみたのですが、CodePipelineの例ばかりでした。
そのためCodeBuildをメインとして自身で手を動かした内容をまとめておきました。
概要
本記事では以下の事をやっています。
- CodeBuildの実行
- 取り扱うファイルを格納するため、CodeCommitを用意します
- CodeBuildで利用するインスタンスから、ファイルをS3に格納
- 格納用のS3バケットを用意します
参考
Level0:動かすだけ
まず、CodeCommitを作ります。以下は作成するCFnテンプレートですが、コンソールから作成してもよいです。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyCodeCommitRepo:
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: forCodeBuild
作成したCodeCommitに、以下のbuildspec.yml
ファイルをコミットします。
version: 0.2
phases:
build:
commands:
- echo "Hello, CodeBuild!"
- echo "This is a sample build."
今回は単純なので、コンソールで操作しています。コンソールからファイルをアップしたり、新規で作成することができます。
最初に作成されるブランチ名はmain
になります。
ソースは先ほど作成し、コミット時に作られたmain
ブランチを指定します。
ログは、buildspec.yml
でのechoを見るために、CloudWatchを使います。グループ名、ストリーム名は空で問題ないです。
ビルドログに色々出てきます。buildspec.yml
のechoで指定した文字列が出力されているか確認します。
CFnで作る
(ほぼ)コンソールでやってきたことを、CFnテンプレートで作成しました。
以下のリソースを作成するCFnテンプレートになります。
- CodeCommitのリポジトリ
- CodeBuild用のCloudWatchロググループ
- CodeBuild用のIAMロール
- ロググループに出力権限付与
- リポジトリからPULL権限付与
- コンソールが作成する際に付与される以下の権限はつけない
- CodePipelineのバケット用のポリシー
- レポート用のポリシー
- CodeBuildプロジェクト
- CodeCommitリポジトリの
main
ブランチを見ています
- CodeCommitリポジトリの
クリックで表示
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ProjectName:
Type: String
Default: testProjectByCfn
RepositoryName:
Type: String
Default: forCodeBuildByCfn
Resources:
MyCodeCommitRepo:
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: !Ref RepositoryName
LogGroupForCB:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/codebuild/${ProjectName}"
RetentionInDays: 3653 # 未指定時は「失効しない」
RoleForCB:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: writeLogs
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !GetAtt LogGroupForCB.Arn
- !Join
- ':'
- - !GetAtt LogGroupForCB.Arn
- '*'
- PolicyName: pullCodeCommit
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- codecommit:GitPull
Resource:
- !GetAtt MyCodeCommitRepo.Arn
# CodePipelineのバケット用のポリシーは作成しない
# レポート用のポリシーも作成しない
CBProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref ProjectName
ServiceRole: !GetAtt RoleForCB.Arn
Artifacts:
Type: no_artifacts
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
# 以下の Image identifier を参照
## https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
Source:
Type: CODECOMMIT
Location: !GetAtt MyCodeCommitRepo.CloneUrlHttp
GitCloneDepth: 1 # 指定しないと、フル
SourceVersion: refs/heads/main
LogsConfig:
CloudWatchLogs:
Status: ENABLED
S3Logs:
Status: DISABLED
作成後はCodeCommitのmain
ブランチにbuildspec.yml
をコミットし、プロジェクトを実行することで、コンソール時と同じ結果が得られるはずです。
Level1:チェックを入れる
buildspec.yml
の中身を書き換えて、一緒にコミットするファイルの中身に特定の文字列があるかをチェックするようにします。
チェックするファイルを以下のように追加します。
hogehoge
mogemoge
togetoge
チェック処理はgrepを使ってみます。
version: 0.2
phases:
build:
commands:
- echo "Hello, CodeBuild!"
- echo "This is a sample build."
+ - grep -q "mogemoge" sample.txt
CodeCommitに追加後、プロジェクトを実行します。特に問題なく成功するはずです。
わざと失敗するため、sample.txt
の中身を書き換えてコミットします。
hogehoge
pogepoge
togetoge
実行すると失敗と出ます。
ログメッセージは以下のようになっています。
Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: grep -q "mogemoge" sample.txt. Reason: exit status 1
エラーの理由をメッセージで出すため、このようにしてみました。
version: 0.2
phases:
build:
commands:
- echo "Hello, CodeBuild!"
- echo "This is a sample build."
- - grep -q "mogemoge" sample.txt
+ - |
+ if ! grep -q "mogemoge" sample.txt; then
+ echo "Test failed: 'mogemoge' not found in sample.txt"
+ exit 1
+ fi
以下のように、指定したメッセージを出してエラーにしてくれます。
Test failed: 'mogemoge' not found in sample.txt
Level2:S3に出力する
次は、CodeBuildで扱ったファイルを、S3に置いてみます。
出力用バケットを作成
以下のCFnテンプレートでバケットを作成します。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
MyS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Sub "out-artifacts-ap-northeast-1-${AWS::AccountId}"
CodeBuildに設定
作成したCodeBuildに、コンソールから出力先を指定できます。
コンソールで以下のチェックを入れると、使っているIAMロールに出力先バケットへの権限を付与してくれます。
ポリシーに以下が追加されていました。
{
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::out-artifacts-ap-northeast-1-123456789012",
"arn:aws:s3:::out-artifacts-ap-northeast-1-123456789012/*"
],
"Action": [
"s3:PutObject",
"s3:GetBucketAcl",
"s3:GetBucketLocation"
]
},
buildspec.ymlに記載
出力する旨をbuildspec.yml
に記載します。
artifacts:
files:
- '**/*'
実行すると、指定したバケットに保存されます。再実行の際は上書きされました。
CFnで作る
先のCFnテンプレートに、以下を追加したものになります。
- S3バケット
- バケットへのアクセス権限
- IAMロールに
- Artifactsセクション
先の環境を作成したCFnスタックを、以下で更新します。
クリックで表示
AWSTemplateFormatVersion: 2010-09-09
Parameters:
ProjectName:
Type: String
Default: testProjectByCfn
RepositoryName:
Type: String
Default: forCodeBuildByCfn
Resources:
MyCodeCommitRepo:
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: !Ref RepositoryName
MyS3Bucket:
Type: AWS::S3::Bucket
LogGroupForCB:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/codebuild/${ProjectName}"
RetentionInDays: 3653 # 未指定時は「失効しない」
RoleForCB:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- codebuild.amazonaws.com
Action:
- 'sts:AssumeRole'
Path: /
Policies:
- PolicyName: writeLogs
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- logs:CreateLogStream
- logs:PutLogEvents
Resource:
- !GetAtt LogGroupForCB.Arn
- !Join
- ':'
- - !GetAtt LogGroupForCB.Arn
- '*'
- PolicyName: pullCodeCommit
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- codecommit:GitPull
Resource:
- !GetAtt MyCodeCommitRepo.Arn
- PolicyName: putBucketArtifacts
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:GetBucketAcl
- s3:GetBucketLocation
Resource:
- !GetAtt MyS3Bucket.Arn
- !Join
- '/'
- - !GetAtt MyS3Bucket.Arn
- '*'
CBProject:
Type: AWS::CodeBuild::Project
Properties:
Name: !Ref ProjectName
ServiceRole: !GetAtt RoleForCB.Arn
Artifacts:
Type: S3
Location: !Ref MyS3Bucket
EncryptionDisabled: true
Environment:
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_SMALL
# 以下の Image identifier を参照
## https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-available.html
Image: aws/codebuild/amazonlinux2-x86_64-standard:5.0
Source:
Type: CODECOMMIT
Location: !GetAtt MyCodeCommitRepo.CloneUrlHttp
GitCloneDepth: 1 # 指定しないと、フル
SourceVersion: refs/heads/main
LogsConfig:
CloudWatchLogs:
Status: ENABLED
S3Logs:
Status: DISABLED
Level3:作成したファイルだけ置く
先ほどは、CodeCommitからPULLしたファイルをすべてS3に置きました。今度はチェック後、そのファイルを元に新しくファイルを作成しS3に置く、というのをやってみます。
sample.txt内の文字列をすべて大文字にしてsample2.txtを作り、そのファイルだけをS3に置くようにします。
version: 0.2
phases:
build:
commands:
- echo "Hello, CodeBuild!"
- echo "This is a sample build."
- |
if ! grep -q "mogemoge" sample.txt; then
echo "Test failed: 'mogemoge' not found in sample.txt"
exit 1
fi
+ - cat sample.txt | tr [:lower:] [:upper:] > sample2.txt
artifacts:
files:
- - '**/*'
+ - sample2.txt
先ほどのファイルが残っている場合は、S3を空にしておいてから実行します。
中身もちゃんと大文字になっています。
buildセクションで失敗するようにしていた場合、ファイルは何も変更ありませんでした。ちゃんと止まるようです。
片付け
以下のリソースが作成されていますので、不要であれば削除してください。CFnテンプレートで作成した場合も、S3バケットを空にした後にスタックの削除を行ってください。
- S3
- バケットを空にしてから
- CodeCommit
- CodeBuild
- IAMロール・ポリシー
- CodeBuildプロジェクト作成時に自動作成されたもの
- Cloudwatchロググループ
おわりに
今回はCodeBuildの初歩の初歩を自分なりにまとめて記事にしました。
私のように「CodeBuildだけ試しに使ってみたい」という方のお役に立てれば幸いです。