Github Actionsを使ってGithubからEC2までのDjangoのCICD環境構築

#はじめに

できるだけ正確に書くよう努力しますが、若輩者故誤り等ございましたらご指導ご鞭撻のほどよろしくお願いいたします。
下記サイトを参考にさせていただきました。ありがとうございます。
https://developer.yukimonkey.com/article/20200420/

#環境
AWS EC2　：　ubuntu 18.04

#1,EC2インスタンスのSSH key作成
EC2インスタンスに接続し、下記コマンドを入力します。
※EC2インスタンスへはSSH接続でも良いし、Session Managerという方式でもつなげます。

このコマンドで、~/.ssh/id_rsa_gitという秘密鍵と~/.ssh/id_rsa_git.pubという公開鍵を作成します。

```
ssh-keygen -t rsa -b 4096 -m pem -C "SSHkey" -f ~/.ssh/id_rsa_git -N ""
```

次に、作成した公開鍵を~/.ssh/authorized_keysに統合し、ファイルのパーミッションを変更します。

```
cat ~/.ssh/id_rsa_git.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys
```

次は、SSHのconfigファイルを編集します。おそらくファイルはデフォルトで存在しないので、vimで開いて、

```
vim ~/.ssh/config
```

下記のconfigを記述します。

```config:config
Host github.com
HostName Github.com
IdentityFile ~/.ssh/id_rsa_git
User git
```

次に、Githubに登録する秘密鍵を表示させます。

```
openssl rsa -outform pem < ~/.ssh/id_rsa_git
```
と入力すると、下記のような鍵が表示されます。これを、----BEGINから最後の　KEY----までコピーしてください。
文字列の羅列部分だけだと、フォーマットがあってないと怒られます。
----BEGIN RSA PRIVATE KEY----
<文字列の羅列>
-----END RSA PRIVATE KEY-----

これでEC2の作業は終わりです。

#2,Githubの設定

Githubのデプロイしたいレポジトリで、Settings > Secretsから、このGithubレポジトリで使える環境変数を設定できます。Secretのような扱いができるので、ここに先ほど作ったEC2インスタンスへの秘密鍵を登録できます。一度登録すると中身を見ることはできず、削除か上書きしかできません。
※自分の所有してないリポジトリはSettingsがないので、リポジトリの所有者にコンタクトしてください。

以下の3つのSecretsを作成してください。
注意点は、作成したインスタンスがubuntuであればEC2_USERはubuntuです。（おそらくAmazon Linuxではec2-user）
秘密鍵
- Name: SECRET_KEY
- Valueは先ほどコピーした秘密鍵
ユーザー名
- Name: EC2_USER
- Value: ubuntu
ホスト名
- Name: EC2_HOST
- Value: EC2のIPアドレス(○○.○○.○○.○○)

#3,Github Actionsの設定

ここからが本題です。

準備は整ったので、Github ActionsでCICD環境を作りましょう！
GithubのActionsというタブから新しいActionを作成できます。

Github Actionsはpushなどのトリガーが起きるとコンテナ起動して設定したコマンドを実行してくれます。
設定ファイルはymlで記述し、.github/workflows/の階層にファイルが保存されます。Web上で設定ファイルを作成すれば、自動で所定の階層に保存されるのでご心配不要です。

私が作成したテンプレートは以下の通りです。
プロジェクト名と仮想環境名だけご自身の環境に合わせて下さい。

```yaml:deploy.yml

name: Test and Deploy 

on:
  push:
    branches: [ develop, master ]
  pull_request:
    branches: [ develop ]

jobs:
  build:

    runs-on: ubuntu-latest
    strategy:
      max-parallel: 4
      matrix:
        python-version: [3.6, 3.7]

    steps:
    - uses: actions/checkout@v2
    - name: Set up Python ${{ matrix.python-version }}
      uses: actions/setup-python@v1
      with:
        python-version: ${{ matrix.python-version }}
    - name: Install Dependencies
      run: |
        python -m pip install --upgrade pip
        pip install django==2.1.0 pandas django-bootstrap4
    - name: Run Tests
      run: |
        python manage.py makemigrations
        python manage.py migrate
        python manage.py test
    - name: deploy
      run: |
        echo "$SECRET_KEY" > secret_key
        chmod 600 secret_key
        ssh -oStrictHostKeyChecking=no ${EC2_USER}@${EC2_HOST} -i secret_key "source <仮想環境名>/bin/activate \
        && cd ~/<プロジェクト名>\
        && git pull origin develop \
        && python manage.py makemigrations \
        && python manage.py migrate \
        && deactivate \
        && sudo systemctl restart gunicorn"
    env:
      SECRET_KEY: ${{ secrets.SECRET_KEY }}
      EC2_USER: ${{ secrets.EC2_USER }}
      EC2_HOST: ${{ secrets.EC2_HOST }}
```

これで、Github Actionが起動すると、各stepが実行されます。↓画像はdeployまで成功した例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377659/2a1711ae-9372-fd64-7d6f-2b3f75b8a980.png)



簡単に説明していきます。
このActionのトリガーは
・develop, masterブランチへpushされたタイミング
・developブランチへプルリクエストされたタイミング

pythonのversionは3.6と3.7でテストします。

前半のテストの部分はほぼGithubが用意しているテンプレートそのままです。
ここから、環境をbuildして、stepsに沿ってコマンドを実行してくれます。
テンプレートのままで、勝手にテストしたいブランチへ移動してくれます。

必要なパッケージのインストールはrequirements.txtを使わず、手入力しました。

```
        python -m pip install --upgrade pip
        pip install django==2.1.0 pandas django-bootstrap4
```


テストコマンドです。
テストするフォルダの指定がわからなかったので、全テストを実行しています(いい方法があれば教えてください)
ここでテストに失敗するとエラーが出て、buildは終わります。

```
python manage.py makemigrations
python manage.py migrate
python manage.py test
```

↓画像では、テストは成功し、レビュー待ちになっています。このように、自動テストが行われ、結果が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377659/c73d734b-eaa6-f535-5cc6-218937767889.png)

さあ、最後はデプロイのところです。
ここで、Githubに設定したSecretsを読み込んでEC2インスタンスにSSH接続します。
※Amazon Linuxだとエラーが出るかもしれません。


SSH接続されたら、github環境をpullします。
ここで問題です。ユーザ名とパスワードの入力を求められます。
上手い方法があれば教えてください。あまりやりたくなかったですが、~/.netrcに下記のようにユーザ名/パスワードを書きました。

```
machine github.com
login username
password xxxxxxx
```

一応これで、ユーザ名/パスワードを入力せずともgit pullできるようになりました。

あとは、pullした環境をgunicornに反映させるために、restartさせて終わりです。

#まとめ

いかがでしたか？
私はほぼ初心者でこの環境構築をやってみたのですが、参考サイトの通りにやればかなりスムーズにやれました。
ぜひ皆さんもGithub Actionsで快適なCICD環境を作ってくださいね。

#参考URL
Github Actionsに関して
https://developer.yukimonkey.com/article/20200420/

DjangoをEC2にデプロイすることに関して
https://qiita.com/tachibanayu24/items/b8d73cdfd4cbd42c5b1d