CircleCIでサクッとビルドチェーンを実現する

この記事は CircleCI Advent Calendar 2015 - Qiita の1日目の記事です。

  • 2日目はtakusさんです

というわけでCircleCIのAdvent Calendarの一発目です。一応複数記事書いて出来る限り埋めたいと思ってるので、小ネタ戦略でいきます。今回やりたいことは以下の通りです。 

やりたいこと

「Aのリポジトリのビルドが成功したら、Aに依存しているBのリポジトリのビルドを自動で開始したい」

CircleCIはリポジトリがPushやPull Requestされた際にビルドが実行されるという仕組みが基本であり、またJenkinsの「依存するスナップショットがビルドされたときにビルド」のようなビルドチェーンの機能を持っているわけでもありません(そもそも思想が違うので)。

とはいえ、一つのモノリシックなリポジトリだけで開発をしていくというケースは稀でしょう。共通的に利用するモジュールを別のリポジトリで管理していたりというケースは言語を問わずよくあることです。 リポジトリがモノリシックであればあるほどCIは非効率になる傾向が強くなるので、やはり適当な粒度で切られているのが望ましい。

幸い、CircleCIにはREST APIが用意されており、任意のタイミングで任意のリポジトリのビルドを実行するということが可能です。

APIトークンの取得

ビルドしたいプロジェクトのAPIトークンを Project Settings -> API Permissions で作成します。ここで必要な権限はALLです(ラベルは適当につけてください)。

Create TokenするとAPIトークンが生成されるので、これを利用します。

利用するAPI

POST: /project/:username/:project/tree/:branch

このAPIは任意のリポジトリの任意のブランチのビルドを実行するためのAPIです。基本的にこのAPIを駆使するだけでCircleCIでのビルドチェーンは実現できます。 :username :project :branch を任意の値に差し替えます。 最後にリクエストパラメータとして circle-token を付与します。

curl -X POST https://circleci.com/api/v1/project/stormcat24/ecs-formation/tree/master?circle-token=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

ビルドチェーンを実現するには、これを依存しているリポジトリのビルドが正常に通ったときに実行すれば良いわけです。CircleCIのコンテナの中からCircleCIのAPIを実行するということになります。

circle.yml

となるとcircle.ymlは以下のように書けばよいわけです。

test:
  override:
    - echo test!!

deployment:
  chain:
    branch: master
    commands:
      - curl -X POST https://circleci.com/api/v1/project/stormcat24/ecs-formation/tree/master?circle-token=$CHAIN_PROJECT_TOKEN

ここでは master ブランチの場合にdeploymentフェーズでAPIを実行しています(ブランチをmasterに限定する必要は特にないです。ご自由に)。APIトークンをcircle.ymlに晒すのはさすがにアレなので、Project Settings -> Environment variables で環境変数として定義しておくのが良いでしょう。circle.ymlでも環境変数を定義できますが、UI上で設定した方がナンボかはマシです(コンテナの中でechoすれば見えちゃうけど)。

パラメータ付きのビルドチェーン

POST: /project/:username/:project/tree/:branch のAPIでは任意のパラメータを渡すこともできます。これによってパラメータ付きのビルドチェーンも可能です。CircleCIではParameterized Buildと言われています。

例えば、以下のようにパラメータをJSONとして付与してAPIを実行すると

{
  "build_parameters": {
    "param1": "value1",
    "param2": 500
  }
}

実行されたビルドでは、$param1 $param2 といった形で参照することが可能です。これで、Aのビルドの結果によって得られた値をBのビルドに渡すということができます。

まとめ

  • CircleCIでも割と簡単にビルドチェーンは実現できます
  • さすがにJenkinsのBuild Pipelineのように、パイプライン進捗が可視化されるわけではないです