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 notesを使って、コミットにスキップしたい旨のメモを追加し、CI側でそれをハンドリングする。
流れ
git pushする側
- コミット
git commit -m "xxx"
- メモadd
git notes add -m "[skip-ci]"
- デフォルトでHEADが対象
- メモpush
git push origin refs/notes/commits
- コミットpush
git push origin head
コミットのpush前にメモをpushしても怒られない。特に確認はしてないのだろう。
CircleCI側
全体: config.yml
- checkout
- 終了ステータスが0以外でも中断させないようにする*1
- set +e
- メモfetch
git fetch origin refs/notes/commits:refs/notes/commits
- HEADのメモを見てスキップしたい旨が書いてあるか確認
git notes show | fgrep "[skip-ci]"
- 終了コード見て0だったらexit 1させる
check-skip-ciというjob名だが、successするときはスキップせずにfailureの時はスキップさせている。スキップする時はfailureにすることでGitHubのstatus checkを機能させないようにする。
job名の方を否定形にしてあげれば人間に優しそう。
作ったもの
最近ちょっとした素振りのリポジトリは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 notesは見ることができなさそう
- config.yml内のrunでジョブを終了させる:
run: circleci-agent step halt
- git notesでメモを追加する時の追加先は変更可能。専用の場所を用意するとより良さそう
- git notesで追加したメモをpushする処理をコミット時のgit-hooksとしてpre-pushにスクリプトを書いたが、どちらもpushなので無限ループ発生した、それはそう
- 翻訳で改善できそうな箇所があったためissueを上げた