vpsにgithub actionsでデプロイする(したかった)

# はじめに
最近portfolioを作ろうということでvpsを契約、ドメイン購入後、`ssl`などの設定をした後、portfolioを`Next.js`で作成
ただ修正点や機能追加などは後々から見つかるもので毎回毎回`vps`に繋いで手動でデプロイするのはいささか面倒である

ということでgithub actionsを用いてvpsにデプロイをしていく

# github actions
筆者はgithub actionsなどいじったことが今までなかったので今回初めての試みである。
まずはプロジェクトのルートディレクトリ配下に
`.github/workflows/`を作成する
どうやらここに`yml`ファイルを作成することで`github actions`として動くようだ

もちろん筆者はymlファイルを書くことがあまりないのでここも難しい点であった。

`yml`ファイルの書き方としては以下のようになっているようである
```yaml:.github/workflows/deploy.yml

name: deploy

on:
    push:
        branches:
            - "main"

jobs:
    deploy:
        name: deploy_to_vps
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v2
            - name: create .env
              run: |
                  touch .env
                  echo "NEXT_PUBLIC_GITHUB_API_KEY=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
                  echo "NEXT_PUBLIC_USER_NAME=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
                  echo "NEXT_PUBLIC_QIITA_API_KEY=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
            - name: create ssh_config
              uses: shimataro/ssh-key-action@v2
              with:
                  key: ${{ secrets.SSH_KEY }}
                  name: ssh_config
                  known_hosts: ${{ secrets.KNOWN_HOSTS }}
                  config: |
                      Host ${{ secrets.HOST }}
                      HostName ${{ secrets.HOSTNAME }}
                      User  ${{ secrets.HOSTUSER }}
                      Port  ${{ secrets.HOSTPORT }}
                      IdentityFile ~/.ssh/ssh_config
                      StrictHostKeyChecking no
            - name: install
              run: |
                  ssh vps "cd ./node/portfolio;git pull origin main; pnpm i; pnpm build; pnpm dlx kill-port 3000; pnpm start;"

```
以下は筆者が実際に書いてみて理解した内容である(厳密には意味が違うかもしれないので悪しからず)
`name`:ワークフローの名前
`on`:このファイルが実行されるときのトリガー(このファイルでは`main`ブランチに`push`された時)
`jobs`:実行されるワークフロー
`runs-on`:実行環境
`steps`:実行手順(?)
`uses`:使用される`github actions`ライブラリのようなもの(?)


# エラー
この時筆者は
1. `.env`を作成
1. `ssh_config`を作成
1. `ssh`接続をして`pull`,`build`
といった感じに実装していたが以下エラーに遭遇した

`bash: pnpm: command not found`

筆者はパッケージマネージャに`pnpm`を使っているため問題なのはこの点ではない
`pnpm`がそもそも見つからないことである
ローカル環境でssh接続をして`which`コマンドを使うとちゃんと見つかる
しかしymlファイルと同様のコマンド
`ssh vps "cd ./node/portfolio;git pull origin main; pnpm i; pnpm build; pnpm dlx kill-port 3000; pnpm start;"`
を使うとローカル環境でも同様のエラーが観測できた

正直な話原因はわからないが予測ではバージョンマネージャが関係しているのではないかと考えた。

筆者は`node`のバージョンマネージャに`volta`を使用している。
`volta`を用いた`vps`デプロイに関する記事が少なかったため絶対にこれが原因といえない。

とりあえず原因がはっきりしないまま`volta`をアンインストールして`pnpm`を`volta`からではなく`npm`からインストールしようと考えた

ローカルでvpsに接続後以下を実行
`npm i -g pnpm`
`pnpm`がインストールされたのを確認後`github actions`を再び動かすと以下のエラー

`permission denied`

これに関しては全くわからない
同様にローカル環境から実行しても同じエラーが確認できた
しかしssh接続をして実行権限を確認すると
`-rwxrwxr-x`
実行権限はあるのである。

理解できないまま以下記事を参考に`yml`ファイルを編集
[GitHub Actions から VPS にSSH 接続して CI / CD 環境を構築する](https://qiita.com/0622okakyo/items/5295b7b13daf3c35b3e1)

これは実際に中に入ってコマンド実行するので再び`volta`はインストール済み

```yml
         - name: deploy
           uses: appleboy/ssh-action@master
          　　with:
              key: ${{ secrets.SSH_KEY }}
              host: ${{ secrets.HOST }}
              username: ${{ secrets.USERNAME }}
              port: ${{ secrets.PORT }}
              script: |
                cd ./node/portfolio/
                git pull origin main
                pnpm i
                pnpm build
                pnpm dlx kill-port 3000
                pnpm start &
                exit

```

github actionsの結果に緑のチェックが！！！！！

念の為ログを見てみる

```
err: bash: line 2: /usr/bin/pnpm: Permission denied
err: bash: line 3: /usr/bin/pnpm: Permission denied
err: bash: line 4: /usr/bin/pnpm: Permission denied
err: bash: line 5: /usr/bin/pnpm: Permission denied
==============================================
✅ Successfully executed commands to all host.
==============================================
```

何も解決してなかった

いよいよわからない


とりあえずpnpmの場所を特定するために以下を実行
```
ssh [vps] "which pnpm"
```

何も出力されない


以下に分けて実行
```
ssh [vps]
which pnpm
```
`/home/[user]/.volta/bin/pnpm`


やはり`volta`の問題なのだろうか


一旦`volta`をアンインストール
`npm` `pnpm` `node`もアンインストール

`pnpm`をアンインストールしたのち`pnpm -v`を実行
`-bash: /usr/bin/pnpm: Permission denied`


まさかと思ってpnpmの権限を確認しにいく

`-rwxr-xr-x`

そもそも権限がついてなかった
さっき確認した時はついていたのだがなんの差なんだろうか

# 最終実装
最終的に以下のように実装した
`node` `pnpm`をグローバルインストール

```yaml:.github/workflows/deploy.yml

name: deploy

on:
    push:
        branches:
            - "main"

jobs:
    deploy:
        name: deploy_to_vps
        runs-on: ubuntu-latest
        steps:
            - uses: actions/checkout@v2
            - name: create .env
              run: |
                  touch .env
                  echo "NEXT_PUBLIC_GITHUB_API_KEY=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
                  echo "NEXT_PUBLIC_USER_NAME=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
                  echo "NEXT_PUBLIC_QIITA_API_KEY=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
            - name: create ssh_config
              uses: shimataro/ssh-key-action@v2
              with:
                  key: ${{ secrets.SSH_KEY }}
                  name: ssh_config
                  known_hosts: ${{ secrets.KNOWN_HOSTS }}
                  config: |
                      Host ${{ secrets.HOST }}
                      HostName ${{ secrets.HOSTNAME }}
                      User  ${{ secrets.HOSTUSER }}
                      Port  ${{ secrets.HOSTPORT }}
                      IdentityFile ~/.ssh/ssh_config
                      StrictHostKeyChecking no
            - name: install
              run: |
                  ssh vps "cd ./node/portfolio;git pull origin main; pnpm i; pnpm build; pnpm dlx kill-port 3000; pnpm start &"
```
# 結論

今回やったことでgithub actionsがどういうものかということは理解できた
が、今回の実装はあまり綺麗なものではないと感じる
`node` `pnpm`をグローバルインストールしている点もそうだし、先に`build`が通ってからvpsにデプロイするべきだと感じた
個人のプロダクトであるため、そこまでこだわる点ではないのかもしれないが、チーム開発をするという点においては0点である。

また`volta`に関しては感しては今後時間がある時に掘り下げていきたいと思っています。

アドバイスなどありましたらいただけると幸いです。