概要
以下を目標に、Go言語で簡単なCLIツールを作りながらCI/CDを実践してみました!- CIで
test
やbuild
を実行して、README
にバッジを貼る - テストカバレッジ計測し、
README
にバッジを貼る - gitで
tag
がついたら、バイナリを作ってgithubのリリースページにアップする
実践内容をハンズオンっぽくまとめると共に、ポイントやお世話になった記事をあわせて紹介したいと思いますʕ◔ϖ◔ʔ
A repository to play around with using CircleCI.
github.com/kemokemo/try-circle-ci
CIでtest
やbuild
を実行して、README
にバッジを貼る
今回は、CircleCIを使ってCI/CDを実践することにしました。特にCircleCIに対するこだわりがある訳ではなく、「使用経験ないから学習してみっか!」ぐらいの軽い感覚で選定しました。dockerイメージを使ってビルド
CIは繰り返し実行するものです。CIの設定が同じなら何度実行しても同じ結果が得られるように(=冪等性があるように)dockerコンテナを使います。幸い、CircleCI公式でGo言語用のコンテナを用意してくれているのでこれを使います。言語ガイドを見ながら最初の
config.yml
ができました。test
とbuild
のjobを並行に実行します。version: 2 jobs: test: docker: - image: circleci/golang:1.13.5-node working_directory: /go/src/github.com/kemokemo/try-circle-ci steps: - checkout - run: go version - run: go get -v -t -d ./... - run: go test -v -cover ./... build: docker: - image: circleci/golang:1.13.5-node working_directory: /go/src/github.com/kemokemo/try-circle-ci steps: - checkout - run: go get -v -t -d ./... - run: go build workflows: version: 2 test and build: jobs: - test - build
executor
を定義して複数のjob
で使う
さて、お気づきの方もいらっしゃると思いますが、上記のconfig.yml
では複数のjobで下記の「stepを実行する環境」の記述が重複して記述されてます。docker: - image: circleci/golang:1.13.5-node working_directory: /go/src/github.com/kemokemo/try-circle-ciちょっとモヤモヤします(´・ω・`) 同じ設定で良いならば、1箇所で定義して使いまわしたいです。そこで
executor
という仕組みの出番です!まず、
executor
を使うためにはconfig.yml
のバージョンを2.1
以降に変更する必要があります。上述の内容にgo-113-5
という名称をつけてexecutor
として定義するとこんな感じになります。version: 2.1 # add a docker executor for golang executors: go-113-5: docker: - image: circleci/golang:1.13.5-node working_directory: /go/src/github.com/kemokemo/try-circle-ci (後略)よしよし。良いですね、名前がつけばそれを呼び出すことができます。実際に使ってみましょうʕ◔ϖ◔ʔ
version: 2.1 executors: go-113-5: docker: - image: circleci/golang:1.13.5-node working_directory: /go/src/github.com/kemokemo/try-circle-ci jobs: test: executor: go-113-5 # using my executor! steps: - checkout - run: go version - run: go get -v -t -d ./... - run: go test -v -cover ./... build: executor: go-113-5 # using my executor! steps: - checkout - run: go get -v -t -d ./... - run: go build workflows: version: 2 test and build: jobs: - test - build
テストカバレッジ計測し、READMEにバッジを貼る
無事にCircleCIでビルドできるようになったら、README
にバッジを貼りましょう。CIを使っていて且つビルドが成功しているバッジがあれば、「どんなツールかなぁ」と思ってリポジトリを見に来た時の安心感がグンと増します。(もちろん真っ赤なFail
バッジになっていると逆効果ですが・・)- CircleCIのバッジを追加する - CircleCI
- Adding Status Badges - CircleCI (英語の説明の方が画面付きで雰囲気つかみやすいかも)
テストカバレッジ計測し、README
にバッジを貼る
せっかくCIでtest
ジョブも実行しているのですから、テストカバレッジも継続的に計測して可視化したいです。まさにやりたいことそのまんまな以下の記事を参考にして、 Codecov というサービスを使うことにしました。
codecov
のorb
を追加
オーブと聞くと、ドラゴンクエストⅢで6つ集めるアレとか、ドラゴンクエストⅤで砕けたり砕けなかったりするアレとかを思い出すのですが、ここで言うorb
とは「CircleCI を手早く使い始めるのに便利なコンフィグパッケージ」(引用元:Orbs を使う - CircleCI)だそうです。codecov
のorb
を追加してみたのが以下です。version: 2.1 # add codecov's orb orbs: codecov: codecov/codecov@1.0.5 executors: go-113-5: ... (後略)この便利な
orb
という仕組みは、「CircleCI Orb Registry」で検索して探すことができます。上記で追記した内容は、「CircleCI Orb Registry - codecov/codecov」を参考にしました。その他のorb
の例としては、静的サイト生成ツールのhugo
が使える「CircleCI Orb Registry - circleci/hugo」なんかもあります。便利ですね(*´ω`*)カバレッジの生成と収集
test
のジョブでカバレッジ情報をファイルに書き込む処理を追加してcodecov
にアップロードしましょう。その際、codecovサービスに対象リポジトリを追加した時に生成されるtokenを、CircleCIのCODECOV_TOKEN
環境変数に設定するのを忘れずに。以下のようにtest
ジョブのステップを書き換えます。jobs: test: executor: go-113-5 steps: - checkout - run: go version - run: go test -v -cover - run: go get -v -t -d ./... # adding coverprofile - run: go test -v -cover -coverprofile=coverage.out ./... # adding upload process to the codecov - codecov/upload: file: ./coverage.out build: ... (後略)これで、
test
ジョブを実行する度に最新のカバレッジ情報がcodecov
にアップロードされるようになります。カバレッジの可視化と言えばバッジです。上図のように
codecov
のSettings - Badge
からREADME
にコピペして使いましょう。
gitでtag
がついたら、バイナリを作ってgithubのリリースページにアップする
このパートの内容は、以下の記事を参照してイメージを掴みつつ現在のCircleCI公式のドキュメントで学びながら実践しました。素晴らしい記事です、ありがとうございます。
deploy
ジョブを追加
deploy
ジョブでのおおまかな処理内容は以下です。- mitchellh/gox を使って、マルチプラットフォーム向けのバイナリを生成
- tcnksm/ghr を使って、GitHubのタグページにバイナリをアップロード
gox
を使ってマルチプラットフォーム向けのバイナリを生成する処理を追加します。これが実行されると、release
フォルダにドババっとバイナリが生成されます。(前略) jobs: (中略) deploy: executor: go-113-5 steps: - run: echo 'export PATH=${GOPATH}/bin/:${PATH}' >> $BASH_ENV - checkout - run: go get -v -t -d ./... # install gox and add the build process using the gox - run: go get github.com/mitchellh/gox - run: mkdir release - run: gox -output "./release/{{.Dir}}_{{.OS}}_{{.Arch}}" ./ ./... workflows: .... (後略)次に、
ghr
を使ってGitHubのタグページにファイルをアップする処理を追加します。実際に動かす前に、CircleCIに対してGITHUB_API
環境変数の設定が必要です。 「GitHub API Token - tcnksm/ghr」 の内容を参考に、repo
スコープ付きのトークンを生成して設定しておきましょう。(前略) jobs: (中略) deploy: executor: go-113-5 steps: - run: echo 'export PATH=${GOPATH}/bin/:${PATH}' >> $BASH_ENV - checkout - run: go get -v -t -d ./... - run: go get github.com/mitchellh/gox - run: mkdir release - run: gox -output "./release/{{.Dir}}_{{.OS}}_{{.Arch}}" ./ ./... # install ghr and add the upload process using ghr - run: go get github.com/tcnksm/ghr - run: ghr -u $CIRCLE_PROJECT_USERNAME $CIRCLE_TAG release/ ... (後略)
deploy
ワークフローを追加
「v」から始まるタグに対してのみ、上述のdeploy
ジョブを実行するようにワークフローを設定してみましょう。「ジョブの実行を Workflow で制御する - CircleCI」の内容を参考に以下ようにしてみました。(前略) workflows: (中略) - deploy: jobs: - build: filters: tags: only: /.*/ - deploy: requires: - build filters: tags: only: /^v.*/ # 「v」から始まるタグに対してのみ実行します。 branches: ignore: /.*/実際に「v0.0.1」というタグをつけて
deploy
ワークフローを動作させてみた結果が以下です。うむ、素晴らしいです。およそ考えられるほぼ全てのプラットフォーム向けのバイナリが、CI/CDの仕組みによって生成されました。gox
もghr
も実に良いですね。おまけ
Go言語のリポジトリなら「Go Report Card | Go project code quality report cards」という仕組みを使って、多角的にコードの品質を可視化してくれるサービスも利用可能です。自分のGitHubリポジトリのパスを入力すればレポートを作れますし、バッジも貼れます。良きʕ◔ϖ◔ʔまとめ
CircleCI良いですね。特にorb
の仕組みに感動しました。Ver. 2.1
から使用可能になったexecutor
の仕組みも大変興味深く、自在にCI/CDを構築できる感触を得ました。他にもいくつか同様の仕組みを導入したいツールがあるので、引き続き学習しながら使って行きたいと思います。