Edited at

githubにcommitをpushしたらCircleCIでgo buildを実行できるようにする


設定ファイル



  • version: 2でCircleCI 2.0の設定と明示する


  • build用のdocker imageはcircleciが用意しているものを使用する



基本的な流れは以下


  1. キーからキャッシュを復元

  2. もしvendorがなければdep ensureを実行

  3. depもなければインストール

  4. dep自体とvendor以下をキャッシュに保存

  5. go build


#.circlci/config.yml
jobs:
build:
working_directory: /go/src/github.com/tanden/go-echo-with-mysql/

docker:
- image: circleci/golang:1.10

steps:
- checkout

- restore_cache:
keys:
- v1-vendor-{{ .Branch }}-{{ checksum "src/Gopkg.lock" }}
- v1-vendor-{{ .Branch }}
- v1-vendor
- v1-dep

- run:
name: dep ensure
command: |
cd src/
if [ ! -d vendor ]; then
if ! type dep >/dev/null 2>&1; then
go get -u github.com/golang/dep/cmd/dep
fi
dep ensure
fi
# ローカルとcircleci上でgo getしたdepのversionが異なると
# dep ensureしたときにGopkg.lockのchecksumが変わってしまい
# 別のcacheとして保存されてしまいrestore_cacheで取り出せない
# cacheしてるdepのversionはv0.5.0
- save_cache:
key: v1-vendor-{{ .Branch }}-{{ checksum "src/Gopkg.lock" }}
paths:
- src/vendor

- save_cache:
key: v1-dep
paths:
- /go/bin/dep

- run:
name: go build
command: |
go build -v -o src/app src/server.go

- persist_to_workspace:
root: .
paths:
- src/

workflows:
version: 2
build:
jobs:
- build


depとvendorのキャッシュ

パッケージをdep管理しているので、CircleCI上のコンテナでdep ensureコマンドを実行しvendor以下にパッケージをインストールします。


ただ、Gopkg.lockの内容に変化がない(使用しているパッケージが変わらない)場合、前回と同じインストールされたパッケージを使いたい。インストールに6〜7秒かかるので(毎回行われるので合計するとバカになりません)


なので、depコマンド自体と、vendor以下をCircleCIのキャッシュ機能をつかってキャッシュさせます。


キャッシュクリアするにはキーの名前を変える

キャッシュクリアをするために、都度キーの名前を変えるてしまうのがよいようです(restore_cacheをいちいち消して、キャッシュをリストアせずに新しくインストールしてキャッシュした値を更新する、、、などしなくてよくなります)


ドキュメントでは、v1などのバージョンプレフィックスをつけてキーの名前を変えていくことを推奨しています


https://circleci.com/docs/2.0/caching/#clearing-cache


はまったこと:vendorをキャッシュできない

vendorをキャッシュできず、はまりました。


src/Gopkg.lockのchecksumの値をキャッシュのキーにしているのですが、commitしているGopkg.lockとCircleCIのコンテナ上にcloneしたGopkg.lockのchecksumが異なりrestore_cacheでリストアできませんでした。


自分のローカルのdepのバージョンが古く、最新のdep(CirclCIでgo getしたdepのバージョン)では、Gopkg.lockのフォーマットが異なるようです。


  1. checkoutでcloneしたリポジトリ上のGopkg.lockのchecksumでrestore_cacheを行う

  2. restoreできない

  3. 再度 dep eusureする

  4. Gopkg.lockのchecksumが変わる

  5. 変わった後のchecksumを使ったkeyでキャッシュを保存してしまう

  6. 1でrestoreできない

CircleCI上のコンテナにインストールしているdepのバージョンと、ローカルのバージョンを同じにして再度dep initを行なって、新しいGopkg.lockをcommitしなおすと想定通りキャッシュしてくれるようになりました!