その手の平は尻もつかめるさ

ギジュツ的な事をメーンで書く予定です

Ukigumo入門 ― 2014年スタイル

とりあえずデモサイトを示しますので適当に見て下さい.
http://ukigumo.moznion.net/

さて今回はゆるふわCIシステムであるところのUkigumoのナウいスタイルについて説明しようと思います.
ここ最近ではUkigumo::AgentというAgentサーバが存在しており,これを使うとまあ便利なんですけれども,ドキュメントが少ない為か *1 あまり利用されている事例を見かけませんので,それらも踏まえて解説したい感じです.

まずUkigumoとは何か

CIシステム.Perl製.
Perl製だが,もちろん他言語のプロジェクトでも使える.

Travisのようにサービスとして提供されている感じではなく,自前でインストールして使う.
多分,感覚としてはJenkinsに近いと思うが,そこまで複雑ではなく,シンプル.
基本的に,「テストの実行及びその結果の取得」と「テスト結果の保存」が主な仕事.詳細は後述.

Ukigumoの登場人物

Ukigumo::Server

Clientから送られてくるテスト結果を保存する為のサーバ.
保存しているテスト結果をブラウザから閲覧するためのウェブアプリケーションもサポートしている.
端的にいうとCPAN Testers Reportsみたいな存在.

Ukigumo::Client

実際にテストを走らせて,Serverにその結果を送る存在.
例えば,Ukigumo::Clientのインスタンスを作って,$client->run()などと実行してやると,テスト対象のリポジトリをclone or pullしてきて,実際にテストを走らせる.そしてその結果をServerに対してPOSTしてその儚いライフサイクルを終える.

Ukigumo::Agent

Agentサーバ.テストランナーサーバとも言える.
何らかのイベントが発火して,Agentにタスクをenqueueする (AgentサーバのAPIにPOSTする) とAgentが適宜Clientのインスタンスを作って,そのClientのインスタンスにタスクを振って処理を行わせる,という事が出来る.
中にジョブキュー的な機構を持っているので,「次から次へとClientに処理を実行させた結果、ハングして処理を詰まらせる」みたいな悲劇を防ぐことが可能.
実際の例を挙げると,GitHubのPushのWebHooksにAgentサーバのAPIのアドレス (GitHub WebHooksだと/api/github_hook)を登録しておくと,リポジトリにpushされる度にイベントが発火してWebHooksでリポジトリの情報がAgentサーバのAPIにPOSTされる (つまりenqueueされる) ので,リポジトリにpushされる都度テストを走らせる,みたいなことが出来るようになる.

構成の今昔

かつての構成

かつてはAgentサーバを使わず,下図のようにServerとClientのみでまかなう構成が多かった.
Cron等で定期的に実行するという素朴な感じ.

f:id:moznion:20140503134026p:plain

ここ最近の構成

Agentサーバを使って,Agentが何らかのイベントを受け取ったらClientを立ち上げてジョブを走らせるようにする.
例えばリポジトリにpushされたらそのイベントをAgentに投げて,その都度テストを回してやるという感じ.

f:id:moznion:20140502180827p:plain

最近のインストールの方法

最近ではUkigumoシリーズはCPANにアップされているので,それを使うと楽.今回はこの方法を紹介する.
GitHubに上がっているもの *2 をcloneしてcarton等で実行するのでも良い.そういうことしたい人は説明しなくても出来ると思うので説明略!

なお今回の説明では,簡単化の為にUkigumo::ServerとUkigumo::Agentを同じマシン上で立ち上げるものとする.もちろんそれぞれが別のマシンに存在していて良い.

インストールは至って簡単,以下のコマンドを叩くだけで良い.

$ cpanm Ukigumo::Server Ukigumo::Client Ukigumo::Agent

最近の構成で実際に使ってみる

1. サーバ群を立ち上げる

なにはなくともServerとAgentを立ち上げる必要があるので立ち上げる.

Server
$ ukigumo-server --port=2828 --host=127.0.0.1 --max-workers=4 --config=/path/to/config.pl

--port--hostはそれぞれサーバを立ち上げるポートとホスト.
--max-workersは動かすワーカーの最大数.--configについては後述.
詳細はukigumo-server --helpを参照のこと.
とりあえずこうすると,localhost:2828にUkigumo::Serverが立ち上がる.

Agent
$ ukigumo-agent --port=2829 --server_url=http://127.0.0.1:2828 --work_dir=/tmp/

--portはAgentサーバを立ち上げるポート番号.
--server_urlはテスト結果をPostするサーバのアドレス (つまり上で立ち上げたUkigumo::Serverのアドレス) .
--work_dirはClientがリポジトリから実際にコードをcloneしてきてテストを走らせる為に割り当ててあげるワークスペースのディレクトリ.
こういう塩梅で実行するとUkigumo::Agentも立ち上がる.

2. テストしたいリポジトリのルートに.ukigumo.ymlを置く

.ukigumo.ymlというのは,.travis.ymlのようなもので,Ukigumo::Clientはプロジェクトルートに置かれているこのファイルを見てよしなにもろもろ設定をしてくれる.
以下が例:

before_install:
  - "cpanm -L $HOME/.ukigumo/ukigumo-server/extlib --installdeps --with-develop -n ."
install: "ln -s $HOME/.ukigumo/ukigumo-server/extlib ./extlib"
script: prove -lrv -Iextlib/lib/perl5 t

before_installと言うのはinstallの前段階で走るコマンドで,installはその名の通りインストール時に走るコマンド.scriptでは実際にテストを実行するコマンドを指定する.
あけすけに言うと,だいたい.travis.ymlでできることが出来る.現状セット出来るオプションは以下のとおり.実行される時系列順に示している.

  • before_install
  • install
  • before_script
  • script
  • after_script


<追記>
すっかり忘れていた.
.ukigumo.ymlではこれ以外にもnotificationsという項目が設定できて,これが便利.
テストの結果を任意のNotifierに渡して,通知を飛ばすということができる.
例えば,以下のように書いてやると,GitHubのStatuses API *3 を使ってテスト結果をGitHubのcommitに反映させる,みたいなことが可能.

notifications:
  guthub_statuses:
    - api_endpoint: https://api.github.com
      access_token: __ACCESS_TOKEN__

他にも色々な通知 (とは言え限定的なのだけれど……) に対応している.Ukigumo::Client::Notify::*というモジュールがそうした通知に対応している *4.<追記ここまで>


ここらへん,現状公式のドキュメントが無いので書く必要を感じている.

とにかく,こういうものを置くと,Ukigumo::Clientは上手く処理してくれる.

3. (例えば) GitHubのWebHooksに登録してやる

リポジトリにpushされたらその都度テストが走る,みたいな事をさせたいのでGitHubのWebHooksを設定する.

リポジトリの設定のWebHooksのところに,Ukigumo::AgentのサーバのAPIに対するアドレスを突っ込んでやる.
例: http://your.ukigumo-agent.net/api/github_hook

push以外のPayloadが来てもしょうがないので,Push Onlyで問題ない.

(今回はGitHubを例に採っているが,別のものでも構わない.その場合,登録するアドレスは`http://your.ukigumo-agent.net//api/v0/enqueue`のようになると思う *5.しかしここ最近のUkigumoはGitHubに寄せていて,「GitHubを使っていると更に便利!」という風になっているという旨を記す)

4. リポジトリにpushする

こうすると,GitHubリポジトリにpushされるや否やAgentサーバがそのHookを受け取り,Clientを立ち上げてテストを実行し,その結果をServerに投げるという一連の処理を実現できる.

Ukigumo関連の設定の勘所

Ukigumo::Server

サーバを立ち上げる時のオプションである--config=/path/to/config.plに食わせるコンフィグファイルの話.
コンフィグファイルは以下のような感じになる.

+{
    'DBI' => [
        'dbi:SQLite:dbname=deployment.db',
        '',
        '',
        +{
            sqlite_unicode => 1,
        }
    ],

    max_num_of_reports => 5000,
    max_num_of_reports_by_branch => 1000,
    enable_compression => 1,
};

DBIはもちろんDBの設定で,Ukigumo::ServerはMySQLSQLiteに対応している.たいていの場合はSQLiteで問題がない (と思う).
max_num_of_reportsmax_num_of_reports_by_branchはそれぞれ「保存するレポートの総個数の上限」と「ブランチごとの保存するレポートの個数の上限」を表している.これを超えると,古いものから順に自動的に消去される.
enable_compressionは,レポートの内容をgzip圧縮するかどうかの設定で,たいていの場合はenable (つまり1) にすると良いと思う.

Ukigumo::Client

特になし..ukigumo.ymlを使えば良いという位.

Ukigumo::Agent

特になし.強いて言えばukigumo-agentコマンドには--timeoutというコマンドがあって,テストの実行に指定した以上の時間がかかると強制的に処理を終了させる,ということが出来る (その場合はTIMEOUTという風になり,失敗扱いになる).

そんな感じです

かなり駆け足でしたが,こんなふうにすると使えますよ,という感じでした.
割と簡単に導入できることがお分かりいただけたと思います!!
「単純にテストを走らせて,その結果だけとれればいいワ」みたいな用途だとハマるのではないでしょうか.

ああ,次は公式のドキュメントだ……

突然ですが職質テックトークの12回目やります

唐突ですが職質テックトークの12回目を今日の18:00位からやります.
ゲストは以前にも1回お越しいただいた[@uzulla:twitter]さんです.

Future PHPやAlt PHPの話などをする予定です.
以下のURLで配信しますのでよろしくお願いします.

http://www.ustream.tv/channel/shock-sheets-tech

Gitでmerge済みのブランチをローカル・リモート共々消す

merge済みのブランチがいつまでも環境に居座っていると精神衛生上よろしくないのでこまめに消す派なのですが,いちいち手作業でやるのもダルいしコマンド一発ですべてを片付けたいというのが人情と言うものなので,最近ではゴリッとスクリプトを書いてそれを使っています.

ここにも同じものを置いてあります.
シェル力が低いので,正直これが良いやり方なのかどうかはわかっていませんが,とりあえず動いていて便利なので記した次第.

GitHub Webhooksのpushイベントで重複しているcommitを判別したい

TL;DR

commitオブジェクトに生えているdistinctプロパティを見れば良い.
distinctが0の場合,それは重複しているcommitであることが分かる.
Ref; https://developer.github.com/v3/activity/events/types/#payload-18

本編

さて,GitHubのWebhooksのpushイベントを受け取って,それをIRCや他のチャットツール等にフォワードしたくなるようなことがままあると思います.

これをナイーブに実装しようとすると,pushイベントを受け取って,そのpayloadに乗ってくるcommitsをベロっと舐めてフォワードするような感じになるでしょう.
つまり,

2ac1745 commit3
26cecfa commit2
8ee5552 commit1

というcommit郡がpushされると,これらのcommitの情報がフォワードされるという感じですね.


で,例えばこの場合のpush先がfeatureブランチだったとして,そのfeatureブランチをmasterブランチにmergeするとどうなるかというと,webhookのpushイベントが発火して,merge commitと共に*1 上記のcommitsの情報が再びpayloadに乗ってやって来ることとなります.
このpayloadの情報をすべてフォワードすると,既にフォワードされた内容が再びフォワードされてしまうことになるので具合が悪いことがあります.


これをどう解決するかというと,冒頭に書いたとおりcommitのオブジェクトに生えているdistinctプロパティを見れば良くて,このプロパティが0の時は重複しているcommit (雑な言い方をすると,過去に1度でもpushイベントのpayloadに乗ったことのあるcommit) で,1の時は重複していないcommitであるということが分かります.
従って,既にフォワードした内容を再度フォワードしたくない場合は,distinctが1のcommitだけをフォワードすれば良いという事になります.
(Perlのコード例で恐縮ですが,つまりこんな感じです: https://github.com/moznion/App-GitHubWebhooks2Ikachan/blob/621e7ddef9d0d05a1396a8325a436f74de17e30a/lib/App/GitHubWebhooks2Ikachan/Events/Push.pm#L15)


かつてはHead Commitのcommit logを見て,「“Merge”から始まるcommitだから,これはmerge commit!」みたいな野蛮な方法で重複commitの判別を涙ぐましく行なっていたわけですが (しかもこの方法だとFast-Forwardの場合に対応できない!),distinctを見ればそんな無駄な努力をする必要はありませんでしたよ,という話でした.

*1:Fast-Forwardの時はmerge commitは無いでしょうが

COOKPAD 5-day winter internshipに参加したのでポエムを

参加してまいりました.
途中までは事実を述べて,途中からはポエムになります.どこからポエムが始まるか,みんなで探してみよう!


開催期間中は毎朝6:30に起床してはdoor2doorで2時間かけて,それも満員の中央線と山手線を駆使して出勤しなければならないという,朝と満員電車に弱い僕にとってはまさに試練とも呼ぶべき催しで,僕の心は幾度も布団の誘惑に屈しそうになりましたが,奇跡的に1日たりとも遅刻せずにインターンシップを終えることが出来ました.というか朝6:30って言ったら僕のような人間にとっては午前3時にも匹敵する早起きですよ!*1


さてインターンシップの内容ですが,1週間でスマートフォンアプリをモリモリッと企画してそれをグワワッと実装して,それをジャーンとプレゼンするという大変にエクストリームリィな内容でした.「1週間でスマートフォンアプリを作る」というのは字面だけを見るとさほど難しいことではないように思えるかもわかりませんがトンデモナイ.時間とはここまでここまでここまで足りないものか,という事を実感した次第です.


率直に言えば,僕はスマートフォンアプリの開発にそれほど興味があったわけでも無いし,アプリケーションの企画という活動について言えば輪をかけて興味がなかったので,「必然的に」という言い方もいかがなものかとは思いますが,僕が持っているそれらにまつわるスキルは低いワケで,当然ながら繰り出される成果物のクオリティはそれはもう大変に大変微妙なものが出来上がったという結果は想像に難くないでしょう.

しかしながら時同じくしてインターンに参加した皆さんの成果物等々を見ると,アイデアは面白く,アプリの品質は高く,プレゼンも明朗,質疑応答も的確とそれはもう力の差をまざまざと見せつけられたワケですよ.




これは悔しいなと.




「興味が無いから」とか「俺はこれだけで十分だから」とか,そういう「〜から」というのは単なる「やらない」という事を正当化する為の言い訳に過ぎない事は自分でも重々承知していて.それでもなお,「僕は興味が無いから」などと宣ってこの程度の結果しか出せないというのは完全に怠惰であるし慢心であるし邪悪でしかない.確かに興味が無い事について興味のある素振りを見せるとそこには確実に苦痛が待ち構えているし,実際この1週間は僕にとってひっじょ〜〜〜〜〜につらかったという事は表明する.しかしそのように「興味ねえーし」というスタンスを貫いて視野角を狭めて得をすることがあるのだろうか? これは反語ではない.正直どうなのかはわからない.これについてジェネリックな結論を出すには,僕にはあまりに経験が足りないし知識も足りない.しかし今回に限って言うと,それによって得をしたことは1つとて無い.微視的に見れば,興味が無い分野であっても,気合と愛で能動的に興味を持つべきだと言える.しかし人生は有限だ.無限に興味を持ち,それを吸収することは叶わない.


例えばこの話題は,「どのようにキャリアを積むか」という話題にも通じると思う.
多角な方面の力を付けて,所謂フルスタッキーな力を付けて,所謂フルスタックな,所謂フルスタックエンジニアとして生きていくのか,あるいは何か「これだ!!!」というものを見つけて,それ一本槍に,そこにパラメータを極振りして突き抜けたエンジニアとして生きていくのか,あるいはのらりくらりと過ごして所謂IT芸人として生きていくのか,あるいはエンジニアをやめるか,あるいは,あるいは……
興味をどこにどう持つか,というのはそういう話だと思う.


ところで僕はウィザードリィが好きだ.ウィザードリィではとりあえず「ちから」と「せいめいりょく」をゴリゴリ上げて,脳筋パーティを作って戦うのが好きだ.僕は阿呆なので,できるだけ魔法の使用回数のことは考えたくない.しかしこのパーティでは長くダンジョンに潜ることは出来ない.全員が全員脳筋野郎ではパーティは回って行かないのだ.従って,パーティのそれぞれのメンバが別方向の能力を特化させ,力を合わせて戦う必要がある.
これを現実に当てはめると,自分のどのパラメータに値を振るかというのは重要な問題で,これにはひょっとすると時期が関係するかもしれない.例えば周りにいるエンジニアがみんな脳筋ばかりな時期に,自分も脳筋にパラメータを振って生きていくのは相当なマッチョじゃないとつらい気がする.しかしだからといって,興味の薄い分野にパラメータを極振りするのも違うベクトルのマッチョさだとも思う.本当は剣で戦いたいのにティルトウェイトを唱え続ける人生で良いのだろうか.難しい問題だ.


また,僕はファイナルファンタジーも好きだ.しかし赤魔道士を愛用したことはシリーズを通して一度たりとも無い.やはり何かに特化している方が好きなんだと思う.赤魔道士にメテオは使えないのだ.




僕は何を言っているんだ?




とにかく,クックパッドのインターンは非常に示唆に富んでいましたし,皆さん総出で僕の頭をスカンと殴ってくれたお陰で甘い認識が晴れたと思います.得るものは,確かに多かったと言えるでしょう.
本当にありがとうございました.

*1:おや待てよ,午前3時って言ったら普段の僕なら起きてるな

「UNIXという考え方」を読んだ

UNIXという考え方」をAmazonのwish listに入れていたらid:kenjiskywalkerさんが贈ってくださったので読みました.お陰でUNIXという考え方を学べました.ありがとうございます!


本書では一貫して「プログラムを小さく作る」という事と「1つのプログラムには単一のことだけを上手くやらせる」という事について言及されています.
プログラムを小さく作るということによって,そのプログラムはコンピュータのリソースに対して優しくなり,なおかつ巨大なプログラムと比較して人間が理解するのが簡単になるので保守がしやすくなり,かつ他の部品と組み合わせやすくなるという論旨です.
プログラムを小さく作ると,必然的にそのプログラムは多くの責務を負えなくなる為,自然とプログラムは単一の機能のみを持つようになります.従ってこれら2つの考え方は対になっていると言えるでしょう.
本書で言われている「プログラム」と言うのは,恐らくexecutableな1つの実行ファイル (例えば1つのシェルスクリプトやコマンド) を指しているものと思われますが,この考え方は例えば「1つのメソッドには1つの仕事だけをさせる」というふうにメソッド (あるいは関数) に負わせる責務の範囲を限定する事や,「全知全能の神クラスを作らない」のようにクラスに負わせるべき責務の範囲を狭める,などといったプログラムの設計に対しても応用できると思いました.
このようなことは確か「リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)」にも書いていた気がします.


データは全てASCIIで保存するべきで,デバイス依存のバイナリファイルで保存するな,という話も参考になりました.これは,データは持ち運べなくなった時点で価値が無くなり死ぬので,データの価値を殺さない為にも可搬性を維持するのは重要であるという意味で,恐らく現在だとASCIIではなくUTF-8で保存するのがベターなのでしょうが重要な知見だと思いました.確かにコンピュータ間でデータコンバートが必要になるのは地獄でしかありません.


UNIXという考え方において重要なポジションを占める「ソフトウェアの梃子を使う」という考え方は,どことなくオブジェクト指向の考え方に似ているように感じました.ソフトウェアの梃子とは,複数の小さなプログラムを組み合わせて1つの機能を実現するという手法の比喩表現で,これは小さなオブジェクトと小さなオブジェクトがメッセージを送り合う事で協調して動作し,1つの機能を提供するというオブジェクト指向の概念に通じるところがあるように思いました.双方とも小さいパーツを再利用して開発効率を高めるというアプローチで,なるほどという感じです.


また,「できるだけ早く試作する」という事に関しても書かれていて,これは最近話題になった「Team Geek ―Googleのギークたちはいかにしてチームを作るのか」にも書かれていたという記憶があります.最初から完全に正しいソフトウェアを書くことは不可能で,更に状況に応じて仕様は変更されるとした上で,誤った前提のままプロジェクトを推し進めるのではなく,早い段階で試作品を出してそれをテストし,批判を受けることによって方向を修正し,成果物を洗練していくという一連の流れが書かれていました.

わけてもその文脈で

1. 短い機能仕様書を書く
2. ソフトウェアを書く
3. テストをして書き直し,これを繰り返す
4. 必要なら詳細なドキュメントを書く

という開発フローが紹介されており,「それってつまりシンプルなアジャイルじゃん!」と思わず膝を打ちました.


あと参考になったのは「100%の完成度よりも90%の解を探す」という思考です.
僕はいわゆる「異常な努力」というやつをよくやってしまうんですが,なぜその「異常な努力」が必要となってしまうか*1 と言うと「あまり頻度は高くないけれどこういうユースケースに対応したい」だとか「ここをpluggableにすればもっと汎用的に使えるのではないか」だとか,そういった100%の完成度を執拗に狙ってしまうからなのです.
しかしそういう異常な努力によって生み出された機能はやはり実際にはあまり使われなくて,実装のコストと吊り合わない結果になることが大半です.本来は90%の完成度で充分満足しているのに残りの10%に多大な労力を割くのは無駄だと言えるでしょう.
100%の完成度よりも90%の解を探すというのは,「異常な努力」をしそうになった時に一旦待ったをかける良い考え方だと思いました.


さて驚くべきはこれが1990年代前半に書かれた書籍ということで *2,こうした考え方や哲学はこの時点で既に存在した訳です.
近頃巷で話題になっている「アジャイル」や「リーン・スタートアップ」,或いは「リーダブルコード」などといった考え方の源流は当時から既に形成されていた訳で,これらは過激に (あくまで過激に) 言うなれば元々あった考え方にone more thingを加えた上で,耳障りの良い言葉にパッケージングし直したに過ぎないという印象を受けました.

根源的な思考を学ぶ事に対する重要性を再認識した次第です.

UNIXという考え方―その設計思想と哲学

UNIXという考え方―その設計思想と哲学

*1:本来は大抵必要無いのだけれど

*2:勘違いされている方がいるので書きますけど,初出は1994年です.ref: http://www.amazon.com/The-UNIX-Philosophy-Mike-Gancarz/dp/1555581234

Released Perl::PrereqScanner::Lite

(日本語は英語の後にあります)


I released Perl::PrereqScanner::Lite.

https://github.com/moznion/Perl-PrereqScanner-Lite
https://metacpan.org/release/Perl-PrereqScanner-Lite


This module is the fast edition of Perl::PrereqScanner.
Perl::PrereqScanner has been using PPI as tokenizer, however Perl::PrereqScanner::Lite uses Compiler::Lexer as tokenizer. Moreover it excludes dependency to Moose. Consequently, Perl::PrereqScanner::Lite realized the acceleration. It is faster about 30 times than Perl::PrereqScanner *1.


Now this module can extract modules as prereqs that are declared in use statement and require statement. Besides it can extract modules that are declared in extends notation (member of Moose family) by using Moose extra scanner. And it is able to extract version number that is specified as Foo::Bar->VERSION(1.0.0) by using Version extra scanner.

If you want other extra scanners, make module that has such as the name; Perl::PrereqScanner::Lite::SCANNER_NAME which has the method of scan(), and register extra scanner by add_extra_scanner('SCANNER_NAME') method.


I put this module in App::scan_prereqs_cpanfile.
Now, you can try scan-prereqs-cpanfile with fast mode.

$ scan-prereqs-cpanfile --fast

--fast option enables fast mode. Fast mode means, scan-prereqs-cpanfile uses Perl::PrereqScanner::Lite as the backend module. Perhaps it will run at a high speed.

For example, the result of executing this command on HEAD of mojo;

$ time scan-prereqs-cpanfile
real   0m20.386s
user   0m20.132s
sys    0m0.126s
$ time scan-prereqs-cpanfile —fast
real   0m1.174s
user   0m1.074s
sys    0m0.096s


Enjoy!


==


Perl::PrereqScanner::Liteをリリースしました.
https://github.com/moznion/Perl-PrereqScanner-Lite
https://metacpan.org/release/Perl-PrereqScanner-Lite


このモジュールはPerl::PrereqScannerの高速化版です.
Perl::PrereqScannerではtokenizerにPPIを使用していましたが,Perl::PrereqScanner::LiteはtokenizerとしてCompiler::Lexerを使うことに加え,Moose依存を排除する事により,30倍程度の高速化を実現しています *2


現在はuserequireによって宣言されたモジュールに加えて,extra scannerとしてMooseを利用するとMooseファミリーの持つextends記法によって宣言されたモジュールを抜き出すことが出来ます.Versionというextra scannerを用いる事によってFoo::Bar->VERSION(1.0.0)のようにして指定されたバージョンを抜き出すことも可能です.

その他のextra scannerが必要な場合は,scan()というメソッドを持ったPerl::PrereqScanner::Lite::SCANNER_NAMEという名前のモジュールを書いて,add_extra_scanner('SCANNER_NAME')という具合にextra scannerを登録してやると良いです.


試しに,という言い方もアレですが,Perl::PrereqScanner::LiteをApp::scan_prereqs_cpanfileに組み込んでみました.最新版だと,

$ scan-prereqs-cpanfile --fast

という風に--fastオプションを付けてやる事でバックエンドがPerl::PrereqScanner::Liteとなり,高速に動作することが見込めます.おそらく体感出来るレベルで速さを知覚出来ると思います.

[追記]
mojoのHEADでコマンドを実行するとこんな感じになりました.

$ time scan-prereqs-cpanfile
real   0m20.386s
user   0m20.132s
sys    0m0.126s
$ time scan-prereqs-cpanfile —fast
real   0m1.174s
user   0m1.074s
sys    0m0.096s


ぜひお試しくださいませ.不具合等ありましたら教えて頂けると嬉しいです.