LoginSignup
7
6

More than 5 years have passed since last update.

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

Last updated at Posted at 2018-08-27

設定ファイル

  • 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しなおすと想定通りキャッシュしてくれるようになりました!

7
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6