読者です 読者をやめる 読者になる 読者になる

pixivの開発・デプロイ環境の変遷(2014年春版)

f:id:devpixiv:20140325045217p:plain

こんにちは。最近社内で「実践F#」読書会を始めた@edvakfです。関数型言語というだけで特に理由なくF#を選んだのですが、弊社のウェブエンジニアの方々がF#にまったく興味が無いことを痛感しました。目下少数精鋭で進行中です。

さて、F#読書会とは別の曜日になりますが、pixivというアプリケーションを開発する上でのプロダクティビティを上げることを目指した「エンジニアリングプロダクティビティ向上ハッカソン」を2013年の後半から始動し、かれこれ半年近く続けています。

昨日 Immutable Infrastructure Conference #1 に参加してきたので、今日はpixivの開発環境やデプロイ環境がこの1年でどう変わったかを振り返ってみたいと思います。

2012年まで

僕が入社した2012年はちょうどsvnからgitへの移行期でした。pixivにはPC版ウェブサイトであるwww.pixiv.netやスマホ版のtouch.pixiv.netなど、いくつか同じデータを扱うアプリケーションがありますが、まだsvnだったPC版のモデル層以下のディレクトリが別のアプリでgit-svn経由でsubmoduleとして使用されているという混沌とした状態でした。

このような状況だったため、PC版のリポジトリのgit移行に際してコントローラ層とモデル層で別のリポジトリになったのは当時としては自然な発想だったのだと思われます。(submoduleをこのように使ったことがある方は分かる思いますが、同じ単位の変更なのに別のリポジトリへのコミットになるのは悪でしか無いです)

デプロイはデプロイ用サーバを経由してアプリケーションサーバにrsyncされていましたが、デプロイ用サーバには手動でscpしていました。(読者の皆様の予想通り、みんな怖いので自分が弄ったファイルだけをscpし、その結果リポジトリとの差分が日常的に発生していました)

デプロイのrsyncは社内のウェブの画面からボタンを押して行っていましたが、様々なアプリケーションをデプロイできるように手が加えられていったためとてもカオスなコードになっていました。

当時からデプロイツールを刷新する予定はあったのですが、アセット用ディレクトリが複数リポジトリで同時に(または別々に)管理されているという状況だったのが足枷となっていました。

f:id:devpixiv:20140326033422p:plain

デプロイサーバへのscpツール

「もうすぐ刷新するから今だけでもデプロイの負担を減らしたい」との思いで、ちょうど去年の3月頃に、デプロイサーバへのscpを簡略化するツールが誕生しました。

手元のブランチとorigin/masterとの差分があるファイルだけをscpするというものでしたが、submoduleのdiffも見るようにしたり、すべてのプロジェクトで使えるようにしたり、アセットは別ディレクトリにscpするようにしたりで、気がつけば意外と手の込んだツールになっていました。

手動ですべての変更のあったファイルをscpしていた頃に比べると、これでも劇的に簡単になっていました。

gitリポジトリ統合

2013年の9月頃に、同じライブラリをsubmoduleにしているリポジトリを全て統合して一つのリポジトリにしました。

上にも書いたようにsubmoduleは悪です。(正確には、疎結合なライブラリ以外で使うのは悪です)

それ以外のモチベーションとしては、モデル層が複数のアプリケーションで別々にsubmoduleとして使われていたため、デプロイされて動いているバージョンも複数あったということです。このため、全プロジェクトに影響するようなモデル層の変更の場合はすべてのアプリケーションを同時に(あるいは連続して)デプロイする必要があり、手間でもありましたし、一旦このフローを始めるとリバートが恐ろしく面倒だというコストもありました。

リポジトリ統合を進めるにあたっては、アセットのディレクトリの整理や、submoduleが無かった時代にPC版pixivからフォークしたプロジェクトで過去の同じライブラリのコピーがまるごと生き残っていたのを撲滅したりもしました(複数…)。

gitのリポジトリ統合についてはqiitaに別途掲載したのでご参照ください。

git pull デプロイ

このような地道な負債解消によって(特にアセットの整理によって)、「デプロイサーバでgit pull --rebaseしてデプロイボタンを押す」という、少し前からすると画期的なデプロイ方法が取れるようになりました。

これによってデプロイされているファイルが常にorigin/masterと同じであることがようやく保証されるようになりました。

この頃から、かねてよりやりたかった、デプロイする度にタグを打つ(git tag $(date +%Y.%m.%d.%H.%M.%S).$USER)というのをするようになりました。tigで履歴を見るときにデプロイバージョンがひと目でわかるのでオススメです。

現在

という道のりを経て、ようやくカオスなデプロイツールを捨てられるようになりました。

これまでは全プロジェクトのデプロイを一つのツールでやっていたのですが、これを卒業し、デプロイ用スクリプトを各リポジトリ内に持つようにしました。

Capistranoやminaを使うことも考えたのですが、所詮PHPのアプリケーションのデプロイでやることはセットアップスクリプトを実行してrsyncするだけなので、自作することにしました。

特徴的な点としては、デプロイスクリプト以外にデプロイ用のindex.phpがある点です。これまでデプロイサーバというものがありウェブ画面でボタンをポチっと押すデプロイ方式だったので、そこからの大幅な変更はひとまずやらずに、画面というものを残しました。index.phpには確認すべきリンクやリポジトリの最新コミットなどが表示されています。みんなが手元でcapを打つより画面からできる方が負担が少なくていいと思います。

f:id:devpixiv:20140326033425p:plain

おわりに

pixivの開発やデプロイで個人的に大切にしていることは、普段からpixivを開発しているチームでなくても誰でも簡単に触ってデプロイできることです。(社内の全員が同意見ではないかもしれませんが)

iOSエンジニアがAPI側の修正をすることもありますし、デザイナーやディレクターもgitの基本的な操作が使えればデプロイできます。

(2012年とかの時代からこのデプロイ方式に付いて来られたディレクターさんがすごいのかもしれませんが…)

このようにしてpixivでは毎日平均20回程度のデプロイを繰り返しています。2014年もさらにこの辺りは進化させていきたいと思っています。

実践 F# 関数型プログラミング入門

実践 F# 関数型プログラミング入門