jtwp470’s blog

日記とかプヨグヤミングとか

GitHubのプロジェクトをCircleCI 2.0でテストできるように移行してみる

前回書いたマストドンの記事が地味にバズっていてびっくりしているたんごです。

今日はマストドンとは全く関係ないですが、自分のGitHubリポジトリでCircleCIでテストをしているプロジェクトをCircleCI 2.0でテストするようにしたので、簡単にそのメモ書きを残しておきます。

CircleCI 2.0ってなんぞ

circleci.com

を読め、という気持ちなんですが簡単に言うと以下のような違いがあります。

  • 基本的にDockerコンテナがそのままCircleCIで動かせるよ。
  • ローカルでビルドできるようになるよ。
  • キャッシュがめっちゃ効かせられるよ

はい。意味がわかりませんね。一番でかいのはやっとNativeのDockerをサポートしたということではないでしょうか。今までだと、例えば docker -v でマウントしたり、docker exec でコンテナ内のコマンドが実行できなかった気がしますが、2.0を使えばそれも簡単にできます。

どうやって始めるの

CircleCI 2.0はまだベータ版なので使いたい人は自分で使いたいよ〜という申請をする必要があります。先程のリンクの下の方にあるAccess CircleCI 2.0’s Beta Nowという部分に行って入力すると、数分後か数日後にメールが届き使えるようになります。

f:id:jtwp470:20170416232320p:plain

とはいっても、すぐに自分のリポジトリがすべて2.0でビルドされるわけではありません。

まず、今までだとプロジェクトルートに circle.yml というファイルを作っていました。2.0を適用させるには、.circleci/config.yml というディレクトリに設定を書く必要があります。

今回私が移行したプロジェクトはこちらです。

github.com

基本的にはPythonのみのコードで構成されておりテストも簡単にユニットテストを動かすだけでした。

machine:
  python:
    version: 3.6.0

dependencies:
  cache_directories:
    - "~/.cache/pip"

test:
  override:
    - python setup.py test

さてこれを2.0用のYAMLファイルに書き直していきます。 ドキュメントとしては以下の2つを読めば事足ります。

circleci.com

circleci.com

はじめにDockerのイメージを指定します。今回は公式イメージから最新のイメージを利用することにしました。

ここまでの設定を書くと次のようになります。

jobs:
  build:
    docker:
      - image: python:3

次にテストの前の依存関係のインストールPythonなら requrements.txt の読み込み、RubyならGemfileからのインストールなどをすると思いますが、そのステップも各必要があるみたいです。

version: 2
jobs:
  build:
    docker:
      - image: python:3

    steps:
      - checkout
      - run: apt-get update && apt-get install -y libgmp3-dev
      - run:
          name: Install dependencies
          command: pip install -r requirements.txt

stepsのはじめの行である checkout によりGitHubからコードを取得してくることができます。

また、runはnameとcommandというキーを持つことができ、これらはWeb UI上で次のように表示されるようになります。

f:id:jtwp470:20170416233407p:plain

お好みで書けばよいでしょう。

最後にテストの部分を追加します。

version: 2
jobs:
  build:
    docker:
      - image: python:3

    steps:
      - checkout
      - run: apt-get update && apt-get install -y libgmp3-dev
      - run:
          name: Install dependencies
          command: pip install -r requirements.txt
      - run:
          name: Run tests
          command: python setup.py test

ローカルでCircleCIのビルドをテストしてみる

さて、今までのCircleCIであればこのあと実際にこれが正しく動くかどうかに関してはコミットしプッシュしてみないとわからないという状況でした。なので初歩的にはYAMLの構文が間違っていたとか、設定に誤りがあった場合その修正コミットを作成してプッシュするという屈辱的な状況に追い込まれていました。

そこでCircleCIコマンドの出番です。

circleci.com

インストールは簡単で1行で済みます。

curl -o /usr/local/bin/circleci https://circle-downloads.s3.amazonaws.com/releases/build_agent_wrapper/circleci && chmod +x /usr/local/bin/circleci

ちなみにDockerが必要なのでよしなにインストールしておいてください。

あとはおもむろにプロジェクトルートで

circleci config validate

  config file is valid

でコンフィグの検証も行え、 circleci build で一貫したテストを行うことができます。

circleci build

====>> Spin up Environment
Build-agent version 0.0.3052-5be8345 (2017-04-15T11:24:20+0000)
Starting container python:3
  using image python@sha256:0a979dbff79f466aad8d92a89980ebe19cbd481b135d8cc9c0d843d8cf802ef9

Using build environment variables:
  CI=true
  CIRCLECI=true
  CIRCLE_BRANCH=master
  CIRCLE_BUILD_NUM=
  CIRCLE_BUILD_TOKEN=**REDACTED**
  CIRCLE_JOB=build
  CIRCLE_NODE_INDEX=0
  CIRCLE_NODE_TOTAL=1
  CIRCLE_REPOSITORY_URL=git@github.com:ryosan-470/cocoa.git
  CIRCLE_SHA1=f8cdb852ca92b53ae61768852ad23a9871e3ea8b

====>> Checkout code
Warning: skipping this step: running locally
====>> apt-get update && apt-get install -y libgmp3-dev
  #!/bin/bash -eo pipefail
apt-get update && apt-get install -y libgmp3-dev
Get:1 http://security.debian.org jessie/updates InRelease [63.1 kB]
...

...
writing manifest file 'cocoa.egg-info/SOURCES.txt'
running build_ext
============================= test session starts ==============================
platform linux -- Python 3.6.1, pytest-3.0.6, py-1.4.32, pluggy-0.4.0 -- /usr/local/bin/python
cachedir: .cache
rootdir: /home/ubuntu/cocoa, inifile: setup.cfg
collected 5 items

tests/test_factorize.py::TestFactorizeTestCase::test_fermat_success PASSED
tests/test_factorize.py::TestFactorizeTestCase::test_fermat_timeout PASSED
tests/test_factorize.py::TestFactorizeTestCase::test_pollard_rho PASSED
tests/test_factorize.py::TestFactorizeTestCase::test_small_prime PASSED
tests/test_factorize.py::TestFactorizeTestCase::test_trial_division PASSED

=========================== 5 passed in 3.73 seconds ===========================
Success!

こんな感じです。あとはコミットしてプッシュすればおしまいです。

あとはWeb UIにアクセスしてみると表示が2.0 になっています。 f:id:jtwp470:20170416234405p:plain

参考

engineer.crowdworks.jp

masutaka.net