Circle CI + rails  + AWS で自動テスト、自動デプロイが失敗した（Autoscaling 使用）

#概要

うまくいかなかったので、teratailの下記の質問に答えていただけたらとても嬉しいです。

[https://teratail.com/questions/359594](https://teratail.com/questions/359594)


前回書いた下記の記事からの続きです。
[EC2 + RDS + Capistrano + unicorn + nginxでrailsアプリを自動デプロイ メモ](https://qiita.com/nakayama_ryotaro/items/ea935c668bba97821b8e)

前回はCapistranoでしたが今回はCode〇〇　の４つを使った自動デプロイを行います。
まずは自動テストをCircleCIで、できるようにします。

#database.yml の編集
テスト用のデータベースが使えるよう、前回からdatabase.ymlを変更
もしかしたら必要ない記述もあるかもしれません。

```yml:database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  port: 3306
  pool: <%= ENV.fetch("RAILS_MAX_THREADS"){5}%>

development:
  <<: *default
  username: root
  password: password
  database: product_register_new_development
  host: <%= ENV['DB_HOST'] %>

test:
  <<: *default
  database: product_register_new_test
  username: root
  host: <%= ENV['DB_HOST'] %>
  password: password

production:
  <<: *default
  database: product_register_new_production
  password: <%= ENV['DATABASE_PASSWORD']%>
  socket: /var/lib/mysql/mysql.sock
  username: <RDSマスターユーザー>
  host: <RDSのエンドポイント>
```
**git push**しておきましょう。

#自動テスト

github にpush したとき、自動でRspec が走るようにします。

##Rspecのインストール##
Genfile に下記を追加

```a:Gemfile
group :development, :test do
  gem 'rspec-rails', '~> 4.0.1'
end
```
インストール

```
[<アプリ名>]$ bundle install
```

下記を実行

```
[<アプリ名>]$ bin/rails generate rspec:install
      create  .rspec
      create  spec
      create  spec/spec_helper.rb
      create  spec/rails_helper.rb
```
rspec binstubを使うことで、テストスイートの起動時間を速くすることができます。

テストスイートとは、目的や対象ごとに複数のテストケースをまとめたものです。

Gemfileを開き、:developmentのグループ内にgemを追加します。

```a:Gemfile
group :development do
  gem 'spring-commands-rspec'
end
```

インストール

```
[<アプリ名>]$ bundle install
```

binstubのgemがインストールできたので、以下のコマンドを実行して新しいbinstubを作成しましょう

```
[<アプリ名>]$ bundle exec spring binstub rspec
```

コマンドがうまく実行できていれば、アプリケーションのbinディレクトリ内にrspecという実行用ファイルが作成されているはずです。

先ほどインストールしたbinstubを使って、RSpecが正しくインストールされているかを確認します。

ターミナルを開いて、以下のコマンドを実行してください。

```
[<アプリ名>]$ bin/rspec
```

以下の結果が返ればOKです

```
Finished in 0.03718 seconds (files took 0.78572 seconds to load)
0 examples, 0 failures
```

これから新しいモデルやコントローラーなどを作成する時に、一緒にRSpecのテストファイルも自動で作成してもらえるように設定しましょう。

config/application.rbを開き、以下のコードを追加します。

```ruby:config/application.rb
require_relative 'boot'

require 'rails/all'

Bundler.require(*Rails.groups)

module MiyachaApp
  class Application < Rails::Application
    config.load_defaults 6.0


ここから  
    config.generators do |g|
     g.test_framework :rspec,
       fixtures: false,
       view_specs: false,
       helper_specs: false,
       routing_specs: false
    end
ここまで

  end
end
```
これでテストを書く環境が整いました！

circle ci では **bin/rspec** を実行します

##.circleci/config.yml の編集##

.circleci/config.yml を以下のように編集します。

environmentのDB_HOST は　localhost ではうまくいかなかったので127.0.0.1　にしました。

```yml:.circleci/config.yml
version: 2.1
jobs:
  build:
    docker:
      #以降のコマンドは一つ目のイメージをベースに実行
      - image: circleci/ruby:2.5.9-node-browsers
        environment:
          - RAILS_ENV: 'test'
      - image: circleci/mysql:5.6
        environment:
          - MYSQL_ROOT_PASSWORD: password
    environment:
      # circleci/mysql:5.6がポート3306を EXPOSE しているので、一つ目のコンテナで127.0.0.1 からフォワードできる様になっている
      # `127.0.0.1:3306` で circleci/mysql:5.6に接続可能
      #portはdatabase.ymlで3306を指定
      DB_HOST: 127.0.0.1
    steps:
      - checkout
      - restore_cache:
          key: gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
      - run:
          name: install dependencies
          #自分のアプリで使っているbundler のバージョンを設定
          command: |
            gem install bundler -v 1.17.3
            bundle install --path vendor/bundle
      - save_cache:
          key: gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      - run:
          name: データベースの起動を待機
          command: dockerize -wait tcp://127.0.0.1:3306 -timeout 1m
      - run:
          name: データベースのセットアップ1
          command: bundle exec rake db:create
      - run:
          name: データベースのセットアップ2
          command: bundle exec rake db:migrate
      - run:
          name: run tests
          command: bin/rspec

```

#自動デプロイ

前回はCapistano を使った自動デプロイを行いましたが今回は、CodePipeline,CodeDeploy,Codecommit,Codebuilde を用いた自動デプロイ環境を構築します。

git push 後にテストが走り、テストが成功した後、自動デプロイが走るようにします。

図としては以下のようになります。

また**Autoscaling Group** を用いて　複数のインスタンスを増やしたときに自動でデプロイされることを確認します。

##product-ec2インスタンスのAMI作成##

product-ec2のAMIを作成します

|設定項目 |設定  |
|---|---|
|イメージ名|product-register-image|
|イメージの説明 - オプション|product-register-image|


##起動テンプレートの作成##

インスタンスのところから起動テンプレートを作成します。

|設定項目 |設定  |
|---|---|
|起動テンプレート名  |product-auto-group-template|
|AMI|product-register-image|
|セキュリティグループ|Security_for_product_app_EC2|
|Auto Scaling のガイダンス|チェック|



##Autoscaling Group の作成##

|設定項目 |設定  |
|---|---|
|Auto Scaling グループ名 |Product-auto-scaling-group|
|起動テンプレート|product-auto-group-template|
|テナンシー|デフォルト|
|vpc|product_vpc|
|サブネット|product_public_subnet_for_EC2|
|ロードバランシング|ロードバランサーがありません|
|グループサイズ|希望する容量 1 ,最小キャパシティ 1 ,最大キャパシティ 2|

他はデフォルトのままで行います。

生成されるインスタンスに名前をつけ忘れたのでproduct-ec2-autoを追加しました。

product-ec2-autoにElasticIP を割り当てておきます。

product-ec2-auto にSSH 接続してください

```
ssh -i ~/Desktop/product.pem ec2-user@<public IP>
```

一度アプリフォルダを削除します

```
[ec2-user@ip-<IP アドレス> <アプリ名>]$ rm -rf product_register_new
```

ローカルでフォルダを作成して

```
git init

git clone git@github.com:ryotaro-tenya0727/code4-product-register.git
```

その後Githubリポジトリを新たに作成し、Githubリポジトリを変更するために下記を実行
**code4-product-register** という名前にしました。

```
git remote set-url origin git@github.com:ryotaro-tenya0727/product_register_new.git
```

その後git push

```
git push -u origin master
```

**次にローカルでconfig/unicorn.rb を、インスタンスに接続して/etc/nginx/conf.d/rails.confを編集します。**



以下の記事のCapistrano を用いる前に戻し,**アプリ名の部分はcode4-product-registerにします。またIPアドレスは新しいインスタンスのIPに変えます**


[EC2 + RDS + Capistrano + unicorn + nginxでrailsアプリを自動デプロイ メモ](https://qiita.com/nakayama_ryotaro/items/ea935c668bba97821b8e)

unicorn.rb を編集したら**git push**しましょう。

nginx を編集

```
sudo vi /etc/nginx/conf.d/rails.conf
```

インスタンスにSSH接続して下記実行

```
git clone git@github.com:ryotaro-tenya0727/code4-product-register.git
```

コンパイル実行

```
rails assets:precompile RAILS_ENV=production
```

下記の**データベース作成、Railsを起動**を順に実行

[EC2 + RDS + Capistrano + unicorn + nginxでrailsアプリを自動デプロイ メモ](https://qiita.com/nakayama_ryotaro/items/ea935c668bba97821b8e)

アプリが表示されればOK

#Code〇〇でのデプロイ環境の構築

これから、CodeDeploy,Codecommit,Codebuild,Codepipeline　を用いたデプロイ環境を構築していきます。

##CodeDeploy用のIAMロールの作成##

IAM の画面に行きます。

次に、IAMの画面からロールを選択してください。

ロールの作成を選択してください。

以下の画面が表示されたら、CodeDeployを選択してください。

![スクリーンショット 2021-09-12 4.08.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/f816c91f-5e89-f5e4-1c85-a85760b23e53.png)

次のステップに行きます。

AWSCodeDeployRoleというIAMポリシーが表示されます。

これはCodeDeployとして必要な権限が全て付いているIAMポリシーです。

これを付与したIAMロールを作成するので、そのまま次のステップを押してください。

![スクリーンショット 2021-09-12 4.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/23b66340-7da9-ccee-48f3-bbd759739505.png)

タグの追加画面が表示されますが、特にタグは付けないので、そのまま次のステップを押してください。

ロール名に**CodeDeployServiceRole**と入力してください
入力を終えたら、ロールの作成を押してください。他の項目はそのままで構いません。

##CodeDeployのアプリケーションとデプロイグループの作成##

AWSのデプロイ自動化サービスであるCodeDeployの「アプリケーション」と「デプロイグループ」を作成します

AWSのマネジメントコンソールのサービス一覧からCodeDeployを選択してください。

次の画面で左側の開始方法を押し、その後に表示された画面で右上が東京リージョンとなっていることを確認の上、アプリケーションの作成を押してください。

![スクリーンショット 2021-09-12 4.22.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/e46a47f4-f686-bdd8-9292-bdf60e2b825b.png)

アプリケーション名を**product-auto-group** として作成します。

![スクリーンショット 2021-09-12 4.24.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/c802fde0-d9d1-c72f-1801-af9b3d2a4af6.png)

次にデプロイグループを作成します。

|設定項目 |設定  |
|---|---|
|デプロイグループ名|product-auto-group|
|サービスロール|CodeDeployServiceRole|
|デプロイタイプ|インプレース|
|ここから**環境設定**||
|Amazon EC2 Auto Scaling グループ|チェック入れる|
|Amazon EC2 Auto Scaling|Product-auto-scaling-groupを選択|
|Amazon EC2 インスタンス|チェック入れる|
|インスタンス指定|Name: product-ec2-auto|
|AWS Systems Manager を使用したエージェント設定|今すぐ更新し、更新をスケジュール|
|Load balancer|チェックしない|

作成を押下します。

##EC2用のIAMロールの作成とEC2への割り当て(後からcodepipeline 用のS３追加)##

構築する自動デプロイでは、S3に保存されたビルド結果のファイルをEC2が取得します
そのためには、EC2がS3からファイル(S3オブジェクト)を取得できる権限を持っている必要があります。
デプロイ用のS3からファイルを取得可能な権限を持つIAMロールを作成し、これをEC2に割り当てます。

また後から、Codepipeline 作成時に生成されるS3をIAMのインラインポリシーに追加します。

ロールの画面でEC２を選択します。
![スクリーンショット 2021-09-12 6.22.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/41e3ddbf-31a4-d64a-2782-2fd9b635ee80.png)

次のステップに行きます

**ポリシーの選択は行わず、次のステップに行きます。**

**タグは特に付けないので、そのまま次のステップを押してください。**

**ロール名はproduct-auto-ec2にします**

**作成を押下します**

**次に本パートで作成したIAMロールをEC2に割り当てます**

##CodeDeployエージェントのインストール##

CodeDeployを使ってEC2にデプロイを行うためには、EC2にCodeDeployエージェントというものをインストールする必要があります。


CodeDeployエージェントはRuby製のプログラムであるため、まずRubyをインストールします。
product-ec2の環境構築ですでにインストール済みですが、それだとうまくいかなかったので、インストールが必要みたいです。

```
sudo yum install ruby -y
```


/home/ec2-userディレクトリで下記コマンド実行

```
wget https://aws-codedeploy-ap-northeast-1.s3.ap-northeast-1.amazonaws.com/latest/install
```

続いて、以下コマンドを実行してください

```
chmod +x ./install
```

```
sudo ./install auto
```

CodeDeployエージェントの実行状態の確認をするために以下を実行

```
sudo service codedeploy-agent status
```

下記のように表示されれば成功

```
The AWS CodeDeploy agent is running as PID 26710
```

##CodeDeployに指示するためのCircleCI用のIAMユーザー作成とCircleCIへの環境変数登録##

デプロイ開始を支持できるようなIAMユーザーを作成します。
さらに、そのIAMユーザーのアクセスキーIDとシークレットアクセスキーを発行し、CircleCIの環境変数に登録します。

ユーザー名をproduct-deployer 、プログラムによるアクセスにチェックを入れてIAMユーザーを作成します。

![スクリーンショット 2021-09-12 8.08.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/3765a13b-18be-9eca-5d69-ff0b4e7f2fa9.png)

以下の画面では、既存のポリシーを直接アタッチを選択の上、ポリシーのフィルタ欄にdeployerと入力してください。

すると、AWSCodeDeployDeployerAccessという管理ポリシーが表示されるので、この行の左端にチェックを入れてください。

このAWSCodeDeployDeployerAccessというポリシーには、CodeDeployを操作するために必要な権限が付いています。

チェックを入れたら、次のステップを押してください。

なお、デプロイ用S3へのアップロードを可能とするポリシーについては、後ほどIAMユーザーに直接書き込みます(インラインポリシーとして追加します)。

![スクリーンショット 2021-09-12 8.11.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/17b7af66-b385-ee05-e91d-16b2ea91cf32.png)

タグの追加画面が表示されますが、特にタグは付けないので、そのまま次のステップを押してください。

ユーザーの作成を押下してください。

ユーザーの作成を押すと、以下の画面となり、アクセスキーIDとシークレットアクセスキーが確認できるようになります。

これらをCircleCIに登録するので、この画面は閉じずにそのままにしておいてください。

![スクリーンショット 2021-09-12 8.28.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/f2c33b8c-68b3-6f7e-d556-723f5d3cbb1b.png)

##CircleCIの環境変数の登録##

CircleCi code4-product-registerリポジトリのProject Settings画面でEnvironment Variables(環境変数)を選択してください

以下の画面が表示されるので、

Name: AWS_ACCESS_KEY_ID
Value: AWSの画面に表示されているアクセスキーID

Name: AWS_SECRET_ACCESS_KEY
Value: AWSの画面に表示されているシークレットアクセスキー

を入力して、Add Environment Variableボタンを押してください。



![スクリーンショット 2021-09-12 8.38.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/6af1ec56-fe60-aaf7-b8a3-099627cc740d.png)

アクセスキーIDの登録を終えたら再度Add Variableボタンを押してシークレットアクセスキーを登録

##AppSpec Fileとシェルスクリプトの作成##

本パートでは、CodeDeployのデプロイ時の処理内容を定義するAppSpec Fileを作成します。

また、AppSpec Fileから使用されるシェルスクリプトを作成します。

appspec.ymlにはS3でZipファイルになったソースコードがEC2に送られる際の、Zipファイルから見た視点での動作を記述します。
ディレクトリはrails のapp やGemfile と同じ場所にします。

appspec.yml をapp,Gemfile と同じディレクトリに作成し下記のように編集
(Downloadbundle を記述しないでデプロイを行った時、Codepipeline エラーが起こったので、何かルールがあるのかも)

```yml:appspec.yml
version: 0.0
os: linux
files:
  #現在のディレクトリをEC2のアプリケーションにデプロイする設定
  - source: /
    destination: /var/www/code4-product-register
permissins:
  #/var/www 以下の全てのディレクトリに755の権限を設定
  - object: /var/www/
    pattern: '**'
    mode: 775
    owner: ec2-user
    group: ec2-user
hooks:
  ApplicationStop:
    - location: scripts/stop_server.sh
      timeout: 300
      runas: ec2-user
  BeforeInstall:
    - location: scripts/clean.sh
      timeout: 300
      runas: ec2-user
  AfterInstall:
    - location: scripts/after_install.sh
      timeout: 300
      runas: ec2-user
  ApplicationStart:
    - location: scripts/start_server.sh
      timeout: 300
      runas: ec2-user

```

CodeDeployでは、デプロイの開始から終了までを以下のイベントで進行していきます。

**1.ApplicationStop
2.DownloadBundle(デプロイ対象のファイルをEC2内の一時的な保存場所に置く。フックとして利用不可。)
3.BeforeInstall
4.Install(EC2内の一時的な保存場所からファイルをデプロイ先のパスに配置する。フックとして利用不可。)
5.AfterInstall
6.ApplicationStart
7.ValidateService**

よってそれぞれのタイミングで実行してほしいスクリプトをscriptsディレクトリ に記述していきます。

下記でunicorn のプロセスを終了させています

```sh:scripts/stop_server.sh
#!/bin/bash
kill -KILL -s QUIT `cat /var/www/code4-product-register/tmp/pids/unicorn.pid`
```



下記でS3からソースコードをEC2に送る前に前回のソースコードを削除します。

```sh:scripts/clean.sh
#!/bin/bash
sudo rm -rf /var/www/code4-product-register/
```


```sh:scripts/after_install.sh
#!/bin/bash
source ~/.bash_profile
cd /var/www/code4-product-register
RAILS_ENV=production bundle exec rake assets:precompile
RAILS_ENV=production bundle exec rake db:migrate

```

```sh:scripts/start_server.sh
#!/bin/bash
source ~/.bash_profile
cd /var/www/code4-product-register
sudo systemctl reload nginx
sudo systemctl start nginx
bundle exec unicorn -D -E production -c config/unicorn.rb
```

##CodeCommitにリポジトリを作成する##

CodeCommitは、AWS版のGitHubのようなものです。

本章で構築する自動デプロイでは、サンプルアプリケーションのmasterブランチをCircleCIからCodeCommitにプッシュします

そして、その後はCodeCommitのmasterブランチのソースコードをもとにビルドやデプロイを行なっていきます。

**AWSのマネジメントコンソールのサービス一覧からCodeCommitを選択しリポジトリを作成を押下します。**

**リポジトリ名をproduct-ec2 とします。**

##CodeCommit接続用IAMユーザーの作成と公開鍵の登録##

CircleCIからCodeCommitへmasterブランチをプッシュ可能とするために、以下を行います。

1.CodeCommitへプッシュ可能な権限を持ったIAMユーザーを作成する

2.秘密鍵と公開鍵をあなたのPCで作成し、公開鍵をIAMユーザーのCodeCommit用SSHパブリックキーに登録する

3.秘密鍵をCircleCIにSSH Keyとして登録する

以上を行うことで、CircleCIからSSH接続にてCodeCommitへのプッシュが可能となります

##IAMユーザーの作成

コンソールからIAMユーザーのところに移動し、IAMユーザー作成を押下します。

ユーザー名はproduct-ec2-codecommit-pusherとします。

アクセスの種類はプログラムによるアクセスをチェックします(実際は使用しないのですが、チェックしないと先に進めないのでチェックします)。

入力、選択を終えたら次のステップを押してください。

以下の画面では、既存のポリシーを直接アタッチを選択の上、ポリシーのフィルタ欄にcommitと入力してください。
![スクリーンショット 2021-09-12 10.56.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/a1aeb44f-dc27-2729-3b65-174dfb962d74.png)

いくつか表示されたうち、AWSCodeCommitPowerUserという管理ポリシーの左端にチェックを入れてください。

チェックを入れたら、次のステップを押してください。

タグの追加画面が表示されますが、特にタグは付けないので、そのまま次のステップを押してください。

ユーザー作成を押下した後、アクセスキーIDとシークレットアクセスキーが表示されますが、使用しないので閉じるを押します。

##IAMユーザーのCodeCommit用SSHパブリックキーに公開鍵を登録する

IAMユーザーのCodeCommit用SSHパブリックキーに公開鍵を登録します(鍵をまだ作成していませんが、後ほど作成します)。

IAMユーザーの product-ec2-codecommit-pusher の**SSHパブリックキーのアップロード**を押下します

![スクリーンショット 2021-09-12 12.08.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/fafa2de9-ec74-6631-45af-90337cafa706.png)

ここに公開鍵を登録していきます。

##IAMユーザー用の秘密鍵と公開鍵の作成

ローカルで以下を実行してください

```

$ cd ~/.ssh

$ ssh-keygen -m pem -C "" -f product-ec2-codecommit-pusher

#公開鍵のコピー
$ cat ~/.ssh/product-ec2-codecommit-pusher | pbcopy
```
IAMユーザーの画面でクリップボードから公開鍵を貼り付け、SSHパブリックキーのアップロードを押してください

![スクリーンショット 2021-09-12 12.13.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/813e9078-2c08-494e-082b-df111e757129.png)

IAMユーザーの詳細画面に戻り、SSHキーIDが発行されていれば、公開鍵の登録は完了です。

##CodeCommitへの接続確認

先ほどの画面のSSHキーIDが、SSH接続で使用するユーザー名となります。

CodeCommitへのSSH接続確認を行うため、あなたのPCで以下コマンドを実行してください。

```
$ ssh SSHキーID@git-codecommit.ap-northeast-1.amazonaws.com -i ~/.ssh/product-ec2-codecommit-pusher
```

以下のように表示されれば成功です

```

You have successfully authenticated over SSH.
You can use Git to interact with AWS CodeCommit.
Interactive shells are not supported.Connection to git-codecommit.ap-northeast-1.amazonaws.com closed by remote host.
Connection to git-codecommit.ap-northeast-1.amazonaws.com closed.
```

IAMユーザーproduct-ec2-codecommit-pusherの作成時にアクセスキーを発行しましたが、これを利用する予定はありません。

利用予定の無いアクセスキーを使える状態にしておく必要も無いので、無効化します。

##SSHキーIDと秘密鍵をCircleCIに登録する

作成したIAMユーザーのSSHキーIDと秘密鍵をCircleCIに登録します。

これにより、CircleCIがCodeCommitにプッシュ可能となります

まず、IAMユーザーproduct-ec2-codecommit-pusherのSSHキーIDを、CircleCIに環境変数AWS_SSH_KEY_IDとして登録します。

IAMユーザーの画面で確認しておいてください。

アクセスキーIDやSSHキーではなく、SSHキーIDですので注意してください。

**Project Settings** で

Name: AWS_SSH_KEY_ID
Value: IAMユーザーproduct-ec2-codecommit-pusherのSSHキーID
を入力して、Add Environment Variableボタンを押してください。

##秘密鍵の登録

**Project Settings**画面で**SSH Keys**を選択し、**Add SSH Key**ボタンを押してください

そして
Hostname: git-codecommit.ap-northeast-1.amazonaws.com
Private Key: あなたのPCの~/.ssh/product-ec2-codecommit-pusherの内容
を入力してください。

Private Keyについては、あなたのPCで以下コマンドを実行することでクリップボードにコピーできます

```
cat ~/.ssh/product-ec2-codecommit-pusher | pbcopy
```

##.circleci/config.ymlを修正し、masterブランチをCodeCommitにプッシュするジョブを追加

PC上の.circleci/config.ymlを以下の通り編集してください。

```yml:.circleci/config.yml
version: 2.1
jobs:
  build:
    docker:
      #以降のコマンドは一つ目のイメージをベースに実行
      - image: circleci/ruby:2.5.9-node-browsers
        environment:
          - RAILS_ENV: 'test'
      - image: circleci/mysql:5.6
        environment:
          - MYSQL_ROOT_PASSWORD: password
    environment:
      # circleci/mysql:5.6がポート3306を EXPOSE しているので、一つ目のコンテナでlocalhost からフォワードできる様になっている
      # `localhost:3306` で circleci/mysql:5.6に接続可能
      #portがdatabase.yml 3306を指定
      DB_HOST: 127.0.0.1
    steps:
      - checkout
      - restore_cache:
          key: gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
      - run:
          name: install dependencies
          #自分のアプリで使っているbundler のバージョンを設定
          command: |
            gem install bundler -v 1.17.3
            bundle install --path vendor/bundle
      - save_cache:
          key: gem-cache-v1-{{ arch }}-{{ .Branch }}-{{ checksum "Gemfile.lock" }}
          paths:
            - vendor/bundle
      - run:
          name: データベースの起動を待機
          command: dockerize -wait tcp://127.0.0.1:3306 -timeout 1m
      - run:
          name: データベースの作成
          command: bundle exec rake db:create
      - run:
          name: データベースのマイグレーション
          command: bundle exec rake db:migrate
      - run:
          name: run tests
          command: bin/rspec
  deploy_tmp:
    docker:
      - image: circleci/ruby:2.5.9-node-browsers
    steps:
      - checkout
      #add_ssh_keysを使うことで、CircleCIのProject Settings画面で登録したSSHの秘密鍵を使用できるようにしています。
      - add_ssh_keys
      - run:
          name: deploy to prod
          command: |
            echo -e "Host git-codecommit.*.amazonaws.com\n   User ${AWS_SSH_KEY_ID}\n   StrictHostKeyChecking no" > ${HOME}/.ssh/config
            git push ssh://git-codecommit.ap-northeast-1.amazonaws.com/v1/repos/product-ec2

workflows:
  version: 2
  build_deploy:
    - build
    - deploy_tmp:
    #build が成功しなければdeploy_tmpを実行しない
      requires:
        - build
      filters:
      #masterブランチにマージした時のみ実行
        branches:
          only:
            - master

```

echo...の部分では、CircleCIの環境のホームディレクトリ配下の.ssh/configファイルを以下の内容で作成しています。

```
Host git-codecommit.*.amazonaws.com
  User IAMユーザーproduct-ec2-codecommit-pusherのSSHキーID
  StrictHostKeyChecking no
```
StrictHostKeyChecking noは、これまで接続したことの無いサーバーに初めてSSHログインしようとした時に表示される、

```
Are you sure you want to continue connecting (yes/no)? (接続を続行してもよろしいですか (はい/いいえ)?)
```

というメッセージを表示させなくするオプションです

Codecommitのリポジトリにソースコードがあれば成功です。

#BuildSpec Fileの作成とCodeCommitへの反映

CodeBuildの処理内容を定義するBuildSpec Fileを作成します。



##buildspec.ymlの作成

Gemfile と同じディレクトリにbuildspec.ymlというファイル名で作成します。
buildspec.yml はCodecommitからS３に渡される際のソースコードから見た視点の視点です。
インストール、コンパイルなどの操作を記述します。

**buildspec.yml を書いた後に、この記事のデプロイにおいてCodebuildを使う意味がそれほどないとわかりました。appspec.yml でもbundle　install しているので、、まだ使用する利点を理解できてない部分が多いので、今回は使う際の流れを追ってもらえればと思います。**


```yml:buildspec.yml
version: 0.2

phases:
  #codebuild から S3 に渡すとき。
  install:
    runtime-versions:
      nodejs: 10
  pre_build:
    commands:
      - rbenv install 2.5.9
      - gem install bundler -v 1.17.3
      - bundle install --path vendor/bundle
artifacts:
  files:
    - './**/*'
```

artifactsに指定したファイルが、CodeBuildの出力ファイルとなります。

ここでは全てのファイルを指定しています。

この出力ファイルは、本教材の場合であれば、CodePipelineが管理するS3にzip形式でコピーされます

##buildspec.ymlをCodeCommitに反映する

CircleCI を実行しCodecommit にbuildspec.yml を反映させます。
反映できていたらOKです。

![スクリーンショット 2021-09-13 15.51.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/e7ee3e59-ba05-838a-b6ce-2bc0f68d1c44.png)

#CodePipelineとCodeBuild(ビルドプロジェクト)の作成

CodePipelineにCodeCommitを組み込みます。

##CodePipelineの作成

AWSのマネジメントコンソールのサービス一覧からCodePipelineを選択してください。
次にパイプラインの作成を選択してください。

![スクリーンショット 2021-09-13 15.56.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/959dff21-af5b-19ab-d366-d00883fbcb6a.png)

###Step1 パイプラインの設定を選択する###
下記のように設定項目を入力します。

|設定項目 |設定  |
|---|---|
|パイプライン名|product-auto|
|サービスロール|新しいサービスロール|
|ロール名|インプレース|
|ロール名の下のチェックボックス|チェックを入れる|

![スクリーンショット 2021-09-13 16.04.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/71bb1b45-ee1a-92f1-ca7a-24c2835fb973.png)

###Step2 ソースステージを追加する###
ソースステージの設定では、CodePipelineを動かすにあたり、ソースコードをどこから持ってくるか等を指定します。

|設定項目 |設定  |
|---|---|
|ソースプロバイダー|AWS CodeCommit|
|リポジトリ名|product-ec2|
|ブランチ名|master|
|検出オプション|Amazon CloudWatch Events(推奨)|
|出力アーティファクト形式|CodePipeline のデフォルト|

![スクリーンショット 2021-09-13 16.12.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/0b139f5d-62ad-334a-9293-a5b07ddef44e.png)


###STEP3 ビルドステージを追加する###

ビルドステージの設定では、ビルド処理について設定します。

まず、以下を選択してください。

・プロバイダー: AWS CodeBuild
・リージョン: アジアパシフィック(東京)

プロジェクト名にはCodeBuildのビルドプロジェクト名を入力するのですが、まだCodeBuildのビルドプロジェクトを作成してません。

そのため、プロジェクトを作成するを選択してください。

![スクリーンショット 2021-09-13 16.19.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/14920ec5-62f1-8449-a86c-dc3a1c657ec1.png)

###CodeBuildのビルドプロジェクトの作成###


プロジェクトを作成するを選択するとブラウザの別ウィンドウが開きます。

ここからはCodeBuildのビルドプロジェクトを作成します(作成が終わると、元のCodePipelineの画面へ戻る流れとなっています)。

以下のように設定

・プロジェクトの設定

|設定項目 |設定  |
|---|---|
|プロジェクト名|product-auto|
|環境イメージ|マネージド型イメージ|
|ランタイム|Standard|
|イメージ|aws/codebuild/amazonlinux2-x86_64-standard:2.0|
|イメージのバージョン|(選択できる中から末尾の年月日ができるだけ新しいものを選んでください)|
|環境タイプ|Linux|
|特権付与|チェックしない|
|サービスロール|新しいサービスロール|
|ロール名|codebuild-product-auto-service-role|


・環境

|設定項目 |設定  |
|---|---|
|タイムアウト|時間: 0 分: 5|
|キュータイムアウト|時間: 0 分: 5|
|証明書|証明書をインストールしない|
|VPC|空欄のままとしてください|
|コンピューティング|3GBメモリ、2vCPU|

これ以降は空欄で大丈夫です。

・Buildspec

|設定項目 |設定  |
|---|---|
|ビルド仕様|buildspec ファイルを使用する|
| Buildspec名 |空欄|

・ログ

|設定項目 |設定  |
|---|---|
|ログ|CloudWatch Logs|

ここまで設定したらCodePipelineに進むを選択してください。
以下のような画面になればOKです。

![スクリーンショット 2021-09-13 16.39.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/59e6233c-3b6a-53e2-c847-e7fbf6776a8d.png)

###Step4 デプロイステージを追加する###

本来であれば、作成済みのCodeDeployのデプロイグループProduct-auto-scaling-groupを指定します。

しかし、現段階ではCodePipelineにまだデプロイ処理は行わせないので、導入段階をスキップするを選択してください

![スクリーンショット 2021-09-13 16.47.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/5e78e59a-b99b-e83e-92d9-a67d98ea59f6.png)

パイプラインを作成するを押してください。
すると下記のように処理が開始されます。

![スクリーンショット 2021-09-13 20.41.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/15992515-398a-e913-888e-ba2bf6911a83.png)

成功すれば完了です。

##EC2のIAMロールにCodePipeline用S3への読み取り権限を追加する

### S3バケット名の確認

CodePipeline用のS3バケット名を確認します。

AWSコンソールのS3からCodepipeline用のS3の名前を確認します。
codepipeline-ap-northeast-〇〇〇〇〇〇〇〇〇〇〇〇　の部分です。

![スクリーンショット 2021-09-13 21.01.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/5986dfbf-a259-970a-0fc3-2685d32a4c60.png)

##IAMロールの権限追加

次に、EC2に割り当てたIAMロールに権限を追加します。

AWSコンソールのIAMからロールを選択し、product-auto-ec2 を選択します。

IAMロールlaravel-ci-ec2の詳細面が表示されるので、インラインポリシーのマークを押してください。

![スクリーンショット 2021-09-13 21.07.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/c7e1f5ea-dff7-f041-e6b6-c4fde2463cf1.png)

次の画面で、JSONタブを選択した上で、以下のように入力し、ポリシーの確認を押してください。

```json:json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:GetObjectVersion",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::codepipeline-ap-northeast-〇〇〇〇〇〇〇〇〇〇〇〇",
                "arn:aws:s3:::codepipeline-ap-northeast-〇〇〇〇〇〇〇〇〇〇〇〇/*"
            ]
        }
    ]
}
```

確認ボタンを押した後、「S3」という名前で作成ボタンを押してください

##CodePipelineへのCodeDeployの組み込み

CodePipelineに、CodeDeployのデプロイグループproduct-auto-groupを組み込みます

###ステージの追加
AWSコンソールからCodepipelineのproduct-autoを選択し編集を押します。
今回、Buildステージの後にデプロイ処理を行うので、一番下のステージを追加するを選択してください。

![スクリーンショット 2021-09-13 21.25.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/ebaf95cb-7f7c-aa24-e328-4308c569970d.png)

deploy という名前にします

![スクリーンショット 2021-09-13 21.27.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/51e95048-ad32-f967-4c1a-82c0c8fa57a5.png)


次にアクショングループを追加を選択

![スクリーンショット 2021-09-13 21.29.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/7f51abbf-729c-5101-4cac-2410c5dc6e12.png)

下記のように入力して完了します

![スクリーンショット 2021-09-13 21.33.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1461885/f0760eb0-59a7-8e11-0f40-c35355f5a826.png)

完了を押すと、一つ前の画面に戻り、DeployステージにCodeDeployが表示された状態となります。

そのまま、保存するを押してください。
これで、CodePipelineでデプロイ処理まで行えるようになりました。

ではGithubにpush してプルリクエストをマージしてデプロイできているか確認しましょう。

###これがうまくいきませんでした###