AWS CDKのCI/CD(CodeBuild + CodePipeline)を実装しようとしたらハマった話
おはようございます。DWSの木村です!
今回、AWS CDKのデプロイについて、CI/CD環境を構築しようとしたら、「Error: Cannot find module '../lib'」というエラーが表示され、ハマってしまったので、その紹介をしようと思います。
構成

上記のような構成で、各フローで下記のような処理を実行しております。
- CDKコードをCodeCommitにpush
- CodeBuild(Build stage)で必要なmoduleのインストールや、cdk synth/cdk diffを行い、CodeBuild(Deploy stage)でcdk deployを実行
- CloudFormationでコードを展開する
CodeBuildのBuild/Deploy stageでは下記のようなコードを使っていました。後で解説しますが、このコードだと、Deploy stageでエラーとなります…
CodeBuildのBuild stage(buildspec.yml)
version: 0.2
phases:
install:
on-failure: ABORT
runtime-versions:
nodejs: 20
pre_build:
on-failure: ABORT
commands:
# 依存パッケージのインストール
- "npm install"
build:
on-failure: ABORT
commands:
# synthを実行
- "npx cdk synth -c env=dev"
post_build:
on-failure: ABORT
commands:
# diffを表示
- "npx cdk diff -c env=dev --all --change-set=false"
artifacts:
files:
- "**/*"
base-directory: "."
CodeBuildのDeploy stage(deployspec.yml)
version: 0.2
phases:
install:
on-failure: ABORT
runtime-versions:
nodejs: 20
build:
commands:
# デプロイ
- "npx cdk deploy -c env=dev --require-approval never --all --method direct"
どんなエラー?

では、実際にどんなエラーが起きたのかを見てみます。
冒頭でも軽く説明しましたが、エラー内容はDeploy stageで上記図のような、「Error: Cannot find module '../lib'」というエラーが発生しました。
このエラーに直面してから、デバッグでやったこととしては下記になります。
- Artifactの受け渡しが上手くいってなくて、libディレクトリ無くなってるのかな…?
- Deploy stageで
ls -alのコマンドを実行してみる- →libディレクトリはあった…
- Deploy stageで
- 今いるディレクトリの位置が変なのかな…?
- Deploy stageで
pwdのコマンドを実行してみる- →「
/codebuild/output/src2131391406/src」特に変な位置にいないな…
- →「
- Deploy stageで
- CDK CLIツール(aws-cdk)抜け落ちてないよな…?
- Deploy stageで
npm list aws-cdk || echo 'aws-cdk not found in npm list'のコマンドを実行してみる- →「
`-- aws-cdk@2.1002.0」aws-cdkあるな…
- →「
- Deploy stageで
色々試した結果、下記記事に出会い大変助かりました!
[小ネタ]CodePipeline上でシンボリックリンクを利用していたコードが想定外の動きをした話
https://dev.classmethod.jp/articles/tips-codepipeline-symlink/
CodePipeline上でファイルを受け渡す際に、シンボリックリンクが切れて、挙動がおかしくなるらしい…
下記のデバッグを実行し、シンボリックリンクに変化が起きていないか確認
- エラーになっているDeploy stageの該当ファイルのシンボリックリンクの参照先を、コマンドが正常に実行できるローカルと比較してみた
- 「readlink -f node_modules/.bin/cdk || echo 'Not a symlink or cannot read link'」を実行(結果は下記表より)
| 環境 | readlink 結果 |
|---|---|
| CodeBuild | /codebuild/output/src1573507447/src/node_modules/.bin/cdk |
| ローカル | <project>/node_modules/aws-cdk/bin/cdk |
シンボリックリンクの参照先の/node_modules以降のパスがローカル環境と、AWS CodeBuild環境でなんか違う!!
やはり、シンボリックリンクが切れていました!
エラーの直接原因とみてほぼ間違いなさそうです!次項でその解決策を見ていきたいと思います。
エラーの解消方法
AWS公式ページを見ると、この事象の解決策が書かれていました!
artifacts/enable-symlinks
オプション。出力タイプが
CodeBuild のビルド仕様に関するリファレンスZIPの場合、内部シンボリックリンクを ZIP ファイルに保持するかどうかを指定します。これにyesが含まれる場合、ソース内のすべての内部シンボリックリンクがアーティファクト ZIP ファイルに保持されます。
つまり、Build stageのbuildspec.ymlのartifactにenable-symlinks: yesを追記するだけで、シンボリックリンクを残したままArtifactを引き継げるようです!
下記がbuildspec.ymlの修正後のコードになります
CodeBuildのBuild stage(buildspec.yml)
version: 0.2
phases:
install:
on-failure: ABORT
runtime-versions:
nodejs: 20
pre_build:
on-failure: ABORT
commands:
# 依存パッケージのインストール
- "npm install"
build:
on-failure: ABORT
commands:
# synthを実行
- "npx cdk synth -c env=dev"
post_build:
on-failure: ABORT
commands:
# diffを表示
- "npx cdk diff -c env=dev --all --change-set=false"
artifacts:
enable-symlinks: yes
files:
- "**/*"
base-directory: "."buildspec.ymlを修正して、再度CodePipelineを実行してみると、下記のようにDeploy stageが緑になりました!やはりシンボリックリンクが原因でした!

まとめ
いかがでしたでしょうか?
今回はCDKをCI/CD(CodeBuild + CodePipeline)でデプロイしようとした時に、ハマったエラーとその解消方法について紹介させていただきました。
同じようなエラーに遭遇する人は多い気がするので、参考になれば幸いです!!

