GitHubとJIRAでリリース管理


GitHubとJIRAでリリース管理

どのチームになっても最初に苦労が見えるのはリリース管理だったりします。

  • 次のリリースいつだっけ?
  • これいつリリースしたっけ?
  • この機能っていつリリースされるの?

要件定義からリリースまでのフローとその内容がきっちり管理されていないとよくある話だと思います。
今回は、以前いたチームで数年間運用方法を殆ど変えなかったやり方を紹介します。
うまくいっていたから変えずに済んだのだと今更ながら思ったので。

この記事はサーバーサイドエンジニア目線です。
他の職種の方が見た場合に気分を害すこともあるかと思いますが、悪意は無いので怒らないで優しく指摘してもらえると嬉しいです。

参考にしてもらえると嬉しい方々

  • 短期間で定期的にリリース作業がある(1〜2週間に1回くらい)
  • 機能開発/改善を定常的に行っている
  • 少人数のチーム(だいたい20人位まで)
  • JIRAとGitHub(GHEやGitLab含む)を使っている

今回は毎日小さなデプロイを何回もしているといった運用の話では無いです。
超有名なサービスで「マイクロサービス何十個もあるぜぃ♪いぇい♪」的な大所帯チームや、
「何となく作って『えぃ、やぁ!』でデプロイしてるし」みたいな方々はあまり参考にならないかもです。

JIRA編

1. リリースサイクル

定期的にリリースするなら毎週水曜日、みたいに決めておいた方が色々計画が立てやすいです。
でもリリースサイクルとスプリントは必ずしも一致しなくても良いと思います。

2. 要件定義

常日頃プランナーやディレクターは決まっている戦略やKPIと睨めっこしながら、次のことをリストアップします。

  • やりたいこと
  • 何故やりたいか
    • どのKPIでどれだけの改善が目的なのか
    • 戦略に沿った一手であるか
  • いつまでにやりたいか

3. 開発項目の洗い出し

出てきた案にそって、費用対効果や期限を考慮し優先度をつけていきます。
そしてそれを開発項目毎に落としていきます。
この時に

  • どの担当の作業が必要か
  • それぞれの担当工数
  • リリース希望日

とかも洗い出せていると、この先の話がスムーズに進みます。
なので、開発ディレクターはエンジニアやデザイナーとこのフェーズで軽く相談しておくと良いと思います。
このタイミングでエンジニアやデザイナーから逆提案されることもあるので、一番建設的なフェーズだと個人的には思っています。
この時のチーム内の職種はこんな感じでした。

  • デザイナー
  • Androidエンジニア
  • iOSエンジニア
  • フロントエンドエンジニア
  • サーバーサイドエンジニア

そして整理された項目をJIRAチケットに起こします。
JIRAチケットには要件を詳細に書いておきます。

4. スプリントキックオフ

来る1週間、もしくは2週間でできることをエンジニアやデザイナーは項目に沿ってJIRAチケットに起こしていきます。
この時起こしたJIRAチケットは次のルールで作成し、今回のスプリントに登録します。
今回のスプリントに入りきらないものは、次のスプリントやバックログに登録します。

4.1. タイトルにコンポーネントを入れる

ServerとかFrontとかiOSとか。
コンポーネントも別途設定しますが目的が違うので、タイトルにも設定していました。
理由は後述します。

4.2. コンポーネントを割り当てる

これもServerとかFrontとかiOSとか。
JIRAのボードでグルーピングしたり検索する際に役立ちます。

4.3. is child task ofとして関連付ける

のような名前だったと思うのですが、事前に発行されたチケットの関連チケットとして親子関係にしておきます。
サブタスクではないです。JIRAのサブタスクはスプリントを跨げないので使いませんでした。
JIRAの設定上この種のリンクが無い場合は単純にrelated toとかで良いと思います。
但しチケットの上限関係はわかりやすくしておくために、関連付け方向は一方向に統一した方が良いですね。

4.4. 作業見積もりを入れる

何となく大変さをアピールできます。
あまり細かい見積もりはいれず、0.25日単位とかにしてました。1時間で終わる内容でも0.25。

4.5. 担当者を設定する

その職種が複数いる場合は職種リーダーが中心になって決めます。

4.6. 修正バージョンを設定する

それがいつリリースされるのかを宣言しておきます。
リリースできそうになかったら、周知の上バージョンを付け替えたりします。
リリースバージョンは成果物のまとまりと1:1になるようにJIRAでリリース日と併せて登録しておきます。

  • フロントの1.5.0
  • サーバーサイドの3.2.0
  • Androidの2.1.0
  • iOSの3.1.0

みたいな感じで。

4.7. チケット内容にメモでも何でも書いておく

殆ど担当者本人しか見ないと思うので、メモでも何でも記しておきます。
恒久的に参照したい内容なら別途Wikiに書いてリンクしておきます。

5. 実装開始

後はチケットを消化するだけです。
PRレビューが終わりマージまでされたら、チケットを「Resolved」または「Close」します。
個人的にはリリースされたタイミングで「Close」にしていましたが、リリースが次のバージョンに回されたり、そのチケットの作業はそのスプリントで終わる予定でもリリースが更に先だとスプリントを跨いでしまうので、適当なタイミングで「Close」にした方が良いかもしれません。

6. リリース

各自リリース作業して終わりです。
簡単なリリースノートはConfluenceでJIRAのバージョン選択して自動生成します。
これはGitHub見れない人用のリリースノートです。

GitHub編

とここまでは主にJIRAのお話でした。
次からはGitとGitHubの方のお話です。

1. ブランチ運用

これが個人的には超絶うまくいったと思っていたりします。
問題点もありましたが。。

基本的には以下のブランチで運用します。

ブランチ名 役割 作成元 マージ先
master アーカイブ目的。
基本的にはproductionと同じ。
- -
develop (default) 開発ブランチ。
ここへはPRレビュー無しにローカルで動作確認が済んだら他の人に確認してもらう目的でどんどんマージしてOK。
ただし、直接コミットは無し。
- -
staging_{version} ステージングブランチ。
このブランチへのマージはPRレビューでOK出ないとマージされない。
master, stating_{version} production
production テストを全て終えたstaging_{version}ブランチのみがこのブランチにマージできる。 - master
feature/{ticket_id}_{feature name} 機能開発用ブランチ。この単位でPRを出す。 master develop, stating_{version}
fix/{ticket_id}_{bug} バグ修正用ブランチ。この単位もPRを出す。 master develop, stating_{version}
hotfix/{ticket_id}_{bug} 緊急バグ修正用ブランチ。この単位もPRを出す。 master develop, stating_{version}

ブランチ名のプレースホルダー

ブランチ名にあるプレースホルダーの内容です。

プレースホルダ 説明
version リリースバージョンです。
タグもこの名前で切ります。
ticket_id JIRAチケットのIDです。
プロジェクトコードと番号で形成されていると思います。
JIRAとGitHubを連携している場合はJIRAのチケットにPRへのリンクが出現するので便利です。
feature name 機能名です。端的に表現しましょう。
僕は英語苦手なので長くなること多かったです。。
短く表現するとカッコイイです。
bug 悲しくもバグは発生するものです。
バグの内容を端的に表現しましょう。

1.1. バージョンの運用方法

majorバージョンはチームで足並み揃えて気分で上げれば良いと思います。
minorバージョンは定期リリースでインクリメントしていきます。
buid numberは不定期なバグ修正リリースでインクリメントしていきます。

1.2. 緊急リリースでもJIRAチケットを発行する

緊急でもリリース履歴を残すべきです。
JIRAでバージョン作ってチケット切って、staging_{version}ブランチとhotfix/{ticket_id}_{bug}masterから作って作業しましょう。

PR後、マージが終わったらステージングで確認してからproductionにマージしてリリースです。

1.3. リリース後はmasterにマージする

masterをあらゆるブランチ元にしていたので、リリース後はproductionmaster にマージします。
この時、必ずfast forward mergeになるはずなので、そうでなかったら差分を確認した方が良いです。
そして、更に進んでいるdevelopstaging_{version}にもmasterをマージしておきます。

1.4. 意外に便利なstagingブランチの使い捨て

バージョンごとに切ることによって機能単位のリリースバージョンの延期や前倒しがスムーズにできます。
但し、Revertコミットの伝染は要注意です。本当は適切にその機能のコミットをdropした方が良いと思いますけどね。
まぁ、masterからstagingにマージする際はRevertコミットが含まれていたら注意するくらいで大丈夫だと思います。

1.5. developブランチを定期的にクリーンアップする

developmasterともstaging_{version}ともproductionとも交わることはありません。
独自で進んでいきます。
これをそのままにしているとコミット履歴が他のブランチと違いすぎて、次の問題が出てきます。

  • developだけコンフリクトする
  • リリースしたと思っていたのにdevelopにしかマージされていなかった

これを防ぐためにリリース後、もしくは何回かのリリースに1回はmasterブランチと同期させます。

$ git checkout develop
$ git fetch origin
$ git reset --hard origin/master
$ git push origin develop -f

これをやると、未リリースのものがdevelopブランチからいなくなります。
そこで、「あぁーー、これ今作ってる途中なのにー」とか「あれ?これずっと前にリリースしたと思ってたんだけど無くなってない?」みたいな苦情がチラホラ聞こえてくることもあります(笑)
ここでGitHubのブランチ一覧画面です。
developブランチに対して進んでいるコミットがあれば、最終コミッターに確認しdevelopにマージしていきます。
全てマージが終わればpushしてdevelopが動いている環境にデプロイしておきます。

問題は「あれ?これずっと前にリリースしたと思ってたんだけど無くなってない?」とか言い出すやつです。
developが動いている環境しか眼中に無いとこうなります。
でも、これもmasterと同期を取ることで判明するので、悲劇ではありますが早めに把握して対処することが重要です。

あと、feature, fix, hotfix, stagingブランチはリリースされたら削除します。
ブランチ一覧のページが長くなってしまうので。

また、masterを更新したら一度masterをデフォルトブランチに変更して未リリースブランチが認識済みであるかをチェックしておきます。
チェックが終わったらまたdevelopブランチに戻しておきます。戻さないと他のメンバーから「GitHub上でcompreしづらい!」と怒られます。

2. Pull Request

2.1. stagingブランチにPRを出す

  • 期限
  • Reviewer
  • Milestore(version)

を設定します。マイルストーンも検索用途です。
またdevelopへのPRと区別するためにstagingラベルもつけていました。

2.2. 不安ならdevelopにPRを出す

不安なら後戻りが多くなる前に不完全でもdevelopにPR出して実装内容を確認してもらいます。

3. タグ&リリースノート

リリース後はタグを切ります。
コマンドでやりません。
GitHubのリリースノート機能を使います。
まずJIRAでそのバージョンを「リリース済み」にします。
この時に終わっていないチケットがあれば、JIRAに怒られます。
現在どうなっているか確認して対処しましょう。

次にそのバージョンのリリースノートページに遷移します。
HTMLで出力されているのでそのままコピーして、GitHubのリリースノートに貼っつけます。
リリースノートをPublishするとリリースノートの出来上がりです。
ここでJIRAのタイトルにServerとかFrontとか入れている効力が発揮されます。
サーバーとフロントで同じリポジトリでやっている場合、成果物は同じになります。
ただ、APIはリリースされたけどフロントからのつなぎこみはリリースされていない等は、これにより判断が可能になります。
別リポジトリの場合は気にしなくて大丈夫です。

このリリースノートはJIRAチケットへのリンクがあります。
そこからPRへのリンクへも辿れるので、ここで全て繋がります。
単純にPRだけで見たいときはマイルストーンとラベルで絞り込めばリリース内容がPRの一覧で作れます。

GitHub運用の問題点

この方法でもいくつかの問題点はありました。

developのクリーンアップ後のマージ作業が大変なときがある

コンフリクトの嵐にぶつかった場合は悲惨です。
頑張って解消していきます。

機能間の依存関係を解消しながら開発するために開発前後でコミットの操作が多少必要なときもある

事前に開発していたAPIが未リリースだが、それを使った別機能の実装とかしている場合は、動作確認でAPIのブランチをマージしてから開発してたりします。
だけどPRにそれのマージコミットまで入ってしまうので、PR前にrebaseしたりcherry-pickしたりでコーディングよりコミット操作に時間を割いてしまうこともチラホラ。。

緊急バグリリースがある場合は一時的にステージング環境が奪われる

これはブランチの問題より環境をどれだけ用意できるかの問題ですかね。
サーバーサイドの話ですが、stagingブランチが複数あって環境が一つしか無い場合は必然的に直近のリリースバージョンが当たっています。
しかし別バージョンのテスト中に緊急バグ修正リリースバージョンを当ててテストしたりした場合に、ステージングを使って次期機能の開発をしているアプリエンジニアが困ってしまいます。

まとめ

JIRAとGitHub連携して、ちゃんとバージョン管理したら幸せになれます。
リリースノートはあんまり頑張って書かないで、JIRAチケットを頑張って書きましょう。
画面キャプチャーも無くすみません。

(初めてコードが無い記事を書いた。。)