GithubのActionsでLaravelのデプロイ

# 前提条件
* Laravelをローカルでデプロイヤーとしてdeployerを利用している（公開鍵を利用）

# やりたいの
* ローカルでのdeployerを利用するデプロイはそのまま使用可能
* Actionsを利用したデプロイもdeployerを利用
* Staging環境のデプロイはbranchのpushで自動デプロイ
* 本番環境のデプロイは手動デプロイ

# 環境周りの設定
## Githubへ公開鍵の設定
利用するレポジトリの「Settings > Secrets」に入って、「New secret」クリックし公開鍵を登録します。
![img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489182/ecd52d82-9fed-598b-768c-bc1c705341e3.png)

* Name：SSH_DEPLOY_KEY
* Value：ローカルのDeployerで使用している鍵（.pubでない方）の中身をコピーして入れる

![img2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489182/cf6548ea-b254-890a-7f18-629bd6e81c70.png)

## サーバーでの設定
CIで実装されるので、「やりたいの」で書いた公開鍵を利用したsshの接続することと同様にDeployerの実行の中でGithubからのソースのcloneする際にもパスワードが入力しなくても可能にする必要が有ります。
サーバーで以下の作業が必要です。

### 公開鍵の作成
鍵を入れるフォルダに移動しましょう。

```
$cd ~/.ssh
```
はじめて鍵を生成するときは何もないはずです。次のコマンドで鍵を生成します。

```
$ssh-keygen -t rsa
```
他のオプションを利用しても良いですが、ここでは一番簡単な感じでやります。

```
$ ssh-keygen -t rsa 
Generating public/private rsa key pair. 
Enter file in which to save the key (/Users/(username)/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again:
```
鍵のファイル名やパスワードを聞かれますが、3回エンターを押して飛ばします。
id_rsaとid_rsa.pubの2つの鍵が生成されます。__既にid_rsaが存在する人は上書きされてしまうので注意です。__

### Githubで鍵の登録
Githubに入って上記で作成した鍵を登録します。[https://github.com/settings/ssh](https://github.com/settings/ssh)で公開鍵の設定が出来ます。

ローカルのデプロイでも使用していれば既に登録されている物があると思います。画面右上の「Add SSH key」のボタンを押します。
![img3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/489182/9188fa9b-ff60-7a0e-a309-398615136180.png)

* Title：公開鍵名（任意）
* Key：公開鍵の中身

なお、鍵の中身のクリップボードへのコピーは以下の感じです。鍵の名前は自分の作成したもの。

```
$ pbcopy < ~/.ssh/id_rsa.pub (Mac)
$ clip < ~/.ssh/id_rsa.pub (Windows)
```

### 接続のテスト
サーバーで以下を実行してみます。

```
$ ssh -T git@github.com
Hi (account名)! You've successfully authenticated, but GitHub does not provide shell access.
```
で返ってきたら接続が可能とことです。

しかし、鍵を作るときに名前を指定していれば、うまくいかないかもしれません。それは、ssh接続の際「~/.ssh/id_rsa」、「~/.ssh/id_dsa」、「~/.ssh/identity」しかデフォルトでは見にいかないからです。
それに対応するためには~/.ssh/configを作成し、以下の内容を追記します。

```
Host github github.com
  HostName github.com
  IdentityFile ~/.ssh/id_rsa #ここに自分の鍵のファイル名
  User git
```
テスト！！

```
$ ssh -T github
```

# Actionsのworkflowを作成
対象リポジトリの「Actions」に入って新しくTempleteを利用して作成しても良いです。

## トリガーの部分
### Staging
Stagingは要求内容にも書いてますが、特にエンジニアーが管理する必要がないかと思いましてgitにPushするタイミングでデプロイが動くと良いかと思いました。

```
name: deploy dev

on:
  push:
    branches:
      - deploy/dev
```

### production
本番の場合はGitのPushミス等の可能性でエンジニアーが手動でする必要があるかと思いましたので、以下のトリガーにしました。

```
name: deploy pro

on:
  workflow_dispatch:
    branches:
      - deploy/pro
```

## テストの部分
他の記事や資料、Githubのテンプレートではphpunitを利用する例が多です。

```
jobs:
  laravel-tests:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - name: Copy .env
      run: php -r "file_exists('.env') || copy('.env.example', '.env');"
    - name: Install Dependencies
      run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
    - name: Generate key
      run: php artisan key:generate
    - name: Directory Permissions
      run: chmod -R 777 storage bootstrap/cache
    - name: Create Database
      run: |
        mkdir -p database
        touch database/database.sqlite
    - name: Execute tests (Unit and Feature tests) via PHPUnit
      env:
        DB_CONNECTION: sqlite
        DB_DATABASE: database/database.sqlite
      run: vendor/bin/phpunit
```
でも今回はウェブの状態を確認するように構成してみました。以下のように書きました。

```
jobs:
  test:
    name: serve test
    runs-on: ubuntu-latest

    services:
      mysql:
        image: mariadb:10.4.11
        ports:
          - 3306:3306
        options: --health-cmd "mysqladmin ping -h localhost" --health-interval 20s --health-timeout 10s --health-retries 10
        env:
          MYSQL_ROOT_PASSWORD: pass
          MYSQL_DATABASE: db_sample

    env:
      DB_CONNECTION: mysql
      DB_HOST: 127.0.0.1
      DB_PORT: 3306
      DB_DATABASE: db_sample
      DB_USERNAME: root
      DB_PASSWORD: pass

    steps:
      - uses: actions/checkout@v2
      - name: cache vendor
        id: cache
        uses: actions/cache@v1
        with:
          path: ./vendor
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-composer-
      - name: composer install
        if: steps.cache.outputs.cache-hit != 'true'
        run: composer install -n --prefer-dist
      - name: copy .env
        run: cp .env.ci .env
      - name: generate key
        run: php artisan key:generate
      - name: Directory Permissions
        run: chmod -R 777 storage bootstrap/cache
      - name: migrate
        run: php artisan migrate
      - name: run serve
        run: |
          php artisan serve &
          sleep 5
      - name: test
        run: curl -vk http://localhost:8000
```
.env.ciファイルは既存のローカル環境で使用している物を再利用しました。

## デプロイの部分
jobかstepに以下のような条件で分けることで共通化も可能でしたが、今回トリガーで分けるのでファイル次第が別にするしかなかったです。

```
if: github.ref == 'refs/heads/deploy/staging'　<- ブランチが「deploy/staging」の場合
```

以下になりました。

```
  deploy:
    name: deploy
    runs-on: ubuntu-latest
    needs: test

    steps:
      - uses: actions/checkout@v2
      - name: cache vendor
        id: cache
        uses: actions/cache@v1
        with:
          path: ./vendor
          key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
          restore-keys: |
            ${{ runner.os }}-composer-
      - name: composer install
        if: steps.cache.outputs.cache-hit != 'true'
        run: composer install -n --prefer-dist
      - name: ssh_key copy
        run: |
          mkdir -p /home/runner/.ssh
          touch /home/runner/.ssh/deployerで設定されているファイル名
          echo "${{ secrets.SSH_DEPLOY_KEY }}" > /home/runner/.ssh/deployerで設定されているファイル名
          chmod 600 /home/runner/.ssh/deployerで設定されているファイル名
      - name: add known hosts
        run: ssh-keyscan サーバーIP >> ~/.ssh/known_hosts
      - name: install deploy
        run: |
          curl -LO https://deployer.org/deployer.phar
          mv deployer.phar ./deployer/dep
          chmod +x ./deployer/dep
      - name: deploy dev
        run: cd ./deployer && ./dep deploy dev -vvv
```

* .deployer：deployerの設定が入っているフォルダーで、laravelプロジェクト/deployerの感じで設定されている状況です。
* dep deploy dev：deployerで設定されているstage名「->stage('dev')」です。

# 欲しい機能
本番のデプロイをトリガーで手動でしているのでファイルが別々になって共通的な部分が再利用されない状況です。CircleCIかBitbucketのPipelineのように手動でデプロイする他の方があるかとjob等を他のymlファイルをインクルード等出来れば良いかと思いました。

同じ記事：https://fatty-rabbit.tistory.com/11