AWS

AWS CDKのCI/CD(CodeBuild + CodePipeline)を実装しようとしたらハマった話

kim

おはようございます。DWSの木村です!

今回、AWS CDKのデプロイについて、CI/CD環境を構築しようとしたら、「Error: Cannot find module '../lib'」というエラーが表示され、ハマってしまったので、その紹介をしようと思います。

構成

上記のような構成で、各フローで下記のような処理を実行しております。

  1. CDKコードをCodeCommitにpush
  2. CodeBuild(Build stage)で必要なmoduleのインストールや、cdk synth/cdk diffを行い、CodeBuild(Deploy stage)でcdk deployを実行
  3. 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でpwdのコマンドを実行してみる
      • →「/codebuild/output/src2131391406/src」特に変な位置にいないな…
  • CDK CLIツール(aws-cdk)抜け落ちてないよな…?
    • Deploy stageでnpm list aws-cdk || echo 'aws-cdk not found in npm list'のコマンドを実行してみる
      • →「`-- aws-cdk@2.1002.0aws-cdkあるな…

色々試した結果、下記記事に出会い大変助かりました!

[小ネタ]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

オプション。出力タイプが ZIP の場合、内部シンボリックリンクを ZIP ファイルに保持するかどうかを指定します。これに yes が含まれる場合、ソース内のすべての内部シンボリックリンクがアーティファクト ZIP ファイルに保持されます。

CodeBuild のビルド仕様に関するリファレンス

つまり、Build stageのbuildspec.ymlのartifactenable-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)でデプロイしようとした時に、ハマったエラーとその解消方法について紹介させていただきました。

同じようなエラーに遭遇する人は多い気がするので、参考になれば幸いです!!

AUTHOR
kim
kim
記事URLをコピーしました