Help us understand the problem. What is going on with this article?

“Beyond the Twelve-Factor App” & “The Twelve-Factor App”から学びAWSで実践する (1)1つのコードベース、1つのアプリケーション / コードベース - バージョン管理されている1つのコードベースと複数のデプロイ

解説

本ファクターでは、アプリケーションのソースコードの管理方法、デプロイの考え方を述べています。

  1. アプリケーションはバージョン管理されたリポジトリに単一のコードとして管理されていること
    ようするにGitでソースコードを管理しましょうということです。ソースコードの変更がきちんと管理されているというのがアプリケーション開発の出発点になります。企業やチームで開発する場合はもちろんですが、個人で開発する場合も必ずバージョン管理ツールを使いましょう。ソースの修正は意図をもって行い、その意図が記録されているという状況が健全です。

  2. アプリケーションは単一のコードから複数の環境にデプロイされること
    アプリケーションをデプロイする場合には、管理されているコードから実施しましょう。デプロイは開発用、テスト用、ステージング用、プロダクション用といったように様々な用途で複数の環境に展開することができるようにしておく必要があります。なお、単一のコードといっても、同じバージョンのコードがデプロイされている必要はありません。バージョン管理されているコードのどの部分からでも、好きな環境にデプロイできるようになっているべきです。例えば、プロダクション環境はテストがすべて完了したコードのバージョンでデプロイするべきだし、開発やテスト用の環境には新規に追加した機能を含んだコードからデプロイすることになるでしょう。

  3. 一つのコードから複数のアプリケーションを生みださないこと
    一つのコード管理の中に複数のアプリケーションを入れるのはやめましょう。具体的には、複数の起動スクリプトやmain関数などが単一のコードに入っていることを禁じています。この状態は複数の開発チームが単一のコードに対してメンテしている状態になっていることを示しているという指摘です。この状態では他にも、異なるライフサイクルのアプリケーションが一つのコードに入っているということになります。あるタイミングのソースコードはアプリ1はプロダクションレベル、アプリ2が開発中というような状況になると適切なバージョン管理ができません。このようになっている場合には、アプリケーション毎にそれぞれリポジトリを用意し別々に管理することを始めましょう。ソースの分割に当たって、共通ライブラリ的な部分があれば、これも別のリポジトリで管理し分けて管理していきます。
    Beyondの中では、さらにコンウェイの法則(組織やチームの構成はソフトウェアアーキテクチャに反映される)に関してもここで触れています。アプリケーションを適切な単位に分解しマイクロサービス化することを提唱しています。モノリシックで大きなシステムが一つのコードとして管理されている場合、この時も一つのリポジトリで多くの開発チームが同時に作業をしていることでしょう。たとえ複数のアプリケーションを生みだしていなくても結局は同じ状況になります。それを解消するための方法論としてマイクロサービスとなります。これは先ほどの分割よりは大変でしょうが、継続して開発を続けていく上では必要なリファクタリングです。

実践

Gitを使ったソースコードの管理手法

世の中には多くのGit互換のリポジトリが存在します。最も有名なのがGitHubです。他にも、BitbucketGitLabといったパブリックサービスが存在します。使い勝手はそれぞれでしょうが各チームの事情に合ったものを選択してよいと思います。個人で利用する場合でも必ずこういったリポジトリを利用しコードの管理をしましょう。なお、古い体質の日本企業だと「パブリックサービスにソースを預けるなんて」となり簡単には使わせてもらえないこともあるでしょう。その時はGitLabを独自で運用するという選択が現実的かもしれません。また、AWSを使ったサービスの開発を行っているのであれば、CodeCommitを使ってしまうのもありかもしれません(グレーゾーンですが・・・)。

Gitの運用ワークフロー

Gitを運用する上で、ワークフローを決める必要があります。有名どころは、Git Flow、GitHub Flow、GitLab Flowといったところです。開発の現場に合わせたフローを導入すれば良いですが、筆者としてはGitHub Flowをおすすめします。この中では最もシンプルでわかりやすく、普段の開発をスピード感を持って進められます。あまり複雑な手順を開発チーム全員に理解してもらうのは導入コストがかさみますし、複雑なフローは日常の開発でストレスがたまります。GitHub Flowだと開発者にとっての手順は非常に簡単です。デプイに関しては少し工夫が必要かと思いますが、開発のコミットの方がデプロイの回数よりも圧倒的に多いですし、開発作業に携わる人よりもデプロイを担当する人のが少ないのが一般的なので複雑なことをやる人が全体では少なくなります。普段の開発しやすさを重視するのがチーム全体としてはプラスになるのではないかと思います。

GitHub Flow 1.jpg

上がGitHub Flowの簡単な模式図です。GitHub Flowのポイントをまとめると以下になります。

  1. masterブランチ を常にデプロイ可能な状態に保ちます
  2. 新しい何かを始めるときには、masterブランチから説明的なブランチ(feature-X、bugfix-Yといった、何を目的にどんなことをやっているのかがわかるブランチ)を作成して作業を行います
  3. 作業ブランチへのコミットに対して意見をもらいたい場合や、masterブランチにマージしてもらいたいときにはプルリクエストを作成しレビュアーに送ります
  4. レビュアーはプルリクエストに対応して、コードをレビューしmasterブランチにマージします

変更するたびにブランチを作り、変更をすぐに''master''ブランチに反映してしまうモデルです。開発者は''master''ブランチからブランチを作って開発し、''master''ブランチにマージするという作業をひたすら繰り返すとこになります。
この時最も重要なのは''master''ブランチを常にデプロイ可能な状態に保つというところです。masterブランチに変更をマージするときには、ソースコードのレビューだけでなく、きちんとテストを通してから行うことが必須になります。マージリクエスト実施時やマージ時などにCIでテストが自動で動くようにしておく必要があるでしょう、これができていないとmasterブランチがビルドできなくなったり、まったく動かなくなったりすることになるのでこのGitHub Flowの大原則が破綻してしまいます。

デプロイスクリプトの管理

デプロイは当然自動化のためのスクリプトを用意することになると思いますが、ソースコードのmasterブランチが常にデプロイ可能ということは、どのタイミングのmasterブランチでもデプロイできるようになっている必要があります。デプロイのためのコードもソースコードと一緒に管理することが理想だと思います。なお、デプロイをJenkinsを使って実施するといつ構成はよくあるのですが、Jenkinsジョブ自体をこのソース管理と一緒にバージョン管理をするのは結構難しいです。デプロイスクリプトに与えるパラメータに非互換の変更を入れてしまったりすると、XXバージョンまでのデプロイ用ジョブと、XXバージョン以降のデプロイ用のジョブといった形になってしまうことがあります。これは広義の意味で単一のリポジトリでバージョン管理されることを破ってしまっているので。Jenkinsのジョブに修正が必要になるような変更があったとしても過去のデプロイスクリプトが動作するのかといったことはケアするとよいでしょう。

様々なバージョンのデプロイ

GitHub Flowであれば、デプロイは常にmasterブランチの成果物から実施されることになります。日本メーカのように品質保証部門でテストをし品質を担保してから市場へリリースするといった製品ライフサイクルを持つ場合、いくつかの例外ケースでGitHub Flowがはまらないところが出てきます。ここでの話は、組み込みやパッケージといったソフトウェア製品を前提とした製品ライフサイクルがクラウドサービスの開発にも適応されているような現場での話になりますので、いつでも当てはまるわけではなく限られた条件下での話なのでご了承ください。

前提条件

  • 市場へのリリースには、品質保証部門がテストを行い問題ないことを確認したのち行われる(裏を返すと品質保証部門のテストが実施されていないアプリケーションはリリースしてはいけない)
  • 第三者(品質保証部門)によるテストが実施されているので品質は高く市場での障害発生頻度は低い
  • 製品のリリースサイクルは長く、典型的なウォーターフォール開発である

次々バージョンの開発開始

次バージョンの実装は完了し、品質保証部門での評価が行われている途中から次々バージョンの実装が始まることはよく発生します。この場合masterブランチの状態は品質保証部門へ投入したもの、もしくは品質保証部門で発見された障害に対して修正を行ったバージョンとなります。次々バージョン向けの修正が次バージョン向けの製品に混入することはプロセス上許されないので、masterブランチへの次々バージョン向け実装のマージは許されません。ずっとブランチのまま実装をマージせずに放置するのも開発効率という点で良いことがありません。この場合。GitHub Flowの原則を少し破り、一時的に次々バージョンの開発のためにブランチを増やして対応します。下の図で示したV2.0ブランチがそれにあたります。このブランチのライフサイクルは短く、次バージョンであるV1.1のコードがFixするまでの間の短期的なものになります。この期間だけは複数バージョンの平行稼働が行われます。なお、masterブランチのモジュールは品質保証環境に、V2.0ブランチのコードは、開発環境へデプロイするといったこともできるようにしておく必要があります。
なお、逆パターンとしてV2.0を始めざるを得ないタイミングで_V_1.1__側をブランチしてmasterブランチを次々バージョンの開発とする手もありますがGitHub Flowの原則を考えると前者の方法の方が良いと思います。(master`ブランチが最も安定しているバージョンで、次々バージョン用の説明的なブランチがある状態)

障害発生時の対応

次バージョンの開発中にすでにデプロイ済みの現行製品で市場障害が発生した場合の対応です。障害が致命的な場合、直ちに現行バージョンを修正して修正版をリリースする必要があります。評価が完了していない次バージョンがコミットされている''master''ブランチからリリースすることは当然許されません。この場合、一時的なブランチを追加します。下の図に示したV1.0.Xブランチがそれにあたります。このブランチのライフサイクルは現行バージョンに障害が出てから、次のバージョンのリリースが完了するまでです。障害が発生し、急ぎで修正が必要な場合のみなので、障害の少ないプロダクトでは、このブランチは多くの場合存在しないことになります。なお、一度このブランチを作成したらそれは破棄するのではなく、V1.0の障害対応版であるV1.0.1を市場投入した後もV1.1リリースまではブランチを維持しておきます、万が一次の障害が発生したら、このブランチをもとに開発を行いリリースします。

GitHub Flow.jpg

まとめ

最初のファクターとして、アプリケーションのソースコードの管理方法、デプロイの考え方をGitHub Flowを前提において話を進めてきました。AWS色がほぼない記事になってしましたが、このファクターの内容では無理にAWSを利用しなくても良いと思います。

次回は「(2)APIファースト」です。
本シリーズの目次
全シリーズの目次

makotomi
サーバーサイドエンジニアをメインに長いことAWSでサービス開発の仕事をしています。EC2でのWebアプリ開発も、Lambdaを使ったサーバレス開発もどちらも経験。フロント系はあまり得意じゃないですが、AngularJSとReactあたりは多少かじっています。
https://www.makotomi.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした