drupal-contrib-mgmt について
Composer で Drupal contrib モジュールを管理する開発者向けのワークフローガイドです。モジュール更新や互換性確認に加え、ロックファイルの同期、パッチ検証、動作テストを扱います。
主な機能
- 01単一または複数モジュールの更新
- 02Drupal 11 互換性の確認
- 03Drupal Lenient の設定
- 04Composer パッチの適用と検証
- 05パッチの動作テスト作成
- 06パッチ適用のトラブルシューティング
活用シーン
- 01Drupal contrib モジュールのバージョン更新
- 02モジュールのパッチ追加や保守
- 03パッチのロックとコードの同期確認
- 04Drupal 11 へのアップグレード準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ grasmash/ drupal-claude-skills --skill drupal-contrib-mgmtインストール後、Claude Code で/drupal-contrib-mgmtを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
examples/create-custom-patch.shfind-and-apply-patch.shmajor-version-upgrade.shupdate-with-patch.shreferences/contributing-upstream.mdd11-common-deprecations.mdd11-upgrade-workflow.mddrupal-lenient.mddrupal-patches-workflow.mdfinding-and-creating-patches.mdissue-queue-rss-feeds.mdupdate-patterns.md詳細
Drupal Contrib モジュール管理
Composer 管理下の contrib に関する作業全般(モジュールの更新、パッチの追加やデバッグ、バージョン制約の解消、Drupal 11 への準備、修正の upstream へのプッシュ)には、このスキルを使用してください。以下のコア更新ワークフローとパッチのルールは、使用するたびに適用されます。タスク固有の詳細は references/ にあります(末尾の表を参照)。
コア更新ワークフロー
標準的なモジュールの更新
# Update a single module
composer require drupal/module_name --with-all-dependencies
# Update to specific version
composer require drupal/module_name:^3.0 --with-all-dependencies
# Update multiple modules
composer require drupal/module_a drupal/module_b --with-all-dependencies
# After any update, ALWAYS run database updates (updatedb rebuilds caches when it finishes)
drush updb -y
# On a deployed environment, use the full deploy tail instead; see the drupal-deploy-safety skill
# CRITICAL: Test by visiting pages to check for fatal errors
# Visit at least one page that uses the updated module
メジャーバージョンへのアップグレード
新しいメジャーバージョン(例:2.x → 3.x)にアップグレードする場合:
- 互換性を確認する:モジュールが使用している Drupal コアのバージョンに対応していることを確認します
- 課題キューでパッチを検索する:
https://www.drupal.org/project/issues/MODULE_NAME?categories=All - バージョン要件の問題には Drupal Lenient を使用する(下記参照)
- composer.json でパッチを適用する(「パッチ管理」セクションを参照)
- upgrade_status を実行して非推奨項目を確認する
Drupal 11 との互換性の確認
3 つの方法(.info.yml、Composer、drupal.org)と upgrade_status によるアップグレードの全ワークフローについては、references/d11-upgrade-workflow.md を参照してください。
Drupal Lenient プラグイン
mglaman/composer-drupal-lenient プラグインを使うと、バージョン要件がまだ更新されていないモジュールをインストールできます。
Lenient/core-compat のオーバーライドについては、references/drupal-lenient.md を参照してください。このリファレンスでは、UPSTREAM の composer.json/.info.yml 要件(ローカルでパッチを適用したコピーではありません)に照らした候補の検証方法、composer prohibits による確認方法、許可リストにモジュールを追加または削除するタイミングを説明しています。
セットアップ
{
"require": {
"mglaman/composer-drupal-lenient": "^1.0"
},
"config": {
"allow-plugins": {
"mglaman/composer-drupal-lenient": true
}
},
"extra": {
"drupal-lenient": {
"allowed-list": [
"drupal/module_name",
"drupal/another_module"
]
}
}
}
使用方法
# Add module to allowed-list, then install
composer require drupal/module_name --with-all-dependencies
パッチ管理(cweagans/composer-patches)
重要:パッチを確実に適用するには、バージョン 2.x を使用してください。バージョン 1.x は patch バイナリを使うため、一部のシステムで問題が発生することがあります。バージョン 2.x はデフォルトで git apply を使用します。
パッチの設定
{
"require": {
"cweagans/composer-patches": "^2.0"
},
"config": {
"allow-plugins": {
"cweagans/composer-patches": true
}
},
"extra": {
"composer-exit-on-patch-failure": true,
"patches": {
"drupal/module_name": {
"Description of patch": "https://www.drupal.org/files/issues/2024-01-15/module-issue-1234567-8.patch",
"Local patch": "patches/custom-fix.patch"
}
},
"patchLevel": {
"drupal/core": "-p2"
}
}
}
1.x から 2.x へのアップグレード
バージョン 1.x を使用していて、パッチの適用に失敗する場合:
composer require cweagans/composer-patches:^2.0 --with-all-dependencies
2.x における主な違い:
patchバイナリの代わりにgit applyを使用します(より確実です)enable-patchingオプションが削除されました(パッチ適用は常に有効です)- エラーメッセージとデバッグ機能が改善されました
- 重要 —
patches.lock.jsonの適用元:v2 は、Composer がパッケージをインストールまたは更新するたびに(composer install、update、reinstall、patches-repatch)、patches.lock.jsonからパッチを適用します。これらのいずれもcomposer.jsonのextra.patchesを再読み込みしません。ロックファイルを再生成するのはcomposer patches-relockを実行した場合、またはpatches.lock.jsonが存在しない場合だけです(composer-patches 2.0.0、Patches::loadLockedPatches())。そのため、パッチをcomposer.jsonに追加してcomposer installまたはcomposer updateを実行しても、ロックファイルを更新するまではそのパッチは何も適用されません。パッチが「繰り返し元に戻る」最大の原因はこれです。ローカル開発環境では手動で適用したりupdateを実行したりして修正されたように見えても、次のクリーンインストール(CI、チームメイトの環境、新規デプロイ)では古いロックファイルが読み込まれ、パッチが適用されません。extra.patchesを編集したら、必ずcomposer patches-relockを実行し、patches.lock.jsonをコミットしてください。
パッチが適用されているか確認する
異なる 3 つの問題に対して、確認方法は 1 つです:
-
ロックとの同期ずれ(根本原因):パッチが
composer.jsonのextra.patchesに登録されているものの、composer patches-relockが省略されたため、patches.lock.jsonに追加されていません。v2 はcomposer install時にロックファイルからパッチを適用するため、すべてのクリーンインストールでパッチは何も適用されません。解決方法はロックファイルの再生成です。この確認では、composer.jsonにあるすべてのローカルパッチがpatches.lock.jsonにも存在することを検証し、再生成漏れを検出します。 -
コミット済みファイルのずれ(contrib のコードをコミットするプロジェクト):パッチは作業ツリーに適用されていますが、その結果として変更された contrib ファイルが git にコミットされていません。Composer のインストールを実行せず、コミット済みの git 状態からデプロイするプラットフォーム(たとえば Pantheon)では、その変更が反映されず、本番環境ではパッチが適用されていないコードが実行されます。ローカル開発環境では問題なく見えます。
-
パッチハッシュキャッシュの陳腐化:ロックファイルの同期が取れていても、予期しない再インストールやベンダーの更新によって、パッチの再適用がスキップされることがあります。(1)と(2)に比べればまれですが、同じ実体化済みファイルのチェックで検出できます。
解決策:プロジェクトには、プッシュ前および CI で実行するパッチ検証スクリプト(例:scripts/verify-patches.sh)を用意する必要があります(このスキルには含まれていません)。このスクリプトでは、次の処理を行います。
- ロック同期チェック:
composer.jsonのextra.patchesにあるすべてのローカルパッチがpatches.lock.jsonにも記載されていることを確認します。これにより、patches-relockの実行漏れを検出できます。 - 実体化済みファイルのチェック(contrib コードをコミットするプロジェクト):パッチが適用された行が、コミット済みの contrib ファイルに含まれていることを確認します。これにより、「パッチは適用したが、コミットしていない」状態を検出できます。
- 検証対象の一覧は
composer.jsonのextra.patchesから取得します。手動で対象を選定しないでください。パッチエントリーを追加するだけで、チェックの対象に含まれるようにします。 - 各ローカルパッチ(値が
patches/で始まるもの)について、すべての+++ b/<path>ヘッダーを解析し、特徴的な追加行をいくつか抽出します(例:空白以外の文字が 8 文字以上あり、同じパッチ内のいずれの-行にも部分文字列として含まれない行を最大 5 行)。その行を対象ファイル内で grep します。drupal/coreパッケージのcore/パスプレフィックスに注意してください。コアパッチは Drupal ルートを基準とし(b/core/lib/...、-p2で適用)、パッケージのインストールパスを前置するのではなく、<docroot>/core/...に対応付けます。 - URL ベースのパッチ(
https://...)は通知を出してスキップします。パッチが重要な場合は、patches/にローカルミラーを追加してください。 - CI では、
composer installより前に実行し、インストール後の状態ではなく、コミット済みツリーを検証します。重要なのはこの実行順序です。
新しいパッチの追加(特に忘れられやすいのがロックファイルの更新手順です):
.patchファイルをpatches/に配置しますcomposer.jsonのextra.patchesに登録しますcomposer patches-relockを実行します。パッチがpatches.lock.jsonに追加されます。これを実行しないと、手順 4 では何も適用されません(v2 はcomposer.jsonではなくロックファイルを読み込みます)。composer reinstall drupal/module_name(またはcomposer patches-repatch)を実行して、作業ツリーにパッチを適用します。v2 では、Composer がパッケージをインストールまたは更新するときにのみパッケージにパッチが適用されるため、すでにインストール済みのモジュールに対して通常のcomposer installを実行しても、パッチは再適用されません。composer.json、patches.lock.json、新しい.patchファイルをgit addしてコミットします。プロジェクトが contrib コードをコミットする場合は、変更された contrib ファイルもコミットしてください。composer installを実行せずに Git からデプロイするプラットフォームでは、パッチを独自に適用できないため、コミット済みの contrib ファイルがすでにパッチ適用済みである必要があります。- パッチで修正した機能の動作テストを作成します(以下を参照)。
- プッシュ前に、プロジェクトのパッチ検証チェックをローカルで実行します。
- プッシュのたびに、CI で同じ検証を再実行します。
すべてのパッチには動作テストを用意してください。 パッチ検証チェックは構造的なチェックです。コミット済みファイルにパッチの 行 があることは証明しますが、パッチ適用後のコードが正しく 動作する ことまでは証明しません。パッチが適用されていても、何も修正されていないことがあります(ハンクの誤り、上流のリファクタリングによるロジックの移動、後続のパッチによる取り消しなど)。モジュールのバージョンを上げてもパッチを確実に機能させるのは、次のテストです。
- 失敗ケース:パッチが修正する具体的なエッジケースをテストします。新しいパッチの場合は、まずパッチ未適用のモジュールを対象にテストを書き、報告された理由で失敗することを確認してください。そうしなければ、バグをテストできていることを証明できません。
- 成功ケース:通常の処理が引き続き正常に動作すること(リグレッションがないこと)を確認します。
- テストは利用するカスタムモジュールの
tests/ディレクトリに配置し、テストの docblock で.patchファイルを参照します。これにより、モジュールのバージョンを上げる人がパッチを見つけられます。 - 動作テストのないパッチを適用しているモジュールのバージョンを上げてはいけません。 先にテストを書いてからバージョンを上げ、テストが引き続き成功すること(またはパッチが上流に取り込まれ、削除できること)を確認してください。 検証でパッチが MISSING と報告された場合:
- ロック同期の失敗 → 誰かが
composer patches-relock(ステップ 3)を実行し忘れています。対処方法:実行して、patches.lock.jsonをコミットし、プッシュします。 - ファイル反映の失敗 → 誰かがパッチ適用済みの contrib ファイル(ステップ 5)のコミットを忘れています。対処方法:ローカルで
composer patches-relock && composer patches-repatchを実行し、パッチ適用済みの contrib/core ディレクトリ(例:web/modules/contrib web/coreまたはdocroot/modules/contrib docroot/core)とpatches.lock.jsonをgit addで追加して、コミットし、プッシュします。
注意点:
- 「結合パッチ」(1 つの
.patchファイルに同じファイルを指す複数の+++ b/<same_file>ヘッダーがあり、通常は競合するハンクを含むコミットをまとめたもの)は見逃されることがあります。特徴的な追加行が 1 つでもあれば合格するチェックでは、一部しか一致していなくても合格してしまいます。patches/に同じファイルを修正する複数のハンクを含むパッチがある場合は、代わりにクリーンな単一コミットの差分として再生成してください。 - PHPCS:パッチ適用済みの contrib ファイルをコミットすると、上流コードに既存の sniff 違反があるため、コミット前の
phpcsタスク(例:GrumPHP)で失敗することがあります。上流コードを「修正」するのではなく、contrib、core、libraries ディレクトリを無視するようにそのタスクを設定してください。
パッチの検索
Issue Queue の検索:https://www.drupal.org/project/issues/MODULE_NAME?categories=All
パッチの命名規則:
- 形式:
module-issue-NODEID-COMMENT.patch - 例:
audiofield-d11-3432063-12.patch - Node ID は Issue の番号です(
drupal.org/node/NODEIDを参照してください)
更新後に既存のパッチが適用できなくなった場合:
- パッチのファイル名から Node ID を特定します(上の例では
3432063) https://www.drupal.org/node/3432063にアクセスします- 最新のコメントで更新済みのパッチを探します
- 新しいパッチ URL で composer.json を更新します
エラーのデバッグとローカルパッチの作成
パッチを作成する前に、既存のパッチがないか Issue Queue を検索してください。手順を追った検索方法と、別クローンでパッチを作成するワークフローは、references/finding-and-creating-patches.md に記載されています。
パッチの適用
# Fresh checkout: packages are installed and patched from patches.lock.json
composer install
# After ANY change to extra.patches (add, edit, remove), relock first
composer patches-relock
# Re-patch a single module (most common). A plain `composer install` or
# `composer update` does nothing for a package that is already installed at
# the locked version, so its patches are not re-applied.
composer reinstall drupal/module_name
# Re-patch ALL patched dependencies (deletes and reinstalls them)
composer patches-repatch
詳細なパッチのワークフローについては、次を参照してください: references/drupal-patches-workflow.md
Drupal 11 互換性ワークフロー
6 段階の upgrade_status ワークフロー(分析、特定、カスタムコードの修正、.info.yml パッチ、lenient リスト、検証)は、references/d11-upgrade-workflow.md に記載されています。
更新チェックリストの全項目
- 現在のモジュールバージョンを確認します:
composer show drupal/module_name - 既知の問題がないか Issue Queue を検索します
- モジュールが D11 に対応しているか確認します
- 新しいバージョンで composer.json を更新します
- 必要に応じて drupal-lenient に追加します
- 必要なパッチを検索して適用します
- モジュールの既存パッチすべてに動作テストがあることを確認し、バージョン更新後に実行します
-
composer require drupal/module_name:^X.0 --with-all-dependenciesを実行します -
drush updb -yを実行します(最後にキャッシュが再構築されます。デプロイ済み環境では、drupal-deploy-safetyスキルにある後続処理一式を実行します) -
drush upgrade_status:analyze module_nameを実行します - 関連するページにアクセスして、モジュールの機能をテストします
- ログで PHP のエラーや警告を確認します
- 変更内容が分かるメッセージを付けてコミットします
トラブルシューティング
パッチを適用できない
# Error: "Cannot apply patch..."
# 1. Check if module version changed
composer show drupal/module_name
# 2. Search issue queue for updated patch
# Visit drupal.org/node/NODEID (from patch filename)
# 3. Update composer.json with new patch URL
# 4. Or remove patch if merged upstream
# 5. Either way: composer patches-relock && composer reinstall drupal/module_name
バージョンの競合
# Error: "drupal/module_name requires drupal/core ^9"
# Add to drupal-lenient allowed-list
パッチはすでに適用済み
# Error: "patch ... has already been applied"
# Module maintainer merged the patch - remove from composer.json, then
composer patches-relock
composer reinstall drupal/module_name
データベースの更新に失敗する
# Error during drush updb
# 1. Check error message carefully
# 2. Last resort only: pm:uninstall DELETES the module's config and stored data.
# Back up the database first, and never do this on a module holding data you need.
drush pm:uninstall module_name
composer require drupal/module_name --with-all-dependencies
drush pm:enable module_name
drush updb -y
ベストプラクティス
- モジュールを更新する際は、必ず
--with-all-dependenciesを使用します - composer の更新後は、必ず
drush updbを実行します - 更新後はすぐにテストします(ページにアクセスし、ログを確認します)
patches/ディレクトリでパッチを整理します- 分かりやすい名前とコメントでパッチを文書化します
- カスタムパッチを作成する前に、まず Issue Queue を確認します
- upgrade_status を使用して D11 との互換性を検証します
- 変更をアトミックにコミットします:1 コミットにつき 1 モジュールを更新します
- パッチへの参照を含む、分かりやすいコミットメッセージを使用します
- drupal-lenient リストは必要最小限に保ちます(必要な場合のみ)
本番環境へのデプロイ
コミット済みの git 状態をデプロイするホスト(サーバー上で composer install を実行しない場合)では、開発用パッケージを含めずにコミット対象の vendor をビルドします:
composer update drupal/module_name --with-all-dependencies # the change itself
composer install --no-dev -o # then build the vendor you commit
git add composer.json composer.lock vendor/ # vendor/autoload.php + vendor/composer/ together
- 後から通常の
composer installを実行して残った開発用オートローダーは、決してコミットしないでください。 vendor/autoload.php、vendor/composer/、パッケージディレクトリをまとめてステージしてください。一部だけをステージすると、サイト全体でComposerAutoloaderInit... not foundの致命的エラーが発生します。config.autoloader-suffixの固定、3 つのサフィックスファイル、コミット前チェックについては、drupal-deploy-safetyスキル(§8)を参照してください。- 変更をプッシュしても、コードが更新されるだけです。対象環境では、
drush crだけでなく、デプロイの最後の手順(updatedbのループ →cache:rebuild→config:import→cache:rebuild→deploy:hookの後に検証)を実行してください。drupal-deploy-safetyスキル(§2)を参照してください。ホストごとのリモート Drush の形式については、drupal-config-mgmtスキルを参照してください。
Contrib モジュールの開発とコントリビュート
シンボリックリンクを使った開発ワークフローと、drupal.org のイシューフォーク/マージリクエストのワークフローについては、references/contributing-upstream.md を参照してください。更新手順の例(既知のパッチ、D11 の修正、破壊的変更を伴うメジャーアップグレード)については、references/update-patterns.md を参照してください。
参考資料
| ファイル | 参照する場面 |
|---|---|
| references/d11-upgrade-workflow.md | モジュールが Drupal 11 に対応しているか確認する場合、または upgrade_status スキャンを実行して検出された問題を修正する場合 |
| references/d11-common-deprecations.md | 特定の非推奨定数、関数、クラス定数、Twig フィルターを置き換える場合 |
| references/drupal-lenient.md | モジュールを drupal-lenient の許可リストに含めるか(または外せるか)判断する場合 |
| references/finding-and-creating-patches.md | Drupal のエラーが発生して既存のパッチを探す場合、またはクリーンなクローンから新しいローカルパッチを作成する場合 |
| references/drupal-patches-workflow.md | composer-patches について詳しく知りたい場合。プラグインのコマンド、リモート/ローカル/MR 差分パッチ、すでにパッチ適用済みのモジュールへのパッチの重ね合わせなど |
| references/issue-queue-rss-feeds.md | drupal.org のイシューキューをプログラムから検索する場合(RSS フィルター、curl/WebFetch による解析) |
| references/update-patterns.md | パッチ適用済みの更新、D11 contrib の修正、ロールバックを伴うメジャーアップグレードの手順例に沿って作業する場合 |
| references/contributing-upstream.md | シンボリックリンクを使って contrib モジュールをローカルで開発する場合、またはイシューフォークとマージリクエストを通じて修正をコントリビュートする場合 |
| examples/ | 同じシナリオを実行できるシェルの手順例 |
参考リンク
- Composer Patches:https://github.com/cweagans/composer-patches
- Drupal Lenient:https://github.com/mglaman/composer-drupal-lenient
- Upgrade Status Module:https://www.drupal.org/project/upgrade_status
- Drupal 11 Deprecations:https://www.drupal.org/about/core/policies/core-change-policies/drupal-deprecation-policy
- パッチ命名規則:https://www.drupal.org/node/1054616
- イシューフォークの作成:https://www.drupal.org/docs/develop/git/using-gitlab-to-contribute-to-drupal/creating-issue-forks
- イシューレポートガイド:https://www.drupal.org/community/contributor-guide/reference-information/quick-info/creating-or-updating-an-issue-report
- テキスト書式設定のヒント:https://www.drupal.org/filter/tips
- Drupal の Git ワークフロー:https://www.drupal.org/docs/develop/git/using-git-to-contribute-to-drupal