見出し画像

GitHub で管理している Serverless Framework プロジェクトのリポジトリに Pull Request がマージされたら CodePipeline を動かして自動デプロイする方法

 いわゆる 継続的デプロイ(Continuous deployment)を実現します。

 デプロイだから CodeDeploy を使うんだろ? なんて思ってしまいがちですが、CodeBuild を用いたデプロイとなります。

 確かこの辺りは AWS 認定デベロッパーアソシエイト試験範囲で、「S3 へのデプロイは何使う?」みたいなやつが模擬問題だったか何かで見た気がします(うろ覚え感)。Serverless Framework も同じ理屈で CodeBuild です。

Serverless Framework プロジェクトのリポジトリを GitHub に用意する

 今回も Serverless Framework + TypeScript で行います。ただしコードの変更は今回はありませんので aws-nodejs-typescript 以外のテンプレートでも応用が利くでしょう。

 先に GitHub 上でリポジトリを作ってから git clone してそのディレクトリ内で、serverless create が手っ取り早いと思います。

 そんなわけでリポジトリを作りました

 直接的な影響はありませんが serverless.yml を以下のように変更しています。東京リージョンにデプロイ予定です。バケット名も固定してしまっていますので、下記を流用する際は適宜変更してください。バケットも先に作っておいてください。

buildspec ファイルを用意する

 Serverless Framework は dev と prod のステージを持っているのでそれぞれにデプロイするには buildspec もそれぞれに用意してあげます。今回は prod のみのデプロイを行いますので dev の方は不要ですが一応用意しておきます。これをリポジトリ直下に置いておきます。

buildspec-dev.yml

version: 0.2

phases:
 install:
   runtime-versions:
     nodejs: latest
   commands:
     - npm install -g serverless
 pre_build:
   commands:
     - npm install
 post_build:
   commands:
     - serverless deploy

buildspec-prod.yml

version: 0.2

phases:
 install:
   runtime-versions:
     nodejs: latest
   commands:
     - npm install -g serverless
 pre_build:
   commands:
     - npm install
 post_build:
   commands:
     - serverless deploy --stage prod

CodePipelineを作成する

 AWS コンソールにログインして、CodePipeline の画面を開きます。そしてオレンジ色の「パイプラインを作成する」ボタンを押します。

コメント 2020-05-05 210530

 パイプライン名にこのプロジェクトのパイプラインと分かるような名前を入力し、それ以外はデフォルトのまま「次に」ボタンを押します。

コメント 2020-05-05 210652

 ソースステージの追加で、ソースプロバイダーに GitHub を選択します。

コメント 2020-05-05 210843

 「GitHub に接続する」ボタンが表示されますので、それをクリックしGitHubと連携させます。下記の文言が出れば正常に連携できています。

✔ プロバイダに正常にアクションを設定しました。

 ※ GitHub Organization のリポジトリを使用する場合は、GitHub の Organization settings の Third-party access で 「Grand access」ボタンを押して許可する必要があります。

 そして対象のリポジトリとブランチを選択し、「次に」ボタンを押します。ブランチ名はテキスト入力可能ですので現時点で存在しないものも設定可能です。

コメント 2020-05-05 211602

 ビルドステージの追加にてAWS CodeBuild を選択します。そして中段の「プロジェクトを作成する」ボタンを押します。

コメント 2020-05-05 211711

CodeBuild プロジェクトを作成する

プロジェクト設定
プロジェクト名に分かりやすい名前を入力します。この名前は後から変更できません。説明やタグも必要に応じて入れましょう。

コメント 2020-05-05 212849

環境
 それっぽく Amazon Linux 2 で Standard で最新イメージを使います。

コメント 2020-05-05 212944

Buildspec
 Serverless Framework に則って CodePipeline 側のステージを dev と prod に分けようと思っていたのですが面倒になったので、master マージで prod にデプロイしようと思います。なので buildspec-prod.yml を設定します。

コメント 2020-05-05 213210

 ログはお好みで。一通り CodeBuild の設定が完了しましたら「CodePipeline に進む」ボタンを押して戻ります。

CodePipeline で残りの設定を行う

 成功メッセージが表示されていることを確認し、「次に」ボタンを押します。

✔ CodeBuild で sample-serverless-codepipeline が正常に作成されました。

コメント 2020-05-05 213640

 デプロイステージはスキップします。

 最後にレビュー画面が出てきますので「パイプラインを作成する」ボタンを押し、作成を完了させます。

 作成完了させるとパイプラインが動き出します。そして失敗します。😇

コメント 2020-05-05 214740

IAMロールを変更する

 なぜ失敗したかって? IAM 権限です。

 Serverless Error ---------------------------------------

 Could not locate deployment bucket. Error: Access Denied

 Get Support --------------------------------------------
    Docs:          docs.serverless.com
    Bugs:          github.com/serverless/serverless/issues
    Issues:        forum.serverless.com

 Your Environment Information ---------------------------
    Operating System:          linux
    Node Version:              12.16.1
    Framework Version:         1.69.0
    Plugin Version:            3.6.9
    SDK Version:               2.3.0
    Components Version:        2.30.6


[Container] 2020/05/05 12:46:11 Command did not exit successfully serverless deploy --stage prod exit status 1
[Container] 2020/05/05 12:46:11 Phase complete: POST_BUILD State: FAILED
[Container] 2020/05/05 12:46:11 Phase context status code: COMMAND_EXECUTION_ERROR Message: Error while executing command: serverless deploy --stage prod. Reason: exit status 1

 Serverless Framework は AdministratorAccess が必要とドキュメントに書かれていますからね。

 必要なものだけ設定してやる方法も上記に書かれていますが、今回はAdministratorAccess を用意してやります。

 コンソールで IAM を開き、ロールから CodeBuild プロジェクト作成時に自動生成されたIAM ロールを開き、「ポリシーをアタッチします」ボタンを押します。

コメント 2020-05-05 215522

 そして AdministratorAccess を選択し「ポリシーのアタッチ」を行います。

コメント 2020-05-05 215652

 アタッチが成功したら下記メッセージが表示されます。

codebuild-sample-serverless-codepipeline-service-role にポリシー AdministratorAccess がアタッチされました。

 試しに CodePipeline を手動実行してみましょう。CodePipeline の画面から「変更をリリースする」ボタンを押すことで手動実行ができます。

 IAM ポリシーをアタッチしたらデプロイも成功しました。

コメント 2020-05-05 220425

 Build の詳細からログを追っていけば prod/hello の URL があると思いますのでアクセスするとレスポンスが返ってくるのが確認できます。

コメント 2020-05-05 220633

GitHub 上で Pull Request をマージしてみる

 ローカルで適当にブランチを作り、適当にコードを編集し、適当にコミットしプッシュをします。そして適当に Pull Request を作成します。

 作成したらマージします。

 Webhook での連携なのですぐに CodePipeline が動き始めます。最新の master を取得できていることが確認できますね。

コメント 2020-05-05 221119

 少し待てば Build も成功しました。

コメント 2020-05-05 221843

 同じく /prod/hello にアクセスしてみると変更されていることが確認できました。

コメント 2020-05-05 221959

おまけ:GitHub で master への直 push を禁止する

 master への直 push を禁止し、変更は全部 Pull Request 経由にすることで、コードレビューされていない変更のデプロイを防ぐことができます。

 GitHub 側で以下のように設定が可能です。マージで他者のレビューを必須にする場合は1個目のチェックを付けましょう。

コメント 2020-05-05 222204

まとめ

 CodePipeline と CodeBuild を構築し GitHub を設定することで、Pull Request を受け入れたら即座に変更を反映させることができました。

 これはデプロイまでを自動化しているので継続的デプロイと呼びます。

 実際の現場では develop ブランチへのPull Request マージ時には検証環境に継続的デプロイ、master ブランチへの Pull Request マージ時には上長の承認後に本番環境に継続的デリバリーを行いたいかと思います。試していませんがその辺りも CodePipeline 上で実現できると思います。

 ローカル環境で serverless deploy --stage prod されたら本番環境にデプロイできてしまいますが、この辺りを防ぐ手立てが私も知りたいです🤔


😉