CircleCIを使ったリリースフローに git-pr-release を導入した話

# 概要

 [CircleCI Advent Calendar 2020](https://qiita.com/advent-calendar/2020/circleci) の7日目の記事になります。

最近めっきり寒くなりましたね。

trocco[^1]ではCI/CDのツールとしてCircleCIを利用していますが
今回 git-pr-release というライブラリを導入し、リリース運用の効率化を試みました。

# 背景と課題

開発チームメンバーが増え、開発スピードが増えて嬉しい反面、
リリースの回数も増えたことで、開発スピードに追いつけず遅れが生じやすくなっていました。
また、当時はmasterブランチへのpushをフックにstagingへのリリースが行われており、
masterブランチに未リリースのコミットが含まれるタイミングがある状態でした。
もちろん、ステージング環境でのチェックをした後、本番環境へのリリースが行われていたのですが、
この状態だと、hotfixなどの差し込みリリースができない状態でした。

# アプローチ

git-flowのような開発・リリースフローへの変更と、
リリースノートなどの状況の可視化の効率化のためにググってみると、**git-pr-release** というツールが
便利らしいということで検証と導入をしました。

# git-pr-releaseについて

- https://github.com/x-motemen/git-pr-release
- コマンドを叩くことで、featureブランチをまとめたrelease用プルリクエストを生成します。

これをCircleCIと組み合わせることでGitHubへのpushや他の操作などと連動し、
リリース用のプルリクエストを生成できるようになります。

# .circleci/config.yml 内容

git-pr-release は RubyGemとして提供されているので、 imageを `ruby` とし、
stepsでは `gem install` した後 `git-pr-release` コマンドを実行します。

```yaml
# .circleci/config.yml
jobs:
  # ...
  git-pr-release:
    docker:
      - image: circleci/ruby:2.5.8
        environment:
          # featureブランチをmergeする先のブランチ名
          GIT_PR_RELEASE_BRANCH_STAGING: "release"
          # production環境へリリースするブランチ名
          GIT_PR_RELEASE_BRANCH_PRODUCTION: "master"
          # リリース用pull-requestに設定できるラベル
          GIT_PR_RELEASE_LABELS: "release確認"
          # プルリクエストのdescriptionに記入される内容のテンプレートファイル
          GIT_PR_RELEASE_TEMPLATE: .github/GIT_PR_RELEASE_TEMPLATE.md 
          DEBUG: true
    steps:
      - checkout
      - run:
          name: Gem Install
          command: gem install -N git-pr-release
      - run:
          name: Create PR
          command: git-pr-release --no-fetch
```

また、workflowsではフィルタ機能を使うことで`release`ブランチへの操作のみ、 
git-pr-releaseのジョブが実行されるように設定しました。

```yaml
# .circleci/config.yml 続き
workflows:
  ci_cd:
    jobs:
      - test
      # ...
      - git-pr-release:
          filters:
            branches:
              only:
                - release
```

# プルリクエストテンプレートのカスタマイズ

デフォルトの場合は以下のようなテンプレートで出力されます。
eRuby（ERB）形式のテンプレートなので、Rubyのスクリプトを埋め込み自由にカスタマイズできます。

```erb
Release <%= Time.now %>           <%# 1行目: プルリクエストのタイトル %>
<% pull_requests.each do |pr| -%> <%# 2行目以降が description に展開される %>
<%=  pr.to_checklist_item %>      <%# チェックボックス付きのfeatureプルリクエストが一覧表示される ex) - [ ] #1234 xxx機能の追加 @mension %>
<% end -%>
```


trocco開発チームでのリリーステンプレートでは、

- CircleCIジョブ履歴ページへのリンク
- 各featureブランチのステージング最終チェック担当者の割り振り
- featureブランチのプルリクエストにラベルを設定しておくことで、リリースプルリクエストの一覧にもラベルを表示

ような内容を書いています。

※ 詳しいカスタマイズ内容は先月 [Nagano.rb#6](https://naruby.connpass.com/event/193411/) のLTで紹介させていただきました。LT資料は[こちら](https://speakerdeck.com/u110/git-pr-release-nagano-rb-6-2020-11-28)


# その他

- featureブランチのプルリクエストは元々masterブランチを指して行っていましたが、
このツールを導入することで、releaseブランチを指して行うようにしました。
  - GitHubではベースブランチを指定できるため、プルリクエストを作成するときもデフォルトでreleaseブランチを指すようにでき、
開発者が作業を変える必要はありませんでした。(ここ重要！


# 導入後の開発・運用の変化

- リリース対象の featureプルリクエストが、一覧で表示（チェックボックスも設定されている）されたことで、
最終チェックの割り振りや確認状況がリリースプルリクエストにまとまり、状況がわかりやすくなった。
- hotfixリリースは（他のリリース対象のブランチを意識せず）直接masterブランチへのプルリクエストを作成することで実施できるようになった。

# まとめ

- CircleCIを使ったリリースフローに git-pr-release を導入しました。
- git-flowライクなリリース運用にスムーズに切り替えることができた。
- チェック状況や役割分担が可視化できたことで、効率よくリリースができるようになった。

これからもCircleCI使い倒していこうと思います。

[^1]: 私たちが開発、運用している分析基盤のためのデータ統合サービスです。 https://trocco.io/lp/index.html