はじめに
この記事では、CircleCI で「コミットメッセージに特定の文字列が含まれていれば、ある処理を行いたい」場合の実現方法について紹介します。結論としては、circleci-agent step halt
コマンドを利用することで比較的シンプルに実現できます。
今回は、CircleCI 2.1 で動作確認を行っています。
実現したかったこと
これまで、iOS プロジェクトにおいて以下のルールでワークフローを定義していました。
- master 以外のブランチは、
Unit test
を実行する - master ブランチは、
Unit test
に加えて、UI test
とApp Store Connect へのデプロイ
を実行する
これに加えて、新たに以下のルールを追加しました。
- master 以外のブランチは、コミットメッセージに「kick-ui-test」が含まれていれば、
Unit test
のあとにUI test
を実行する
定義したワークフローの全体像
図: master ブランチ以外の Workflow |
図: master ブランチの Workflow |
yaml の全体像
※ 各ジョブ内で行っている処理(呼び出している commands)については省略して例示します。
version: 2.1
jobs:
unit_test:
<<: *defaults
steps:
- unit-test
run_ui_test_as_needed:
<<: *defaults
steps:
- checkout
- run:
name: Decide whether to run ui-test, depending on the content of the commit message.
command: |
COMMIT_MESSAGE=$(git log -1 HEAD --pretty=format:%s)
TRIGGER_MATCH_PATTERN="^.*kick-ui-test.*$"
if [[ ${COMMIT_MESSAGE} =~ ${TRIGGER_MATCH_PATTERN} ]]; then
echo "Continue to run ui_test, as the commit message contains kick-ui-test."
else
echo "Since the commit message does not include kick-ui-test, this job will be successfully terminated."
circleci-agent step halt
fi
- ui_test
ui_test:
<<: *defaults
steps:
- ui_test
deploy_appstore:
<<: *defaults
steps:
- deploy
workflows:
build-workflow:
jobs:
- unit_test
- run_ui_test_as_needed:
requires:
- unit_test
filters:
branches:
ignore:
- master
- ui_test:
filters:
branches:
only:
- master
- deploy_appstore:
requires:
- unit_test
- ui_test
filters:
branches:
only:
- master
run_ui_test_as_needed
ジョブについて
このジョブで 「コミットメッセージに「kick-ui-test」が含まれていれば、 Unit test
のあとに UI test
を実行する」という制御を実現しています。
run_ui_test_as_needed:
<<: *defaults
steps:
- checkout
- run:
name: Decide whether to run ui-test, depending on the content of the commit message.
command: |
COMMIT_MESSAGE=$(git log -1 HEAD --pretty=format:%s)
TRIGGER_MATCH_PATTERN="^.*kick-ui-test.*$"
if [[ ${COMMIT_MESSAGE} =~ ${TRIGGER_MATCH_PATTERN} ]]; then
echo "Continue to run ui_test, as the commit message contains kick-ui-test."
else
echo "Since the commit message does not include kick-ui-test, this job will be successfully terminated."
circleci-agent step halt
fi
- ui_test
主に shell script で以下の処理を行っています。
- 直近のコミットメッセージを取得
- 正規表現で、特定したい文字列(今回であれば
kick-ui-test
)を定義 -
1.
で取得したコミットメッセージに特定文字列が含まれているかを判定- もし、含まれていれば何もしないことを
echo
するだけで、次のステップへ進む - もし、含まれていなければその時点でジョブを正常終了する
- もし、含まれていれば何もしないことを
-
ui_test
を実行する
3.2 で、ジョブを正常終了させる際には、circleci-agent step halt
コマンドを利用しています。このコマンドは、ジョブを失敗させずに終了させることができるもので、ジョブを条件付きで実行する必要がある今回のようなケースに便利です。
Ending a Job from within a step | CircleCI
さいごに
今回は、master ブランチ以外(機能の実装途中など)でも手軽に ui_test
を実行したいケースがあり、run_ui_test_as_needed
job を追加しました。
CircleCI 2.0 から次のジョブを続行する前に手動による承認操作を待つ制御が可能になりましたが、仕組み上、手動で承認する手間が発生するため、今回のようにコミットする時点で特定ジョブの実行を制御できると便利だと感じました。
参考
- [Ending a Job from within a step | CircleCI](Configuring CircleCI - CircleCI)