はじめに
CircleCI2.0の一番好きのはAPIでジョブをトリガーできる機能です。アレのおかげでローカルのバソコンからのコードでもCircleCI上で実行できるようになりました。これはdebugしたい時などめちゃめちゃ便利です。
ですが、CircleCI2.0でも色んな問題があって一番鬱陶しかったのは複数parallism種類を設定したいならコードが冗長になることです。
これはCircleCI2.1ですべて解決されます。
CircleCI2.1は実CircleCI上で2.0バーションに変換されてジョブを実行しますので(transpileされるかんじですね)
問題
環境設定の冗長
以下の設定の部分を見てからわかると思いますが。
jobs:
demo_test:
machine:
image: circleci/classic:latest
docker_layer_caching: true
working_directory: /home/circleci/test
shell: /bin/bash --login
environment:
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
ENV1: /env/test1
ENV1: /env/test1
ENV1: /env/test1
demo_test_x2:
parallelism: 2
machine:
image: circleci/classic:latest
docker_layer_caching: true
working_directory: /home/circleci/test
shell: /bin/bash --login
environment:
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
ENV1: /env/test1
ENV1: /env/test1
ENV1: /env/test1
ジョブdemo_test
とジョブdemo_test_x2
の違いはparallelism
の設定だけなのに他の設定も複製しないといけないので超面倒くさいです。
ジョブのステップの定義
CircleCI2.0で環境設定だけじゃなくてジョブのメインロジックなステップだちも冗長されます。
例えば
jobs:
demo_test_cmd1:
steps:
- checkout
- run:
name: Run prepare database
command: prepare_database.sh
- run:
name: Run build image
command: build-image.sh
- run:
name: Run init data
command: init_data.sh
- run:
name: Run command without parallelism
command: command.sh
demo_test_cmd2:
parallelism: 2
steps:
- checkout
- run:
name: Run prepare database
command: prepare_database.sh
- run:
name: Run build image
command: build-image.sh
- run:
name: Run init data
command: init_data.sh
- run:
name: Run command with parallelism
command: command.sh $CIRCLE_NODE_TOTAL $CIRCLECI_NODE_INDEX
この上記のdemo_test_cmd1
とdemo-test_cmd2
の違いのはただ最後のステップなんですがCircleCI2.0でステップ作用ができないので全部の準備のステップは冗長になりました。
今の例は2つのジョブしかないですが現在はもっと多くなる可能性があるのでconfig.yml
のファイルの量が大きくなって読みにくいし維持しにくいしとてもよろしくないと思います。
CircleCI2.1で解決
環境の設定
Executor
で環境設定をまとめられます。それを一回を定義して色んなジョブで使えるようになります。
さっきのconfigはこんな感じみたい書けます。
executors:
my_demo_test_executor:
machine:
image: circleci/classic:latest
docker_layer_caching: true
working_directory: /home/circleci/test
shell: /bin/bash --login
environment:
CIRCLE_ARTIFACTS: /tmp/circleci-artifacts
CIRCLE_TEST_REPORTS: /tmp/circleci-test-results
ENV1: /env/test1
ENV1: /env/test1
ENV1: /env/test1
jobs:
demo_test:
executor: my_demo_test_executor
demo_test_x2:
parallelism: 2
executor: my_demo_test_executor
めっちゃ短くなるじゃないですかね。あとは、設定再利用できますので維持しやすいし読みやすいですね。
ジョブのステップの定義
Command
を使って色んなステップを一つステップとして定義されて各ジョブにあの集合ステップを使えます。
それを使えば前の設定ファイルはこんな綺麗設定ファイルになります。
commands:
prepare:
steps:
- checkout
- run:
name: Run prepare database
command: prepare_database.sh
- run:
name: Run build image
command: build-image.sh
- run:
name: Run init data
command: init_data.sh
jobs:
demo_test_cmd1:
steps:
- prepare
- run:
name: Run command without parallelism
command: command1.sh
demo_test_cmd2:
parallelism: 2
steps:
- prepare
- run:
name: Run command with parallelism
command: command.sh $CIRCLE_NODE_TOTAL $CIRCLECI_NODE_INDEX
これよりもっとリファクタリングできます。 condition
を使えば直前のcommand.sh
を実行するステップを抽象して使いやすくなるかもしれません。もっとparallelism種類があったらめっちゃ効果が見えます。
commands:
prepare:
steps:
- checkout
- run:
name: Run prepare database
command: prepare_database.sh
- run:
name: Run build image
command: build-image.sh
- run:
name: Run init data
command: init_data.sh
run_command:
parameters:
is_parallelism: string
default: ""
step:
- prepare
- when:
condition: <<parameters.is_parallelism>>
step:
- run:
name: Run command with parallelism
command: command.sh $CIRCLE_NODE_TOTAL $CIRCLECI_NODE_INDEX
- unless:
condition: <<parameters.is_parallelism>>
step:
- run:
name: Run command without parallelism
command: command.sh
jobs:
demo_test_cmd1:
steps:
- run_command
demo_test_cmd_x2:
parallelism: 2
steps:
- run_command:
is_parallelism: "yes"
demo_test_cmd_x3:
parallelism: 3
steps:
- run_command:
is_parallelism: "yes"
demo_test_cmd_x4:
parallelism: 4
steps:
- run_command:
is_parallelism: "yes"
まとめる
- CircleCI2.1のおかげでプログラミングの心得できます。
- APIトリガーがなくなるのは寂しいです。
- まだVersion2.0で冗長コードがあればぜひ2.1を上げて上長コードを消しましょう。