以前はLambdaのデプロイを手作業で行っていました。
- ZIPファイルを作成
- AWSコンソールからアップロード
- 動作確認
という流れです。
運用できないわけではありませんが、毎回同じ作業を繰り返すため、
- デプロイ漏れ
- テスト忘れ
- 手順の属人化
といったリスクがありました。
そこで、AWSのマネージドサービスを利用して、Node.js製Lambdaのビルド・テスト・デプロイを自動化しました。
全体構成
GitHub
│
▼
CodePipeline
│
▼
CodeBuild
│
├─ npm ci
├─ Jest
├─ ZIP作成
│
▼
Lambda
GitHubへ変更を反映すると、CodePipelineが起動し、CodeBuildでビルドとテストを実行します。
テストが成功した場合のみ、Lambdaを更新する構成です。
使用したサービス
| サービス | 用途 |
|---|---|
| CodePipeline | パイプライン制御 |
| CodeBuild | ビルド・テスト実行 |
| Lambda | 実行環境 |
| IAM | 権限管理 |
| CloudWatch Logs | ログ確認 |
パイプラインの流れ
- GitHubへpush
- CodePipelineが起動
- CodeBuildで
- 依存関係のインストール
- ユニットテスト(Jest)
- ZIPファイル作成
- テスト成功時のみLambdaを更新
テストが失敗した場合は、その時点でパイプラインが停止するため、本番環境へデプロイされることはありません。
buildspec.yml
version: 0.2
phases:
install:
runtime-versions:
nodejs: 18
commands:
- npm ci
pre_build:
commands:
- echo "Running tests..."
- npm test
build:
commands:
- zip -r deployment.zip . -x "*.git*" "node_modules/aws-sdk/*"
artifacts:
files:
- deployment.zip
Lambdaの更新
Lambdaの更新にはAWS CLIを利用しています。
aws lambda update-function-code \
--function-name my-node-lambda \
--zip-file fileb://deployment.zip
CodePipelineからこの処理を実行することで、デプロイまで自動化できます。
ユニットテスト
実装
// calc.js
function add(a, b) {
return a + b;
}
module.exports = { add };
テスト
// calc.test.js
const { add } = require("./calc");
test("adds numbers correctly", () => {
expect(add(2, 3)).toBe(5);
});
Jestのテストが失敗すると、その時点でパイプラインが終了し、Lambdaは更新されません。
導入前後
| 導入前 | 導入後 |
|---|---|
| ZIP作成・アップロードを手作業 | GitHubへのpushで実行 |
| テスト忘れの可能性 | テスト成功時のみデプロイ |
| 手順が人に依存 | 手順をパイプライン化 |
| デプロイのたびに手作業 | 毎回同じ手順を自動実行 |
導入して感じたこと
今回の目的は「デプロイを速くすること」だけではありませんでした。
一番大きかったのは、毎回同じ品質でデプロイできるようになったことです。
人が作業すると、どうしても手順の抜け漏れや確認忘れが起こる可能性があります。
一方で、CI/CDとして手順を定義してしまえば、誰がデプロイしても同じ流れで実行されます。
Lambdaはデプロイ自体が簡単だからこそ、ビルドやテストまで含めて自動化するメリットは大きいと感じました。
まとめ
今回構築したパイプラインでは、
- GitHubへpushすると自動でビルド
- Jestでユニットテストを実行
- テスト成功時のみLambdaを更新
という流れを実現しました。
CI/CDは「デプロイを自動化する仕組み」というだけでなく、安全に変更をリリースするための仕組みでもあります。
小規模なLambdaであっても、自動化しておくことで運用負荷を減らし、安心して開発を進められるようになりました。