Stackageに自分のパッケージを上げる

最近はもうstackとstackageには頼りっきりで、使いたいパッケージがstackageに入っていないとちょっとイラッとくるくらいになってきたが、そういえば自分もいくつかのパッケージをhackageに上げている。大したものではないとはいえ、それらをstackageに載せないのはスジが通らないなと思い、stackageに上げることにした。

さて、自分のパッケージをstackageに上げるにはどうすればいいか。必要なことは以下のページに書いてある。

手順としては、stackageレポジトリをforkして、build-constraints.yamlに自分の名前とパッケージのリストを追加して、pull requestを送るだけだ。

ただし、stackageに入れるパッケージは以下の3点を満たす必要がある(あるいは、満たす「べき」である?)

  1. All packages are buildable and testable from Hackage.
  2. All packages are compatible with the newest versions of all dependencies.
  3. All packages in a snapshot are compatible with the versions of libraries that ship with the GHC used in the snapshot

travisスクリプトとビルドエラー対応

第1の条件はこれまで通りきちんとパッケージングしてhackageに上げれば満たされる。

テストに関しては.travis.ymlが提供されているのでこれをサクっと利用するのがいいだろう。

GHC + cabalおよびstackを用いたビルドパターンをいくつかのバージョンでやっている。なかなか良さそうだ。

なお、stackageに上げたパッケージがビルドに失敗する場合、「1週間以内を目安に解決しろ」とのこと。


依存パッケージのバージョン上限問題

第2の条件は、stackageに上げるパッケージが依存するパッケージのバージョン上限に関係する。

例えば、.cabalファイルに以下のようなbuild-dependsがある場合、

  build-depends: foo-bar >=0.3.0.1 && <0.5

foo-bar-0.5がリリースされると第2の条件が満たされなくなる。この場合、foo-barに依存しているパッケージの作者が(1週間以内を目安に)解決しなければいけない。foo-barの変化が小さければ新バージョンでのビルドとテストを確認してbuild-dependsを変更するだけでよい。そうでない場合はちょっと厄介なことになるだろう。

ここで問題となるのは、依存パッケージが他人のものである場合、それがいつメジャーバージョンアップされるか分からないということだ。この問題に対処するために、以下のサービスが公開されている。

このサービスは検索したパッケージの依存パッケージのバージョン上限を調べ、それが現在の最新版をカバーしているかチェックしてくれる。パッケージ検索ではauthorフィールドも検索対象になるので、例えば筆者の場合は

をウォッチすればいい。RSSフィードも吐いてくれるので、こいつをフィードリーダーに突っ込んでおけば速やかに依存パッケージのメジャーバージョンアップに対処できる、はずだ。

なお、PVPには反してしまうが、依存パッケージにバージョン上限を記載しないという考え方もある。この件についてMichael Snoyman氏がブログに書いている。

stackage的にはバージョン上限はあってもなくても構わない、ということだろうか。また、stack sdistとstack uploadには--pvp-boundsというオプションがあり、build-dependsのバージョン下限・上限をいい感じに書き加えてくれるらしい。

個人的には、今のところbuild-dependsのバージョンは自分で管理すればいいと思っている。いろいろ規模が大きくなると破綻しそうな気もするが。


依存パッケージのバージョン下限問題

第3の条件は依存パッケージのバージョン下限に関係する。要は、「GHCにバンドルされるパッケージバージョンがカバーされるくらいには下限を広く取れ」ということである。

このことの理由は以下で詳細に説明されている。

"lenient"とは"not as strict as expected"という意味らしい。

例えばあるGHCバージョンにパッケージfoo-bar-0.2がバンドルされており、自分のパッケージのbuild-dependsがfoo-bar >=0.3だとする。すると、バンドルされたfoo-bar-0.2とユーザスペースにインストールされたfoo-bar-0.3が混在する状況になりうる。これが結構ややこしいコンパイルエラーを引き起こし、運が悪い場合は詰む。

さらに言うと、Haskell Platformで提供されるパッケージバージョンをカバーしておくといいようだ。これらは以下のページで確認できる。

ぶっちゃけそれほど多くないので、現状では人力でチェックすればいいと思う。