CircleCI2.1の新機能のおかげで人生が楽しくなりました

# はじめに
CircleCI2.0の一番好きのはAPIでジョブをトリガーできる機能です。アレのおかげでローカルのバソコンからのコードでもCircleCI上で実行できるようになりました。これはdebugしたい時などめちゃめちゃ便利です。
ですが、CircleCI2.0でも色んな問題があって一番鬱陶しかったのは複数parallism種類を設定したいならコードが冗長になることです。
これはCircleCI2.1ですべて解決されます。
CircleCI2.1は実CircleCI上で2.0バーションに変換されてジョブを実行しますので(transpileされるかんじですね）

# 問題
##　環境設定の冗長
以下の設定の部分を見てからわかると思いますが。

```yaml
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で環境設定だけじゃなくてジョブのメインロジックなステップだちも冗長されます。
例えば

```yaml
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でステップ作用ができないので全部の準備のステップは冗長になりました。

今の例は２つのジョブしかないですが現在はもっと多くなる可能性があるので`config.yml`のファイルの量が大きくなって読みにくいし維持しにくいしとてもよろしくないと思います。

# CircleCI2.1で解決
## 環境の設定
`Executor`で環境設定をまとめられます。それを一回を定義して色んなジョブで使えるようになります。
さっきのconfigはこんな感じみたい書けます。

```yaml
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`を使って色んなステップを一つステップとして定義されて各ジョブにあの集合ステップを使えます。
それを使えば前の設定ファイルはこんな綺麗設定ファイルになります。

```yml
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種類があったらめっちゃ効果が見えます。

```yml
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"
```

#まとめる

1. CircleCI2.1のおかげでプログラミングの心得できます。
2. APIトリガーがなくなるのは寂しいです。
3. まだVersion2.0で冗長コードがあればぜひ2.1を上げて上長コードを消しましょう。