My External Storage

Jun 8, 2020 - 5 minute read - Comments - go circleci

[Go]次世代イメージcimg/goとcircleci/go Orbsを使った2020年版CircleCIの環境構築

2020年になって、CircleCIのCI用の公式ベースイメージはcimg/base派生になった。
ただ、2020/06/07現在、Go向けの言語別公式ガイドの中身は古いままである。
cimg/goを使ったGo向けのCircleCIの設定をまとめる。

TL;DR

  • CircleCIで利用するコンテナイメージに次世代版が登場した。
  • 直接使わなくても、Orbsが便利
  • go-junit-reportgo getしなくてもよい
    • gotestsumコマンドがデフォルトインストールされている
  • GOPATHは変更されているので注意する
    • /home/circleci/go

最小構成のサンプルコードは次のとおり。

version: 2.1
orbs:
  go: circleci/go@1.2.0
jobs:
  build:
    executor:
      name: go/default
      tag: '1.14.4'
    environment:
      TEST_RESULTS: /tmp/test-results
    steps:
      - checkout
      - run: mkdir -p $TEST_RESULTS
      - go/mod-download-cached
      - run: gotestsum --junitfile ${TEST_RESULTS}/unit-tests.xml -- -p 6 -race -cover ./...
      - run: go build ./...
      - store_artifacts:
          path: /tmp/test-results
          destination: raw-test-output
      - store_test_results:
          path: /tmp/test-results

サンプルリポジトリは以下。

なお、動作確認で使ったツールの各バージョン情報は次のとおり。

version
Go 1.14.4
cimg/go image 1.14.4
circleci/go orbs 1.2.0

次世代型イメージのCirclCIの公式イメージ cimg/go

2020年2月にCircleCIはcimg/baseを基にした次世代版のCI用のベースイメージを提供しはじめることをアナウンスした。

そして5月にはGo用のcimg/goが正式リリースされた。

リリース文のとおり、これは従来のcircleci/golangに取って代わるものだ。

This is a direct replacement for the legacy CircleCI Go image (circleci/golang). You can find this image on Docker Hub, and the source code & documentation on GitHub.

cimg/xxxx系はcircleci/xxx系と比較して、起動時間が高速化されていてリリーススケジュールも安定しているらしい。
(ただ今回作成したサンプルリポジトリではそこまで高速化の恩恵を感じることはできなかった)。
Go以外にもRubyやRust用のイメージもリリースされている。

ただ、2020/06/07現在CircleCI公式ページの言語別セットアップガイドは古いcircleci/golangイメージを使った.circleci/config.ymlの設定のままだ。

なので、2020/06/07時点の最新のCircleCIの設定方法をまとめる。

cimg/goをつかったCircleCIの設定

cimg/goイメージと、circleci/go orbsを使った環境設定方法をまとめる。

circleci/golangイメージを使った従来のCircleCIの設定

まず、公式のGo用の環境構築に記載されている従来の設定は次のとおり(CircleCIの設定ファイルバージョンとGoのバージョンは変更している)。 明示的にGo Modulesを実行していない。 テスト結果を保存するためにjstemmer/go-junit-reportgo getしていたり冗長な処理が多い。

version: 2.1
jobs:
  build:
    docker:
      - image: circleci/golang:1.14.4
    environment:
      TEST_RESULTS: /tmp/test-results
    steps:
      - checkout
      - run: mkdir -p $TEST_RESULTS
      - restore_cache:
          keys:
            - v1-pkg-cache
      - run: go get github.com/jstemmer/go-junit-report
      - run:
          name: Run unit tests
          command: |
            trap "go-junit-report <${TEST_RESULTS}/go-test.out > ${TEST_RESULTS}/go-test-report.xml" EXIT
            go test -v -p 6 -race -cover ./... | tee ${TEST_RESULTS}/go-test.out            
      - run: go build ./...
      - save_cache:
          key: v1-pkg-cache
          paths:
            - "/go/pkg"
      - store_artifacts:
          path: /tmp/test-results
          destination: raw-test-output
      - store_test_results:
          path: /tmp/test-results

cimg/goとcircleci/go orbsを使った2020年版の設定

次世代イメージを使った環境設定は次のとおりになる。 cimg/goイメージをベースに作成された公式orbsイメージを使えばかなりシンプルに書けるようになる。

version: 2.1
orbs:
  go: circleci/go@1.2.0 # https://circleci.com/orbs/registry/orb/circleci/go

jobs:
  build:
    # mysqlイメージなども使いたいならばdockerタグでcimg/goを指定すればよいだろう。
    executor:
      name: go/default # the base image is cimg/go
      tag: '1.14.4'

    environment:
      TEST_RESULTS: /tmp/test-results

    steps:
      - checkout
      - run: mkdir -p $TEST_RESULTS
      - go/mod-download-cached

      - run:
          name: Run unit tests
          command: |
                        gotestsum --junitfile ${TEST_RESULTS}/unit-tests.xml -- -p 6 -race -cover ./...
      - run: go build ./...

      - store_artifacts:
          path: /tmp/test-results
          destination: raw-test-output

      - store_test_results:
          path: /tmp/test-results

CircleCIの実行結果は次の通り。

YAML上の設定で変わった点は次のとおりだ。

  • OrbsでGo Modulesまわりが簡潔に宣言できる
  • コンテナに最初から入っているgotestsumでテスト結果のXMLを出力できる

Go Modulesとcache周りの設定

circleci/go orbsを使えばGo Modules周りの設定は一行で完了する。
このOrbsはcimg/goイメージをベースに作られている。

go/mod-download-cachedはOrbsに定義された次の処理を一括で行なうステップなので、これだけでCircleCIキャッシュのロード、go mod download、キャッシュの保存が完了する。

  • go/load-cache
  • go/mod-download
  • go/save-cache

もちろん個別に利用することもできる。

gotestsumを使ったテスト結果の集計

従来の設定では、go-junit-reportを使ってテスト結果をXMLで集計していた。

- run:
  name: Run unit tests
  command: |
    trap "go-junit-report <${TEST_RESULTS}/go-test.out > ${TEST_RESULTS}/go-test-report.xml" EXIT
    go test -v -p 6 -race -cover ./... | tee ${TEST_RESULTS}/go-test.out    

cimg/goイメージには、gotestsumコマンドが標準で含められており、これを使えばわざわざgo getせずともXMLでテスト結果を集計できる。

そのため、次のような1行でテスト結果を集計しながらこちらで決めたオプションを使ってgo testが実行できる。

- run: gotestsum --junitfile ${TEST_RESULTS}/unit-tests.xml -- -p 6 -race -cover ./...

ちゃんと設定できていると、ジョブ実行結果のテストタブでテスト結果が集計される。

テスト結果の集計

cimg/goのGOPATH

既存のYAMLに手を加えず、circleci/golangからcimg/goにひとまず移行したいときもあるかもしれない。
circleci/golangという指定をcimg/goに変更するだけでも動くのだが、GOPATHは変わっているので注意すること。
cimg/goイメージのGOPATH/home/circleci/goになっている。

終わりに

Orbsを使うことでだいぶYAMLがさっぱりした。 最近は流行りもありGitHub Actionsを使いがちだったが、CircleCIのキャッチアップができてよかった。

参考

関連記事