GitHub Actions経由でのNode.jsアプリケーションのデプロイを高速化する


Azure WebAppsにGitHub Actions経由でアプリケーションのデプロイをするとデフォルトで作成されるymlファイルの設定的にめちゃめちゃデプロイが遅いので、設定を見直してみました。

結果からいうと **25分から1分代にまで時間が短縮**できました。（デフォルトが掛かりすぎ疑惑あります）

Azureなど関係なく高速化できそうなポイントがあると思います。

過去にもGitHub Actionsの設定見直しをしていましたが、今回も久々にAzure WebAppsにデプロイしてトライしたあたりのメモを書いていきます。

https://qiita.com/n0bisuke/items/e49b1ab4f54225271d85

前提としてNode.jsでのDiscord BotのプログラムをAzure WebAppsにコードデプロイをしています。

## Azure側から発行されるデフォルトの設定でデプロイ（25分）

物によると思いますが、デプロイしようとしたDiscord Botのアプリケーションはとりあえずそのままデプロイすると25分かかりました。結構かかりますね...

> ![スクリーンショット 2023-06-09 18.15.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/d0ad1787-71a3-0c3f-482d-66bdcadbf165.png "スクリーンショット 2023-06-09 18.15.35.png")

デフォルトだと`npm run test --if-present`のあたりでコケるのでコメントアウトだけして動かしています。

<details>
<summary>初期のYAMLファイル</summary>
<div>

Azure側から自動生成されるやつです。

```yml
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Build and deploy Node.js app to Azure Web App - prototoout-bot

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up Node.js version
        uses: actions/setup-node@v1
        with:
          node-version: '18.x'

      - name: npm install, build, and test
        run: |
          npm install
          # npm run build --if-present
          # npm run test --if-present
      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v2
        with:
          name: node-app
          path: .

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'Production'
      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v2
        with:
          name: node-app

      - name: 'Deploy to Azure Web App'
        id: deploy-to-webapp
        uses: azure/webapps-deploy@v2
        with:
          app-name: 'prototoout-bot'
          slot-name: 'Production'
          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_xxxxxxxxxxxxxxxxxxxxxxxxxx }}
          package: .
```

</div>
</details>

## zip化する（25分=>8分に）

デフォルトのままだとnode_modulesなどに含まれる多数のファイルをデプロイしますが、ファイル数が多いことによって時間がかかっている模様でした。

@horihiroさんの記事が参考になりました。

https://uncaughtexception.hatenablog.com/entry/2022/05/07/160811

release.zipというファイルにカレントディレクトリ内のフォルダをまとめつつ、

```
run: zip release.zip ./* -qr
```

release.zipの1ファイルだけをアップロードする感じです。

```
path: release.zip
```

8分19秒、だいぶ早くなりました。

> ![スクリーンショット 2023-06-09 19.09.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b87fb602-c26d-4a7a-58e0-01165c28c5a3.png "スクリーンショット 2023-06-09 19.09.13.png")

## pnpmとキャッシュを試す（8分=>6分）

pnpmが速いという噂があるのでキャッシュ込みで更に試してみました。

pnpmがどうというよりもキャッシュさせたところが効いていた気がします。

> ![スクリーンショット 2023-06-09 19.15.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/55d8ad7e-5c0c-e01a-ed00-cf5f4ec551a0.png "スクリーンショット 2023-06-09 19.15.38.png")

> 参考: https://obel.hatenablog.jp/entry/20230524/1684875600

確かこの時のキャッシュされたキャッシュサイズが25MBほどでした。

ただ、たぶん設定はあると思いますが、pnpmの仕様上なのか、グローバルにモジュールがインストールされるような仕組みの模様で、zip化してデプロイするときにうまくファイルが乗らずデプロイ先のWebAppsでアプリケーションが上手く起動できない事象が発生していました。

一応記録的に記事には残してますが、pnpmは最終版では採用していません。

## yarnとキャッシュを試す（6分=>4分）

yarnはどうなのだろうとyarnとキャッシュを入れて試してみました。4分代にまで短くなっています。

確かキャッシュサイズは30~40MBほどになってました。

> ![スクリーンショット 2023-06-09 19.28.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/9054f800-e09f-13d6-2d75-6107fafdbb02.png "スクリーンショット 2023-06-09 19.28.21.png")

> 参考: https://blog.lacolaco.net/2021/06/github-actions-yarn-cache/

結構早くなってきてますね。

## 利用するActionのバージョンを上げる（4分=>3分）

利用するActionがAzureのデフォルトのままだと2系になっていますが、3系に直しましょうといったアラートがちょくちょくでていました。

> 最初に出ていたアラート
> ![スクリーンショット 2023-06-09 19.25.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/4d6d4fed-bff3-aa22-1c3d-7ad0bc5dd809.png "スクリーンショット 2023-06-09 19.25.00.png")

`actions/setup-node@v3`や`actions/download-artifact@v3`などActionのバージョンを2から3に指定しなおすことで若干早くなった印象です。

> ![スクリーンショット 2023-06-09 19.18.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/f8602799-2942-fb2b-aca6-3a54fae7988b.png "スクリーンショット 2023-06-09 19.18.17.png")

現時点で最新にしてアラートがなくなったYAMLファイルはこちらです。

```yml
# Docs for the Azure Web Apps Deploy action: https://github.com/Azure/webapps-deploy
# More GitHub Actions for Azure: https://github.com/Azure/actions

name: Build and deploy Node.js app to Azure Web App - prototoout-bot

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Code Checkout
        uses: actions/checkout@v3

      - name: Set up Node.js version
        uses: actions/setup-node@v3
        with:
          node-version: '18.x'
      
      - name: Get yarn cache directory path
        id: yarn-cache-dir-path
        run: echo "dir=$(yarn cache dir)" >> $GITHUB_OUTPUT

      - uses: actions/cache@v3
        id: yarn-cache # use this to check for `cache-hit` (`steps.yarn-cache.outputs.cache-hit != 'true'`)
        with:
          path: ${{ steps.yarn-cache-dir-path.outputs.dir }}
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-
      
      - name: npm install, build, and test
        run: |
          yarn install

      - name: Zip artifact for deployment
        run: zip release.zip ./* -qr # 除外したいディレクトリがあるなら -x オプションで指定

      - name: Upload artifact for deployment job
        uses: actions/upload-artifact@v3
        with:
          name: node-app
          path: release.zip

  deploy:
    runs-on: ubuntu-latest
    needs: build
    environment:
      name: 'Production'
      url: ${{ steps.deploy-to-webapp.outputs.webapp-url }}

    steps:
      - name: Download artifact from build job
        uses: actions/download-artifact@v3
        with:
          name: node-app

      - name: 'Deploy to Azure Web App'
        id: deploy-to-webapp
        uses: azure/webapps-deploy@v2
        with:
          app-name: 'prototoout-bot'
          slot-name: 'Production'
          publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_xxxxxxxxxxxxxxxxxxxx }}
          package: release.zip
```

## アプリケーション内のライブラリの更新と整理（3分=>1~2分に）

これが原因かは分からないですが、Discord.jsをv13からv14に上げた辺りでデプロイの速度がまた上がっていました。

> ![スクリーンショット 2023-06-09 19.30.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/9fc3439b-1530-2ede-fa8f-4f87da6f2d7e.png "スクリーンショット 2023-06-09 19.30.33.png")

> 参考: https://qiita.com/n0bisuke/items/2cc07f9693fd21fd468f

他のライブラリも更新したタイミングだったのでイマイチ原因不明感はありますが、効率化されてる部分もあるのかもしれません。

## まとめ

zipは偉大ですね。
キャッシュはもっと上手く使える気がします。