ShipIt を使って Perl モジュールのリリース作業を自動化する
ShipIt は Perl プロダクトのビルド、テスト、リリースを自動化してくれるツールで、CPAN へのアップロードもできます。
今回は以下の作業を半自動化するために、ShipIt を利用しました。
前提として、プロジェクトはスクラッチで開発しており、lib/ 以下にモジュールが出来ているものとします。
1. ShipIt のインストールと初期設定
cpanm で ShipIt をインストールします。
cpanm ShipIt
プロジェクトのルートディレクトリで次のコマンドを実行し、設定ファイル .shipit
を生成します。
shipit --write-config
今回、.shipit の内容は以下のようにします。
steps = FindVersion, ChangeAllVersions, CheckChangeLog, DistTest, Commit, Tag git.push_to = origin
ChangeAllVersions を使うと、プロジェクトの全モジュールの VERSION を更新することができました。
※追記※
今回の目的に照らし合わせると、DistTest は不要でした。
2. Module::Build によるビルドの用意
shipit を動かすには最低限 Build.PL や Makefile.PL などが必要なようです。 試しに用意せずに shipit を実行すると次のようなエラーになります。
$ shipit (git)-[master][~/path/to/project] Running step ShipIt::Step::FindVersion=HASH(0x7fddc2b6f688) Unknown project type. Can't find Makefile.PL, Build.PL, configure.ac, etc.. at ~/.plenv/versions/5.18.2/lib/perl5/site_perl/5.18.2/ShipIt/ProjectType.pm line 47.
今回は Module::Starter でビルドの雛形を作って、必要なものをプロジェクトのリポジトリにコピーすることにします。
DistTest
を実施しないのであれば、以降で生成されるファイルの内、最低限必要なものは Build.PL だけなので、もっと簡易なやり方もあります。(後述)
Module::Starter がない人は cpanm でインストールしましょう。
ビルドモジュールとしては Module::Build を使うことにします。
$ cpanm Module::Starter $ cd ~/tmp $ module-starter --module=Foo::Bar --author="Your Name" --email="your.name@example.com" \ --build=Module::Build $ ls Foo-Bar/ Build.PL Changes MANIFEST README ignore.txt lib t
今回は lib/, t/, README, Changes は既にプロジェクト側で用意していたので、Build.PL, ignore.txt をコピーしました。
MANIFEST は後で Module::Build によるビルドで生成します。
3. MANIFEST 生成
※shipit で DistTest
を実施しない場合、こちらの手順は不要です。
まず Build.PL から Build スクリプトを生成します。
perl Build.PL
次に標準の MANIFEST.SKIP ファイルを生成した後、プロジェクトのファイル群を MANIFEST に追加します。
./Build manifest_skip ./Build manifest
4. shipit 実行
shipit を実行する前に、ビルドに必要なファイルは git add しておかないと、git への push が失敗します。
shipit を実行すると、対話式インタフェースで処理が進行します。
$ shipit (git)-[master][~/path/to/project] Running step ShipIt::Step::FindVersion=HASH(0x7f8a08828c60) Current version is: 0.01 Next/release version? 0.02 Running step ShipIt::Step::ChangeAllVersions=HASH(0x7f8a08c0ef90) Update $VERSION in lib/Foo/Bar.pm. Update $VERSION in lib/Foo/Bar/Baz.pm. Running step ShipIt::Step::CheckChangeLog=HASH(0x7f8a08c77b60) No mention of version '0.02' in changelog file 'ChangeLog' Edit file? [Y/n] y /* エディタで ChangeLog を編集 */ "ChangeLog" [converted] 37L, 868C written Running step ShipIt::Step::DistTest=HASH(0x7fdbd9c78c40) Could not get valid metadata. Error is: Invalid metadata structure. Errors: License 'Artistic_2_0' is invalid (license -> Artistic_2_0) [Validation: 2] at ~/.plenv/versions/5.18.2/lib/perl5/site_perl/5.18.2/Module/Build/Base.pm line 4555. Could not create MYMETA files Creating new 'Build' script for 'Foo-Bar' version '0.02' Creating Makefile.PL *** Did you forget to add META.yml to the MANIFEST? Creating Foo-Bar-0.02 Could not get valid metadata. Error is: Invalid metadata structure. Errors: License 'Artistic_2_0' is invalid (license -> Artistic_2_0) [Validation: 2] at ~/.plenv/versions/5.18.2/lib/perl5/site_perl/5.18.2/Module/Build/Base.pm line 4555. Could not create MYMETA files Creating new 'Build' script for 'Foo-Bar' version '0.02' Building Foo-Bar No tests defined. Cleaning up build files Cleaning up configuration files Running step ShipIt::Step::Commit=HASH(0x7fdbd9c7f3c8) [master 3cd888d] Checking in changes prior to tagging of version 0.02. 13 files changed, 163 insertions(+), 5 deletions(-) create mode 100644 .shipit create mode 100644 Build.PL create mode 100644 MANIFEST create mode 100644 MANIFEST.SKIP create mode 100644 Makefile.PL create mode 100644 ignore.txt pushing to origin at ~/.plenv/versions/5.18.2/lib/perl5/site_perl/5.18.2/ShipIt/VC/Git.pm line 74. Counting objects: 33, done. Delta compression using up to 4 threads. Compressing objects: 100% (17/17), done. Writing objects: 100% (20/20), 3.16 KiB | 0 bytes/s, done. Total 20 (delta 6), reused 0 (delta 0) To git@github.com:key-amb/perl5-Foo-Bar.git 272c0ad..3cd888d master -> master Running step ShipIt::Step::Tag=HASH(0x7fdbd9c7f7d0) pushing to origin at ~/.plenv/versions/5.18.2/lib/perl5/site_perl/5.18.2/ShipIt/VC/Git.pm line 116. Counting objects: 1, done. Writing objects: 100% (1/1), 186 bytes | 0 bytes/s, done. Total 1 (delta 0), reused 0 (delta 0) To git@github.com:key-amb/perl5-Foo-Bar.git * [new tag] 0.02 -> 0.02 $
shipit 内で(というか ShipIt::Step::DistTest の中で)ビルド生成物のクリーンアップも行ってくれるようです。
補遺
後で ShipIt のソースを読みながら試したところ、ShipIt::Step::DistTest を実施しない場合、最低限の Build.PL の内容は次で十分です。
+{ dist_version_from => 'lib/Foo/Bar.pm', };
Makefile.PL の場合は次のようになります。
version_from 'lib/Foo/Bar.pm';
感想
CPAN にモジュールを上げるときは Minilla を使うと楽でよいですが、今回のような限定的な用途だと、shipit の方が向いてるのかなと思いました。
ハマったこと
実は bin/ 以下にスクリプトを置いていて、そちらにも VERSION を付けていたのですが、 ShipIt::Step::ChangeAllVersions
のせいで実行ビットが落ちてしまったので、とりあえず VERSION を消しました。
(追記) Issue 上げたところ、作者に速攻で直してもらえました:D https://github.com/gfx/Perl5-ShipIt-Step-ChangeAllVersions/issues/2