[drone.io] drone-serverのデバッグ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/5ddfb4aa-cab3-5b82-7189-93018bf143bd.png)

【[IIJ 2018 TECHアドベントカレンダー](https://eng-blog.iij.ad.jp/archives/2215) 12/17（月）の記事です】

IIJではGithub Enterpriseと連携するCIサーバーとしてdroneを利用していますが（[IIJ Engineers Blog - IIJのサービス開発を支えるGithub Enterpriseとdrone.io](https://eng-blog.iij.ad.jp/archives/2238)）、[droneの知名度はまだTravis CIやCircleCIほどではなく](https://trends.google.com/trends/explore?date=2013-01-01%202018-12-14&geo=JP&q=travis%20ci,circle%20ci,drone%20ci)、エラーメッセージをググっても出てこないことがあります。こんな時にはdrone-serverを直接デバッグするとすぐ解決することがあります。デバッグを始めるまでちょっとしたノウハウが必要だったので本記事で紹介したいと思います。

drone-serverはUbuntuのデスクトップPCで動かしてデバッグすることを想定します。（多分macOSでも以下の手順で動くと思います。Windowsは `/var/lib/drone/` などのパスを変える必要があると思います。）

## droneのバージョン

2018/12/14現在droneの最新版は1.0.0-rc.2となっていますが、[ソースコードはまだ公開されていません](https://discourse.drone.io/t/drone-1-0-source/3111/3)。公開されている最新版は[0.8.10](https://github.com/drone/drone/releases)となっているため、このバージョンを使うことにします。ドキュメントは[こちら](https://0-8-0.docs.drone.io/)です。

<!--
archive
https://web.archive.org/web/20181009085806/https://docs.drone.io/
source
https://github.com/drone/docs/tree/master/content
-->

// `docker inspect drone/drone:1.0.0-rc.2` を見ると、drone 1.0.0はプライベートレポジトリ https&#58;//github.com/bradrydzewski/drone-ee （あるいはそのフォーク元）で開発されているようです。

## セットアップ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/d81f91a6-3280-0a5c-472a-a3797a0c3d64.png)

参考:

- https://0-8-0.docs.drone.io/installation/
- https://0-8-0.docs.drone.io/install-for-github/
- https://docs.drone.io/installation/github/single-machine/
- https://0-8-0.docs.drone.io/getting-started/

デスクトップPCで動かすため[ngrok](https://ngrok.com/)を使います。
**ngrokを使う際はセキュリティに十分気を付けて下さい。特にGitHub Enterpriseには繋がないで下さい。URLが分かればレポジトリ一覧を閲覧することができてしまいます。**
`ngrok http 9999`:
![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/bec0398b-810c-670e-1f2e-7218aff59d80.png)
http&#58;//localhost:4040 を出しておくとトラブルシューティングに役立つかもしれません。
https://github.com/settings/applications/new でOAuth applicationを登録します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/f60d08c4-b971-ee55-43d7-6129d57f0566.png)
以下の `docker-compose.yaml` で `docker-compose up` を実行してdrone-serverを起動してみます。
// httpsだとSSL handshakeが失敗したのでhttpにしています

```docker-compose.yaml
version: '2'

services:
  drone-server:
    image: drone/drone:0.8
    ports:
      - 9999:8000
      - 9000
      - 2345:2345
    volumes:
      - ./:/var/lib/drone/
    restart: always
    environment:
      - DRONE_OPEN=true
      - DRONE_HOST=https://27be75f8.ngrok.io
      - DRONE_GITHUB=true
      - DRONE_GITHUB_CLIENT=07cf285492f97c12f701
      - DRONE_GITHUB_SECRET=11a318b4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
      - DRONE_SECRET=foobar
      - DRONE_DEBUG=true
    privileged: true

  drone-agent:
    image: drone/agent:0.8
    command: agent
    restart: always
    depends_on:
      - drone-server
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - DRONE_SERVER=drone-server:9000
      - DRONE_SECRET=foobar
```

drone-serverの `ports:2345:2345`, `privileged: true` は後に出てくるdlvのために必要です。

<!-- 1.0.0-rc.2

```sh
docker pull drone/drone:1.0.0-rc.2

# https://docs.drone.io/installation/github/single-machine/
# for debugging,
# removed: --detach=true
# added: --env=DRONE_LOGS_{DEBUG,TEXT,PRETTY,COLOR}=true
docker run \
    --volume=/var/run/docker.sock:/var/run/docker.sock \
    --volume=/var/lib/drone:/data \
    --env=DRONE_GITHUB_SERVER=https://github.com \
    --env=DRONE_GITHUB_CLIENT_ID=07cf285492f97c12f701 \
    --env=DRONE_GITHUB_CLIENT_SECRET=11a318b4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
    --env=DRONE_RUNNER_CAPACITY=2 \
    --env=DRONE_SERVER_HOST=27be75f8.ngrok.io \
    --env=DRONE_SERVER_PROTO=http \
    --env=DRONE_TLS_AUTOCERT=true \
    --publish=9999:80 \
    --publish=443:443 \
    --restart=always \
    --name=drone \
    --env=DRONE_LOGS_DEBUG=true \
    --env=DRONE_LOGS_TEXT=true \
    --env=DRONE_LOGS_PRETTY=true \
    --env=DRONE_LOGS_COLOR=true \
    drone/drone:0.8
```

dockerコンテナをシャットダウンしてから再度起動する場合は `docker run` の前に `docker stop drone; docker rm drone` を実行して下さい。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/8b783498-0d21-f810-e656-e82e97c9c8c0.png)

```.drone.yml
kind: pipeline
name: default

steps:
- name: test
  image: alpine
  commands:
  - ls
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/fc701bec-7281-dd0e-e17f-93bc69aeaafd.png)
-->

http&#58;//27be75f8.ngrok.io にアクセスするとGitHubの認証ページにリダイレクトさるので "Authorize <username>" をクリックします。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/7eb0652f-96d2-4b39-fd06-914d8b58dfce.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/b0fc9777-93ce-acf5-c2ce-39366d9a4c7b.png)
GitHubから[dronetest](https://github.com/wataash/dronetest)のような適当なレポジトリを作って、droneでACTIVATEしてから以下の `.drone.yml` をpushします。

```.drone.yml
pipeline:
  build:
    image: alpine
    commands:
      - ls
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/7fcf8e27-8f16-d0ef-b455-b8644b68dc76.png)
無事にテストが実行されました。

### トラブルシューティング

上手く行かない場合環境をリセットすると良いかもしれません。

- ngrok再起動
  - https://github.com/settings/developers -> "drone" の "Homepage URL" と "Authorization callback URL" を修正
  - `docker run` の `--env=DRONE_SERVER_HOST=` を修正
- docker containerリセット: `sudo rm /var/lib/drone/database.sqlite; docker stop drone; docker rm drone; docker run ...`
- https://github.com/settings/developers -> "drone" -> "Revoke all user tokens"

### drone-serverデバッグ用docker image作成

![image.png](https://qiita-image-store.s3.amazonaws.com/0/167409/3045de45-55b3-96c4-a4f4-adadc0ecf7bf.png)

```sh
cd work/

env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go get -v github.com/drone/drone/cmd/drone-server
env CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go get -v -u github.com/derekparker/delve/cmd/dlv
file $GOPATH/bin/drone-server  # on macOS: $GOPATH/bin/linux_amd64/drone-server
file $GOPATH/bin/dlv           # on macOS: $GOPATH/bin/linux_amd64/dlv
# => /home/wsh/go/bin/dlv: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, with debug_info, not stripped

# on linux, without CGO_ENABLED=0, dlv will be dynamically linked:
# /home/wsh/go/bin/dlv: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=f414998edff629d1700948bb15644cbd6985aa73, with debug_info, not stripped

vim Dockerfile
cp $GOPATH/bin/drone-server $GOPATH/bin/dlv ./
docker build -t dronedebug .

# drone-server: image: drone/drone:0.8 を
# drone-server: image: dronedebug      に書き換え
vim docker-compose.yml

docker-compose up

# 別ターミナルで docker-compose exec app bash
```

<!--
1.0.0-rc.2
```
docker run \
    --volume=/var/run/docker.sock:/var/run/docker.sock \
    --volume=/var/lib/drone:/data \
    --env=DRONE_GITHUB_SERVER=https://github.com \
    --env=DRONE_GITHUB_CLIENT_ID=07cf285492f97c12f701 \
    --env=DRONE_GITHUB_CLIENT_SECRET=11a318b4XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX \
    --env=DRONE_RUNNER_CAPACITY=2 \
    --env=DRONE_SERVER_HOST=27be75f8.ngrok.io \
    --env=DRONE_SERVER_PROTO=http \
    --env=DRONE_TLS_AUTOCERT=true \
    --publish=9999:80 \
    --publish=443:443 \
    --restart=always \
    --name=drone \
    --env=DRONE_LOGS_DEBUG=true \
    --env=DRONE_LOGS_TEXT=true \
    --env=DRONE_LOGS_PRETTY=true \
    --env=DRONE_LOGS_COLOR=true \
    -it --priviledged --publish=2345:2345 dronedebug
```

先程の `docker run` に `-it --priviledged --publish=2345:2345` を足しました。`--priviledged` は `dlv` に必要なためです。

Dockerfile ENTRYPOINT ["/bin/sh"]
-->

`Dockerfile` の内容：

```Dockerfile
FROM drone/drone:0.8
EXPOSE 8000 9000 80 443 2345

COPY dlv /bin/
COPY drone-server /bin/

ENTRYPOINT ["/bin/dlv", "exec", "--headless", "--listen=:2345", "/bin/drone-server"]
```

<!--
dlvで [config substitute-path](https://github.com/derekparker/delve/commit/48288edd1) が使えればdrone-serverのビルドは不要なんですが、上手く動かない…調査中
-->

## drone-serverのデバッグ

`docker-compose up` を実行するとdlv serverがポート2345で待ち受けます。

```
$ docker-compose up
Recreating drone_drone-server_1_79abe9cfaada ... done
Recreating drone_drone-agent_1_ff203d9ce2d0  ... done
Attaching to drone_drone-server_1_79abe9cfaada, drone_drone-agent_1_ff203d9ce2d0
drone-agent_1_ff203d9ce2d0 | {"time":"2018-12-18T10:59:49Z","level":"debug","message":"request next execution"}
drone-server_1_79abe9cfaada | API server listening at: [::]:2345
drone-agent_1_ff203d9ce2d0 | INFO: 2018/12/18 10:59:49 grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: Error while dialing dial tcp 172.22.0.2:9000: getsockopt: connection refused"; Reconnecting to {drone-server:9000 <nil>}
```

<!--
1.0.0-rc.2
docker containerで `dlv exec --headless --listen=:2345 /bin/drone-server` を実行してからホストで `dlv connect localhost:2345` を実行するとリモートデバッグが開始されます。
-->

ホストで `dlv connect localhost:2345` を実行するとリモートデバッグが開始されます。

```
(dlv) b main.main
Breakpoint 1 set at 0xa3ecd3 for main.main() /home/wsh/go/src/github.com/drone/drone/cmd/drone-server/main.go:27
(dlv) c
> main.main() /home/wsh/go/src/github.com/drone/drone/cmd/drone-server/main.go:27 (hits goroutine(1):1 total:1) (PC: 0xa3ecd3)
Warning: debugging optimized function
    22:	
    23:		_ "github.com/joho/godotenv/autoload"
    24:		"github.com/urfave/cli"
    25:	)
    26:	
=>  27:	func main() {
    28:		app := cli.NewApp()
    29:		app.Name = "drone-server"
    30:		app.Version = version.Version.String()
    31:		app.Usage = "drone server"
    32:		app.Action = server
(dlv) n
> main.main() /home/wsh/go/src/github.com/drone/drone/cmd/drone-server/main.go:28 (PC: 0xa3ece1)
Warning: debugging optimized function
    23:		_ "github.com/joho/godotenv/autoload"
    24:		"github.com/urfave/cli"
    25:	)
    26:	
    27:	func main() {
=>  28:		app := cli.NewApp()
    29:		app.Name = "drone-server"
    30:		app.Version = version.Version.String()
    31:		app.Usage = "drone server"
    32:		app.Action = server
    33:		app.Flags = flags
```

冒頭の画像ではGoLandを使ってリモートデバッグしています。

## おわりに

droneはdockerコンテナ上で動作する上にソースコードホスティングサービスとの連携もあるため手順は煩雑でしたが、ネイティブプログラムと同じようにdelveによるデバッグを行うことができました。
本記事の手順で検証用droneサーバーのリモートデバッグも可能になると思います。

## ライセンス

<a rel="license" href="http://creativecommons.org/licenses/by/4.0/"><img alt="クリエイティブ・コモンズ・ライセンス" style="border-width:0" src="https://i.creativecommons.org/l/by/4.0/88x31.png" /></a><br />この 作品 は <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">クリエイティブ・コモンズ 表示 4.0 国際 ライセンス</a>の下に提供されています。

関連するソフトウェアの公式ドキュメントのメンテナの方へ：この記事の内容を公式ドキュメントに記載して頂ける場合、この記事にコメントして頂くか、twitter [@wata_ash](https://twitter.com/wata_ash) にご連絡下さい。