Perl Hackers Hub

第65回 依存モジュールの更新 ―update-cpanfile,GitHub Actionsで実現!(1)

この記事を読むのに必要な時間:およそ 3.5 分

本連載では第一線のPerlハッカーが回替わりで執筆していきます。今回のハッカーは,はてなでマンガビューアを開発しているhitode909さんで,テーマは「依存モジュールの更新」です。

長期間にわたって開発・運用するアプリケーションでは,依存モジュールを管理し,最新版に更新することが重要です。本稿では,アプリケーションの依存モジュールの管理方針のグッドプラクティスと,ツールを使って継続的にモジュールを更新するための手法を紹介します。

本稿のサンプルコードは,執筆時点(2020年11月)の最新であるPerl 5.32.0で動作確認を行っています。本稿のサンプルコードは,WEB+DB PRESS Vol.120のサポートサイトから入手できます。

Perlのアプリケーションでの依存モジュール管理

まず,PerlアプリケーションにおけるCartonを使った依存モジュールの管理について簡単におさらいします。

Cartonを使ったモジュール管理

Cartonは,CPANモジュールの依存管理ツールです。Node.jsにおけるnpmNode Package Managerやyarn,RubyにおけるBundlerと同種のツールで,Perlを使ったアプリケーション開発ではデファクトスタンダードです。

Cartonがモジュール管理のために利用するファイルがcpanfileとcpanfile.snapshotです。

そのうち,開発者が主に触ることになるのはcpanfileです。cpanfileには,アプリケーションが要求するモジュールと,バージョンの範囲を記します。

cpanfile
# List::MoreUtilsの0.418以上を要求する
requires 'List::MoreUtils', '0.418';
# DateTimeの1.50を要求する
requires 'DateTime', '== 1.50';
# JSON::XSの3.00以下を要求する
requires 'JSON::XS', '<= 3.00';

# テストフェーズでのみ要求するモジュール
on test => sub {
    # Test::Moreをバージョンを問わず要求する
    requires 'Test::More';
};

cpanfileを用意したのちにcarton installを実行すると,cpanfileでの指定をもとに依存モジュールがインストールされ,cpanfile.snapshotが生成されます。cpanfile.snapshotには,インストールされたモジュールとそのバージョンが書き込まれます。

cpanfile.snapshot
# carton snapshot format: version 1.0
DISTRIBUTIONS
(中略)
  List-MoreUtils-0.419
    pathname: R/RE/REHSACK/List-MoreUtils-0.419.tar.gz
    provides:
      List::MoreUtils 0.419
      List::MoreUtils::PP 0.419
    requirements:
      Exporter::Tiny 0.038
      ExtUtils::MakeMaker 0

上記のcpanfile.snapshotではList::MoreUtils部分のみを抜粋しています。List-MoreUtilsの0.418以上」という要求をもとに,インストール当時のCPANでの最新版であった,バージョン0.419がインストールされたことが記録されています。

このようにCartonは,cpanfile.snapshotが存在しない場合や,cpanfileとcpanfile.snapshotの状態がずれている場合に,CPANに公開されているバージョンからcpanfileの要求に合うバージョンを探索してインストールします。2ファイル間の状態がそろっている間は,再度carton installを実行しても結果は変わりません。

本番環境の更新がゴール

アプリケーションの依存モジュールを更新するゴールは,本番環境のアプリケーションを,新しいモジュールとともに期待どおりに動作させることです。依存モジュールの更新時には,更新前後の2つのバージョンが登場するほか,どこまで更新するかを決めるためにCPANで公開されているモジュールのバージョンを確認したり,本番環境で稼働しているバージョンを確認したりと,さまざまな要素が登場します。

冒頭のcpanfileでのList::MoreUtilsについて状況を整理すると,次のようになります。

  • 本稿執筆時において,CPANで公開されている最新版は0.428である
  • cpanfileでは,0.418以上という範囲を要求している
  • cpanfile.snapshotには,cpanfileでの要求範囲を満たす0.419が記録されている
  • 本番環境のサーバには,cpanfile.snapshotの指定に基づいて0.419がインストールされている

本番環境のサーバで動いているバージョンは0.419ですが,CPANの最新バージョンは0.428ですので,古びている状態です。cpanfileやcpanfile.snapshotを編集し,本番環境のバージョンを0.428まで上げることができれば,List::MoreUtilsについては更新成功となります。

その際に,本番サーバを直接操作して新しいモジュールをインストールするのではなく,まずはcpanfileでの指定や,cpanfile.snapshotに記録されたバージョンを書き換え,それらのファイルの指示に従って本番環境に新しいバージョンをインストールするのが,Cartonで管理されたアプリケーションのモジュール更新の流儀となります。

最新のモジュールを使うことの重要性

ここでは,最新のモジュールを使うことの重要性を説明します。

新しいことは良いこと

モジュールが新しくリリースされる理由は,不具合の修正,新機能の追加,パフォーマンスの改善など,モジュールの利用者にとって喜ばしいものばかりです。モジュールの不具合修正やパフォーマンスの改善は,そのままアプリケーションの不具合修正やパフォーマンスの改善につながることが期待されます。

このようにモジュールの更新は,モジュールの利用者である開発者だけでなく,アプリケーションのユーザーにとってもメリットがあります。⁠新しいモジュールは良いモジュール」ということで,どんどん更新しましょう。

脆弱性はいつ発見されるかわからない

利用中のモジュールに脆弱性が発見され,脆弱性の修正がリリースされた場合には,アプリケーション側ではすみやかな更新が要求されます。このとき,アプリケーションが古すぎるモジュールを使っていると,更新に手間どり,脆弱性の対処に時間がかかる恐れがあります。したがって,ちょっとした更新であっても,モジュールは日ごろからこまめに更新しましょう。

著者プロフィール

hitode909

株式会社はてな所属。ブログサービスやマンガサービスの開発に携わる。

趣味はサウナ。京都中の銭湯を巡り,サウナのために旅行に出かける。

GitHub:hitode909
URL:https://blog.sushi.money/