CircleCI の Trigger Pipeline で任意のワークフローを実行する

## はじめに
CircleCI でカスタマーサクセスをしている鈴木です。暑い日が続きますが、頭が大きすぎてあう帽子がなく困っています。ちょっとした帽子専門店でも見つかりませんでした。

本記事では CircleCI の Trigger Pipeline を利用して任意のタイミングで任意のワークフローを実行します。この機能を利用することで、通常は CI のワークフローを実行しておき、社内の承認プロセスを経たあと、デプロイ用のワークフローのみを実行するといったことができます。

## WebUI で　Trigger Pipeline を実行する手順
CircleCI の WebUI のトップページに相当する Dashboard で、リポジトリとブランチを指定すると、手動で Pipeline をトリガーする Trigger Pipeline のボタンがアクティブになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/9708b0ed-f8ce-2f32-f288-d5ead55f205f.png)


このまま Trigger Pipeline のボタンをクリックすると、選択したブランチの最新コミットの config.yml に従って Pipleline を実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/ad74b063-a854-2d25-d638-36602a8cb06c.png)

このウィンドウ内の「Add Parameters (Optional)」の部分を展開すると、下図のような表示となり、Pipeline 実行時にパラメータの値を渡しながら Pipleline を実行することができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/bb3cee93-9153-09ee-bb9c-17453d8fc954.png)

ここで指定するパラメーターと値の組み合わせで任意のワークフローを実行できます。

## サンプルプロジェクトの背景と config.yml の概観 

それでは、config.yml 側にパラメーターと値、そしてその組み合わせに応じて実行するワークフローの設定を行います。今回のサンプルでは、通常のコミットでトリガーされるビルド用のワークフローとは別に、手動の Trigger Pipeline ではデプロイ用のワークフローのみを実行するようにします。さらに、そのデプロイ用のワークフローは変更が merge されたあとの main ブランチから実行できるように制限を加えてみます。
今回のサンプルの config.yml の全体図は以下のようになります。（[こちら](https://github.com/suzucir/cci_trigger_pipeline/blob/main/.circleci/config.yml)に公開しています。）

## config.yml での設定

それでは部分ごとに見ていきます。

まず、**parameters キー**でパラメータを以下のように設定しています。
```yaml:
version: 2.1

parameters:
  action:
    type: enum
    enum: [build, deploy]
    default: build
```
parameters キーの直後に記述している action はパラメーターの名前です。任意の名前をつけることができます。
- **type キー**では値をリスト形式で設定する enum を選んでいます。他にも string, boolean, integer といった type があります。(参考までに boolean を用いた config.yml は[こちら](https://github.com/suzucir/cci_trigger_pipeline/blob/boolean-type/.circleci/config.yml)です。)
- **enum キー**ではパラメーターに渡す値をリスト形式で設定しています。サンプルでは build と deploy という文字列を設定しています。
- **default キー**ではパラメーターの値を明示していない場合に使用する値を設定します。サンプルでは通常時にビルド用のワークフローを実行するよう、build という値をデフォルト値にしています。

**jobs キー**の部分ではビルド用とデプロイ用のジョブを設定しています。
この部分の解説は割愛します。

**workflows キー**の部分でビルド用とデプロイ用のワークフローを設定しています。
以下の build-workflow はワークフローの名前です。任意に設定します。
その下の **when キー**のところで action パラメーターの値が build と等しいときという条件を指定しています。
```yaml:
workflows:
  build-workflow:
    when:
      equal: [ build, << pipeline.parameters.action >> ]
    jobs:
      - build-job
```
action パラメーターのデフォルト値は build にしているので、通常はこちらのワークフローが実行されます。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/95f2a192-6472-8656-3656-3e0f9eee3920.png)



次の deploy-workflow は action パラメーターの値が deploy と等しいときに実行されます。さらにここでは、main ブランチのときに実行されるという条件も追加しています。
```yaml:
deploy-workflow:
    when:
      equal: [ deploy, << pipeline.parameters.action >> ]
    jobs:
      - deploy-job:
          filters:
            branches:
              only:
                - main
```

## サンプルプロジェクトの実行
前述の「WebUI で　Trigger Pipeline を実行する手順」にしたがって Trigger Pipeline のウィンドウを表示させたあと、下図のように action パラメーターに deploy という値を渡してパイプラインをトリガーします。
※ なお、config.yml の parameters では、enum を type に設定していますが、このウィンドウの Parameter type に enum という選択肢はありません。string を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/06553c4e-ad60-a926-a934-5edb64dd0dc5.png)
 
この Trigger Pipeline を main ブランチで実行すると、下図のように deploy-workflow のみが実行されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11243/4a6c0a60-a0ac-ffff-c46e-86707c043c0e.png)


## API でもパラメーター付きの Trigger Pipeline が可能
ここまでは、WebUI 上の Trigger Pipeline ボタンから実行していましたが、[CircleCI API](https://circleci.com/docs/api/v2/index.html) からパイプラインの実行をトリガーする際にもパラメータを渡すことができます。
例えば、[Pipeline を実行するAPI](https://circleci.com/docs/api/v2/index.html#operation/triggerPipeline)のリクエスト Body に以下のような設定をすることで WebUI 上の Trigger Pipeline ボタンと同じ動作を実行できます。

```json:
{
  "branch": "main",
  "parameters": {
    "action": "deploy"
  }
}
```

## おわりに
というわけで CircleCI の Trigger Pipeline という機能で任意のワークフローを実行してみました。今回のサンプルプロジェクトのように、デプロイ用のワークフローは社内の承認プロセスを経て手動で実行したいといったご要望は少なくありません。さらに、デプロイ先を staging1, staging2, production というように制御したり、特定のユーザーグループのみが実行できるように制御することも可能です。ぜひご活用ください。