末尾最適呼び出し化

東京のWebエンジニアの日記帳

CircleCIでコミットメッセージを取得する

前提

  • CircleCI 2.x

背景

本業でCIツールはCIrcleCIを使っているのですが、
werckerと違ってCircleCIは契約したコンテナ数しか使えないので、
開発チーム内の別プロジェクトがコンテナを占拠していると、その実行が終わるまで待たされることになります。

GithubのプッシュをフックにCI実行しているのですが、
適切にCIを実行するべき単位でプッシュするエンジニアだけなら問題はないのですが、
作業単位で適当にプッシュするエンジニアがいると、しかもそれが数コンテナ使うようなプロジェクトだと、
運が悪いと無意味な待ち時間が発生します。

一応その対策として、
Auto-cancel redundant buildsであったり、コミットメッセージに[skip ci]と書くことでCIを実行しない、という機能もあるのですが、
適当にプッシュするエンジニアがskip ciなんかしてくれないので、
より強制的にCI実行するかどうかを選択させる方法を考えました。

[skip ci] と書くことでCIをスキップ、ではなく、 [run ci] と書かないとCI実行されない、という方法です。

CircleCI上でコミットメッセージを取得

CircleCIは環境変数でいろんな値がとれますが、
参考: Using Environment Variables - CircleCI
コミットメッセージは取れません。

なのでややスクリプトを書く必要があります。

git log --format=oneline -n 1 $CIRCLE_SHA1

これでコミットメッセージは取得できます。
再利用したい場合は変数に格納とかするといいかもしれません。

[run ci] と書かないとCI実行しないスクリプト

上をふまえて、

- run:
    name: [run ci] がなければ止める
    command: |
      if git log --format=oneline -n 1 $CIRCLE_SHA1 | grep "[run ci]"; then
        echo "Run"
      else
        echo "Stop"
        exit 1
      fi

これでコミットメッセージにrun ci が含まれなければ exit 1するので実行を止めることができます。

ただ、これだとmasterへのマージコミットにも[run ci]を含めないと止まってしまうので、masterブランチの場合もCIを止めないようにします。

- run:
    name: [run ci] がなければ止める
    command: |
      if test $CIRCLE_BRANCH = "master"; then
        :
      elif git log --format=oneline -n 1 $CIRCLE_SHA1 | grep "[run ci]"; then
        echo "Run"
      else
        echo "Stop"
        exit 1
      fi

これで無事、CircleCIに平穏が訪れます。