皆様こんにちは !
Wantedlyのインフラチームインターンの大坪です。
今回は私がWantedlyのインフラチームで「エンジニアのUXを上げる」取り組みの一環として携わった「環境構築を早くする」課題とその成果について書いて行こうと思います。
環境構築にかかる時間
何か新しい開発を始めようとするとその環境構築で時間が取られるのはよくあることです。それが自分が新しく学ぶことなら良い冒険になるかもしれませんが、業務における長時間のセットアップ作業はなかなか許容できません。
Wantedlyで環境構築
特に少ない社員で多くのインターンを迎えるWantedlyではその時間を短縮することは重要な課題です。Wantedlyに参加するインターンは一週間や数日など短い期間の参加であることも多く、この時間でインターン期間の限られた時間が削られることはもちろん、そのヘルプでメンター社員の時間も削られてきました。すでに巨大化したプロジェクトのセットアップは持ち込んだPCの状態によっては1日かかることもありました。
そもそも環境構築とは
WantedlyのRailsアプリケーション開発では下のようなタスクが求められます。
$ git clone git@github.com:wantedly/repository
$ cd wantedly
$ script/bootstrap
$ bundle exec rake dev:init
極めて一般的かつシンプルですが、ここでいくつかの問題が生じていました。
1. cloneの時間が長い
Wantedlyのrepositoryには10万を超えるコミットがあり、repositoryのサイズは400MB以上あります。ネットワークのスピードにもよりますが、clone完了まで平均で10分かかり、重い時間帯には30分かかることもありました。チームに参加したばかりで他に何もできることがない状態で10分も暇な時間ができてしまうのは効率がよくありません。
2. スクリプトの実行速度が遅く不安定
上記のbootstrapスクリプトがbundle installやnpm installなどをやってくれますが、これの実行が非常に遅く、少し想定と異なる環境が違うPCで実行するとすぐに動かなくなっていました。また、途中で落ちてもエラーメッセージが適切でなく、初めて使うと戸惑うことが多くある状態でした。
3. そもそも今やらなくてもいい
bundle install や npm install などは 秘密保持契約を結んでからでないとGemfileを見せられないなどの問題からインターンの初日からしかできませんが、PostgreSQLを使える環境にする、rubyの2.3.0をビルドするなどのタスクは必ずしもインターン開始後でなくても良いはずです。そのようなタスクも多く詰め込んでいたので速度が遅くなっていました。
4. DBの準備が遅い
データベースは本番環境からデータを取得して、匿名化した後にローカルに保存していました。この当然ながらこの作業に時間を要していました。
5. ドキュメントに不備
WantedlyのrepositoryのREADME.mdには上記のコマンドが4つ書かれていましたが、そのひとつのrake taskにバグがあり実行すると必ず落ちていました。これはすでに不要になっている操作で、ドキュメントの不備でした。この不要なエラーの原因究明にも時間が割かれていました。
問題のまとめ
このようにまともにセットアップすること自体がなかなか難しい状態でしたが、社員がついて問題を一つずつ回避することでこのような問題を解消していました。
解決策
1. shallow clone をする
1のcloneが遅い問題はshallow cloneで対応できます。
git clone --depth=1 git@github.com:wantedly/repository
masterの最新の状態のみを取得する方法で、cloneするデータ容量を抑えることができます。この方法でcloneしたあとは
git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'
git fetch --unshallow
などとして全てのコミットを取得する必要があります。
2. scriptを早く正確にする
2のboostrapの速度と精度が悪い問題は地道に解消しました。
具体的には
・bundle installとnpm installを並列させる。
・bundlerでコケないようにrubyのバージョン確認を事前にする
・PostgreSQLがない場合に'pg' gemのインストールがコケないように自動でパスを解決する
などなど様々な改善を行いました。これによって多くの環境に対応できるようになり、平均で15分かかっていた実行時間も、cloneを含めても平均9分で終わるようになりました。
3. 事前準備をしっかりする
今回の問題はインターン期間中の貴重な時間が削られることを避けたかったことで、3のその時やらなくても良いタスクをある程度インターン前に完了させるさせることでもさせることでも解決できます。例えば必要なPostgreSQLをインストールすることや、必要なrubyのバージョンをビルドしておくことはインターン参加前からでも可能です。bootstrapの内容は秘密保持契約をしてからでないと渡すことはできないという結論に至りましたが、前準備の幾つかの項目は公開しても問題なさそうでした。そこでcheck_environmentという新しいスクリプトを作り、これを実行してもエラーがでない状態にしておくとbootstrapが爆速で終わるようにしました。
4. データベースインスタンスを立てる
本番環境のデータベースを匿名化してローカルにダウンロードするのは時間がかかるので、共用のデータベースインスタンスを立てて、毎日最新のproductionの状態を匿名化したデータベースを作ることにしました。これによりDB作成コストが削減されます。デプロイサーバーの中にすでにデータベースを定期的に保存するタスクが存在したのでこれを流用して構築しました。
5. ドキュメントの整備
ドキュメントの整備をすることで、新しく使う人が戸惑う問題を解消しました。不必要なタスクを削ったり、関連するドキュメントへのリンクをつけたりしました。推奨の開発ツールの情報がまとまっていなかったのでこれを加えることで、今後の環境設定スクリプトのメンテナンスが容易になるように心がけました。
最終的に構築した環境
・pubilcの s3にアップロードした環境設定スクリプトをインターン前に実行して準備
・privateの s3にアップロードしたbootstrapを実行するだけでclone含めてセットアップ完了
・development にアクセスすることでデータベース準備の時間を削減
・それぞれのs3には最新のmasterのスクリプトがCIツールで自動で配置される
という環境を構築しました。
まとめ
「事前にcheck_environmentを配布してエラーが出ない状態にしてもらう」という前提を持てば平均9分でセットアップを完了できるようになりました。「いろんなタスクを事前にやることにした」という部分が速度向上の大きなファクターであるため、結局のところ実際の速度自体は2倍程度にとどまりましたが、インターン初日の開発を始める時間はかなり短縮できました。
エンジニアの一人として開発に集中できるのは非常に楽しいことです。今回はこの環境を作るのに少し時間を使ってしまったので次回は爆速で環境構築できる環境を爆速で作れるようになりたいです。