Laravel Envoy, GitHubActionsを使ってAWS EC2に自動デプロイ

学習として自動デプロイを実装しようと勉強していました。
その過程としてまとめておきたいと思います。

##環境

Mac OS Catalina 10.15.4
Laravel 5.5.48
Docker 19.03.8

##Laravel Envoy

最近まで知りませんでした。
コマンド一発でデプロイを可能にするものです。
[Laravel5.5 Envoy タスクランナー](https://readouble.com/laravel/5.5/ja/envoy.html)

blade構文で記述するので、Laravelを利用している方は学習コストが低いと思います。
何なら初心者の僕でも割とスムーズに導入できたかと思っています。
もちろんいろんな方に助けていただきながら、ですが。

###インストール
```
$ composer global require laravel/envoy
$ composer global update
```
###envoy記述

プロジェクトファイルの直下に```Envoy.blade.php```という名前でファイルを作成します。
その中に記述していきます。

```Envoy.blade.php
    {{-- AWS EC2へデプロイする予定なので、接続先を記述 --}}
@servers(['web' => ['ec2-user@123.45.6.78']]) 

    {{-- serversで記述した「web」のサーバーを対象に、taskで囲った範囲のコマンドを[foo]として定義して実行する --}}
@task('foo', ['on' => 'web']) 
  cd projectfile {{-- ここは環境に合わせて変更する --}}
  git pull git@github.com:hoge/huga.git
  cp -f .env.production .env
  docker-compose down
  docker-compose -f docker-compose.yml up -d
  docker-compose exec -T php composer install
  docker-compose exec -T php php artisan cache:clear
  docker-compose exec -T php composer dump-autoload
@endtask
```

上記の```@servers```のところは、Envoy単独で使用する場合はssh接続のコマンドをそのまま記述するのですが、GitHubActionsを利用するので、このままで保存しておきます。

##GitHub Actions

CI/CDを簡単に「ワークフロー」という形で記述して実行できます。
個人的には全っ然簡単ではなかったのですが。
ファイルはyamlで記述されます。

GitHubのリポジトリのページにいくと「Actions」というタブがあるので、それをクリックすると自動的にテンプレートが作成されます。詳しくは別の記事を参照してください。
今回はLaravelで作成しているので、Laravelベースのものを利用します。

```
name: Laravel
# ワークフロー名

# masterブランチに対してプッシュ時にワークフロー起動 実行
on:
  push:
    branches: [ master ]

jobs:
   # ジョブの名前
  laravel-tests:
    #ジョブ実行の環境
    runs-on: ubuntu-latest

    # 実際のジョブ内容　ステップとして表現
    steps:
    - name: Checkout
      uses: actions/checkout@v2

    # composer インストール
    - name: composer install
      run: composer install -n --prefer-dist

    # Envoy インストール  
    - name: Envoy install
      run: composer require laravel/envoy:1.6.1

    # laravel envoyを利用してEC2に接続、デプロイ
    - name: EC2 connection
      env:
        PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
        USER_NAME: ${{ secrets.USER_NAME }}
        HOST_NAME: ${{ secrets.HOST_NAME }}
      run: |
        # 秘密鍵をgithubactionsにコピー
        mkdir -p /home/runner/.ssh
        touch /home/runner/.ssh/id_rsa
        echo "$PRIVATE_KEY" > /home/runner/.ssh/id_rsa
        # パーミッション変更
        chmod 600 /home/runner/.ssh/id_rsa
        ssh-keyscan 18.181.8.63 >> ~/.ssh/known_hosts

    # Envoy 実行  
    - name: Envoy
      run: ./vendor/bin/envoy run deploy

```
各項目の意味に関しては、やっぱり公式が一番いいですね。
[GitHubヘルプ](https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)

いちいち全部をインストールしてるのは、GitHubActions上での仮想サーバーで動かすためです。
envoyインストールのバージョンを指定しているのは、composerと相性がよくないので低いバージョンのものを利用するようにしています。
composerをupdateしようとしたんですが、なぜかうまく行かなくてずっとエラーだったので、envoyのバージョンを落としたら行けました。ただいずれサポートが切れるようなことも書いているので、若干心配です。
https://github.com/laravel/envoy/issues/178

記述が終了したら、画面右の方の「start commit」をクリックすると自動でワークフローが始まるはずです。
ただこのままだとエラー出まくりです。

##EC2でのssh鍵作成

AWS EC2サーバーとGitHubActionsでssh接続をさせるため、EC2で鍵を作成します。
ローカルからEC2サーバーへssh接続し、

```
[ec2-user@ip-10-0-1-10 ~]$ ssh-keygen -t rsa
```

を実行すると、公開鍵（id_rsa.pub）と秘密鍵（id_rsa）が作成されます。
まずはEC2上の.sshディレクトリにある「authorized_keys」に公開鍵を記録します。

```
$ cat id_rsa.pub >> authorized_keys
```


##ssh接続の準備
上記yamlコードで環境変数を利用しています。
これはGithubのページで設定します。
リポジトリのタブの右の方の「settings」から、左のタブの「Secrets」を選択すると、環境変数を設定できます。
右の方の「New secret」から、任意の名前で作成できます。
<img width="995" alt="スクリーンショット 2020-06-12 21.41.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596140/eecbb51b-696f-0769-b336-75c614e5ed81.png">

```
HOST_NAME : ssh接続する先のIPアドレス　私の場合はEC2のElasticIP
PRIVATE_KEY : さっきEC2上で作成した秘密鍵
USER_NAME : ec2-user
```
上記の秘密鍵は、次のようにして表示させ、中身をコピペします。

```
$ cat ~/.ssh/id_rsa
```

ここのサイト様をめちゃくちゃ参考にさせていただきました。
[Github ActionsでLaravel（EC2）のデプロイ（deploy）自動化](https://noumenon-th.net/programming/2020/05/08/github-actions/)

次に、公開鍵をGitHubに保存します。右上のアバター表示されてるところをクリックして、「settings」に移動。
<img width="206" alt="スクリーンショット 2020-06-12 22.13.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596140/f0a003ac-5f7a-e1b8-253c-cfc02edf608f.png">
画面左に出てくるタブの「SSH and GPG keys」を選択すると、公開鍵を保存する画面が出てきます。
<img width="760" alt="スクリーンショット 2020-06-12 22.15.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596140/f9afe637-9d55-589d-ba58-01d7ded102d2.png">
右の方の「new SSH key」を選択し、公開鍵の中身をコピペして貼り付けます。
<img width="767" alt="スクリーンショット 2020-06-12 22.17.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596140/6bd9c134-ce59-a17b-3584-7d83f2de2732.png">

これで動くはずです。動かなかったらすみません。
GitHub Actions　→　EC2へのssh　と、
Envoy(EC2)　→　GitHub　の両方向sshがあったので、個人的にはめっちゃ困りました。超セキュリティ危ない気がしますし。

##参考記事
[GitHubヘルプ](https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions#jobsjob_idruns-on)
[Github ActionsでLaravel（EC2）のデプロイ（deploy）自動化](https://noumenon-th.net/programming/2020/05/08/github-actions/)
[GitHub Actions で LaravelのCI/CD環境を構築する（MySQL, Deployer）](https://qiita.com/wim/items/7eb8386672fd114c2576)
https://github.com/laravel/envoy/issues/178
http://tusukuru.hatenablog.com/entry/2018/08/29/021651

ありがとうございました。