Shipwrightを学んだのでまとめとか

ShipwrightはPerlのモジュールです。CPANで公開されています。

Shipwright - Best Practical Builder - metacpan.org

Shipwrightはアプリケーションのためのパッケージングツールです。依存しているソフトウェアおよびバージョンをリポジトリで管理します。たいていのPerlで書かれたアプリケーションはCPANモジュールに依存しているので、何らかの方法でそれをインストールする必要があります。思いつく方法としては以下のような方法があります。

  • CPANコマンドで地道にインストール
  • アプリケーションのMakefile.PLでModule::Installを使って依存モジュールを自動インストールする
  • rpmなどで自力でパッケージングする(やりかたしらないけど)
  • 専用のPerlパッケージ(perl本体含んだ)を作成する

この中でお手軽なのは2番です。

# make installdeps

などとするとMakefile.PLで宣言した依存モジュールが自動でインストールされます。さらに、すべてデフォルトの設定でインストールすればいい、という場合はPERL_MM_USE_DEFAULTをセットすることで全力で放置しておくことが可能です(ただしテストがこけても気づかないかもしれない)。

# PERL_MM_USE_DEFAULT=1 make installdeps

さて、ここでインストールされるモジュールはCPANにあがっている最新版になります。Makefile.PLでは依存モジュールのバージョン番号の下限を指定することができますが、特定のバージョンを指定することはできません(よね?)。これはアプリケーションを作成中であれば特に問題ありませんが、作成後いくらか時が過ぎ、依存モジュールもバージョンアップを重ね、知らず知らずのうちに非互換の変更などが行われていたりして、でもそれを見逃してアプリケーションの新規インストールを行ってみたらなぜかうまく動作しない。なーんてことになりそうです。たぶん。

だから、アプリケーションが常にテストされたモジュール群で動作するように、依存モジュールをバージョン管理すればいいんだ。そこでShipwrightの出番だというわけですね。

Shipwrightの利用シナリオは以下のようになります。

  • Shipwrightパッケージの作成
  • アプリケーション本体、依存モジュールをインポート
  • パッケージのビルド(インストール)
  • アプリケーション本体、依存モジュールの更新

順番に見ていきます。

Shipwrightパッケージの作成

$ svk mkdir //test
$ shipwright create -r svk://test/shipwright/hello

こうすると以下のような構成がコミットされます。

test/shipwright/hello
|-- bin
|   |-- shipwright-builder
|   `-- shipwright-utility
|-- dists
|-- etc
|   |-- shipwright-perl-wrapper
|   |-- shipwright-script-wrapper
|   |-- shipwright-source-bash
|   |-- shipwright-source-tcsh
|   `-- shipwright-utility
|-- scripts
|-- shipwright
|   |-- map.yml
|   |-- order.yml
|   `-- source.yml
`-- t
    `-- test

内容については正直あまりよくわかってませんが、次のステップでインポートされたモジュールはdistsに保存され、そのインデックスがmap.ymlやsource.ymlに記載されます。order.ymlはモジュールのインストール順を管理するようです。

アプリケーション本体、依存モジュールをインポート

次にアプリケーション本体や依存モジュールをパッケージにインポートします。
インポート元としては以下のロケーションが使用できるようです。

ここではShipwrightのチュートリアルに従ってAcme::Helloをインポートしてみます。

$ shipwright import -r svk://test/shipwright/hello

CPANモジュールを使ってCPANからAcme::Helloおよびその依存モジュールがダウンロードされ、パケージにコミットされます。ここでファイルシステム上のパスやURLを指定しても基本的に同じです(CPANにアクセスしないだけ)。インポートされたモジュールはdistsに保存され、CPANモジュール名を指定した場合はモジュール名とディレクトリ名の対応がmap.ymlに保存され、ディレクトリやURLの場合はsource.ymlに保存されます。scriptsディレクトリ以下にはbuildとrequire.ymlという2つのファイルがモジュール毎に作成されます。buildにはビルド手順が、require.ymlには依存関係が記載されているようです。

map.yml

--- 
Acme::Hello: cpan-Acme-Hello
Locale::Maketext::Lexicon: cpan-Locale-Maketext-Lexicon

build

make: ./Build
test: ./Build test
install: ./Build install
clean: %%PERL%% Build realclean

require.yml

--- 
build_requires: {}

conflicts: {}

recommends: 
  cpan-Locale-Maketext-Lexicon: 
    version: 0.15
requires: {}

パッケージのビルド(インストール)

リポジトリにアクセス可能な場合は以下のコマンドでビルド(インストール)します。

$ shipwright build -r svk://test/shipwright/hello

ビルド手順は、まずパッケージ全体を一時ディレクトリにチェックアウトしてからインストールするという流れのようです。インストール先はデフォルトでは/tmp/FzLSOqTnarのようなランダムなディレクトリになります。インストール先は--install-baseオプションで指定できるようです。

インストールされたディレクトリの中は以下のような構成になっていました。

/tmp/FzLSOqTnar
|-- bin
|-- bin-wrapped
|-- etc
|-- lib
|   `-- perl5
|       |-- Acme
|       |   `-- Hello
|       |       `-- I18N
|       |-- Locale
|       |   `-- Maketext
|       |       |-- Extract
|       |       `-- Lexicon
|       `-- darwin-2level
|           `-- auto
|               `-- Locale
|                   `-- Maketext
|                       `-- Lexicon
`-- man
    |-- man1
    `-- man3


また、リポジトリにアクセスできない場合でもパッケージに含まれているshipwright-builderを実行するだけでインストールが可能です。

$ ./bin/shipwright-builder

インストール先は先ほどと同様に--install-baseで指定可能でデフォルトでは/tmp配下となります。またこの方法でインストールすると__install_baseというファイルにインストール先が書き込まれ、build.logにインストールログが書き込まれるようです。

アプリケーション本体、依存モジュールの更新

更新は以下のコマンドで行います。

$ shipwright update -r svk://test/shipwright/hello Acme::Hello

これで古いものに上書きする形で最新版に更新されます。

TIPS

ソースが異なると同じモジュールでも別々に扱われる

また古いバージョンが欲しいからURLで指定しよう、と思い立って以下のようにすると元々あるAcme::Helloとは別のAcme::Helloがインポートされます。これはインポートソースが異なるためです。

$ shipwright import -r svk://test/shipwright/hello http://search.cpan.org/CPAN/authors/id/A/AU/AUTRIJUS/Acme-Hello-0.02.tar.gz
$ tree -d -L 1 dists
dists
|-- Acme-Hello
|-- cpan-Acme-Hello
`-- cpan-Locale-Maketext-Lexicon

また、URLで指定したのでmap.ymlではなくsource.ymlにエントリが追加されます。

source.yml

--- 
Acme-Hello: http://search.cpan.org/CPAN/authors/id/A/AU/AUTRIJUS/Acme-Hello-0.02.tar.gz
Perlのモジュール以外も管理できる

これは試してないのですが、Shipwrightの開発元であるbestpractical.comのリポジトリにはいくつかのShipwrightパッケージが置いてあるので見てみると、libgdやexpatといったものもパッケージに入っていますし、perl本体すらあったりします。ビルドは基本的にscriptsディレクトリにあるbuildスクリプトを実行するだけなのでこれが適切に設定されていればなんでもいいということでしょうか。

http://code.bestpractical.com/shipwright/

その他

shipwrightコマンドでごにょごにょやっているとあっという間にリビジョン番号が増加していってビックリします。試しにCatalystをインポートしてみたら283から510まで増加しました。

http://svn.onot.in/public/shipwright/catalyst/

あと/tmpディレクトリもすごいことになります。ランダム10桁の英数字ディレクトリがずらっとできていてビックリしました。

複数台のサーバーを運用している場合、すべて同じマシンであれば1つのサーバでShipwrightパッケージをインストールしてそこから他のサーバーへrsyncとかするといいのかも。

shipwright updateで自動で更新するモジュールと、手動でbuildスクリプトなどを設定するモジュールとをうまく使い分けて管理していくのがいいんでしょうかね。アプリケーションのインストールも全部自動でbuildスクリプト一発でできるようにうまく書けるといいなあ。。(これはshipwrightとは別だけど)