エンジニア2名に聞いた!イタンジのシステム開発(CI/CDについて)
★こちらの記事はエンジニアやPdMなどの方が、イタンジのシステム開発について理解を深める内容となっております★
システム開発において、通常、継続的インテグレーションと継続的デリバリーまたは継続的デプロイのいずれかを組み合わせたプラクティスを指すCI/CD(Continuous Integration / Continuous Deployment)という開発手法が重要視されています。
今回は、10年以上前にエンジニア経験のあるメンバーが、現役エンジニアに対し、現在のシステム開発現場はどのように変化しているのかについて、インタビューしました。イタンジのCI/CDの考え方や実際に行っている内容について、深掘りしていきます!
ーまず、CI/CD(Continuous Integration/Continuous Delivery)とは何かから教えてください。
山崎:
過去に主流だったリリースフローはコードをコンパイル(バイナリーコードなど実行可能な言語に変換)して夜間等のメンテナンス中に手作業で適用し、正常性確認をしたらリリースが完了する流れでした。人力でやっていて大掛かりな作業になるためリリース頻度もあまり多くなかった印象です。
最近は開発してすぐにリリースし、デリバリーできることが求められるようになっています。開発しても世に出していかないと意味がないので、より早いサイクルで回していく必要性が出てきて生まれた開発手法がCI/CDだと思います。
清水:
インテグレーションは「統合」といった意味です。統合するには「このコードってマージしていいんだっけ?」「このプロダクトに適合したコードってなんだっけ?」といったことを自動化して継続的にチェックする仕組みが必要です。
CIは、コード変更を頻繁に統合し、自動的にテストをすることで、バグを早期に発見・修正するプロセスのことで、CDは、CIによって検証されたコードを自動的に本番環境にデプロイするプロセスを示しています。
山崎:
デプロイフローもチームによって違いますよね。
よく使われているのはGitフローとGitHubフローだと思いますが、Gitフローはブランチ(1つのプロジェクトから分岐させ、プロジェクト本体に影響を与えずに開発を行える機能)が、メイン、ディベロップ、フィーチャー、リリース等ブランチが役割によっていくつか分かれており、運用もちょっと複雑ですね。
GitHubフローは、基本的にはメインとフィーチャーのブランチのみで、フィーチャーブランチでテストが通ったら、どんどんマージしてリリースしていきます。
清水:
とはいえチームによっては上記のようなフローに完全に則らずに、独自のアレンジを加えて柔軟に運用しているケースもあります。弊社ではCI/CDのワークフローはCircleCIやGitHubActionsを利用して構築しています。
山崎:
プロダクトによってGitHubフロー、Gitフロー、どちらも使われているのですが、 基本的にはリリース用のブランチにマージした場合、自動でまずCIでテストが動いて、全てのテストが通った後にデプロイが行われ反映されます。
清水:
CIのパイプラインには、プロダクト開発チームは脆弱性診断ツールを入れることが多いと思います。例えば私のチームは、Railsのよくやりがちな脆弱的なコードを事前チェックしてくれるものを入れています。Brakemanといってよく使われているツールです。
ーRailsの脆弱性は、Rails自体が守ってくれるイメージだったのですが、できないことがあるんですね。
清水:
例えば、IDだけを受け取ってリソースを取得するエンドポイントがあると、ID総当たりで全部リソース取れちゃうので、そういったコードは脆弱性としてテストで警告されます。
また、テストとは違うのですが、Rubyだとrubocopというコードを解析してコーディング規約に沿っていないコードを警告、修正してくれるツールがあります。イタンジでは、イタンジ用のルールセットがあります。
ーイタンジ用と言うと、他と何が違うんですか?
清水:
ルールは何百種類もあるんです。その中から、これは違うだろうというものを抜いたり、公式ルールにはないけれど欲しいものを足したりして、カスタムルールを作っています。
今はいい時代なので、ChatGPTに「こういうルール作って」と言ったらすぐ作ってくれますが・・・。コードのレビューは知識の深い人や経験の長い人に集中してしまうことがあり、リソースの不均衡が生まれてしまうので、チームで合意したコーディングルールは積極的にCIに組み込めないかを考えるようにしています。
山崎:
OpenAPIというAPIのドキュメント規格みたいなものがあるのですが、今はそれを静的解析する仕組みを作りたくて。「そのためのリポジトリ(保管場所)を作ってもいいですか?」といった話をちょうど先ほどしていました。
ーテストコード、スタイル、脆弱性診断など、チームごとに考えているんですね。
清水:
そうですね。他の取り組みでいうと、OpenAPIを元にAPIドキュメントを自動生成するステップをCIに組み込んでいるチームもあります。私のチームでは、同じくOpenAPIを利用しているのですが、OpenAPIをもとにコードを自動生成する仕組みも導入しています。そのため開発時に「OpenAPIをドキュメントに反映しコードを自動生成する」コマンドを必ず実行する必要があるので、CIにはドキュメント関連のステップを組み込んでいません。
ー昔、後から入るプロジェクトだと、流れているコードを読んで仕様を理解して、 それを正として開発していましたが今は違うのですね
清水:
長年開発を重ねてソースコードが複雑化、巨大化したプロダクトに自動テストがなかったら何が正しいか分からないので、今後を考えるとかなり厳しいです。テストがあればリファクタリング(プログラムの動作を保ったままソースコードを改善すること)して通ればOKというやり方ができるのですが、テストがないと負債が溜まる一方です。
イタンジも数年動いているプロダクトが多いですし、そのようなプロダクトに今後もエンハンスを重ねていくことを考えるとやっぱりテストは必要です。処理の重要度によってテストの詳細度の強弱はありますが、正常系は少なくとも書いておいた方がよいです。
山崎:
私のチームは結構テスト駆動はやるようにしていますよね。
清水:
バックエンドの処理がメインなのでそうなりますよね。
山崎:
そうですね。通る課題を自分に与えて、それが通るコードを書くこともあります。テストを右の画面で動かしながら、左の画面でコードを書いていくって感じで、結構楽しいです。
ー外部連携のところはスタブ(代用プログラム)を書くから難しいイメージだったのですが、今は楽にできるようになってるんでしょうか?
清水:
がっつりスタブ書いてます。ただ、OpenAPIを書いていると、その型定義に応じたモックは自動生成できます。ドキュメントをちゃんとメンテナンスできていれば比較的スムーズです。
山崎:
私のチームでもスタブを用意するのは少し手間ですがラインカバレッジが低くならないようにテストを書くよう気をつけています。
ー何も書かないよりもテストを書く方がコストがかからないんですか?
清水:
1ヶ月、2ヶ月ぐらいで自動テストを書きつつ開発していくコストと、自動テスト無しに、デグレードなく品質を維持しながら開発を進めていくコストが逆転すると言われています。
山崎:
チーム状況にもよるかと思いますが、新しい人が入ってきた時にはテストがあるかどうかでやりやすさが全然違います。1人の優秀なエンジニアで長くいる人がコミットしているなら、なくても回っていくかもしれないですが、新しい人や新卒が入ってくるのであれば、テストがないとちょっと不安ですね。
ー開発やデリバリーで肝となる考え方はありますか?
清水:
基本的にはアジャイルでの開発なのですが、リリース日?が決まっている大きなプロジェクト開発はどうしてもあるので、そういうところは完全なアジャイルだと厳しいです。ガントチャートなどを使って、ウォーターフォール的?になることもあります。
デリバリーでは、大きな変更を一度に一気に適用することはせず、少しづつ変更を適用することを心がけています。そのために、フィーチャートグルの手法を活用し、適用はするけども機能のON/OFFは別途切り替えることができる形でリリースすることもあります。大きな差分を一気にマージするとなると、精神的にもドキドキするし、もし問題が生じたときに、原因を特定することが難しくなってしまいます。リリースの精神的負荷を下げるためにも、 小さい単位でリリースする必要があります。フィーチャートグルによって、本番環境でのテストが可能になりリリースのリスクを軽減することが可能です。
山崎:
今はコンテナ技術(アプリケーションを動かすための環境を仮想化する技術)があるおかげで、リスクを最小限にできています。
清水:
ECSに頼っていれば、オプションも色々あるので、いい感じにローリングでデプロイしてくれます。
昔と比べるといい時代になったと思います。今、イタンジでは、チームごとに似たようなワークフローを別々で組んでいたりすることもあります。今後はそれらの知見を集合して共通のCIツールなどを開発できれば、もっと生産性が高まるのではないかと思っています。