ikeike443のブログ

ソフトウェアビジネスに関心がある系のブログ

Hudson plugin for Playframwork を書いた

練習がてら、 Hudson のプラグインを書いてみました。

Play むけのプラグインなんて、ほとんど需要無さそうですが、Hudson の ML に投げたら受け入れてもらえたりするんでしょうか??

とりあえず、コードは下記に置いてあります。
https://github.com/ikeike443/HudsonPluginForPlay

出来ること

  • Play auto-test コマンドを実行できます
  • テスト結果を Calimoucho 風*1に閲覧することが出来ます

使い方

プラグインをインストールしたら*2、「Hudsonの管理>システム設定」の下記箇所に Play スクリプトの格納場所を記述します。
f:id:ikeike443:20110125020738p:image


次に、「新規ジョブ作成>フリースタイルプロジェクト」でジョブを作成し、下記2箇所を設定します。

1.「ビルド手順の追加」で 「Play!」を選択し、"auto-test" と設定します。
f:id:ikeike443:20110125020506p:image


2.「ビルド後の処理」で「Play! auto-test reports」にチェックを入れます。
f:id:ikeike443:20110125020508p:image


これで設定は完了です*3。ビルド実行してください。
f:id:ikeike443:20110125020740p:image


ビルドが完了すると、サイドパネルに下記のように Play! のアイコンとともに Play! Test Result というメニューが出現します。
f:id:ikeike443:20110125020509p:image

Calimoucho 風のテスト結果

テスト結果を Calimoucho 風に参照できます。Test runner の画面にも似ています。
f:id:ikeike443:20110125020739p:image


一つ一つのボックスがテストクラスになっています。クリックすると詳細を確認できます。
f:id:ikeike443:20110125022914p:image


Play の auto-test には Selenium がビルトイン*4されています。Selenium のテスト結果も下記のように確認できます。
f:id:ikeike443:20110125020511p:image


テストが失敗した場合、失敗したテストクラスが赤く表示されます。
f:id:ikeike443:20110125020510p:image


クリックすると詳細を見ることが出来ます。
f:id:ikeike443:20110125020512p:image


テストに失敗した場合、ビルドも失敗するようになっています。


と、ここまでが僕の書いたプラグインの機能です。

まとめ?

まとめ、っていっても、ただプラグイン書きましたってだけのブログなのであれですが。。

一応、このプラグインと Cobertura や Ivy などを組み合わせると、そこそこ CI 環境として整うかと思います。

Play! の CI 事情については、また日を改めて書きたいなと思います。

で、ぶっちゃけ、このプラグインって需要あるんでしょうか。。

追記

Hudson の ML に投稿してみたところ、 Hudson の Plugin Developer というものにしていただきました。
これがどういうものなのかまだよくわかってませんが、キャッチアップしてみたいと思います。
おそらく、程なくして Hudson のプラグイン管理画面からダウンロード出来るようになると思います。

追記2

先程Hudson改めJenkinsのアップデートセンターを確認したところ、play-pluginの名で登録されたようです。お使いのHudson改めJenkinsのプラグイン管理画面からインストールできると思います。
これからWikiなどを充実させていきます。

*1:Play の [http://integration.playframework.org/:title=CI Server] は Calimoucho という名前のようです。コードは[https://github.com/guillaumebort/calimoucho:title=ここ]にあります。

*2:Hudsonのリポジトリには置いていないので手動でインストールして下さい。

*3:特に書いていませんが、ソースコードをSCMから取得する設定ももちろんしてください。

*4: Htmlunit を使ってブラウザレスで実行できるので結構便利です。

PlayframeworkのFunctionalTestでFixtureするとき

FunctionalTestでFixtureを使う場合、EntityManagerが初期化されず上手く動かないので、下記のように記述する。

JPAPlugin.startTx(false);
Fixtures.deleteAll();
Fixtures.load("data.yml");
JPAPlugin.closeTx(false);

バグっぽいんだけど、直すつもりはないみたい。
https://bugs.launchpad.net/play/+bug/491403

久しぶりにjad

ちょっと必要があって久しぶりにjadを探しまわった。
なんかもう単体では配布していないのかな。ようわからん。

とりあえず下記からDLできたのでよしとする。
http://web.archive.org/web/20080214075546/http://www.kpdus.com/jad.html#download

PlayframeworkでJobをapplication.confでOn/Offできるパッチを書いた

1.0.3.2と1.1向けにそれぞれ書きました。
簡単に動作確認はしましたが。。

http://gist.github.com/547537
http://gist.github.com/547437

さー飲みイクゾー。。


2010/08/27 追記:
Guillaumeがマージしてくれました。
http://groups.google.com/group/play-framework/browse_thread/thread/8ab15a27eec68814
http://bazaar.launchpad.net/~play-developers/play/1.1-unstable/revision/1021
ちょっと確認します−。自分のパッチだけじゃ足りなかったみたい。

PlayframeworkのJobをOn/Offしたい

Play!では簡易的なジョブフレームワークがある。
play.jobs.Jobを継承して、@Everyか@Onといったアノテーションを書いておくと、それにしたがってスケジュール実行してくれる。
アノテーションの中はCronとほぼ同じ書式。正確にはこっちね。

で、こいつのOn/Offを設定ファイルなどでハンドル出来ないかなーと思ってコードを読んでみた。
以下はそのメモ。
サーバ起動後、JobsPlugin#afterApplicationStartが呼ばれる。下記はEveryアノテーションの部分を抜粋。基本的にOnも一緒。

            // @Every
            if (clazz.isAnnotationPresent(Every.class)) {
                try {
                    Job job = (Job) clazz.newInstance();
                    scheduledJobs.add(job);
                    String value = ((Every) (job.getClass().getAnnotation(Every.class))).value();
                    if (value.startsWith("cron.")) {              ←ココ
                        value = Play.configuration.getProperty(value);     ←ココ
                    }
                    executor.scheduleWithFixedDelay(job, Time.parseDuration(value), Time.parseDuration(value), TimeUnit.SECONDS);
                } catch (InstantiationException ex) {
                    throw new UnexpectedException("Cannot instanciate Job " + clazz.getName());
                } catch (IllegalAccessException ex) {
                    throw new UnexpectedException("Cannot instanciate Job " + clazz.getName());
                }
            }

上記のように、cronで始まるアノテーションがあった場合、confファイルから値を取ってくるように動いている。
ので、スケジュールの設定はapplication.confに書いておけばいいようだ。ジョブごとに設定を変えたいなら、

cron.JobA=5min
cron.JobB=*    0    *    *    *    ?

みたいに書いておけばいい。

が、ジョブをOn/Offする機構はない模様。
試しに0minとかしてみたが、例外吐きました。。

executor.scheduleWithFixedDelay(job, Time.parseDuration(value), Time.parseDuration(value), TimeUnit.SECONDS);

ってところで呼ばれてるjava.util.concurrent.ScheduledThreadPoolExecutorのコード見ると、下記のようになってるのでまあしょうがないかな。。

    public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
                                                     long initialDelay,
                                                     long delay,
                                                     TimeUnit unit) {
        if (command == null || unit == null)
            throw new NullPointerException();
        if (delay <= 0)
            throw new IllegalArgumentException();
        if (initialDelay < 0) initialDelay = 0;
        long triggerTime = now() + unit.toNanos(initialDelay);
        RunnableScheduledFuture<?> t = decorateTask(command,
            new ScheduledFutureTask<Boolean>(command,
                                             null,
                                             triggerTime,
                                             unit.toNanos(-delay)));
        delayedExecute(t);
        return t;
    }

んーむり。一応コミュニティに質問と要望はだしておくか。。

質問を投げたところ、Guillamueから返事きた。パッチ送ってくれとのことなので、余裕があれば送るかも。。
http://groups.google.com/group/play-framework/browse_frm/thread/8ab15a27eec68814

xmemcachedというクライアントがKestrelをサポートしているらしい

http://code.google.com/p/xmemcached/wiki/Getting_Started#Talk_with_Kestrel

Kestrelはflagをセットしても勝手に無視しちゃうので、flagに相当する値をflagではなくvalueの先頭4バイトに押し込むことで対応しているようだ。
ちょっと強引だけど、使えるのかなー。