
はじめに
こんにちは、アプリケーションチームの野地です。
今回は、業務内でAWS CodePipeline V2に触れる機会があったので、CodePipeline V2を使用する際の管理コンソールでの使い方から、開発時に悩んだ「CloudFormationで実装する際のyamlでの記述方法」も合わせて紹介したいと思います。
CodePipeline V2とは
2023年の10月ごろにリリースされたCodePipelineタイプです。
V2で作成したCodePipelineをコンソールからリリースする場合、ユーザーが宣言した環境変数を使用することで、入力パラメータの値を動的に渡すことができます。

今回は以下のような構成で、CodePipeline V2を使用して任意のファイルをS3へアップロードするパイプラインを作成したいと思います。

使い方
管理コンソールでの設定
基本的には通常通りに管理コンソールからパイプラインを作成し、設定をしていきます。
パイプラインの設定を選択する
以前はこのようにV1、V2を選択しましたが、注意書きにもあるように、現在は管理コンソールからはパイプラインV1の作成ができなくなっています。

以前のパイプラインタイプの選択 
現在のパイプラインの設定画面 下にスクロールすると、「変数」の設定が出てきます。ここで変数を設定することで、パイプラインのリリース時に入力パラメータの値を割り当てることができます。

ソースステージを設定する
ソースプロバイダー設定では、リポジトリやブランチ名を指定します。

※今回使用している環境は、パイプライン実行のアカウントとソースリポジトリのアカウントが違うため、管理コンソールからプルダウンで指定することができません。その場合は、yamlテンプレートなどを使用したCloudFormationからの作成によって指定が可能です
ビルドステージを追加する
BuildフェーズでPipelineリリース時に入力したパラメータを受け取るには、「環境変数-オプショナル」の項目で次のように値を入力します。(例として、環境変数名FILENAMEを用いる)
- 環境変数名:FILENAME、変数値:#{variables.FILENAME}

- 環境変数名:FILENAME、変数値:#{variables.FILENAME}
「環境変数-オプショナル」の設定をCloudFormation用にyamlで記述する際に、書き方が見つからずに苦労しましたので、テンプレート例を載せておきます。
yamlの場合は、BuildアクションのConfigurationセクションにEnvironmentVariablesとしてname・value・typeを記述することで反映させることができます。
CloudFormation用のyamlテンプレートでの記述方法
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
EnvName:
Type: String
Mappings:
EnvMap:
develop:
BranchName: 'develop_V2'
EncryptionKey: 'arn:aws:kms:ap-northeast-1:xxxxxx:key/xxxxxx'
Resources:
FileUpdatePipeline:
Type: AWS::CodePipeline::Pipeline
Properties:
PipelineType: V2
Variables:
- Name: 'FILENAME'
DefaultValue: 'DEFAULT'
Description: '更新したいファイル名を入力してください。例:sqs.yamlを更新したい場合→sqsと入力'
Name: !Sub 'file-update-${EnvName}'
ArtifactStore:
Type: S3
Location: !Sub 'artifacts-${EnvName}'
EncryptionKey:
Id: !FindInMap [EnvMap, !Ref EnvName, EncryptionKey]
Type: KMS
RoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role_name
Stages:
- Name: Source
Actions:
- Name: Source
ActionTypeId:
Category: Source
Owner: AWS
Provider: CodeCommit
Version: 1
RunOrder: 1
Configuration:
PollForSourceChanges: false
RepositoryName: 'repository_name'
BranchName: !FindInMap [EnvMap, !Ref EnvName, BranchName]
InputArtifacts: []
OutputArtifacts:
- Name: SourceArtifact
RoleArn: arn:aws:iam::${SourceAccountID}:role_name
- Name: Deploy
Actions:
- Name: Approval
ActionTypeId:
Category: Approval
Owner: AWS
Provider: Manual
Version: 1
RunOrder: 1
- Name: Build
ActionTypeId:
Category: Build
Owner: AWS
Provider: CodeBuild
Version: 1
RunOrder: 2
Configuration:
ProjectName: !Ref 'FileUpdateCodeBuild'
EnvironmentVariables: !Join
- ''
- - '['
- '{"name":"FILENAME",
"value":"#{variables.FILENAME}",
"type":"PLAINTEXT"
- '"}]'
InputArtifacts:
- Name: SourceArtifact
OutputArtifacts:
- Name: BuildArtifact
FileUpdateCodeBuild:
Type: AWS::CodeBuild::Project
Properties:
Name: !Sub 'file-update-${EnvName}'
BadgeEnabled: false
ServiceRole: !Sub arn:aws:iam::${AWS::AccountId}:role_name
TimeoutInMinutes: 60
Artifacts:
Type: CODEPIPELINE
EncryptionKey: !FindInMap [EnvMap, !Ref EnvName, EncryptionKey]
Source:
Type: CODEPIPELINE
BuildSpec: 'buildspec.yaml'
Environment:
Image: 'aws/codebuild/standard:7.0'
Type: LINUX_CONTAINER
ComputeType: BUILD_GENERAL1_MEDIUM
PrivilegedMode: true
EnvironmentVariables:
- Name: ENV_NAME
Value: !Ref 'EnvName'
Type: PLAINTEXT
実際に使ってみる
今回の実装内容
冒頭でも説明しましたが、今回は「受け取った入力パラメータを使って、S3の任意のyamlテンプレートを変数で指定して更新する」ような、BuildフェーズをもつPipelineを作成したいと思います。

Buildフェーズで使用するbuildspec.yamlを次のように記述します。
- buildspec.yamlの記述例
version: 0.2
phases:
install:
commands:
- printf "Installing dependencies..."
- pip install awscli jsonschema PyYAML
pre_build:
commands:
- find $FILENAME.yaml
- EXISTS_STATUS=$?
- |
if [ $EXISTS_STATUS -eq 0 ]; then
printf "go to build phase"
fi
build:
commands:
- |
if [ $EXISTS_STATUS -eq 0 ]; then
printf "Uploading $FILENAME to S3..."
aws s3 cp $FILENAME.yaml s3:/Sample/$FILENAME.yaml
else
printf "Skip build phase due to file not exists"
fi
実行するコマンド内で、$FILENAMEという記述を用いることで入力パラメータを受け取り、任意のファイルを指定できます。
(念の為、指定したファイルが存在するかどうかのチェックも行っています。)
変更のリリース
パイプラインの変更リリース時に、環境変数に入れたい値の入力を求められます。
今回は、S3に保存してある任意のyamlテンプレートを更新したいので、入力パラメータにそのファイル名を入力します。


おわりに
今回紹介したファイルのアップロード作業は、業務内で一部手動で実施していました。
ですが、今回紹介したCodePipeline V2を使用した実装をすることで、コマンド実行時のオペミス回避に寄与できました。
今回はファイルのアップロードをしましたが、そのほかにも、スタックのアップデートをしたければ、同様にコマンド内でテンプレートを指定してあげれば良いので、使い道が色々ありそうです。
実装時にyamlでの記述方法について述べている記事がなかったので、同じ課題を持つ人の助けになれば幸いです。