Dependabot修正

このAstroサイトで失敗しているDependabot PRを包括的に診断し、修正します。`/dependabot-fix <PR番号>` というコマンドで呼び出されたときに使用します。

Dependabot修正 とは?

このスキルは、Astroサイト(EthicalML/ethicalリポジトリ)におけるDependabot PRの失敗を自動的に診断し、修正からマージまでを包括的に実行します。ユーザーがPR番号を指定すると、まずPRのコンテキストを読み込み、CIログやコードベース、リポジトリの規約、テストハーネスをサブエージェントに調査させることで、根本原因を特定します。修正計画はリスクに応じて階層化され、特にレンダリング結果への影響を検出するために、マージベースとのピクセル単位の比較(ビジュアルパリティスイープ)を実施します。これはCIだけでは見逃される視覚的なリグレッションを防ぐための重要なプロセスです。修正は直接Dependabot PRのブランチにコミットされ、CIがパスし、ピクセル差がゼロであることを確認した後にマージされます。最後に、実行結果のレポートをPRにコメントとして投稿し、スキル自体の改善が必要かどうかを評価します。対応するパッケージエコシステムはnpmとGitHub Actionsの2つです。

対応✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/EthicalML/ethical/tree/HEAD/.claude/skills/dependabot-fix

Installed? Explore more 生産性&コラボレーション skills: steipete/gemini, steipete/gh-issues, steipete/skill-creator · View all 6 →

お気に入りのAIに質問する

このエージェントスキルを事前に読み込んだ状態で新しいチャットを開きます。

ドキュメント

Dependabot修正 は何をしますか?

失敗しているDependabot PRを体系的に修正します。ユーザーはPR番号を指定します(例:/dependabot-fix 42)。

このスキルは6つのフェーズ(A~F)で構成されています。フェーズDが完了するまでコードの編集を開始しないでください。フェーズBが完了するまでログの調査に没入しないでください。\n 最初にスクラッチスペースを設定します:

mkdir -p ./tmp && touch ./tmp/null
PR_NUM=<ユーザーからのPR番号>
REPO=EthicalML/ethical

フェーズA — コンテキスト

ステップ1 · PRコンテキスト

メタデータを取得し、PRに関する1段落の要約を作成します(エコシステム、グルーピング、サイズ、セキュリティアップデートかどうか、影響するファイル)。ソースファイルはまだ開かないでください。

gh pr view $PR_NUM --repo $REPO --json title,body,headRefName,labels,files,mergeable,createdAt
gh pr diff $PR_NUM --repo $REPO | head -200

以下を特定します:

  • エコシステム: npm | github-actions — このリポジトリにあるのはこの2つだけです
  • グルーピング: グループ化されている(all、all-security) vs 単独のnpm メジャー(メジャーは設計上allグループから除外されるため、それぞれ個別に届きます)
  • サイズ: ファイル数とおおよそのLOC変更量。npmの場合、package.jsonが変更されたか、package-lock.jsonのみか
  • 変更された依存関係がレンダリング出力に影響を与える可能性があるかどうか — これによりフェーズE(ステップ8.5参照)の要否が決まります

ステップ2 · 高レベルのエラー調査

失敗しているチェックをリストアップし、各失敗ジョブログの最初と最後のエラー行をキャプチャします。まだその意味を調査しないでください — 単に症状を列挙します。

CI(.github/workflows/ci.yml)にはちょうど3つの必須ジョブがあります: lint(ESLint + Prettier)、typecheck(npm run check:ratchet)、build(デモモードの本番Astroビルド、FORM_ENDPOINTなし)。その他の赤いチェックは必須ではありません。

gh pr checks $PR_NUM --repo $REPO

# 各失敗チェックについて、URLからジョブIDを取得しログを取得
gh run view --job <JOB_ID> --repo $REPO --log 2>./tmp/null \
  | grep -iE "error|exit code|##[error]|FAILED|assert|timed ?out" \
  | head -20 > ./tmp/pr-${PR_NUM}-symptoms.txt

出力は以下のような箇条書きにしてください:

  • lint: Prettier check failed: package.json
  • typecheck: astro check reported 3 errors, baseline is 0
  • build: [vite] Rollup failed to resolve import "..."

CIが見えないものに注意してください。 Lint、astro-checkのラチェット、ビルド成功は、ページの見た目については何も語りません。そのギャップを埋めるのがフェーズEの役割であり、このリポジトリにおけるこのスキルの最も価値の高い部分です。


フェーズB — サブエージェントによるコンテキスト取り込み

PRが触れる範囲に基づいて、2つまたは3つの並行exploreサブエージェントを起動します。事前に自分でこれらを読まないでください — 委任してください。

ステップ3 · 規約サブエージェント

.github/copilot-instructions.md はこのリポジトリの唯一の正規エージェントエントリポイントです(ルートの AGENTS.md と CLAUDE.md はそれへのシンボリックリンクです)。サブエージェントにそれを読み、以下を返すように依頼します: 変更ワークフロー、ローカルチェック、コミット/PR規約、および影響を受けるパスに関連する注意点。PRがスタイリングやトークンラチェットに触れる可能性がある場合はSTYLES.mdも、コンポーネントAPIが関係する場合はREUSABLE.mdも対象に含めます。

ステップ4 · テストハーネスサブエージェント

scripts/verify/README.md を読み、ローカル検証ハーネスに関するブリーフィング(約40行)を返すように依頼します。verify:dom、verify:shots、verify:parity、verify:typewriter、check:ratchetがそれぞれ何をアサートするか、テーマフラグとビューポートフラグの動作、出力先、パリティ許可リストのメカニズムとその限界についてです。このブリーフィングはフェーズEが実行する基準となります。

ステップ5 · コードベースサブエージェント

影響を受ける領域に対してターゲットを絞ったマップを作成するように依頼します:

  • diff内のどのパッケージがsrc/**またはscripts/**で実際にインポートされているか、その場所(何もインポートしないものをバンプするのとastroをバンプするのではリスククラスが異なります)
  • ビルドおよびチェックコマンド(npm run build、npm run lint、npm run format:check、npm run check:ratchet)
  • バンプがビルドパイプライン(astro、vite、@astrojs/*、pagefind、mdx/rehype/remarkプラグイン)に触れるか、それともツールチェインのみ(eslint、prettier、typescript)か
  • github-actions PRの場合: どのワークフローが変更され、その変更がデプロイパス(.github/workflows/deploy.yml)に影響を与えるか、それともCIのみか

サブエージェントのブリーフィングがフェーズCの作業コンテキストを形成します。


フェーズC — 深い根本原因診断

ステップ6 · 診断

今 — そして今だけ — フェーズBの完全なコンテキストを持って失敗ジョブのログに飛び込みます。各失敗チェックについて、最初の意味のあるエラーを以下にトレースします:

  1. バンプされた依存関係による直接的なリグレッション(エクスポートの削除、シグネチャ変更、バリデーションの厳格化、デフォルト変更)
  2. 推移的なツールチェインの問題(.tool-versionsが固定するよりも新しいNodeを必要とする依存関係、新しいランタイムを必要とするpostinstall、解決しないオプションのネイティブバインディング)
  3. 無害なバンプによって露呈した既存の脆弱性(astro-checkベースライン、-a###トークンラチェット、またはSTYLES.mdハッシュがフォーマット変更でトリップする)
  4. インフラのフレーク(レジストリレート制限、ジョブキャンセル、npm ciネットワーク障害)

グループ化されたPRの場合、各失敗チェックを個別に診断してください — 失敗は独立した原因を持つ可能性があり、バッチでは通常異なるパッケージにトレースされます。結果を./tmp/pr-${PR_NUM}-diagnosis.mdに記録します。


フェーズD — 修正設計

ステップ6.5 · スコープトリアージ — これは修正すべき問題か、それともDependabot設定の問題か?

修正を計画する前に、PRが修正のスコープ内かどうかを確認します。.github/dependabot.yml は、ルーチンのnpmマイナー/パッチアップデートをエコシステムごとに単一のallグループとall-securityグループにまとめ、npm メジャーをallグループから意図的に除外しているため、各メジャーは個別に届きます。この形状は2つの異なる失敗状況を意味します:

1つのパッケージで失敗しているグループ化されたPR。 これは一般的なケースであり、スコープ内です。バッチを放棄しないでください。問題のある単一パッケージを見つけ、そのコードを修正するか、その1つのパッケージを固定する(範囲を狭めるpackage.jsonのエントリ、またはそのパッケージとバージョンに対するDependabot ignoreエントリ)ことで、残りのバッチをランディングできるようにします。1つ以外は緑のバッチを放棄することは、1つの悪いアップデートのために多数の良いアップデートを捨てることになります。

スコープ拒否トリガー(いずれか1つで十分 — 修正ではなく設定の問題です):

  • 単一のグループPRに2つ以上のメジャーバンプが含まれている — 現在のnpmグループ設定では不可能なはずなので、もし発生した場合、設定自体がドリフトしており、それが実際のバグです
  • フレームワーク層のパッケージ(astro、vite、@astrojs/*、typescript、eslint、prettier、preact、pagefind)に対する単独のメジャーで、真のマイグレーションが必要な場合 — 修正ではなく、プロジェクト単位の作業です
  • バッチのほとんどはルーチンだが、その失敗が1つのパッケージでマイグレーションを必要とし、そのパッケージを迂回して固定できない場合

トリガーされた場合、修正を試みず、PRを自分でクローズしないでください — オーナーのために開いたままにしておいてください。代わりに:

  1. 原因が設定のドリフトである場合、.github/dependabot.ymlの修正を別の小さなPRとして準備します(オーナーがレビューしてマージするために残します)。そうでなければ設定変更は不要で、単にマイグレーションを別の作業としてスケジュールすることを推奨します。
  2. スコープ拒否の決定をDependabot PRへのコメントとして言葉にします: なぜ1回のパスで修正できないのかを説明し、設定PRがあればリンクし、マイグレーションには何が含まれるかを述べます。PRは開いたままにします — 決定を待たず、クローズもしないでください。
  3. フェーズFのコミットフローはスキップします — 修正はありません。レポートの内容はそのコメントに含めます。

セキュリティアップデートグループ(all-security)はバンドルされたままにします: セキュリティバンプは時間に敏感で、十分に稀であるため、分割するコストが節約を上回ります。具体的なブロッカーが強制する場合のみ分割します。

ステップ7 · 包括的な計画

以下の内容をカバーする計画を書きます。リスクに応じて深さを調整します:

セクション常時リスクが中以上の場合
根本原因✅✅
変更が予想されるファイル✅✅
修正アプローチ(および検討した代替案)✅✅
リスク評価(低/中/高)✅✅
再現手順✅✅(実行可能であること)
手動テスト戦略✅✅ 拡張
ロールバック計画✅
影響範囲(レンダリング出力 / デプロイ / URL)✅

リスクが中以上となるのは、いずれかが該当する場合:

  • バンプがビルドパイプラインに触れる(astro、vite、@astrojs/*、MDX/rehype/remarkプラグイン、pagefind)
  • 修正が設定やロックファイルではなくsrc/以下のものを編集する
  • バンプが生成されるHTML、CSSの順序、フォント読み込み、またはハイドレーション動作を変更する可能性がある
  • github-actionsの変更がdeploy.ymlに触れる(デプロイの破損はライブサイトの停止であり、赤いチェックではありません)

npm メジャーはデフォルトで最低でも中リスクです。メジャーが単独で届くのは、それ自体を読んでテストする価値があるからです。同じサイズのバッチよりも厳重に扱ってください。

ステップ8 · 手動テスト戦略(階層化)

ステップ7のリスク評価に基づいて、労力を階層化します:

  • 低(ツールのみ) — 修正を適用し、最も狭い関連ゲートを実行(npm run lint、npm run format:check、またはnpm run check:ratchet)。再現手順は不要。
  • 中(ビルドパイプラインまたはsrc/の編集) — まずPRブランチでローカルに障害を再現し、リグレッションが本物であることを証明します(CIのアーティファクトではない)。その後、修正を適用し、完全なローカルチェックを再実行: npm run lint && npm run format:check && npm run check:ratchet && npm run build。その後、フェーズE。
  • 高(メジャー、レンダリング出力を変更する可能性があるもの、デプロイ変更) — 中のすべてに加え、フェーズEのパリティスイープは必須、さらにビルドされたPRヘッドに対してnpm run verify:dom:all、ヒーローまたはモーショントークンが関係する場合はnpm run verify:typewriter。

すべてのスクラッチ出力は./tmp/(gitignore対象)に保持します。出力を抑制する場合は./tmp/nullをシンクとして使用します:

npm run build 2>./tmp/null

フェーズE — マージベースに対するビジュアルパリティ

CIはサイトがビルドされることを証明します。サイトが同じに見えることは証明しません。依存関係のバンプは定義上ピクセルに影響を与えないはずです — もし影響があれば、何かが異なるレンダリングをしており、誰もそれを見ていなかったことになります。このフェーズこそ、このスキルがこのリポジトリに存在する理由です。

ピクセルベースラインはコミットされていません(scripts/verify/out/とtmp/はgitignore対象)。そのため、比較は実行時に生成する必要があります: マージベースをキャプチャし、PRヘッドをキャプチャし、比較します。

ステップ8.5 · 実行するかどうかの判断

スイープには約4~5分かかります(2回のビルド + 37ルート×2ビューポートに対する2回のスクリーンショットスイープ)。変更がレンダリングに影響を与えない場合のみスキップします。以下のすべてが成立する場合にスキップ可能です:

  • PRがgithub-actionsのみである、または.github/**のみに触れる
  • src/、public/、astro.config.mjs、またはpackage.jsonのdependencies以下のファイルが変更されていない
  • diffが、出力がdist/に決して到達しないdevDependencies(eslint*、prettier、@types/*、typescript(ラチェットが変更されていない場合))に限定されている

それ以外 — astro、vite、@astrojs/*、preact、pagefind、MDX/rehype/remark、フォント、CSSツールのバンプ、およびすべてのnpmメジャー — はスイープを実行します。迷ったら実行してください。5分はライブサイトでの静かなビジュアルリグレッションよりも安いです。

レポートで、この決定のどの分岐を取ったか、そしてその理由を明示的に述べてください。

ステップ9 · キャプチャと比較

Playwrightはリポジトリの依存関係ではありません。ハーネスは、すでにスクリプトに配線されているnpxキャッシュパスからそれを駆動します。各ビルドをプレーンな静的サーバーで提供します。

BASE_SHA=$(git merge-base origin/master HEAD)
mkdir -p ./tmp/parity

# --- マージベース ---
git checkout $BASE_SHA
npm ci
npm run build
cp dist/index.html ./tmp/parity/base-index.html    # 提供しているもののフィンガープリント
nohup npx --yes http-server dist -p 4126 --silent < ./tmp/null > ./tmp/parity/base-server.log 2>&1 &
BASE_SERVER=$!
npm run verify:shots:all
kill $BASE_SERVER
cp -R scripts/verify/out ./tmp/parity/base

# --- PRヘッド ---
gh pr checkout $PR_NUM --repo $REPO
npm ci
npm run build
cp dist/index.html ./tmp/parity/head-index.html
nohup npx --yes http-server dist -p 4126 --silent < ./tmp/null > ./tmp/parity/head-server.log 2>&1 &
HEAD_SERVER=$!
npm run verify:shots:all
kill $HEAD_SERVER
cp -R scripts/verify/out ./tmp/parity/head

# --- ビューポートごとに比較 ---
npm run verify:parity -- ./tmp/parity/base/1440 ./tmp/parity/head/1440 > ./tmp/parity/1440.json
npm run verify:parity -- ./tmp/parity/base/420  ./tmp/parity/head/420  > ./tmp/parity/420.json

古いdistのトラップ。 2つのビルド間でポート4126を再利用することは、自信満々の無意味なグリーンを生み出す最も可能性の高い方法です: 古いサーバーが実際に終了していない場合、またはdistが再ビルドされなかった場合、2回目のスイープは最初のビルドを写真に撮り、ビルドを自分自身と比較したためパリティはパスします。毎回の実行でこれをガードします:

  • 次のサーバーを開始する前に、前のサーバーがなくなっていることを確認します(lsof -i :4126が何も返さない)。
  • 2つのフィンガープリントをdiffします — src/またはビルドパイプラインデップを変更したPRに対してcmp ./tmp/parity/base-index.html ./tmp/parity/head-index.htmlが「同一」を返す場合は、結果ではなく、実行を信頼しないシグナルです。
  • スイープ自身のJSONがcompared: 0またはすべてのルートが欠落していると報告する場合、サーバーが起動していません。実行は無効であり、パスではありません。

verify:shotsはダークテーマの出力をout/<width>/に書き込みます。バンプがライトテーマに異なる影響を与える可能性がある場合(CSSツール、色処理、トークン出力)、スイープを--theme lightで繰り返します。これによりout/light/<width>/に書き込まれ、ダークツリーを上書きしません。

ステップ10 · 結果の解釈

verify-parityはルートあたり2つの数値を報告し、両方が重要です

...

[翻訳のため省略]

関連スキル