Perl Hackers Hub

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

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

CIを使った継続的な更新

ここまで,update-cpanfileを使った更新操作を見てきました。手作業でcpanfileを編集するよりは楽になりましたが,更新を実行し忘れる,コマンドを間違うなど,手間のかかる手順であることには変わりありません。そこで,更新作業を人間が手動で実行する代わりにCI環境から機械的に実行させることで,定期的に決まった手順を繰り返し,手間を軽減します。

その際,update-cpanfileのpinは最初に一度だけ,updateは何度も行うものですので,初回のpinは手動で行い,そのあとのupdateはCI環境から実行するとよいでしょう。

今回は,GitHub Actionsを用いて実現する方法を紹介します。GitHub Actionsは,GitHubと統合されたCIサービスです。update-cpanfileのリポジトリにはサンプルとして,update-cpanfile自体の依存モジュールを更新するGitHub Actions用の設定ファイルを同梱しています。この設定ファイルでは,次の手順を実行してモジュールを更新します。

  • ❶1日に一度タスクを実行する
  • ❷actions/checkoutアクションを使ってリポジトリをcloneする
  • ❸Docker上でupdate-cpanfileをインストールする
  • ❹update-cpanfile update --output jsonを実行して依存モジュールの要求を更新し,結果をJSONとして出力する
  • ❺Pull Requestの本文やタイトルを組み立てるため,実行結果のJSONをjqコマンドでMarkdownに加工する
  • peter-evans/create-pull-requestアクションを使ってPull Request化する

このサンプルによって生成されたPull Requestは,図1にあるように1行1モジュールのリストとなっていて,metacpanへのリンクやChangesへのリンクを掲載しています。開発者は,CIのチェックが通っていることを確認し,Changesを読んでモジュールの変更履歴を把握したうえでマージできるようになっています。定期的に動き,Pull Requestの用意まで自動化されているため,手作業でのミスが入り込む余地のない構成となっています。

図1 自動生成されたPull Request本文

図1 自動生成されたPull Request本文

苦労なく更新するための工夫

筆者のチームでは,update-cpanfileとGitHub Actionsを使った継続的な更新のしくみを運用し,4ヵ月で74件の更新に成功しました。4ヵ月の活動を通じて,苦労なく,継続的にモジュールを更新するために工夫したことを紹介します。

テストや開発用のモジュールは事前に更新しておく

テストに使うモジュールや,アプリケーションの開発のために利用するモジュールは,動作がアプリケーションのユーザーに影響しません。これらのモジュールについては,継続的な更新を行う前処理として,手作業で一気にまとめて更新しておくと,以降の継続的な更新が楽になります。

原始的な方法ですが,update-cpanfile updateコマンドを実行したあとに,生成されたcpanfileから,on develop(開発用のモジュールが記されるセクション)on test(テスト用のモジュールが記されるセクション)の中だけdiffを残す形にテキストエディタで編集することで,開発用のモジュールだけを手動で更新できます。

CIから1個ずつ更新する

update-cpanfileはlimitオプションを実装しており,一度に更新するモジュールの個数を制限できます。筆者のチームでは,毎日のCIからの実行では--limit 1のオプションを付けて,一度に1モジュールずつ更新するPull Requestを作っています。

開発用やテスト用のモジュールと違ってユーザーへの影響がある部分なので,1件ずつ動作確認しながらリリースしています。

更新できないモジュールはスキップする

アプリケーションの都合やモジュールの破壊的な変更などの事情でバージョンを固定したいモジュールがあったとしても,update-cpanfileは容赦なく更新してしまいます。update-cpanfileはignore-filterオプションを持っているので,事情があって更新したくないモジュールの更新はスキップできます。

JSON::XSとDateTimeの更新をスキップする
$ update-cpanfile update --ignore-filter '^(JSON::XS|DateTime)$'
Updated 2 modules
- List::MoreUtils 0.428
- Test::More 1.302181

ただし,このままではモジュールが古びてしまうので,あくまで一時的なスキップという認識で使い,将来的には更新することが望ましいでしょう。

snapshotをCIから作る

新しいモジュールを使ってPull Requestのテストを実行するため,update-cpanfile updateの実行後に,CI上でcarton installを実行し,cpanfile.snapshotを生成してコミットするようにしています。開発者が自由に作業できる手もとの環境ではなく,決まった手順で動くCI環境から生成することで,生成結果を固定でき,意図しないモジュールがcpanfile.snapshotに入り込んでしまうトラブルを避けやすくなります。

筆者のチームでは,GitHub Actions上でcpanfile.snapshotを構築し,Pull Requestに追加でコミットしています。本連載の第61回GitHub ActionsとAmazon ECSを使ったDockerアプリケーションの自動デプロイgeneratecpanfile-snapshot.shを参考にしてください。

レビュアーをランダムにアサインする

モジュールの更新は終わりのない作業ですので,属人化せず,誰にでも運用できる体制を作ることが重要です。筆者のチームではGitHubのTeam Reviewers機能を使って,レビュアーをランダムにアサインしています。ランダムにアサインすることで,メンバー間の負担や知見の偏りを防いでいます。

まとめ

アプリケーションの依存モジュールの管理方法と,管理を楽にする手法について紹介しました。本稿が少しでも参考になり,みなさんのアプリケーションを1日でも長生きさせられることを願っています。

さて,次回の執筆者はkolukuさんで,テーマは「Perlの時間モジュール」です。お楽しみに。

WEB+DB PRESS

本誌最新号をチェック!
WEB+DB PRESS Vol.121

2021年2月22日発売
B5判/168ページ
定価(本体1,480円+税)
ISBN978-4-297-11960-7

  • 特集1
    [さらに速く! さらに書きやすく!]
    詳解Ruby 3
    JITコンパイラ,並列プログラミング,静的型解析
  • 特集2
    UIKit,SwiftUI,iPadOS,ウィジェット
    iOS 14最前線
  • 特集3
    個人と組織の目標がリンクする管理手法
    OKR運用指南

著者プロフィール

hitode909

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

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

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