CircleCIでSAMをデプロイする

概要

業務でSAMを使って、Lambdaの管理を行っていますが、CI/CDの設定ができておらず、手動でデプロイしています。
READMEに手順は書いていますが、「手順がかけているなら自動化だろう!」ということで、デプロイ設定を行っていきます。

準備

アプリケーション

SAMアプリケーションを作成します。
SAMをホストマシンに入れ、下記を実行します。

$ sam init

言語は何でもOKです。自分はGoを選択しました。

AWS

AWSではCircleCI用にユーザを作成します。
ユーザには必要な機能が操作できるように、権限を与えてください。

  • IAM
  • S3
  • CloudFormation
  • Lambda
  • APIGateway

CircleCI

デプロイはCircleCIで行っていきます。
社内ではEnterprise版を使っているため、バージョンは2.0で記載していきます。
※2.1だとOrbsが使えるので、もうちょっと楽できそうな気はします。

ContextにAWSユーザを設定

aws-cliを使うため、ユーザ情報を設定する必要があります。
直接ユーザ情報を書くと漏洩してしまうので、CircleCIのContextにユーザ情報を記載します。
(FYI コンテキストの使用 - CircleCI)

必要な値は下記です。 リージョン以外は事前に作った値で大丈夫です。

設定を記載

CircleCIの設定を記載していきます。
awscliとaws-sam-cliをインストールするため、Pythonのイメージを使います。

今回はmasterブランチをトリガーにします。
対象のブランチ or タグは、適時設定でOKです。

version: 2

jobs:
  deploy:
    docker:
      - image: circleci/golang:1.13
    working_directory: ~/ディレクトリ
    steps:
      - run:
          name: Install awscli
          command: |
            sudo apt-get update && sudo apt-get install -y awscli
      - checkout
      - run:
          name: build
          command: make build
      - run: aws cloudformation package --template-file template.yaml --output-template-file packaged.yaml --s3-bucket バケット名
      - run: aws cloudformation deploy --template-file packaged.yaml --stack-name スタック名 --capabilities CAPABILITY_IAM

workflows:
  version: 2
  default:
    jobs:
      - deploy:
          context: 設定したcontext
          filters:
            branches:
              only: master

これで準備OKです。 あとはmasterへのマージを行えば、CircleCIが動いてデプロイが走ります。

躓いたこと

S3のバケットがないと怒られる

CircleCIでデプロイを実行したところ、下記のエラーがでました…。

S3 Bucket does not exist.

IAMで権限は付与しているので、作成もやってくれるかと思いましたが、バケットの作成はやってくれないようですね…。

CloudFormationのスタックが更新できない

一度デプロイに失敗したので、再度実行したところ下記のエラーがでました…。

Error: Failed to create changeset for the stack: スタック名, An error occurred (ValidationError) when calling the CreateChangeSet operation: **** is in ROLLBACK_COMPLETE state and can not be updated.

CloudFormationは最初のデプロイで失敗したときは更新できないので、一度削除してから対応する必要があります。
(FYI AWS SAMを使う前にCloudFormationテンプレートを書こう - Qiita)

CloudFormationで経験していましたが、忘れてしまっていました。
SAM自体もCloudFormationのテンプレートを作るので、ここらへんの挙動は同じみたいですね。

ビルドを忘れていた

当たり前ですが、Goのコードはビルドをする必要があります。
普段はNode.jsを使っているため、失念していました…。

最後に

いかがでしょうか?
これから対応する人の参考になれば幸いです。

参考