Backlog GitのWebフックを利用して自動デプロイの真似事をしてみる

# 前書き
[株式会社ピーアールオー（あったらいいな！を作ります）Advent Calendar 2021](https://qiita.com/advent-calendar/2021/pro-japan1) の4日目になります。
今回は、Backlogの[Git Webフック](https://backlog.com/ja/enterprise-help/userguide/userguide1581/)を自作のAPIで処理する方法を紹介したいと思います。
~~ちなみに、依頼されて作ったはいいもののなぜか使用されなかった、なんならそもそもSTG(相当)サーバすら作られなかったらしいので、その供養も兼ねています。~~

# 目的
弊社の新人研修では、BacklogのGitを使用してコード管理をしています。
作った成果物については、各自のローカル環境で動かす他、STG(相当)サーバにデプロイすることもあるようです。
これに伴い、研修担当者から以下の依頼がありました。

```  
Gitに上がったらSTG(相当)サーバに自動デプロイする仕組みを作ってほしい  
> ソース管理　Backlog(Git)
```

## 可能か？
BacklogのGitには、例としてGitHub ActionsのようなCIツールが存在しませんが、[Webフック機能](https://backlog.com/ja/enterprise-help/userguide/userguide1581/)が存在します。 
(GitへのPushをトリガーに、コミット情報などを指定したURLにPOSTで送ってくれる)
この機能を使用することで、サーバ側でGitリポジトリ側の変更を検知して何かしらの処理を行うことが可能です。  
  
## 実現手法
Backlogで紹介されている[サンプル](https://backlog.com/ja/blog/gitwebhook-for-monkey/)を見ると、Jenkinsのタスクをキックしています。
が、新人研修期間にだけ使用され、すぐに取り潰されるような今回の用途に対してJenkinsの導入は少々億劫です・・・。
そこで、簡単なAPIをGolangで自作してデプロイ処理を実施することにしました。

## 構成図
リクエストを受けた際に`git pull`とDockerのビルド/ダウンアップを実施します。

:information_source: **注意**
ダウンタイムなどのデプロイに関する諸問題は一切考慮していません！

![pasted-2021.03.22-15.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531974/0f601288-5fcc-c487-7dfa-15f9a9a1fd3c.png)

# ソースコード
作成物は以下のリポジトリに格納しています。
https://github.com/proogw/backlog-webhook

# 動作環境
手元にちょうどいいサーバがないため、Raspberry Pi 4にインストールしたUbuntu(ARM64)で実行しています。
なお、Git、Docker、docker-composeは予めインストールしているものとします。

```bash
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="20.04 LTS (Focal Fossa)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 20.04 LTS"
VERSION_ID="20.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=focal
UBUNTU_CODENAME=focal
```

## API起動まで

ソースをビルドします。今回は`GOARCH=arm64`を指定します。

```bash
$ docker run -e CGO_ENABLED=0 -e GOOS=linux -e GOARCH=arm64 --rm -v "$PWD":/usr/src/myapp -w /usr/src/myapp golang:alpine3.13 go build -v

$ ll
total 6268
drwxr-xr-x  4 ubuntu ubuntu    4096 Dec  3 22:54 ./
drwxr-xr-x 14 ubuntu ubuntu    4096 Dec  3 22:41 ../
drwxr-xr-x  8 ubuntu ubuntu    4096 Dec  3 22:41 .git/
-rwxr-xr-x  1 root   root   6382779 Dec  3 22:54 backlog-webhook* ← ビルドの成果物
-rw-r--r--  1 ubuntu ubuntu      53 Dec  3 22:41 go.mod
-rw-r--r--  1 ubuntu ubuntu    2159 Dec  3 22:41 main.go
-rw-r--r--  1 ubuntu ubuntu     782 Dec  3 22:41 pull.sh
```

生成したバイナリを配備します。

```bash
$ sudo mv backlog-webhook /usr/local/bin/backlog-webhook
$ sudo chown ubuntu:ubuntu /usr/local/bin/backlog-webhook
```

systemctlのサービスファイルを作成します。

```bash
$ sudo vim /etc/systemd/system/backlog-webhook.service
```

```service:backlog-webhook.service
[Unit]
Description = backlog-webhook

[Service]
User = ubuntu
Type = simple
ExecStart = /usr/local/bin/backlog-webhook /home/ubuntu/backlog-webhook/pull.sh /home/ubuntu/git/backlog-sandbox
Restart = always

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

自動起動をONに設定後、起動します。

```bash
$ sudo systemctl enable backlog-webhook
$ sudo systemctl start backlog-webhook
$ sudo systemctl status backlog-webhook
● backlog-webhook.service - backlog-webhook
     Loaded: loaded (/etc/systemd/system/backlog-webhook.service; disabled; vendor preset: enabled)
     Active: active (running) since Sat 2021-12-04 00:31:59 JST; 1s ago
   Main PID: 718797 (backlog-webhook)
      Tasks: 5 (limit: 9257)
     Memory: 2.2M
     CGroup: /system.slice/backlog-webhook.service
             └─718797 /usr/local/bin/backlog-webhook /home/ubuntu/backlog-webhook/pull.sh /home/ubuntu/git/backlog-sandbox

Dec 04 00:31:59 master systemd[1]: Started backlog-webhook.
Dec 04 00:31:59 master backlog-webhook[718797]: 2021/12/04 00:31:59 Listen Server ....
```


:information_source: **ポートについて**
なんとなく8000番を使用するようにしているので、ufwなどを使用して適宜ポートを開ける必要があります。

# 動作確認
実際にBacklogにGitリポジトリを作成しました。
リポジトリの内容は以下の内容になります。

```
.
|-- Dockerfile
|-- docker-compose.yml
`-- html
    `-- index.html
```

index.htmlを表示するだけのNginxコンテナです。
今回は、index.htmlを更新・プッシュすると、WebフックAPI経由でコンテナが更新されることを確認します。

```Dockerfile:Dockerfile
FROM nginx:1.20.2-alpine
COPY html /usr/share/nginx/html
```

```yaml:docker-compose.yml
version: "3"

services:
  nginx:
    build:
      context: .
    image: test/nginx
    ports:
      - "8080:80"
    container_name: nginx
```

```html:index.html
test-1
```

## BacklogのGitからClone

[この手順](https://backlog.com/ja/git-tutorial/reference/ssh/)に従い、BacklogアカウントにSSH公開鍵を設定しておきます。

SSHを使用してクローンします。

```bash
$ git clone バックログアカウント@バックログドメイン.git.backlog.com:/TEST/backlog-sandbox.git
```

## WebフックURLの設定
BacklogのGitリポジトリの設定からWebフックURLを設定します。
※今回はリバースプロキシを使用せず、直接接続させます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531974/73e9028e-1e79-a323-bf21-63f1f79ba020.png)

## 更新確認

更新前の状態です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531974/61ef02c1-9ef9-3040-4bae-3d0adc7f2066.png)

index.htmlを更新し、プッシュします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531974/7c1ef5fc-9d69-28a3-17e2-efbce247bf15.png)

リクエストが処理されていることを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531974/5eafb940-38a0-aa03-c794-eee4acdf8d72.png)

コンテナが更新され、index.htmlの内容が新しくなりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531974/0bb90700-ad54-e20d-0029-fdcb481785c2.png)

# おわりに
商用環境ではとても使えたものではないですが、とりあえず自動デプロイの真似事がしたいということならWebフックも案外ありだなと思いました。
~~これで供養することができました。コードもきっと浮かばれたことでしょう。~~