Github Actions & LFTPで自動デプロイ

# はじめに
実装内容などを簡単にまとめる。
Github Actionsについての説明は今回割愛します。

# なぜFTP（LFTP）を使用したのか
- 使用中のレンタルサーバーで、SSHが許可されていなかった。
- 当初は、FTP-Deployを使用していたがファイルが多くなるにつれデプロイにかかる時間が大幅に増えてしまったためLFTPへ変更。
- LFTP自体の開発が最近でも行われていること、並列処理が可能なことが切り替えの決め手となった。処理にかかる時間がかなり短縮された。

## Github Actionsの使い方
1. 実行したいワークフローを記述した`yaml`ファイルを作成。
2. リポジトリ内`.github`フォルダの中に`workflows`フォルダを作成。  
`yaml`ファイルを格納。  
3. `ftp_upload`ファイルを`.github`配下に格納する。（LFTPを使うための設定ファイル。）

```
app_root/
  ├ .github/
  │  ├ workflows/
  │  │  └ main.yml
  │  └ ftp_upload
```

## 今回作成した自動デプロイの流れ
1. masterブランチにpush（マージ）されたタイミングで処理を開始する
2. 連続でpushされた場合は、先に走っていたワークフローをキャンセルし、後にpushされた内容のワークフローを走らせる  
 - 複数のactionを並行で走らせない。  
 - Github Actionsは、月に3000分までが無料枠なので無駄に処理を走らせないようにしたい。
3. masterブランチをチェックアウト
4. `node.js`のバージョン指定をして、`npm`でビルドする
5. `lftp`でアップロード（サーバー側のファイルを全て削除し、最新のファイル群をアップ）

## main.yamlの内容
```yaml:main.yml
name: 🚀 Deploy website on push
on:
  workflow_dispatch:
  push:
    branches:
      - master

jobs:
  cleanup-runs:
    runs-on: ubuntu-latest
    steps:
      - uses: rokroskar/workflow-run-cleanup-action@master
        env:
          GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
    if: "!startsWith(github.ref, 'refs/tags/')"

  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
      - name: 🚚 Get latest code
        uses: actions/checkout@v2
      - uses: actions/setup-node@v2-beta
        with:
          node-version: '14'
      - uses: bahmutov/npm-install@v1
      - run: npm run build
      - run: which lftp || sudo apt-get update -y && sudo apt-get install lftp -y
      - name: 📂 Run ftp_upload
        run: |
          HOST="${{ secrets.FTP_SERVER }}" \
          USER="${{ secrets.FTP_USERNAME }}" \
          PASS="${{ secrets.FTP_PASSWORD }}" \
          LOCAL_DIR="./dist/hoge/" \
          REMOTE_DIR="/root/test/hoge/" ./.github/ftp_upload
```
## main.ymlの処理解説
### 👍 masterブランチへpushされたら処理を開始

```yaml:main.yml
name: 🚀 Deploy website on push
on:
  workflow_dispatch:
  push:
    branches:
      - master
```
`name:` ワークフローの名前。自由に設定します。絵文字も可🐱。
`workflow_dispatch:` GithubActionのページ上でワークフローを手動で実行するときに便利なオプション。 
詳しくはこちら⇨ [GitHub Actionsをもっと使いやすく！](https://qiita.com/tsukounina25/items/818326d2063cd78b630b "GitHub Actionsをもっと使いやすく！")

### ✌️ ブランチへ連続pushされたときの処理
```yaml:main.yml
jobs:
  cleanup-runs:
    runs-on: ubuntu-latest
    steps:
      - uses: rokroskar/workflow-run-cleanup-action@master
        env:
          GITHUB_TOKEN: '${{ secrets.GITHUB_TOKEN }}'
    if: "!startsWith(github.ref, 'refs/tags/')"
```
`runs-on: ubutu-latest`： `Linux`の環境下で処理を行う宣言。 
`macOS`、`Windows`も設定可能ですが、消費する時間と金額が異なります。特別な理由がない限りは、`Linux`で問題ないです。[About billing for GitHub Actions](https://docs.github.com/en/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions "About billing for GitHub Actions")

`rokroskar/workflow-run-cleanup-action@master`： 連続でマージされた時、事前に走っていたワークフローをキャンセルするワークフロー。[workflow-run-cleanup-action](https://github.com/rokroskar/workflow-run-cleanup-action "workflow-run-cleanup-action")

### 🤟 チェックアウト＆ビルド
```yaml:main.yml
  web-deploy:
    name: Deploy
    runs-on: ubuntu-latest
    steps:
      - name: 🚚 Get latest code
        uses: actions/checkout@v2
      - uses: actions/setup-node@v2-beta
        with:
          node-version: '14'
      - uses: bahmutov/npm-install@v1
      - run: npm run build
      - run: which lftp || sudo apt-get update -y && sudo apt-get install lftp -y
```
`which lftp || sudo apt-get update -y && sudo apt-get install lftp -y` LFTPをインストール
### 👊 サーバーへアップロード
```yaml:main.yml
      - name: 📂 Run ftp_upload
        run: |
          HOST="${{ secrets.FTP_SERVER }}" \
          USER="${{ secrets.FTP_USERNAME }}" \
          PASS="${{ secrets.FTP_PASSWORD }}" \
          LOCAL_DIR="./dist/hoge/" \
          REMOTE_DIR="/root/test/hoge/" ./.github/ftp_upload
```
FTP接続情報をここに記載します。
機密情報は、Github Secretsに登録し参照する形で使用しましょう。
![スクリーンショット 2021-01-31 22.23.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684295/3efc7cc6-a53f-6b6a-7a8b-81ef4c914fc0.png)

## ftp_uploadの内容
```bash:ftp_upload
#!/bin/bash -eu

lftp -d -u $USER,$PASS $HOST -e "\
  set ftp:ssl-allow no; \
  mirror \
  --reverse \
  --delete \
  --verbose \
  --parallel=12 \
  -X .DS_Store \
  $LOCAL_DIR \
  $REMOTE_DIR; \
  exit"
```
記述内容についてはこちら参照⇨[コピペで使えるLFTPスクリプト](https://qiita.com/n_haruka/items/843a18bbbc268aaf912a "コピペで使えるLFTPスクリプト")  
サーバー側のファイルをすべて削除＆アップをしている理由は以下です。
1. ファイルの更新日付が最新のものだけ更新する機能もあるが、ちょくちょく不具合がある。（らしい）
2. そもそもビルドすると全てのファイルの更新日付が変わるのでやっていることは同じになってしまう。

## Github Actionsでエラーが出てしまったときのあるある原因
- 大文字小文字のタイポ  
 `import from 'hogehoge.js' `⇨実際に存在するのは、`hogeHoge.js`  
 ※Linuxの環境下では大文字小文字の違いが区別される。

## あとがき
引き続き改善＆内容更新していきます🐱