GitLabCIでリンクチェックを日常的に行なう

Webページ内のURLリンクをチェックしたくなることがあります。
リンク切れやサーバエラーとなっているリンクがないか、そもそもチェックしようとしているURL自身が存在しているか、といったものです。

具体的には、次の内容を手作業で確認した経験はないでしょうか。

  • URLを変更した際に、サイト内の他のページに記載されているリンクに変更漏れがないか確認する
  • ページを非公開にした際に、サイト内の他のページから参照されていないか確認する
  • 新しくページを追加したとき、既存のページを変更したときに、他のページが500エラーになっていないか確認する *1

1度ぐらいなら手動で確認してよくても、ページ数が多いと修正のたびにすべてを確認するのは大変かもしれません。

普段は、Integrity というアプリケーションを使っています。 大体はこれで事が足りていて、URLリストに対するチェックと各URLに対する再帰的な確認が行えるので助かっています。

一方で、macOSGUIでの動作に限られているため、開発作業と一緒に日常的に確認を行うには少し面倒で後回しにしがちでした。 今回は、CIツールで日常的に確認できる方法を探してみます。

LinkChecker

手っ取り早く確認するには、LinkChecker を使うのが手っ取り早そうです。
コマンドライン上で動作します。

LinkChecker is a free, GPL licensed website validator. LinkChecker checks links in web documents or full websites. It runs on Python 2 systems, requiring Python 2.7.2 or later. Python 3 is not yet supported.

コマンドライン上で実行する場合はdockerイメージが用意されているので、次のコマンドで実行できます。

docker run --rm -it -u $(id -u):$(id -g) linkchecker/linkchecker --verbose https://9bo.hateblo.jp

実行例は次のとおりです。

$ docker run --rm -it -u $(id -u):$(id -g) 9bo/linkchecker --verbose https://9bo.hateblo.jp
INFO linkcheck.cmdline 2019-10-13 21:18:25,168 MainThread Checking intern URLs only; use --check-extern to check extern URLs.
LinkChecker 9.4.0              Copyright (C) 2000-2014 Bastian Kleineidam
LinkChecker comes with ABSOLUTELY NO WARRANTY!
This is free software, and you are welcome to redistribute it
under certain conditions. Look at the file `LICENSE' within this
distribution.
Get the newest version at http://wummel.github.io/linkchecker/
Write comments and bugs to https://github.com/wummel/linkchecker/issues
Support this project at http://wummel.github.io/linkchecker/donations.html

Start checking at 2019-10-13 21:18:25+000

URL        `https://9bo.hateblo.jp'
Real URL   https://9bo.hateblo.jp
Check time 0.168 seconds
D/L time   0.001 seconds
Size       28.25KB
Result     Valid: 200 OK

// 略

Statistics:
Downloaded: 3.42MB.
Content types: 1 image, 122 text, 0 video, 0 audio, 23 application, 0 mail and 642 other.
URL lengths: min=15, max=229, avg=70.

That's it. 788 links in 791 URLs checked. 0 warnings found. 0 errors found.
Stopped checking at 2019-10-13 21:19:16+000 (51 seconds)

オプションはMan pageから確認できます。

GitLab CI で使う

コマンドラインで実行できることが確認できたら、そのままCIツールに組み込んで開発と一緒に実行したくなります。

GItLabCIの場合、単一のURLに対してリンクチェックを実行するには、 .gitlab-ci.yml に次の設定を行えば良さそうです。

pip repository からインストールできるバージョンは古いため、git repositoryからインストールします。
LinkChecker の Dockerfile を参考にしました。

複数のURLに対して実行する

複数のURLに対してチェックを行う場合は、対象のURLを記載した urls.txt を用意して、 .gitlab-ci.yml は次のように設定します。

このとき、 urls.txt は次のような内容です。

https://9bo.hateblo.jp/entry/2019/09/15/010647
https://9bo.hateblo.jp/entry/2019/03/31/202606

指定したURLに記載されているリンクに対してのみリンクチェックを行いたい場合は、linkchecker に -r オプションをつけます。

cat urls.txt | linkchecker --stdin --verbose -r1

UserAgentを指定したい場合は、次のように指定します。

cat urls.txt | linkchecker --stdin --verbose --user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 12_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0 Mobile/15E148 Safari/604.1"

その他のオプションはMan pageから確認するとよいでしょう。

おわりに

LinkChecker を使って、GitLabCI でリンクチェックを行えるようにしてみました。

今回の内容を活用すれば、E2Eテストが用意されていないプロジェクトの場合でも簡易的にかつ継続的に動作確認が行えそうです。
git push をトリガーとして、developブランチやreleaseブランチがデプロイされた環境に対して自動実行したり、スケジューラで定期的に実行してみても良いと思います。

*1:本来はUnitテストやE2Eテストで実施すべき内容ですが、そこまで準備が十分でないプロジェクトの場合もあります(恐怖です)