Skip to content

リンクチェッカーを github-action-markdown-link-check から lycheeverse/lychee-action へ移行 #12018

@KATO-Hiro

Description

@KATO-Hiro

背景・課題

課題 内容
gaurav-nelson/github-action-markdown-link-check が事実上開発停止 上流の tcort/markdown-link-check (npm) のラッパーだが wrapper 固有のバグが放置されている
誤検出が多い 並列度制御が弱く、短時間に大量リクエストを送信 → 対象サーバーが 429/403 を返し「dead」と誤検出
DDoS 懸念 毎日フルスキャンで約 9,600 件の HTTP リクエストを送信

移行先

lycheeverse/lychee-action (lychee v0.x / Rust製)

  • Rust 製で高速・軽量
  • 並列数・リトライ間隔・キャッシュを細かく設定可能
  • GitHub Actions cache を使った結果キャッシュをネイティブサポート
  • 活発にメンテナンスされている(2025 年も定期リリース)

設計方針

負荷軽減

施策 設定値 効果
並列数を絞る --max-concurrency 8 同時に飛ばすリクエストの上限を 128 → 8 に制限。単一サーバーへの同時接続数が減り、スループット(単位時間あたりのリクエスト数)が下がる。リクエスト間に固定の間隔が入るわけではなく、空きスロットができ次第即座に次を送る仕組み
キャッシュ有効化 --cache --cache-max-age 14d 2 回目以降は新規 URL のみチェック
403 ドメインを除外 lychee.tomlexclude リスト リクエスト自体を送らない(後述)
定期実行を週1回に変更 cron: "30 15 * * 0" (日曜 0:30 JST) 毎日 → 週1回

誤検出対策

施策 設定値 効果
429 (Rate Limited) を許容 --accept 429 Rate limit 応答を dead とみなさない
リトライ間隔を設ける --retry-wait-time 3 失敗後 3 秒待ってリトライ
リトライなし --max-retries 0 週次実行+14日キャッシュの構成では、今週の誤検出は来週自然にクリアされる。--accept 429exclude で主要な誤検出原因は既に対処済みのため、リトライは不要

相対パス(./, ../)の扱い:除外せずチェックする

mlc_config.json では ./../ で始まる相対リンクを ignorePatterns で除外していた。

lychee ではこれらを exclude に入れない。理由:

  • lychee は相対パスをファイルの所在ディレクトリ基準でローカルファイルとして解決できる
  • ファイルが存在すればチェック通過、存在しなければ失敗 → 内部リンク切れを検出できる
  • markdown-link-check が相対パス解決に不安定だったため除外していたが、lychee では不要なワークアラウンド

403 ドメインの扱い:--accept 403 ではなく --exclude を使う

現行の mlc_config.jsonignorePatterns は、403 を返すドメインのリストです。

--accept 403(リクエストを送った上でエラー扱いしない)ではなく、exclude(リクエスト自体を送らない)を使うべき理由:

  • 403 Forbidden = サーバーが自動アクセスを明示的に拒否している
  • --accept 403 は拒否している相手にリクエストを送り続けることになり、先方の意向に反する
  • exclude にすることで、リクエスト数も減らせる

429 Too Many Requests とは性質が異なる:

ステータス 意味 正しい対処
429 「今は混んでいる、少し待って」 --accept 429 で許容し、次回チェック時に再確認
403 「あなたのアクセスを拒否します」 exclude でリクエスト自体を送らない

mlc_config.jsonlychee.toml の移行

現行の除外ドメイン(mlc_config.jsonignorePatterns)を lychee.tomlexclude に移行する。
CLI フラグではなく設定ファイルにまとめることで、ワークフロー YAML が肥大化しない。

gaurav-nelson との互換性について

項目 gaurav-nelson lychee
設定ファイル mlc_config.json (JSON) lychee.toml (TOML)
use-quiet-mode 'yes' --quiet
use-verbose-mode 'yes' --verbose
check-modified-files-only 'yes' tj-actions/changed-files で変更ファイル一覧を取得し、lychee の引数として渡す
ignorePatterns mlc_config.json lychee.tomlexclude
retryOn429 true accept = ["429"]
fallbackRetryDelay "75s" retry_wait_time = 3(秒)
retryCount 2 max_retries = 0(リトライなし)

設定ファイル形式は互換性なし。ただし lychee.toml で同等以上の設定を再現できる。

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions