TravisCI + CodeDeployでデプロイする

TravisCI + CodeDeployのフロー

【High Level】
– Merge Pull Request on master
– Travis Builds project automatically / run tests
– Travis uploads zipped project up to S3
– Travis then tells AWS Code Deploy to deploy to EC2 instance

【Index】
1. Pre-Setup
2. Policy For Server
3. Policy For Travis CI
4. Creating Travis User in IAM
5. Role for EC2 Instance
6. Role for Code Deploy Application
7. Create EC2 Instance
8. Create EC2 Tag
9. Create S3 Bucket
10. Setup Code Deploy
11. Project Setup
12. Setting Up Travis User Credentials on Travis
13. Code Deploy Agent Setup

### 1. IAMでEC2のPolicy作成
Policies -> Create Policy
Name: CodeDeployDemo-EC2-Permissions
Description: CodeDeployDemo-EC2-Permissions

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:Get*",
                "s3:List*"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

-> このポリシーによって、EC2がS3からデータを持ってこれる

### 2. IAMでTravisCI、CodeDeployの為のPolicy作成
1.TravisがS3にアップロード
Travis-Deploy-To-S3

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

2.CodeDeployがEC2にデプロイ
Travis-Code-Deploy-Policy
※AccIdHEREはAWSの数字のID
※NameOfTheCodeDeployApplicationNameHEREはCodeDeployのapplication name
※ServerRegionHEREはap-northeast-1

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:RegisterApplicationRevision",
                "codedeploy:GetApplicationRevision"
            ],
            "Resource": [
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:application:NameOfTheCodeDeployApplicationNameHERE"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:CreateDeployment",
                "codedeploy:GetDeployment"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:GetDeploymentConfig"
            ],
            "Resource": [
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:deploymentconfig:CodeDeployDefault.OneAtATime",
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:deploymentconfig:CodeDeployDefault.HalfAtATime",
                "arn:aws:codedeploy:ServerRegionHERE:AccIdHERE:deploymentconfig:CodeDeployDefault.AllAtOnce"
            ]
        }
    ]
}

### 3. IAMでTravisユーザ作成
UserName: Travis
access type: Programmatic access
Set permissions: 上記で作成したTravis-Deploy-To-S3、Travis-Code-Deploy-Policy
->作成後、accesskey、secretkeyを保存

### 4. EC2のロール作成
Create role -> AWS service EC2
Permissions:CodeDeployDemo-EC2-Permissions
Role Name: CodeDeploy_EC2_DEPLOY_INSTANCE

### 5. CodeDeployアプリの為のロール作成
Create role -> CodeDeploy
Permissions: AWSCodeDeployRole
Role Name: CodeDeployServiceRole

### 6. EC2 launch
Amazon Linux 2 AMI (HVM), SSD Volume Type 64x t2.nano 8GiB GP2
Auto-assign Public IP: enable
IAM role: CodeDeploy_EC2_DEPLOY_INSTANCE
Tag: Name travisci

### 7. S3バケット作成
create bucket -> demo-travis-s3

### 8. CodeDeploy作成
Create application -> application nameはIAMのTravis-Code-Deploy-Policyで設定したname
platform: EC2/On-premises

Create Deployment Group -> Deployment Group Name : TravisCodeDeployDemoDeploymentGroup(何でもOK)
Envrionment Configuration -> Amazon EC2 -> 6で作成したtagを選択(Name travisci)
CodeDeployDefault.AllAtOnce

### 9. travis.yml

language: php
php:
  - 7.3

services:
  - mysql

before_script:
  - cp .env.travis .env
  - mysql -e 'create database test;'
  - composer self-update
  - composer install
  - chmod -R 777 storage

script: 
  - ./vendor/bin/phpunit

deploy:
  - provider: s3
    access_key_id: $AWS_ACCESS_KEY
    secret_access_key: $AWS_SECRET_KEY
    local_dir: dpl_cd_upload
    skip_cleanup: true
    on: &2
      repo: hoge/hogehoge
    bucket: demo-travis-s3
    region: ap-northeast-1
  - provider: codedeploy
    access_key_id: $AWS_ACCESS_KEY
    secret_access_key: $AWS_SECRET_KEY
    bucket: demo-travis-s3
    key: latest.zip
    bundle_type: zip
    application: travisci
    deployment_group: TravisCodeDeployDemoDeploymentGroup
    region: ap-northeast-1
    on: *2

script:
  - zip -r latest *
  - mkdir -p dpl_cd_upload
  - mv latest.zip dpl_cd_upload/latest.zip

### 10.Travis側でcrudentialの登録
Environment Variables
– AWS_ACCESS_KEY, AWS_SECRET_KEYを入力

### 11. EC2にCodeDeployインストール
$ sudo yum update
$ sudo yum install ruby
$ sudo yum install aws-cli
$ aws s3 cp s3://aws-codedeploy-ap-northeast-1/latest/install . –region ap-northeast-1
$ chmod +x ./install
$ sudo ./install auto
$ sudo service codedeploy-agent status
$ sudo yum info codedeploy-agent

### 12. appspec.yml

version: 0.0
os: linux
files:
  - source: ./
    destination: /home/test/travisci

### 13. git push & deploy
$ git push -u origin master

### 14. travisci
-> passed
-> Done. Your build exited with 0.

### 15. EC2で動作確認
$ cd /home/test/travisci
$ ls
README.md artisan composer.lock database phpunit.xml routes tests
app bootstrap composer.phar package-lock.json public server.php vendor
appspec.yml composer.json config package.json resources storage webpack.mix.js

– 所感
circleCIはデプロイのjob実装に一日かかりましたが、Travisは多少IAMの設定に時間がかかりましたが、デプロイは一発で上手くいきました。
Gitpullではなく、CodeDeployでデプロイできるので、AWSとはTravisの方が相性が良さそう。
ただ、unitテストはmasterへのpushではなく、ブランチのリポジトリへのpushのタイミングの方が良さそう。