はじめに
2024/02/09のアップデートで、CodePipelineで、追加のパイプライントリガーフィルターに対応しました。
CodePipeline が追加のトリガーフィルターと新しい実行モードのサポートを開始
本機能を利用することで、特定ブランチやリポジトリ内の特定ファイルなど、指定したイベントをトリガーとしてCodePipelineを起動できるようになりました。
ですが、CDK Pipelinesで作ったパイプラインにV2を利用しようとすると、工夫が必要になります。
そこで今回はCDK Pipelines+CodePipeline V2を実現させ、その上で新機能を試してみたいと思います。
条件
- CodePipeline V2であること
- 以下のソースであること
- GitHub.com
- GitHub Enterprise Server
- Bitbucket.com
- GitLab.com
- GitLab セルフマネージド
記載のように、AWS CodeCommitでは本機能が利用できません。
現状、CodeCommit環境では簡単には実装できず、AWS公式ドキュメントにLambdaを使ったアーキテクチャが公開されておりました。
今回はGitHubを利用して実装します。
バージョン情報
aws-cdk: 2.143.0 で検証。
実装イメージ
CodeStarConnectionの準備
CodePipelineの設定>接続より、事前にGitHubとの接続を作成しておく必要があります。
CodePipeline V2対応
CDK PipelinesのデフォルトPropsで自動作成されるパイプラインではV2に対応しておらず、V1が作られてしまいます。
ですが、CDK PipelinesのL3 Construct CodePipelineには、
codePipeline
プロパティがあり、別途定義したCodePipelineを利用できます。
そのため、aws-codepipelineのL2 Construct PipelineをV2で作成し、そのパイプラインをCDK Pipelines用のパイプラインとして利用することで間接的にV2を利用できます。
サンプルコード
import * as codepipeline from "aws-cdk-lib/aws-codepipeline";
import {
CodeBuildStep,
CodePipeline,
CodePipelineSource,
} from "aws-cdk-lib/pipelines";
export class PipelineStack extends cdk.Stack {
constructor(scope: Construct, id: string, props: PipelineProps) {
super(scope, id, props);
// <中略>
// GitHub Connection
const source = CodePipelineSource.connection(
"github_user_name/repository_name", // GitHubのリポジトリ名を設定
"main", // ブランチ名を設定
{
connectionArn:
"arn:aws:codestar-connections:ap-northeast-1:XXXXXXXXXXXX:connection/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx", // CodeStarConnectionのARNを設定
}
);
// aws-cdk-lib/aws-codepipeline のPipelineをV2で作成
const codePipeline = new codepipeline.Pipeline(this, "CDKPipelineV2", {
pipelineName: "CDKPipelineV2",
pipelineType: codepipeline.PipelineType.V2,
role: pipelineRole,
crossAccountKeys: true,
restartExecutionOnUpdate: false,
});
// aws-cdk-lib/pipelines" のPipelineを作成し、上で作成したcodePipelineを設定。
const cdkPipeline = new CodePipeline(
this,
"Docs"
{
codePipeline: codePipeline,
synth: new CodeBuildStep("BuildStep", {
input: source,
installCommands: getInstallCommands(),
commands: ['npm ci','npm run build','mkdocs build','npx cdk synth'], // ビルドコマンドを記入
}),
selfMutation: true,
dockerEnabledForSynth: true,
}
)};
};
Deployステージの補足
今回の主題でないためカットしていますが、本来はパイプライン上にデプロイステージ等が必要です。
デプロイステージでは以下のような要素を含んだStackを投入しています。
- WAF
- CloudFront Distribution
- 公開用のS3
- s3deploy.BucketDeploymentによるアセットのS3デプロイ
GitHub Connection
aws-cdk-lib/pipelinesのCodePipelineSource.connection
を利用して、コネクションを設定します。
aws-cdk-lib/aws-codepipeline のPipelineをV2で作成
aws-cdk-lib/aws-codepipeline
で新しいCodePipelineを作成します。
事前に作成することで、pipelineTypeをV2に設定できます。
※サンプルコードでは中略していますが、pipelineRoleは必要なIAM Roleを定義しています。
aws-cdk-lib/pipelines" のPipelineを作成し、上で作成したcodePipelineを設定
aws-cdk-lib/pipelines
でCDK Pipelinesを作成します。
codePipelineパラメータに、上で作ったV2パイプラインを指定することでV2対応できます。
synth:CodeBuildStepのinputには、GitHub Connectionで作成したconnectionを設定します。
トリガーの設定
2024/05/27時点、TriggerクラスでPush時にフィルタリングする設定が実装されておりませんでした。
Trigger
なので今回はaddPropertyOverrideを利用し、L2 Constructで提供されていない部分を直接編集します。
コンストラクトライブラリからの AWS コンストラクトのカスタマイズ
// 上記サンプルコードの続き
// パイプラインを構築(providerTypeで呼ぶため)
cdkPipeline.buildPipeline();
// SourceStageを取得
const sourceStage = cdkPipeline.pipeline.stages.find(
(stage) => stage.stageName === "Source"
);
const sourceAction = sourceStage!
.actions[0] as codepipeline_actions.CodeStarConnectionsSourceAction;
const sourceActionName = sourceAction.actionProperties.actionName;
// トリガーを追加
codePipeline.addTrigger({
providerType: codepipeline.ProviderType.CODE_STAR_SOURCE_CONNECTION,
// the properties below are optional
gitConfiguration: {
sourceAction: sourceAction,
// pushFilterのBranchとFilepathはまだCDK未対応。tagsを仮設定(addPropertyOverrideで上書きする)
pushFilter: [
{
tagsIncludes: ["tagsIncludes"], // 置換されるので適当な文字列を設定
},
],
},
});
// addPropertyOverrideでトリガー条件を上書きする
const pushFilterJson = {
Branches: {
Includes: ["対象にしたいブランチ名"],
},
FilePaths: {
Includes: ["対象にしたいフォルダパス"],
},
};
// cfnPipelineを取得して、addPropertyOverrideを実施
const cfnPipeline = cdkPipeline.pipeline.node
.defaultChild as codepipeline.CfnPipeline;
cfnPipeline.addPropertyOverride("Triggers", [
{
GitConfiguration: {
Push: [pushFilterJson],
SourceActionName: sourceActionName,
},
ProviderType: "CodeStarSourceConnection",
},
]);
パイプラインを構築(providerTypeで呼ぶため)
cdkPipeline.buildPipeline()を挿入することで、パイプラインがビルドされます。
これを入れることで、後続のsourceStage.actions[0] as codepipeline_actions.CodeStarConnectionsSourceAction;
部分が取得可能になります。
トリガーを追加
codePipeline.addTrigger
でトリガーを作成します。
gitConfiguration.pushFilterは先述の通りブランチやファイルパスを設定する項目が現時点で存在しないため、tagsIncludes
のみ設定し、適当な値を設定しておきます。(何も設定しないとエラーとなりました。)
トリガー条件の設定
pushFilterJson
という変数にフィルター条件を設定します。
必要なブランチ名、フォルダパスを設定します。
addPropertyOverrideを実施
cdkPipeline.pipeline.node.defaultChild as codepipeline.CfnPipeline
を使ってcfnPipelineを取得し、
cfnPipeline.addPropertyOverride
を利用してTriggersのプロパティを上書きます。
デプロイ
上記設定でCDK Pipelinesをcdk deployします。
addPropertyOverrideで上書きしたことで、タグの条件は削除されています。
特定フォルダの更新テスト
my-projectフォルダを修正します。
今回のフォルダ配下にはMkDocsで作成したMarkdownファイルが格納されています。
「サイト更新テスト」という文章を追加し、GitHubのリモートリポジトリにPushします。
サイトが無事更新されました。(今回はMkdocsの初期レイアウトを配置しています。)
終わりに
現時点の環境で実現可能な、CDK PipelinesとCodePipeline V2の融合、およびGitHubの特定ブランチや特定ファイルパスの更新をトリガーにする方法を解説しました。
CodePipeline V2では、今回は紹介しませんでしたがQUEUEやParallel等の実行方法も可能になり、より柔軟な設定でパイプラインを実行できます。CDK Pipelinesでもぜひ導入したいところですね。
料金面でもV1はパイプライン1本あたり$1/月が固定でかかる料金体系でしたが、V2では実行時間に対する従量課金制になり、0.002USD/実行時間(分)の料金体系となりました。短時間の実行しかされないような複数のパイプラインを持つ場合でも大幅にコストを抑えられる形となりました。
V2はまだあまり活用できておりませんでしたが、多くの利点があるので今後はV2を軸にパイプライン活用を検討していこうと思います。