リンクチェック

ローカルおよび CI でのサイトのリンクチェック方法。

サイトのリンクチェックには Lychee を使用しており、コミット済みの外部リンクのチェック結果のキャッシュによって裏付けられています。

ローカルでリンクをチェックするには、以下を実行します。

npm run check:links

よく使うコマンド

コマンドチェック範囲
check:linksサイト全体とリポジトリのルートにある Markdown ファイル
check:links:internal同じ範囲、オフライン(外部リンクなし)
check:links:production-internal同じ範囲を本番ビルドに対して実行、オフライン
fix:link-cachecheck:links のエイリアス。リンクキャッシュを更新するために使用

check:links と check:links:internal スクリプトは BUILD_KIND のビルドに対して実行されます。 詳細はフルビルドとリーンビルドを参照してください。

未公開ページへのリンク

非本番のサイトビルドにはドラフトや将来の日付のページが含まれますが、本番ビルドではそれらが省かれます。 そのため、そのようなページへのリンクはデプロイプレビューでは機能し check:links も通過しますが、本番サイトでは 404 を返します。 check:links:production-internal スクリプトはこれを検出します。 リーンな本番ビルドに対してオフラインチェックを実行し、ビルドが生成しなかったターゲットにリンクしているページを報告します。 失敗時のコントリビューター向けの説明は CHECK LINKS (production, internal) を参照してください。

本番チェックは check:links を補完します。 設定が除外するページ(特に乖離したローカリゼーションページ)からのリンクは、どちらでもチェックされません。 外部リンクとその結果を記録するリンクキャッシュは check:links に属します。 オフライン実行では何もフェッチしないため、記録する結果がありません。

設定

リンクチェックは生成された git 管理外の lychee.toml を読み込みます。 generate:config:links スクリプトは lychee.base.toml と 2 つのフロントマターフィールドから算出された除外設定を組み合わせて設定を導出します。

  • link_check_exclude_path:リンクチェッカーがスキップすべきページのサイト相対パス正規表現のリスト。 ブログのページネーションや古いブログ記事などが該当します。 例については content/en/blog/_index.md を参照してください。
    • すべてのロケールをカバーするには、パターンを ^(../)? で始めてください。 オプションの ../ は ja/ のような 2 文字のロケールパスセグメントにマッチします。
  • drifted_from_default:乖離したローカリゼーションページをマークします。 ステータスは true(英語の対応ページが変更された)または file not found(英語の対応ページが削除された)です。
    • 乖離したページからのリンクはチェックされません。 古くなっている可能性があるためです。
    • 乖離したページへのフラグメントリンクは、そのページがビルドに含まれておりその URL の唯一のコンテンツファイルである場合にスキップされます。 それ以外の場合は完全にチェックされます。 実質的な効果として、ページの存在は確認されフラグメントのみがチェックされません。 これは乖離の趣旨に沿っています。 ページには英語の対応ページがその後追加したセクションが欠けている可能性があり、ロケールフォールバックとして表示される英語ページはそれらのセクションにリンクしています。 実装:scripts/lychee/config/index.mjs の toExcludePaths()。

保存された乖離ステータスは次のハウスキーピングステータス同期がマージされるまで英語の変更に遅れるため、ジェネレーターは乖離保留中のページも乖離として扱います。

  • 乖離保留中のページ:乖離ステータスのベースライン以降に英語のページが変更または削除されたロケールコピー。 ただし、そのコピー自体がベースライン以降に変更されている場合はチェック対象のままです(誰かがそのページの作業を行っているため)。
  • 乖離ステータスのベースライン:ツリー全体のステータス同期(npm run fix:i18n)によって data/l10n-drift.yaml に記録された main ブランチのコミット。 ローカルでのステータス同期はこのファイルを書き換えることがあります。 記録されたコミットは upstream に存在しない可能性があるため、その書き換えはコミットしないでください。

ベースラインが存在しないか解決できない場合、設定の生成は失敗します。 CI ジョブは最初にベースラインコミットをフェッチします。 ローカルでは以下のいずれかを行ってください。

  • 不足している履歴をフェッチする:git fetch upstream main。
  • ベースラインをオーバーライドする:DRIFT_BASELINE=HEAD npm run check:links は現在のコミットに対して比較するため、コミットされていない英語の変更のみが乖離保留として扱われます(保存済みステータスのスキップは引き続き適用されます)。

外部リンクのチェック結果は link-cache.jsonc にキャッシュされます。 このファイルは link-cache パッケージが管理するコミット済みキャッシュです。 Lychee 独自のキャッシュファイル .lycheecache は実行ごとにそこから導出され、git 管理外です。 ファイルのフォーマット(エントリを手動でシードする方法を含む)については所有キャッシュを、チェック実行がどの URL をフェッチしどの URL をキャッシュから提供するかについてはオペレーティングモデルを参照してください。 手動編集は意図的なシード専用です。 単にリンクチェッカーをブロックする URL の場合は、かわりに ?link-check=no を URL に付加してください(有効な外部リンクの対処を参照)。

キャッシュは複数のスケジュール実行ワークフローとコンテンツ PR によって日常的に更新されるため、同時更新は Git の 3 ウェイマージで競合する可能性があります。 異なる URL であっても、両サイドが同じソート位置のギャップに挿入したり、一方がプルーニングしたエントリをもう一方がリフレッシュまたは隣に挿入した場合(ハンクがエントリを分割することがあります)に競合が発生します。 ブランチのキャッシュ変更が通常のチェック結果である場合は、main のファイル全体を取得してチェックを再実行すれば、ブランチに必要なものが再追加されます。 それ以外の場合は所有キャッシュの競合ルールに従い、チェックを再実行してファイルを正規化してください。

外部リンクを追加または変更した場合は、PR を送信する前に npm run check:links を実行し(サイトビルドが実行時間の大部分を占めます)、更新された link-cache.jsonc をコンテンツの変更と一緒にコミットしてください。 そうしないと CACHE updates committed? チェックが失敗します。 復旧手順については CACHE updates committed? を参照してください。

キャッシュの更新とハウスキーピングワークフロー

以下のワークフローは毎日スケジュールされ、リンクチェックコマンドを実行します。

ワークフローリンクチェックコマンド
Refcache refreshlog:check:links(フルビルド、プルーニング後)
ハウスキーピング(fix-and-test:all)fix:link-cache(フルビルド)
レジストリバージョンの自動更新fix:link-cache

Refcache refresh は最も古いキャッシュエントリをプルーニングし(件数はワークフローの入力値)、リンクチェックを再実行することで、プルーニングされた URL のうちサイトでまだ使用されているもののキャッシュエントリを更新します。

失敗したリンクのダブルチェック

一部のサイトはブラウザには有効なページを提供しますが、Lychee のようなプレーンな HTTP クライアントを拒否します(ボットウォール、crates.io の無条件 404、npmjs.com のサインインリダイレクト)。 キャッシュされた失敗は毎回の実行で再フェッチされるため、そのようなサイトへのリンクはチェックのたびに失敗することになります。

ダブルチェックツールは、Lychee が報告した失敗をブラウザグレードのプローブで再検証し、解決した URL を link-cache.jsonc に合成ステータス 206(「OK by analysis」)で記録します。 解決できない URL は、チェックが記録した失敗のまま残り、refresh PR でトリアージされます。 Refcache refresh ワークフローはリンクチェックの後にダブルチェックを実行します。 キャプチャされたログに対してローカルで実行するには、以下を使用します。

npm run log:check:links
npm run fix:link-cache:double-check

オプションについては npm run fix:link-cache:double-check -- --help を実行してください。 プローブの動作とセットアップについては double-check README を参照してください。

CI での動作

check-links.yml ワークフローはサイトを BUILD ジョブで(リーン)ビルドし、そのアーティファクトを CHECK LINKS ジョブと共有するため、ローカルでの実行と CI は同じビルドをチェックします。 リンクチェックが失敗するとそのジョブは失敗し、更新されたキャッシュを CACHE updates committed? ジョブに渡します。 このジョブは、実行によってコミット済みの link-cache.jsonc が古くなった場合に失敗します。

CHECK LINKS (production, internal) ジョブは BUILD と並行して独自のビルドで実行されます。 check:links:production-internal を実行します。