RedmineのtrunkのDockerイメージを毎日自動でビルドする

この記事はRedmine Advent Calendar 2019の4日目です。

3日目の記事はankosoftさんの権限のない一般ユーザーがRedmineのマイページのカレンダーを乗っ取った件でした。一般ユーザーが自由にRedmineの機能を拡張できるようになるといろいろ捗りそうな現場はたくさんありそうですね。

最初にまとめ

RedmineのDockerイメージいろいろ

今年の11月に開催されたRedmine.tokyoの参加者アンケートでは、DockerでRedmine環境を構築している人は1割未満、増加傾向にあるものの普及はこれからという状況のようです。

すでにDocker Hubには実運用が可能なDockerイメージがいくつか公開されています。

公式のイメージとしてhttps://hub.docker.com/_/redmineが提供されています。「公式」といってもredmine.orgのコアメンバーが管理しているわけではなく、docker.comとしての公式イメージという位置づけです。GitHubリポジトリhttps://github.com/docker-library/redmine)がありますが、RedmineというよりDockerのコミュニティーに近そうな人のコミットも目立ちます。

sameersbn/redmineは人気のあるサードパーティのイメージです。SSL対応なども組み込まれているので、手間をかけずに実運用に乗せたいときには便利かもしれません。

trunkのソースコードを差し込む

今回は手軽に新機能の動作検証ができるイメージを作りたかったので、Dockerの公式のRedmineイメージをベースにします。

シンプルなRailsアプリであれば一からDockerfileを書いてもよさそうですが、公式のDockerfileはRedmineの特殊な挙動(database.ymlの内容によってGemfileの評価結果が変わる)にがんばって対応しているので、その成果をそのまま使わせていただくことにしました。*1

Dockerfileの中でソースコードのtarballをwgetで取得している箇所をsvn coに書き換えるだけです。 中間証明書が抜けていたり、新しめのDebianではTSL 1.0が無効化されているあたりもagileware-jp/redmine-plugin-orbのやりとりを参考にしつつ、まじめに実装しました

TravisCIで毎日ビルドする

Dockerの公式のRedmineイメージのリポジトリでは、TravisCIを使った自動テストを行っています。イメージがビルドできるか確認してから、Redmineのサービスが正常に起動することも検証しています。

テストコードとその呼び出し処理は以下のあたりです。

CIの設定はリポジトリ.travis.ymlに記述されていて、cloneすればそのまま使えます*2。あとは定期的にCIのジョブを実行してイメージをpushする仕組みを付け足すだけで完成です。

TravisCIではCron Jobという機能を使うとジョブを定期的に実行することができます。

Docker Hubにイメージをpushするシェルスクリプトscript/deploy.bashに置いています。仕組みを作った当時はdocker loginにアカウントのパスワードをそのまま使うしかなくてやや不安だったのですが、2019年9月にDocker HubにPersonal Access Tokenが追加されて、いい感じになりました。

Herokuにデプロイする

Dockerイメージが作れたらどこかにデプロイしたくなりますね。今回は無料で手軽に使えるという理由でHerokuを選びました。Dockerイメージがpushされるとhttps://redmine-trunk-demo.herokuapp.com/に自動でデプロイされるようにしています。

デプロイ手順の詳細はここでは省きます。Heroku appと連携しているリポジトリhttps://github.com/vzvu3k6k/heroku-redmine-trunkです。関心のある方はご参照ください。

Redmineのメール通知、ファイルアップロード、リポジトリなどの機能をHeroku上で動かすには個別の設定やプラグインが必要になります。デモ環境では一部の機能が欠けていても差し障りはないだろうということでデフォルトのままにしています。Herokuではデプロイ後にファイルシステムに加えた変更が永続化されないので、おそらくファイルをアップロードしても数時間後には消えてしまうはずです。

また、デプロイ後にbin/rails db:fixtures:loadでテスト用のデータを流し込んで、DBのデータもリセットするようにしています。リセット直後にトップページを開くと、ニュース欄に「John Smith さんが13年以上前に追加」というテキストが表示されていて、コードベースの歴史を感じてしまいますね。

明日はak.iwasakiさんの「新プラグインリリース」です。

*1:公式のDockerfileのライセンスはGPL 2なので、今回のDockerfileのライセンスも同じくGPL 2としています。

*2:Dockerイメージの名前をキーにしてテストコードを探す仕組みになっています。ネームスペースは無視されるので、イメージ名をfoobar/redmineという形にしておけばRedmineのテストが実行されます。

left-padに依存していたプロジェクトの数と、Babelで採用されたことの影響について

問題は、たった17行のコードに、こんなに明らかな問題があるのに、事件が起こるまで誰にも気づかれずに、 Babel を始めとした大量のプロジェクトで利用されていたことだ。 僕は JSer じゃないので憶測だが、この開発者がJS界で超有名人で信頼されていたというよりも、「Babelも使ってるし」といった感じでどんどん依存が広まっていったのでは無いだろうか? Babel の中の人はそこまで考えて依存するライブラリを選んでいただろうか。(Babelよりも先に left-pad に依存していた有名プロジェクトがあったらごめんなさい)

依存するパッケージは厳選しよう - methaneのブログ

この部分を読んでいて

  1. Babelはleft-padにどのような経路で依存していたのか
  2. left-padが削除された時点で、Babel以外でleft-padに依存していたプロジェクトがどれほどあったのか
  3. Babelに依存されたことが、他のプロジェクトの採用の後押しになったのか

が気になったので調べてみた。

Babelはleft-padにどのような経路で依存していたのか

最初にleft-padの依存が入ったコミットではbabel → line-numbers → left-padという依存関係だった。

3/22のBabelからleft-padの依存を取り除いたコミットの時点では、Babelがモジュール化されて(babel-core, babel-helper-transform-fixture-test-runner, babel-traverse) → babel-code-frame → line-numbers → left-padという依存関係になっている。

Babelのパッケージがleft-padに直接依存したことはなかったと思う。git clone https://github.com/babel/babel.git && cd babel && git log -p --full-diff -- '*package.json' | grep left-padを実行してもマッチしなかった。

left-padに依存していたプロジェクトがどれほどあったのか

https://www.npmjs.com/package/left-padで、left-padを直接のdependencies*1 に含むパッケージ(dependents)の一覧を見ることができる。このdependentsを再帰的にたどることでleft-padに依存しているパッケージの一覧が取得できる。

left-padがnpmから削除された当時のdependentsを確認したいところだが、npmjs.comには過去のdependentsを表示する機能はなさそう。

アーカイブサイトを探すと、Wayback Machinehttps://www.npmjs.com/package/left-pad2015年9月のスナップショットがあった*2。このスナップショットを出発点にして、left-padに依存していたパッケージをたどってみる。指定した日時に一番近いスナップショットを検索するAPI*3を使って、できるだけ出発点のleft-padのスナップショットに近い日時のスナップショットを取得した。Wayback Machineに保存されていなければnpmjs.comを参照する。*4

graphvizで依存ツリーを描画してみた様子がこれ。ページの保存時期がバラバラなので正確な内容ではないけれど、line-numbersとprettify-error(これはleft-padの作者によるパッケージ)をハブにして依存が広がっているらしい。left-padが削除されたのは2016年3月なので、半年間で状況が変わっていた可能性はある。

line-numbersの影響

Babelがline-numbersに依存してからは、line-numbersがleft-padのダウンロード数の大半を集めるという状況がずっと続いていたようだ。left-padとline-numbersの月間ダウンロード数をグラフにしてみると*5、ほとんど一致している。一致しすぎてleft-padの線がほとんど隠れた。

ただし、月間ダウンロード数はleft-padのほうが数千から1万数千ほど多いので、line-numbers以外からもそれなりに利用されていたとは言えそう。

Babelが依存したことでleft-padが使われるようになったのか

2015年9月22日の時点でleft-padに直接依存していたパッケージを対象に、left-padが依存に追加されたコミットの時期を調べた。タイムゾーンは揃えていないので日付に±1日の誤差がある。

日付 名前 できごと
2014-03-14 left-pad 0.0.0がpublishされる
2014-03-14 prettify-error left-padに依存する(最初のコミット)(left-padの作者によるパッケージ)
2014-09-21 format-date left-padに依存する(最初のコミット)(left-padの作者によるパッケージ)
2014-12-20 line-numbers left-padに依存する(最初のコミット)
2015-01-13 textlint-formatter left-padに依存する(最初のコミット)
2015-02-21 babel line-numbersに依存する
2015-04-15 component-counter 1.1.0でleft-padに依存する*6
2015-05-20 simple-timestamp left-padに依存する(最初のコミット)
2015-06-11 color2 left-padに依存する
2015-09-11 date-prompt left-padに依存する
2015-09-14 time-tracking left-padに依存する

微妙な結果になった。Babelに依存されてから依存パッケージの増えるペースが早くなっているようにも見える。

Babelが間接的に依存するようになってからleft-padのダウンロード数が激増している*7ので、見た目の信頼度のようなものが高まった感じはあるが、実際にどれぐらいleft-padの普及に貢献したのかは分からない。

Babelが依存したことでline-numbersが使われるようになったのか

http://web.archive.org/web/*/https://www.npmjs.com/package/line-numbers

line-numbersに依存しているパッケージはBabel関連ツールを除けばcastborgしか確認できなかった。大きな影響はなかったように見える。

感想

「依存するパッケージは厳選しよう」という主張はもっともだと思う。有名なプロジェクトが使っているパッケージを参照するというのは自分もよくやるので、Babelの影響でleft-padが使われるようになったという結果がはっきり出るかと予想していたが、意外とそうでもなかった。

line-numbersがleft-padのダウンロード数の大半を集めていたのも予想外だった。もしもline-numberがleft-padに依存していなかったら、騒ぎはもっと小さくなっていたかもしれない。

ところでgraphvizの描画結果、入力上は1本しかないはずなのに、provaからprettify-errorに矢印が2本伸びているように見えるのが気になる。

*1:npmにはdependencies, devDependencies, peerDependencies, bundledDependencies, optionalDependenciesの5種類の依存がある。https://docs.npmjs.com/files/package.json

*2:他にarchive.is, webcite, ウェブ魚拓を確認したが、保存されていなかった。

*3:https://archive.org/help/wayback_api.php

*4:ソースコードはGitHubに置いた。汚くて何をやっているかわからないかもしれない。

*5:集計に使ったコードもGitHubに置いた。

*6:component-counterはリポジトリが更新されていないようだったのでnpmのtarballを確認した。

*7:http://npm-stat.com/charts.html?package=left-pad&author=&from=2014-03-14&to=2016-04-01

QiitaとStack Overflow

Qiitaは技術系のTipsとかを書く場所で、Stack OverflowはQ&Aサイトだから単純な比較はできないんだけど、情報を調べる側から見た差について書く。特に結論はない。

Stack Overflow

複数の回答がついている場合、それぞれの主張を読み取って自分の中でベストな回答を見つける必要がある。スコアが一番高いものだけを読んでいると、後から書き込まれたよりよい答えを見逃す可能性がある。回答が一つの文章にまとまっていればいいのにと思うことがしばしばある*1

おそらく回答を一つにまとめてしまうと、誰が書いた部分が役に立ったかよく分からなくてvoteがうまく機能しないから、めいめいが回答を書くシステムにしているのだと思う。仕方がない。

Qiita

Stack Overflowでは問題を明確に設定しなければ回答が得られないのに対して、Qiitaは自己完結的にエントリを書くことができるので、コードだけがどかっと置かれていて、本人以外が読んでもどういう意味なのかよく分からないものがときどきある*2

*1:「○○とはどのような概念なのでしょうか?」のように、各人によって多様な回答があってまとめることが難しいテーマもあるが、ハウツーなら誰が書いても内容自体は同じようになるだろう。

*2:そういうのを書くのはけしからんとか言いたいわけではないです。他人が読んでも意味が分かるような説明を付けるのは大変だし。

大学図書館は貸出履歴を長期保存していることがある

ネット上で「図書館は利用者のプライバシーを保護するため、本が返却された時点で貸出記録を消去している」という話をしばしば見かける*1。大学図書館では必ずしもそうではない。

大学図書館における個人情報・プライバシー保護という文書では、2005年の私立大学図書館協会西地区部会に加盟する各大学図書館241館を対象とした貸出履歴の扱いについてのアンケート調査の結果が報告されている。資料が返却されても個人の貸出履歴を保有し続けている図書館が87%を占めたという。

"OPAC 貸出履歴"でググると自分の貸出記録を確認する方法を解説したページがいくつも見つかる。ほとんどが大学図書館のものだ。返却後も個人の貸出履歴を保有し続けている大学図書館は今でも多い。

研究や学習のための資料の貸出が主要な目的である大学図書館では、履歴を抹消してプライバシーを厳格に保護するよりも、以前読んだ本を簡単に確認できることのほうが大事だという意見もあるかと思う。確かに借りた本をメモするのは面倒だ。

しかし、上記のアンケートでは、返却後も記録を保持する理由として、利用者からの要望を挙げた回答は17%にすぎず、利用統計を取るためという回答が51%と最も多かった。上記のまとめではオウム事件のときに履歴がすべて残っていたためにプライバシーが保てなくなりました。そのために全国のソフトが履歴を削除するようになったのですと説明されている。はっきりした資料が見つからなかったが、1995年に国会図書館で起きた問題らしい。それから10年後の2005年になっても私立大学図書館ではいまだに貸出履歴が長期にわたって保存されている状態で、貸出履歴を可能な限り保持しないという考え方が根付いていないというのは意外なことだ。 一般的な公共図書館と私立(に限らないかもしれないが)大学図書館ではなぜここまでスタンスが違っていたのか(あるいは現在も違うのか)が気になる。