CircleCIを使ったDeploy Workflowパターン集

この記事は[CircleCI Advent Calendar 2019](https://qiita.com/advent-calendar/2019/circleci)の4日目の記事です。

プライベートや業務で使っているいるCircleCIのDeploy Workflowパターンを紹介します。

* Merge即ちDeployパターン
* Workflow Approvalパターン
* Tag Releaseパターン
* Deploy Botパターン

Merge即ちDeployパターン
---

master branch等にmergeしたのをフックに自動でデプロイする方法です。
手軽なので、プライベートで雑にデプロイしていいやつはこの方法を採用しています。

```yaml
workflows:
  version: 2
  deploy:
    - build:
        branches:
          only: master
    - deploy:
        requires:
          - build   
```

Workflow Approvalパターン
---

master branch等にmergeしたのをフックにデプロイのWorkflowは発火するものの、デプロイまでは自動でやらず、CircleCIのWorkflowの画面で承認ボタンを押すとデプロイがされます。小さいチームで「mergeされたら自動でProductionにデプロイされるのはちょっと・・・」というときや、feature branchを検証環境にデプロイしたいときに便利です。
承認フローは[CircleCIのApproval](https://circleci.com/docs/2.0/configuration-reference/#type)を使います。

また、デプロイの準備ができたら通知してほしいので、SlackにWorkflow画面へのリンクを送ってくれると便利ですよね。
`circleci/slack`というorbを使うと、簡単に実現できます。（欲を言えば、Slackから承認ボタンを押したら承認できるようにApproval APIが欲しい）
https://circleci.com/orbs/registry/orb/circleci/slack

欠点としては、排他制御ができないので、関係者が増えると、デプロイ中にうっかり違うデプロイが走りはじめる...ということが起こりうります。

```yaml
orbs:
  slack: circleci/slack@3.4.1

workflows:
  version: 2
  deploy:
    - build:
        branches:
          only: master
    # デプロイの準備ができたことをSlackに通知する
    # 環境変数 SLACK_WEBHOOK にWebhookのURLをセットすること
    - slack/approval-notification:
        requires:
          - build
    # 承認するまでデプロイしない
    - deploy-approval:
        type: approval
        requires:
          - slack/approval-notification
    - deploy:
        requires:
          - deploy-approval   
```

feature branchを検証環境にデプロイするも非常に簡単で以下のサンプルのような感じになります。
承認するまでデプロイされないので、デプロイしないときは放置するだけです。
毎回pushするたびSlack通知されてもウザいので、面倒ですが、Workflowに自分で見に行って承認するパターンにすることが多いです。

便利な一方、デプロイまでしないとGitHub Pull Requestのステータスチェックは途中を示す丸マークのままなので、気持ち悪さもあります。（検証環境にデプロイして、ちゃんと検証すればいいだけの話ですが）

```yaml
workflows:
  version: 2
  feature:
    - build
    - test
    - lint
    - deploy-approval:
        type: approval
        requires:
          - build
          - test
          - lint
    - deploy:
        requires:
          - deploy-approval   
```

Tag Releaseパターン
---

GitのTagを切ったのをフックにデプロイするパターンです。
Workflow Approvalパターンと同様、mergeとリリースを分けられる、リリースをGitのTagでも管理できるのがいいところです。

```yaml
workflows:
  version: 2
  deploy:
    - build:
        branches:
          filters:
            branches:
              ignore: /.*/
            tags:
              only: /.*/
    - deploy:
        requires:
          - build   
```

Deploy Botパターン
---

Botにデプロイを命令して、Botがデプロイ用のブランチを切ってpush、Workflow側はデプロイ用のブランチにpushされたことを検知してデプロイするパターンです。
Botに状態管理をさせることで、デプロイ中に新しいデプロイがされるのを防げます。
また、同じ原理でロールバック用のWorkflowも作れます。

```yaml
workflows:
  version: 2
  # Botがdeploy branchをpushすることで発火する
  deploy:
    - build:
        branches:
          only: deploy
    - deploy:
        requires:
          - build
  # Botがrollback branchをpushすることで発火する
  rollback:
    - rollback:
        branches:
          only: rollback
```

おわりに
---

他にもパターンとかありそうだなと思いつつ、自分が触れたことのあるパターンのみ紹介しました。
個人的にはWorkflow Approveパターンは気に入っていて、他のCIではなかなか実現しづらいパターンなのかなと思っています。

説明を簡単にするために省略しましたが、デプロイを始める前後に[circleci/slack](https://circleci.com/orbs/registry/orb/circleci/slack)を使って通知をしてあげたり、`slack/status` commandを使ってデプロイに失敗したら通知するようにしてあげると、より充実したDeploy Workflowに育つのでおすすめです。