GithubにGoで書いたDockerをTravisでCIする

あまり他人のソフト使うのが上手くないので、色々とハマりポイントがあったもので
Git履歴よりハマりポイントのおさらい

#目指すもの
GithubにTravisCIを連携させることで、PushやPullRequestした時などに
自動的にTestやLintを行い、コードカバレッジを行う事ができる
大手の開発では一般的なスタイルではなかろうか？

個人的に勉強ついでに作っていた SlackBotのプログラムを使って勉強してみた

https://github.com/YukiMiyatake/GOSICK

SlackBotである。プラグインを入れる事で機能拡張を行う事ができる
とりあえず勉強用テストプロジェクトである
これからリファクタリングしたり interface化して、LintなりTestなり色々な改造を行う予定
（現在 gomodule導入テストのためプラグインもecho以外動かないはず）

#dockerファイルを修正
今までDockerfileにて go buildして実行ファイルを起動させていたが
TravisやローカルでTestをまわすために
また、コード修正のたびに docker-compose buildしたくないので
Dockerでは何もせず、シェルスクリプトでビルド実行やテストを行うように変更した

##Dockerファイル
```dockerfile:dockerfile
WORKDIR /build
COPY src .
CMD ./build.sh
CMD ls

CMD ./GOSICK
```

この辺りを削除した。ぶっちゃけ Goのイメージそのまま使うのでDockerfileは不要で
docker-composeにimage指定するだけでいいけど
今後なにかインストールする可能性もあるので　Dockerファイルはのこした

##build.sh

今回はプラグインのビルドなども入るので、ワンライナーで書かず
ビルドをシェルスクリプトでわけたかった
（最終的にはMakefile等にしたいなあ）

```bash:build.sh
if [ $TEST = "test" ]; then
    cd plugins/echo
    go test -v ./... --buildmode=plugin
    cd ../..

    go test -v ./...
else
    cd plugins/echo
    go build --buildmode=plugin
    cd ../..

    go build
fi
```

テストと通常ビルドを分けるため $TEST環境変数で分けることにした


##Script

```bash:docker_app_build
docker-compose up -d
docker-compose exec gosick_app bash -C '/app/build.sh'
```

```bash:docker_app_test
docker-compose up -d
docker-compose exec -e TEST=test gosick_app bash -C '/app/build.sh'
```

テストと実行でファイルを分けたが、環境変数以外はかわらないので、まとめてもいいなあ
docker-compose up も別にすべきかなあ

等色々考えているが、しばらく使って考える予定

#GithubにTravisを連携させバッヂをつける

https://qiita.com/hoshimado/items/4090d8e64beb8a7f95e1

例えばこの辺を参考に、バッヂまでつける

#Travisの設定
とっても苦労したTravisの設定
とりあえずはどのリポジトリをPushしても通知が入るようにしている
プロジェクトのルートに .travis.yml ファイルを作成してPush

##最初の設定
```yaml:.travis.yaml
sudo: required

services:
  - docker

before_install:
#  - docker-compose up -d

install:

before_script:

script:
  - scripts/docker_app_run
 # - docker-compose exec golang go test -v ./...

after_script:

notifications:

```

いろんなサイトをみて上記の設定ファイルを書いたが、色々なエラーが出てダメ
なので色々と

##language設定
TravisのページをみるとRubyと判断されていたのでlanguageを設定

```yaml:.travis.yaml
language: go
```

ただ、Goのバージョンが古かったのでちゃんとバージョン指定してみた

```yaml:.travis.yaml
language: go
go: 
  - 1.12.x
```


##GO111MODULE
ログをみていると GO111MODULE=autoになっていた
今回はgo module使いたいので onにしたいので下記のようにかいてみた

```yaml:.travis.yaml
script:
  - env GO111MODULE=on scripts/docker_app_test
```

ところがログをみても GO111MODULE=autoのままだった

どうやらenvセクションに書く必要があった

```yaml:.travis.yaml
env:
  - GO111MODULE=on
```

## go_import_path
githubのアドレスを加えた

```yaml:.travis.yaml
go_import_path: github.com/YukiMiyatake/GOSICK
```

##スクリプトパーミッション
Windowsで開発を行っていたため、ファイルのパーミッションがおかしくなっていた
Travis内でパーミッションを設定してもいいが、根本的な解決としてスクリプトファイルにパーミッションをあたえPushした

https://qiita.com/maosanhioro/items/aaade68cdca591232159

この辺をみて、パーミッションを正しく設定したら動いた

##DockerComposeのバージョンが古い
docker-composeのバージョンが古かったので念のためバージョンアップを行った

まず、TravisのDockerやDockerComposeバージョンは例えば下記で調べられる

```yaml:.travis.yml
before_install:
  - docker-compose -v
  - docker -v
```

これによると

>$ docker-compose -v
docker-compose version 1.17.1, build 6d101fb
before_install.3
$ docker -v
Docker version 17.09.0-ce, build afdb6d4

Dockerはとりあえず今回はバージョンはいいとします
DockerComposeだけ 1.24.1にバージョン上げます

```yaml:.travis.yml
env:
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1

before_install:
  - sudo rm /usr/local/bin/docker-compose
  - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
  - chmod +x docker-compose
  - sudo mv docker-compose /usr/local/bin
```

Travis公式のドキュメント通りです。

ところが色々不可解なエラーが出ます

##Yamlの罠

yamlじたいほとんど書かないのでよくわかってませんが、気になるポイントをみつけた

```yaml:.travis.yml
env:
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1
```

結論からいうと

GO111MODULE:on
だとGO111MODULEは定義されずautoになる

GO111MODULE: on
だとGO111MODULEはtrueが定義されてしまう

GO111MODULE= on
だとGO111MODULEは空文字が定義される

よって
GO111MODULE=on

以外はダメ


DOCKER_COMPOSE_VERSION = 1.24.1
DOCKER_COMPOSE_VERSION:1.24.1
DOCKER_COMPOSE_VERSION :1.24.1
は共に定義されない


DOCKER_COMPOSE_VERSION: 1.24.1
DOCKER_COMPOSE_VERSION=1.24.1
はOK
 
:の場合は前にスペースNG、後ろにスペース必須
=の場合は 前も後ろもスペースNG
GO111MODULEには=しか使えない
DOCKER_COMPOSE_VERSIONは上記ルールを守っているなら:でも=でもOK

細かい事はおいといて

```yaml:.travis.yml
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1
```

とするとちゃんと定義されるようになった

##並列実行問題

```yaml:.travis.yml
env:
  - GO111MODULE=on
  - DOCKER_COMPOSE_VERSION=1.24.1
```

で両方の環境変数は定義されたが、なぜか2つ実行されているっぽい
その2つの環境変数は

GO111MODULE=on, DOCKER_COMPOSE_VERSION定義なし
GO111MODULE定義なし, DOCKER_COMPOSE_VERSION=1.24.1

の2つ
どう考えても並列実行されている
ドキュメント見た感じだと globalに設定すればよさそう

```yaml:.travis.yml
env:
  global:
    - GO111MODULE=on
    - DOCKER_COMPOSE_VERSION=1.24.1
```

これで、すべての実行環境において上記のフラグが立つようになった
今回は使用していないが metrix: に環境変数配列を列挙すると並列で実行できるので
テストの高速化を行う時は使ってみよう
（ただし無料版だとたぶん2並列までしかできない）

##DBのbind問題

下記の謎エラーが出て結構悩まされた

```
ERROR: for gosick_mysql  Cannot start service gosick_mysql: driver failed programming external connectivity on endpoint gosick_mysql (cb76f17f3761214c04ca3c4ca03fe4b993e65b0ca14b76b711606651d40c8a8c): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
ERROR: for gosick_mysql  Cannot start service gosick_mysql: driver failed programming external connectivity on endpoint gosick_mysql (cb76f17f3761214c04ca3c4ca03fe4b993e65b0ca14b76b711606651d40c8a8c): Error starting userland proxy: listen tcp 0.0.0.0:3306: bind: address already in use
```

BindAddressが使われている。3306なのでMySQLが既に立ち上がっているようだが、いくら見渡してもそれらしいものがない・・
ので困った
MySQLのDockerは今は使ってないので消せば解決はするが、ちゃんと解決させたいので調べたら、まさかの！ TravisでMySQLが立ち上がっていた・・・

ので、実行前にTravisのMySQLを落とす

```yaml:.travis.yml
before_install:
  - sudo /etc/init.d/mysql stop
```

やった！できた！


#まとめ

色々な罠があったが、とりあえずTravisCIを動かすことができた
一通り自分の陥った罠をリストアップしたので、誰かの役にたてば幸いです

なぜかすべてのテストが通ってないので問題は残ってるけど、TravisCIの問題は解決したということで。

最終的な設定ファイル（不要な設定もあるかもしれないけど）

```yaml:.travis.yml
language: go
go:
  - 1.12.x

go_import_path: github.com/YukiMiyatake/GOSICK

env:
  global:
    - GO111MODULE=on
    - DOCKER_COMPOSE_VERSION=1.24.1

services:
  - docker

before_install:
  - sudo /etc/init.d/mysql stop
  - docker-compose -v
  - docker -v
  - sudo rm /usr/local/bin/docker-compose
  - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose
  - chmod +x docker-compose
  - sudo mv docker-compose /usr/local/bin
  - docker-compose build

install:

before_script:

script:
  - scripts/docker_app_test

after_script:

notifications:
```