コミットメッセージを汚さずにCircleCIのCIをスキップさせるようにしたが、汚したほうが楽という結論に至った

TL;DR

  • CircleCIを使ってる場合、コミットメッセージに [skip ci], [ci skip] を含めるとそのコミットに対するCIの実行をスキップできる
  • コミットメッセージを汚したくないので、git notesを使ってスキップする仕組みを作った
  • 日常的に使うには面倒くさいので、素直にコミットメッセージに [skip ci], [ci skip] を含めた方が楽そう

モチベーション

ジョブとワークフローのスキップとキャンセル - CircleCI

CircleCIを使ってる場合、コミットメッセージに [skip ci], [ci skip] を含めるとそのコミットに対するCIの実行をスキップできる。
だがコミットメッセージを汚したくないので他の方法を用いてCIをスキップさせたい。

アプローチ

コミットメッセージ以外でコミットに情報を紐付ける手段として、git notes がある。

Git - git-notes Documentation

git notesを使って、コミットにスキップしたい旨のメモを追加し、CI側でそれをハンドリングする。

流れ

git pushする側

  1. コミット
    • git commit -m "xxx"
  2. メモadd
    • git notes add -m "[skip-ci]"
      • デフォルトでHEADが対象
  3. メモpush
    • git push origin refs/notes/commits
  4. コミットpush
    • git push origin head

コミットのpush前にメモをpushしても怒られない。特に確認はしてないのだろう。

CircleCI側

全体: config.yml

  1. checkout
  2. 終了ステータスが0以外でも中断させないようにする*1
    • set +e
  3. メモfetch
    • git fetch origin refs/notes/commits:refs/notes/commits
  4. HEADのメモを見てスキップしたい旨が書いてあるか確認
    • git notes show | fgrep "[skip-ci]"
  5. 終了コード見て0だったらexit 1させる

check-skip-ciというjob名だが、successするときはスキップせずにfailureの時はスキップさせている。スキップする時はfailureにすることでGitHubのstatus checkを機能させないようにする。
job名の方を否定形にしてあげれば人間に優しそう。

作ったもの

github.com

最近ちょっとした素振りのリポジトリはASB-xxxという命名にしている。遊び場(ASobiBa)の略。

おわりに

他に色々な方法が考えられそう。先のアプローチはgit pushする側とCI側でそれぞれ設定が必要で、またコミットをpushする前にメモをpushする必要があって面倒くさい。

チーム開発での導入を考えていたのだが面倒なので素直にコミットメッセージに [skip ci] などを入れたほうが楽だな、という結論に至った。

汚したくないけどスキップしたい時は苦しいが git commit -m 'xxx' -m '[skip ci]' な感じで 2つ目以降の -m オプションに [skip ci] を渡すとGitHub上のblameの一覧には表示されないので良いかもしれない。

GitHub上の `git commit -m '_' -m '[skip ci]'` で行ったコミット

メモ

参考