CI始めました

Welcome to Jenkins CI! | Jenkins CI

なんとなく Java はメンドイという思い込みで避けていたんだけど、先週末にちょっと思い立って Jenkins のインストールを試してみた。Debian で試したところものすごく簡単だったので職場にも起こしてみることにした。

DebianにJenkinsをインストール

Debian 6 にJenkinsをインストール - cactusman日誌

を参考に。

まずインストールはとても簡単。各種パッケージシステム用にパッケージが用意されてるから。

自分は Debian を使ったんだけど、上のエントリと java のパッケージが違う以外は

apt-key add
apt-get update
apt-get install

でイケた。これだけで、

  • jenkins ユーザーの作成
  • daemon の起動スクリプトと必要な設定

が展開されるので、あとは

/etc/init.d/jenkins start

するだけ。ここら辺とてもよく Debianize されてる印象。

Debian + Jenkins の考え方

  • jenkins ユーザーでプロセスが動いて
  • jenkins ユーザーのホームディレクトリ以下に各種情報が集まっていく(そういう設定ファイルが自動でセットされる)

ので、この jenkins ユーザーの扱いがキモになる。

インストール後にやったこと

  • jenkins ユーザーのホームディレクトリ変更
    • デフォルトは /var/lib/jenkins 以下になるんだけど、ここはそんなに容量用意してなかったので、別ディスクに移動
    • jenkins の設定ファイルと /etc/passwd のホームディレクトリ設定の両方変えておく1
  • rbenv 環境を用意して jenkins ユーザーは rbenv を通して ruby を起動するように .bash_profile を設定
    • 今はアプリ一つだけど将来的に増えた際にバージョンが合ってない可能性を考慮して2

※ jenkins ユーザーでの作業は su と source で行いました。ログインできる必要ないので。

ジョブはとりあえず全部フリースタイルで

  • LLのジョブしかないのでフリースタイルで
    • rake spec を叩く sh スクリプト、自前のテストスイート実行の sh スクリプトを jenkins のジョブ設定画面から放り込んでおく。現在の jenkins 環境に特有の呼び出し方なのでこれはリポジトリには入れないでおく3

Rails アプリのビルドは以下を参考にした。

Testing Rails apps with Jenkins - komagata

rvm の gemset は使っていないのでもっとずっとシンプル。要するに bundle install, rake db:migrate, rake spec するだけ。

ちょっとハマったこと

  • ジョブ名にスペースを入れると workspace にそのまま反映されて、sh スクリプトやら make やらパスにスペースが入っている場合を考慮していないものが軒並み失敗する
    • スクリプトをいじるのは面倒なのでジョブ名を変更して対処
  • メモリ不足でスコンスコン落ちる
    • rake spec で全部一度に処理しようとするとメモリが不足して jenkins が落ちる

なんとか節約する。

省メモリ Rails アプリ CI

  • spec:* を一つずつジョブに分割
  • 一つだけ SCM をポーリング
  • こいつをトリガにして別なジョブを次々に起こす

Jenkins 用語で言う上流、下流プロジェクトで対処する。

当然ディスクも手間も食うけど、一気に実行してメモリが足りないという状況は回避できる。CI サーバ落ちたら意味ないので苦肉の策。

PHP は Debian 6 の 5.3 のまま使う

実際は 5.1 が production のバージョンなんだけど、5.3 への移行を考えたうえでの CI の導入なので、Debian 6 の標準パッケージである PHP 5.3 をそのまま使うことにした。

本当は PHP についても phpfarm でも使って複数バージョンを動かせるようにするのも手なんだけど、面倒なのでやってない。

workspaceのディレクトリレイアウトに依存したsetup

PHP のアプリが特定のディレクトリツリーを利用しており、この準備を早く確実なものにするために setup 用のスクリプトを用意している。

ビルド用 sh スクリプトの中で $WORKSPACE という変数を使うと workspace のパスを得ることができるので、例えば他のジョブの workspace にある何かを使うといったこともできる。

テストが独立していなかった

rake spec を分割したところ動かない spec がいくつか出てきた。急ぐときは直接 bundle exec rspec spec/**/*.rb で動かしつつ、全体の rake spec は落ちないように注意しながら進めていたんだけど、spec:* 単位で分割したらあちこち落ちて、かつその修正に意外に時間を取られてしまった。

最初の頃は stub すごいと思って喜んで使って、最近は fixture, fixture replacement も適切に使った方がいいよねと考えながら spec を書いてるんだけど、fixture, fixture replacement を使ったときのテストの独立性がちゃんと確保できていなかったらしい。

まだまだ精進が必要だ。

あと期待していること

これでとりあえずの目的は達成できた。今のところ全自動でちゃんとビルドできるものは多くないのでジョブも少ない。ただ今後はもう少し活用できるんじゃないかと思っている。

外部ジョブの監視

Jenkins には XML の POST でジョブの結果を受け付ける機能がある。これは Jenkins の動いているホスト上で直接何かを実行していなくてもジョブの結果だけを扱えるということだ。

例えばあるホストの cron の記録をメールではなく XML にして Jenkins に POST すれば成功、失敗を記録でき、失敗のときだけメールを飛ばすということが可能になる。以前から cron のメールが多すぎてロクに見ないことを問題に感じていたので、これで少し扱いやすくできないかなーと目論んでいる。

p.s. ユニットテスト始めました から6年半か…。ずいぶん経ったな。

  1. 実際には一通り設定し終わってから容量の問題に気づいたのでちょっと苦労した。先にちゃんと設計しよう。 

  2. やはり rbenv rehash を忘れますね… 

  3. 入れて呼ぶ方がビルドスクリプトもバージョン管理できるから良いと書かれてるけど 

More

Categories

Tool 日々 Web Biz Net Apple MS ことば News Unix howto Food PHP Movie Edu Community Book Security Text TV Perl Ruby Music Pdoc 生き方 RDoc ViewCVS CVS Rsync Disk Mail FreeBSD Cygwin PDF Photo Zebedee Debian OSX Comic Cron Sysadmin Font Analog iCal Sunbird DNS Linux Wiki Emacs Thunderbird Sitecopy Terminal Drawing tDiary AppleScript Life Money Omni PukiWiki Xen XREA Zsh Screen CASL Firefox Fink zsh haXe Ecmascript PATH_INFO SQLite PEAR Lighttpd FastCGI Subversion au prototype.js jsUnit Apache Trac Template Java Rhino Mochikit Feed Bloglines CSS del.icio.us SBS qwikWeb gettext Ajax JSDoc Rails HTML CHM EPWING NDTP EB IE CLI ck ThinkPad Toy WSH RFC readline rlwrap ImageMagick epeg Frenzy sysprep Ubuntu MeCab DTP ERD DBMS eclipse Eclipse Awk RD Diigo XAMPP RubyGems PHPDoc iCab DOM YAML Camino Geekmonkey w3m Scheme Gauche Lisp JSAN Google VMware DSL SLAX Safari Markdown Textile IRC Jabber Fastladder MacPorts LLSpirit CPAN Mozilla Twitter OpenFL Rswatch ITS NTP GUI Pragger Yapra XML Mobile Git Study JSON VirtualBox Samba Pear Growl Mercurial Rack Capistrano Rake Win RSS Mechanize Sitemaps Android JavaScript Python RTM OOo iPod Yahoo Unicode Github iTunes God SBM friendfeed Friendfeed HokuUn Sinatra TDD Test Project Evernote iPad Geohash Location Map Search Simplenote Image WebKit RSpec Phone CSV WiMAX USB Chrome RubyKaigi RubyKaigi2011 Space CoffeeScript Nokogiri Hpricot Rubygems jQuery Node GTD CI UX Design VCS Kanazawa.rb Kindle Amazon Agile Vagrant Chef Windows Composer Dotenv PaaS Itamae SaaS Docker Swagger Grape WebAPI Microservices OmniAuth HTTP 分析基盤 CDN Terraform IaaS HCL Webpack Vue.js BigQuery Middleman CMS AWS PNG Laravel Selenium OAuth OpenAPI GitHub UML GCP TypeScript SQL Hanami Develop Document Jekyll