Go言語:自分のライブラリをGitHubで公開する方法+drone.ioで継続的インテグレーション


# この記事の目的

* Go言語でライブラリを作る
* 作ったライブラリをリモートリポジトリパッケージとしてGitHubで公開する
* drone.ioで継続的インテグレーション(continuous integration 以下 CI)する

# Go言語のパッケージ管理

Go言語はパッケージ管理ツールが標準化されていて、依存するパッケージをGitHub上などから簡単にダウンロードすることができる。


```shell:BDDスタイルでテストするライブラリをダウンロードする例
go get github.com/r7kamura/gospel
```

# ライブラリを作る

今回サンプルとして作るライブラリは、Hello Worldを返すというもの。パッケージ名は `gohelloworld` とする。

まずは、`gohelloworld` パッケージ用のディレクトリを好きな場所に作る:

```
mkdir ~/Desktop/gohelloworld
cd ~/Desktop/gohelloworld/
```

ライブラリの実装を書くファイル `helloworld.go` を作る:

```
touch helloworld.go
```

ちなみに、ファイルの名前はパッケージ名と同一でなくても良い。

`HelloWorld` 関数を実装する:

```go:helloworld.go
package gohelloworld

func HelloWorld() string {
	return "Hello World"
}
```

パッケージ名はディレクトリ名と同じ `gohelloworld` にする。ここで作った `HelloWorld` 関数は依存するコードからは `gohelloworld.HelloWorld()` のようにパッケージ名を前につけて呼び出すようになる。


次に、`HelloWorld` 関数の単体テストを書くファイルを作る:

```
touch helloworld_test.go
```

ファイル名は `_test.go` で終わるものであれば何でも構わない。

今回はBDD風にテストコードを書きたいので、`gospel`というライブラリを使う。使うためにはリモートリポジトリからライブラリを取ってきておく必要がある:

```
go get github.com/r7kamura/gospel
```

テストコードを記述する:

```go:helloworld_test.go
package gohelloworld

import (
	. "github.com/r7kamura/gospel"
	"testing"
)

func TestDescribe(t *testing.T) {
	Describe(t, "HelloWorld", func() {
		Context("call HelloWorld", func() {
			It("should be 'Hello World'", func() {
				Expect(HelloWorld()).To(Equal, "Hello World")
			})
		})
	})
}
```

テストを実行してみる:

```
go test
```

テスト実行結果:

```
.PASS
ok      _/Users/suin/Desktop/gohelloworld       0.014s
```


# GitHub上でリポジトリを作る

上で作った `gohelloworld` ライブラリを公開するためのリポジトリをGitHubに作る。

[GitHubの新規リポジトリ作成ページ](https://github.com/new)に行き、パッケージ名と同じ名前でリポジトリを作成する:

![Create_a_New_Repository-3.png](https://qiita-image-store.s3.amazonaws.com/0/889/c62d556f-10c0-ba7a-e99a-321ab2e37cdd.png "Create_a_New_Repository-3.png")


リポジトリが作成されると、初期化のためのコマンドが表示されるので、それらを実行する:

![suin_gohelloworld.png](https://qiita-image-store.s3.amazonaws.com/0/889/36e31a61-d9bf-8c82-8c57-1d84f775fc7c.png "suin_gohelloworld.png")

最後に、`helloworld.go` と `helloworld_test.go` をコミットしてリモートリポジトリにpushしておく:

```
git add -A
git commit -m "add source code"
git push
```

これで `gohelloworld` パッケージがリモートパッケージとして利用できるようになる。

試しにリモートパッケージに依存するプロジェクトを作ってみる:

```
mkdir ~/Desktop/other_go_project
cd ~/Desktop/other_go_project/
touch main.go
```

```go:main.go
package main

import "github.com/suin/gohelloworld"

func main() {
	println(gohelloworld.HelloWorld())
}

```

※ `suin` のところはご自分のアカウント名に書き換えてください

リモートパッケージをダウンロードする:

```
go get github.com/suin/gohelloworld
```

※ `suin` のところはご自分のアカウント名に書き換えてください

実行してみる:

```
go run main.go
```

画面に `Hello World` と表示されていれば成功。


# drone.ioでCIする

[drone.io](https://drone.io/)はCIをウェブサービスとして提供しており、簡単にGoのCI環境を利用することができる。

今回はdrone.ioを使ってGitHubにpushがあるたびに、単体テストが自動で実行されるようにする。

まずは、drone.ioにGitHubアカウントでログインする:

![Login___drone_io_continuous_integration.png](https://qiita-image-store.s3.amazonaws.com/0/889/6855e55a-6da6-43f1-494d-cf54e908dcc7.png "Login___drone_io_continuous_integration.png")


「New Project」を開き、

![Dashboard___suin.png](https://qiita-image-store.s3.amazonaws.com/0/889/2ce14250-f636-6c29-848e-f8f38895ace5.png "Dashboard___suin.png")

リポジトリの中から「GitHub」を選ぶ:

![Add_Repo___drone_io.png](https://qiita-image-store.s3.amazonaws.com/0/889/b3f79265-6079-b6cd-d81b-3d348765bdaf.png "Add_Repo___drone_io.png")

GitHubのリポジトリの一覧が表示されるので、その中から `gohelloworld` の「Select」を押す:

![Add_Repo___drone_io-4.png](https://qiita-image-store.s3.amazonaws.com/0/889/af754420-b31e-417b-85ba-98f0b2c6a782.png "Add_Repo___drone_io-4.png")

言語を選択する画面が出るので、「Go」を選ぶ:


![Add_Repo___drone_io-3.png](https://qiita-image-store.s3.amazonaws.com/0/889/04e2b85a-7442-303f-3de6-d1773d10809e.png "Add_Repo___drone_io-3.png")



ビルドスクリプトの設定画面になるので、下記のスクリプトをフォームに入力し、「Save」を押すとプロジェクトのセットアップが完了となる:

```
go get github.com/r7kamura/gospel
go test -short -cover
```

![Add_Repo___drone_io-7.png](https://qiita-image-store.s3.amazonaws.com/0/889/be654825-5bb0-db89-c7d1-2ff97ba487f4.png "Add_Repo___drone_io-7.png")

初回のビルドは「Build Now」を押すとすぐに実行できる:


![Build_Setup___gohelloworld.png](https://qiita-image-store.s3.amazonaws.com/0/889/425cce87-ca70-f0af-d454-c28efcbc832a.png "Build_Setup___gohelloworld.png")

しばらく待つと結果が表示される:

![Build__1___gohelloworld.png](https://qiita-image-store.s3.amazonaws.com/0/889/935bcbfe-e262-81d8-78f3-82a9f1fe9b13.png "Build__1___gohelloworld.png")


## ビルドステータスバッジをGitHubに載せる

ビルドがうまく行っているかどうかをGitHubで確認できるように、drone.ioのステータスバッジをREADMEに貼り付ける。

ステータスバッジのタグは「Setting」→「Status Budges」から得ることができる:

![Badges___gohelloworld-3.png](https://qiita-image-store.s3.amazonaws.com/0/889/83127b4a-c775-02b9-072c-35d7444d3cac.png "Badges___gohelloworld-3.png")


README.mdにタグを貼り付ける:

```markdown:README.md
# GoHelloWorld

[![Build Status](https://drone.io/github.com/suin/gohelloworld/status.png)](https://drone.io/github.com/suin/gohelloworld/latest)
```

GitHubにpushする:

```
git add README.md
git commit -m "add drone.io status badge"
git push
```

GitHubを開いてみると、ステータスバッジが表示されている:

![suin_gohelloworld-2.png](https://qiita-image-store.s3.amazonaws.com/0/889/15472b91-8c13-c527-d3dc-91c90e151433.png "suin_gohelloworld-2.png")


ちなみに、今のコミットでdrone.io上ではビルドが自動で一度行われる:

![Builds___gohelloworld-2.png](https://qiita-image-store.s3.amazonaws.com/0/889/266ac2c3-469d-9788-c792-d6f5424b274f.png "Builds___gohelloworld-2.png")