【nginx+webhook】github actionsに依存しない自動デプロイ

## 背景

github actionsで自動デプロイ最高！
↓
あっという間に無料枠を使いきる
↓
枠があるの知らなかった😭
気にせず使いたいなあ。githubのwebhookを使えばよさそうだ！

## やりたいこと
1. ローカルからgithubにpush
1. githubからサーバーにpushされたことをお知らせ
1. サーバーが自動デプロイ

## 環境
サーバーの環境は以下のとおり
- Ubuntu(22.04.4 LTS)
- nginx(1.24.0)

## 手順

### 自動デプロイの実行ファイルを作成

あらかじめサーバー上に実行ファイルを作成しておいてください
ここは今回説明したいこととすこしずれるので割愛
こんなのをつくったとする↓

```/opt/webhook/deploy.sh
#!/bin/bash

git fetch origin main
git merge origin/main
```

実行ファイルの権限は`chmod a+x deploy.sh`しておく

### adnanh/webhookをダウンロード

#### adnanh/webhook とは

https://github.com/adnanh/webhook

「webhookを受け取ってコマンドを実行する」をあっという間にできるツールを使わせていただきます。すぎょい

#### adnanh/webhookをcurl経由でダウンロード

aptコマンドでもダウンロードできますが、最新版が欲しかったのでcurlでダウンロードします

なお執筆時点（2024/05/21）の最新バージョンは`2.8.1`でした

```/opt/webhook/.
$ curl -L https://github.com/adnanh/webhook/releases/download/2.8.1/webhook-linux-amd64.tar.gz -O
$ tar zxvf webhook-linux-amd64.tar.gz
```

#### 設定ファイルを作成

```/opt/webhook/webhook-linux-amd64/.
$ vi github-webhook.json
```

```/opt/webhook/webhook-linux-amd64/github-webhook.json
[
  {
    "id": "github-webhook",
    "execute-command": "/opt/webhook/deploy.sh",
    "command-working-directory": "/path/to/your/project",
    "trigger-rule":
    {
      "and":
      [
        {
          "match":
          {
            "type": "payload-hmac-sha1",
            "secret": "mysecret",
            "parameter":
            {
              "source": "header",
              "name": "X-Hub-Signature"
            }
          }
        },
        {
          "match":
          {
            "type": "value",
            "value": "refs/heads/main",
            "parameter":
            {
              "source": "payload",
              "name": "ref"
            }
          }
        }
      ]
    }
  }
]
```

各パラメータの説明
- id
    - エンドポイントのパラメータになる値
- execute-command 
    - 実行ファイル(今回の例だとdeploy.sh)の絶対パス
- command-working-directory
    - 実行ファイルの作業ディレクトリ
- trigger-rule
    - 実行ファイルの発動条件

この例だと、mainブランチにプッシュされたとき、`/path/to/your/project`上で`/opt/webhook/deploy.sh`を実行します

#### サーバー上でテストしてみる

webhookを起動してみる

```/opt/webhook/.
$ ./webhook -hooks github-webhook.json -verbose

[webhook] 2024/05/29 12:22:29 version 2.8.1 starting
[webhook] 2024/05/29 12:22:29 setting up os signal watcher
[webhook] 2024/05/29 12:22:29 attempting to load hooks from github-webhook.json
[webhook] 2024/05/29 12:22:29 os signal watcher ready
[webhook] 2024/05/29 12:22:29 found 1 hook(s) in file
[webhook] 2024/05/29 12:22:29   loaded: github-webhook
[webhook] 2024/05/29 12:22:29 serving hooks on http://0.0.0.0:9000/hooks/{id}
```

デフォルトが9000番を使うようになってます
別のコンソールを起動して、同じサーバー上からアクセスしてみる

```
$ curl http://17.0.0.1:9000/hooks/github-webhook
```

```/opt/webhook/.
$ ./webhook -hooks github-webhook.json -verbose

[webhook] 2024/05/29 12:22:29 version 2.8.1 starting
[webhook] 2024/05/29 12:22:29 setting up os signal watcher
[webhook] 2024/05/29 12:22:29 attempting to load hooks from github-webhook.json
[webhook] 2024/05/29 12:22:29 os signal watcher ready
[webhook] 2024/05/29 12:22:29 found 1 hook(s) in file
[webhook] 2024/05/29 12:22:29   loaded: github-webhook
[webhook] 2024/05/29 12:22:29 serving hooks on http://0.0.0.0:9000/hooks/{id}
# アクセスしたら、ここにアクセスされたよーてきなログがでる
# ただしtrigger-ruleがマッチしないので実行ファイルは実行されない
```

できたら、`ctrl+c`で一度終了します

### デーモン化

webhookは動いていそうなので、systemdでデーモン化します

```
$ vi /etc/systemd/system/webhook.service
```

```/etc/systemd/system/webhook.service
Description=webhook

[Service]
Type=simple
User=nginx
ExecStart=/opt/webhook/webhook-linux-amd64/webhook -hooks /opt/webhook/webhook-linux-amd64/github-webhook.json -verbose
TimeoutSec=60
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=webhook
Restart=always

[Install]
WantedBy=multi-user.target
```

細かいところはお好みで


```
$ sudo systemctl daemon-reload
$ sudo systemctl enable webhook
$ sudo systemctl start webhook
```

自動起動を有効化して、webhookを起動

### nginxのプロキシを設定

プロジェクト用のnginxの設定ファイルを編集します

```
$ vi /etc/nginx/conf.d/project.conf
```

```/etc/nginx/conf.d/project.conf
server{
　　server_name your-project.jp;

　　# これを追加
    location /github-webhook/ {
        proxy_pass http://127.0.0.1:9000/hooks/github-webhook;
    }

    # かならずインデックスより上に書くこと！
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}
```

これで`https://your-project.jp/github-webhook/`に接続すると、先ほどのwebhookに飛ばされます


### githubにwebhookを追加

リポジトリ＞Settings>Webhooks>Add webhook

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3580241/fa3756d6-7e70-9eb8-a8bd-fe877447d85a.png)

content typeをapplication/jsonにしないとうごきませんでした

これで作成してpingが通ればOK！

## 参考
この方々がいなければ一生github actionsの苦しみから逃れられませんでした。マジ感謝。ありがとうございます

https://ansonvandoren.com/posts/configuring-nginx-to-proxy-webhooks/

https://sky-joker.tech/2019/10/14/go%e8%a3%bd%e3%81%aewebhook%e3%82%92%e4%bd%bf%e3%81%a3%e3%81%a6%e3%81%bf%e3%82%8b/

https://zenn.dev/sim1222/articles/9fc18b31e7f602#%E3%82%A2%E3%83%83%E3%83%97%E3%83%87%E3%83%BC%E3%83%88%E3%82%81%E3%82%93%E3%81%A9%E3%81%8F%E3%81%95%E3%81%84