CIを活用すると、開発の一連の流れを自動化しコストを削減することができます。また、自動テストによって、開発者の単体テストの時間を軽減でき、人為的エラーが少なくなります。今回はAWS構築の際の自動テスト、自動レポート機能であるCIについての設定方法の紹介とデモンストレーションをします。
CICDは「Continuous Integration(継続的インテグレーション)/Continuous Delivery(継続デリバリー)」の略称です。アプリケーション開発のステージに自動化を取り入れて、クライアントに提供する頻度を高める手法です。実際CICDは、作業→テスト→公開という流れを「自動化」するという意味で使われています。
CIとは
CIは「Continuous Integration」の略で、「継続インテグレーション」と訳されています。開発チーム内部で新規コードをプッシュしてCIのトリガーを開始します。CIのシナリオは以下のステップを順番的に進行します。
・開発者はコードをGitlabにコミット
・CIサーバーはコードをレビューして変更内容があるかどうか確認
・変更がある場合、自動でビルドして単体テストと結合テストを実行
・CIサーバーはフィードバックとレポートをチームメンバーに送信

CIのメリット
・バグを検出して早期に修正することでリスクを軽減し、テストと検査を自動化することでソフトウェアの品質を向上させます。
・手動プロセスを最小限に抑える。代わりに自動ビルド、自動テストを実行します。
・いつでもどこでも公開できるアプリケーションを生成します。
CDとは
CDは「Continuous Delivery」の略で、「継続デリバリー」と訳されています。
CIの自動テストが完了して問題ない場合、自動的に色々の環境(開発・ステージング・本番)へ反映する。ソフトウェアのリリースプロセスを完全に自動化します。

「継続デリバリー」と同じCDは「継続デプロイメント」です。本番環境へ反映する時、手動か自動かは大きな違いです。
「継続デプロイメント」は本番環境へ反映する際に、自動化をしたいというケースなのですが、簡単ではありません。理論的には実装可能なようでも、実際、ステージング環境と本番環境は別々のサーバーなので同じ設定でも本番環境でうまく動く保証はありません。また、完全な自動テストは難しいことなので、自動デプロイできないこともあります。そのような理由で「継続デリバリー」の方が一般的になっています。

AWSのCICDソリューション
現在AWSはCICDソリューションを実装するサービスを提供しています。
AWSCodeCommit: ソースコードの管理サービス。GithubとGitlabと同じ。
AWSCodeBuild: 新規のコードが確認できてからアプリをビルドして設定したテストシナリオを実施。また、ビルドレポートも提供。
AWSCodeDeploy: ビルド完了の際に自動で設定した環境へ反映。
AWSCodePipeline: CICDの流れの設定。
上記のサービスを合わせてCICDのソリューションを実施することができます。

CICDをAWSで展開
手動ですが順番にサービスを設定する方法があります。下記のURLをご参考いただければと思います。
ソフトウェア開発の自動化支援、JenkinsでCI/CDの設定方法
しかし実際の現場ではたくさんのプロジェクトがあり、プロジェクトごとにCICDを応用したい場合、上記の方法を何回も実施せざるを得ず想定以上に手間がかかります。また、人間の操作なので人的エラーがよく起こります。
そこで再利用できてエラーを最小限にする方法があります。「Infrastructure as Code」という方法です。AWSで構築を展開するには3つのツールがあります。
・CloudFormation
・AWS CDK
・Terraform
今回AWS CDKでCICDの展開方法を紹介したいと思います。なぜCDKなのか、下記のリンクをご参考いただければと思います。
AWSクラウドの環境を効率化するAWS CDKとは ⋆ ONETECH

AWS CDKでCICDを展開
CICDは画像のように3ステージに分かれています。
- Source stage:新規のCommitがあるかどうか確認するステップです。
- Build stage: 新規のソースをビルドして自動単体テストを実施します。単体テストがエラーになったらロールバックします。また、テストのレポートも出力します。
- Pipeline update: 指定の環境にデプロイする。複数のリージョンでもデプロイできます。
Githubと連携
AWSにはGithubと同じようなサービスがあります。CodeCommitです。CodeCommitのソースコードの格納する場所はS3ですので、大量のソースの場合は有料になるので注意が必要です。今回は無料のソースコード管理Githubツールを使ってCodeBuildと連携したいと思います。
Source stage: Github
Build stage: CodeBuild
Pipeline update: CodeDeploy
Pipeline management: CodePipeline
まず、Githubにログインして、設定画面に入ります。

左側のメニューでデベロッパー設定に選択します。

Personal access tokensオプションに開いてGenerate new tokenを選択します。

Tokenをネーミングして多少のオプションを設定する必要があります。

Repoオプションは全ソースコードをアクセス出来るような権限です。

Admin:repo_hookはPipelineを「ソースコードに更新があればアラートする」の権限に許可される。

最後「Generate Token」ボタンを押してTokenが生成されます。

そのTokenを利用してCodeBuildがGithubにアクセスできます。
ソースコードに貼り付けてすぐにアクセスできますが、セキュリティの問題なので、TokenをAWS Secret Managerサービスに保存します。
AWSコンソールを開いて「Secrets Manager」のサービスを選択します。

「Store a new secret」ボタンを選択して新規秘密パラメーターを作成してGithubのTokenを保存します。

画像のように設定いただければと思います。
Select secret type: Other type of secrets
PlainText: GithubのToken

「Next」ボタンを押してSecretの名前と説明を付けます。

次のページは暗号化キーを定期的に変更する設定ですが、今回はデモなのでこのオプションを利用しません。「Disable automatic rotation」でよいです。

次のページをレビューして「Store」ボタンを押して完了します。
Sourceのステージの作成
AWSでのCICDの基本は3ステージに分かれています。Source、Build、Deployという流れです。まず、Sourceステージの作成を案内いたします。
最初はステージに親のようなPipelineを登録して後はステージをPipelineに追加します。
Pipelineの登録のソースは以下の感じです。

pipelineName: pipelineの名前
crossAccountKeys:複数のアカウントでアクセスできるキーが発生します。1ヶ月/1ドルかかります。今回利用する必要はないのでFalseにします。
restartExecutionOnUpdate: 新規のソースがあれば、起動中のPipelineを停止して再度Pipelineを実施します。最新のソースを反映したいのでtrueに設定します。
次はSourceステージにGithubを連携して作成します。

上記のソースを参考いただいてSourceステージが作成できます。
現在、AWSCDKはGithub連携のメソッドを用意してくれました。GitHubSourceActionのクラスを利用してGithubの必要な情報を入れば連携できます。
Owner:GitHubのアカウント
Repo:GitHubのソースのフォルダ
Branch:GitHubのブランチ
ActionName:ステージの中に複数なアクションがありますので、ネーミング必要です。例:インフラのアクション、APIのアクション。アクションごとにソースコードが違います。
oauthToken: AWS Secret Managerで登録したGitHubのTokenです。
Output: ソースコードのアウトプットというアーティファクトが必要なので下記のコードで作成できます。

Buildステージの作成。
BuildステージでAWS CodeBuildサービスを利用します。CodeBuildはSourceステージのアーティファクトを読み込んでAMIイメージを出力します。AMIイメージは今回Linux_Standardバージョン5.0を使います。
Build-specsの定義は基本的に自動単体テストとCloudFormationの作成という作業を指定してCodeBuildは実施します。自動単体テストは後程案内いたします。
下記の図をご参考いただければと思います。

下記のコードでBuildステージを定義してPipelineに付けます。

stageName: 簡単な名前でBuildにします。
actionName: 一つのステージで複数なアクションが追加できます。例:インフラのビルドとAPIのビルドとなります。なので区別するためネーミング必要です。
Outputs: Sourceステージと同じ、実施完了のあとのアウトプット場所

Project:ビルド環境の設定です。
buildImage:LinuxOSを選択します。
buildSpec:ビルドの手順の定義ファイルです。
buildSpecファイルの作成方法を案内いたします。
まずは、build-specsフォルダとcdk.outフォルダを作成します。
build-specsフォルダの中にcdk-build-spec.yamlファイルを作成して画像のような内容をインプットします。

InstallのフェーズでAMIイメージにnpmをインストールします。
BuildのフェーズでソースをビルドしてCloudFormationフォーマットに変換してcdk.outフォルダに保存します。
Buildのステージの作成は完了です。一旦AWSにデプロイして確認します。
- Gitに新しい変更をプッシュします。
- Cdk deploy コマンドを実施して変更内容を確認して同意します。
- AWS CodePipelineをアクセスします。新しいPipelineの作成中だと確認できます。

- Pipelineのステージの動作が確認できます。


このステップまではCICDのインフラが大分設定できました。インフラ構築はあまり変更しないので、毎回cdk deployする時、インフラを再度デプロイする必要がないです。構築の変更を確認して、変更がある場合、デプロイします。なので、更新のステージを追加します。

templatePath: Buildステップのアーティファクトのcdk.outフォルダの中にスタックのjsonのパスです。Buildステージを実装したなら、必ずあります。
自動単体テスト
単体テストのシナリオは依頼によって違いますが、今回簡単なシナリオの作成方法を紹介します。
シナリオ:インフラの構築は安定しました。変更防止のため、インフラは変更内容があればビルドは失敗します。
テストファイルの拡張子は.test.tsとなります。Build-spec.yamlの実装する時、.test.tsファイルを実施します。ネーミングは自由です。

現在の構築をバックアップとしてスナップショットを作成します。次回のビルドはスナップショットと比べて変更内容があれば「toMatchSnapshot」機能は失敗します。

次はBuild-specファイルに「npm run test」行に追加してビルドするとき、テストを行います。
※もし、インフラ構築を更新したい場合、スナップショットを更新する必要があります。Package.jsonファイルを開いて「scripts」のコマンド一覧に「”test:update”:”jest –updateSnapshot”」行を追加いただければと思います。

更新したいなら、「npm run test:update」コマンドを実施してスナップショットを更新します。
テストレポート
現在、AWSCodeBuildは下記のテストレポートフォーマットを提供しています。
- Cucumber JSON (.json)
- JUnit XML (.xml)
- NUnit XML (.xml)
- NUnit3 XML (.xml)
- TestNG XML (.xml)
- Visual Studio TRX (.trx)
今回、junitXMLのやり方を紹介します。
Package.jsonファイルを開いて新しいパッケージを追加します。

Jest.config.jsファイルを定義します。

AWSでJestの定義のドキュメントがありますのでご参考いただければと思います。
Set up test reporting with Jest – AWS CodeBuild (amazon.com)
重要なパラメーターは「testMatch」、「outputDirectory」、「outputName」です。テストファイル(.test.js)のフォルダを正確に指定する必要があります。
次は「npm run test」コマンドを実施してテストレポートファイルを自動で生成します。

Configファイルのように設定した「outputDirectory」、「outputName」が生成されました。
次、AWS CodeBuildでテストレポートを表示します。
Build-specファイルをテストレポートの定義を追加します。

テストレポートの設定は完了です。
最後、「cdk deploy」のコマンドを実施してCodeBuildを確認します。
CodeBuildの成功状態になったことを待ちます。

左側のメニューでBuild→Report groupsメニューを選択します。

テストレポートが出ました。
この画面で色々な情報が確認できます。


まとめ
今回のデモはCIのステップのみですが、CDの方はインフラ構築だけでなくサービスのAPIも同時にデプロイする必要がありますので別の記事で紹介したいと思います。
しかし、開発の段階ではCIの方が大切です。CIでは流れを全部自動化しコストを削減することができます。また、自動テストによって、開発者の単体テストの時間を軽減でき、人為的エラーが少なくなります。今回紹介したテストシナリオは簡単ですが、CDKではたくさんの機能があって自由にシナリオを設計できます。例えば:開発環境、本番環境の設定の間違いとか、AWSリソース不足とか、というリスクが防止できます。
最後まで読んでいただきありがとうございます。
ベトナムオフショア開発会社 ONETECHはAWSセレクトティアパートナー
もし、AWSについてプロのアドバイスが欲しいのなら、ぜひONETECHにご相談ください。
ONETECHはオフショア開発会社として100社以上との取引実績を誇ります。
ONETECHではAWS資格保有のエキスパートがお客様の課題をカタチにします。
- インターネットサービスの企画はあるがどうしたら良いか
- どのようにクラウドを利用したら良いかわからない
- クラウドを利用するためのコストやポイントを知りたい
- 保守運用まで考慮した設計をしたい
Lambdaを含むAWSのコンサルティングサービスを提供しています。気になること、不安なことをお気軽にご相談ください。
AWS導入について相談する