Jenkins はじめました + ほか3つ
こんにちは。加藤和良です。
まずあの話を書いて、それを前提にあの話を書いて、みたいなキューが筆者の中にはあったのですが、正直キューの先端につまってる話はだんだん個人的な関心および記憶がうすれてきました! 昔のはなしですからね。
というわけで、最近のまとめをさらっと書いて、新しいネタをすぐ書ける状態にリセットしたいと思います。
Jenkins
mixi ではバージョン管理システムとして Subversion を使っています。安定した、いつでもリリースできるバージョンを trunk に、開発中の機能は branches 以下に作業ブランチをつくり、レビューや QA などの後に trunk にマージする、という運用です。
Buildbot はこのうち trunk だけを追っていたのですが、徐々に「このブランチも Buildbot で追うようにして、結果をこの IRC チャンネルに書きこんでほしい」といった要望をうける機会がふえてきました。Buildbot で複数のブランチを追いかけるのは簡単です。しかし「特定のブランチの状況を特定のチャンネルにのみ書きこむ」という方法がよくわかりませんでした。MailNotifier にある builders という引数が IRC Bot にないところを見ると、できないのかもしれません。
パッチを書くか、Buildbot のサーバーを複数たてるか、と考えていたところ Android のチームで Hudson をつかっている というはなしをききました。
Hudson と Android Emulator Plugin を用いた自動ビルド環境の構築、 Test Driven Development といったアジャイルのプラクティスの数々(と書いて文明の利器と呼ぶ)を積極的に取り込むことで、無事リリースに至る事ができました。このあたりの詳しいお話も、またどこかのタイミングで書けたらなと思います。
mixi 全体で継続的インテグレーションのソフトウェアをそろえるのも悪くないかな、ということで試してみたら「特定のブランチの状況を特定のチャンネルにのみ書きこむ」というのがさくっと設定できたので、そのまま Hudson → Jenkins と乗り換え、今にいたります。
Jenkins は Buildbot にくらべるとなにかと機能が多いです。筆者は可視化まわりの充実が気にいっています。
マルチコアと Test::Synchronized
継続的インテグレーションに使っているホストもかなりスケールアップしました。mixi の開発環境は、基本的には物理的なホストを何個かにきりわけた VM なのですが、Jenkins だけは VM なしで生で使えるホストを新しく設置してもらいました。
論理的には24コアあるので、24行くらいの端末から top を起動して 1 を押すと "Sorry" と謝られてしまいます。
Perl のテストまわり (TAP::Harness) には古き良き UNIX プロセスをつかった並列化の機能があり、コア数を活かすべく、いまは30並列くらいで実行しています。ただ、テストのなかには共有のサーバーを叩くような、同時に走ると困るものもいくつかありました。
「テストがたくさんあり、コアもたくさんあるので並列で実行したいけど、数個のテストは同時に動かされると困る」という問題を解決するべく書いたのが Test::Synchronized です。Test::Synchronized はごく単純なロック機構を提供し、use されたテスト同士が同時に走らないことを保証します。
このロック機構はローカルのファイルシステムとプロセス ID をつかっているため、mixi 社内のユースケースですら完璧にはカバーしていません。たとえば、開発者のホストと継続的インテグレーションのホスト、みたいな粒度ではロックがききません。これについては Test::Synchronized をがんばるよりは、そもそも共有資源を使わない方向に寄せるべきかと思います。
/dev/shm
こうしてテストを並列化していくと、今度は IO 待ちがボトルネックになってきました。これについては /dev/shm 以下にディレクトリを作り、Jenkins がチェックアウトする Subversion のワーキングコピーをそこへのシンボリックリンクにすることで、かなり改善しました。
CPU はまだまだ余裕がありますが、赤色の iowait はとりあえず減らせました。
Selenium
いまさらはじめたのが Selenium です。
mixi ではいままでも Selenium を Selenium IDE と HTML のテーブル形式のテストケースで使っていました。これは、人力での QA の省力化というところが出発点にあったものと認識しています。
しかし、最近は Test::WWW::Selenium を中心に、開発者テストに寄せた Selenium を使い方を模索しはじめています。まだ mixi.jp のサービスそのものについてのテストは少なく、どちらかというと UnittestJS や QUnit を使ったライブラリの単体テストが多めです。
JavaScript のテストに関しては PhantomJS や Envjs のようなウィンドウの開かない (headless な) ブラウザを使うという手法もあります。筆者としては、開発中は PhantomJS で高速に実行し、継続的インテグレーションで Google Chrome, Firefox, Internet Explorer にそれぞれ通す、という組み合わせが良いかなと思っています。
まとめ
mixi のテストまわりの最近の出来事について説明しました。
- それぞれのブランチの状況をそれぞれの IRC に伝えるために Buildbot から Jenkins に変えました。
- マルチコアを活かすべくマルチプロセスで実行しています。
- IO 待ちが多かったので /dev/shm に Subversion のワーキングコピーを置きました。
- Selenium も Jenkins から実行しています。
ブログはこまめに書きましょう。