「そろそろDrupal9へのアップグレードが狙えそうになってきた」と2020年12月4日金曜日の深夜に書いて、土曜日にアップグレードに着手した。
引用記事に書いたが、Blogサイトをインストールした時に利用したdrupal-composer/drupal-projectで生成されたcomposer.jsonが古くてcomposer2ではエラーが出て動かない。このBlogサイトは最初はさくらインターネットのさくらのクラウドの1Core-1GBプランで立ち上げたが、2020年6月12日に実験も兼ねて、Google Computing Platformの無料プラン(f1-micro(vCPU x 1、メモリ 0.6 GB))に移行した。メモリが少ないので、composerが重くて苦労が耐えないのだ。今でもさくらのクラウドは利用していて事前の検証はそちらで行っている。現在のDrupal8の最新版でイメージを落としてくると、drupal/legacy-projectでこちらはcomposer2で問題なく動作する。
私はコードを書かないので、導入したモジュールやテーマを再インストールして、サブテーマの構成定義とsites/default/filesをコピーすれば問題なくリニューアルができる。とはいえ、25もcontributionを使っているので、いちいち手で打つのは面倒くさいし、移行時には何度もやり直しが伴うのが常である。だから、移行用のシェルスクリプトを書いた。もっときれいに書くこともできるとは思うけれど、一回限りのものなのでとりあえず動けば良い。結果的に、既存ファイルから生成したコマンドラインは1行である。
composer2 require drupal/admin_toolbar drupal/adsense drupal/ctools drupal/entity drupal/form_mode_manager drupal/google_tag drupal/group drupal/honeypot drupal/imce drupal/linkit drupal/mailsystem drupal/mathjax drupal/metatag drupal/pathauto drupal/schema_metatagdrupal/sendgrid_integration drupal/simple_sitemap drupal/social_auth_google drupal/token drupal/upgrade_status drupal/variationcache drupal/webform drupal/bootstrap
その生成および実行スクリプトは以下の通り
ls web/*/contrib |grep -v social_api|grep -v "contrib:"|grep -v _auth\$|grep -v hagi|grep -v temp|\
awk 'BEGIN{printf("composer2 require ")}length(\$1)>0{printf("drupal/%s ",\$1)}END{printf("\n")}' |\
tee /tmp/debug.txt|(cd \$1; sh)
cp -r web/themes/contrib/hagiblog \$1/themes/contrib/hagiblog
cp -r web/sites/default/files \$1/sites/default
cd \$1
composer2 require drush/drush 'drupal/linkit:^6.0@beta' 'drupal/mathjax:^3.0@beta' 'drupal/webform:^6.0@beta' drupal/form_mode_control
sudo chown -R www-data.www-data sites/default
sudo chmod -R g+w sites/default
古いインストーラーでは、プロジェクトのディレクトリの下にwebというディレクトリを作ってそこをwebrootにしている。最近のインストーラーでは、プロジェクトのディレクトリがそのままwebrootとなる。改めて考え直すと、webrootにはできるだけ余計なものは置かない方が良いので、古いインストーラーの方が良い形のように見える。それが今の形になった理由は分からないが、とにかくcomposerコマンドを生成したい。最初の"ls web/*/contrib"でインストールしたものの一覧は取れる。ただ、邪魔なメッセージも入るので、grep -v "contrib:"などで、ゴミを取る。ロートルなのでperlではなく古のawkを利用してコマンドを生成した。最初はgrep -vの除外スクリプトはほとんどなかったのだが、生成されたcomposerコマンドを実行するとそのままでは動かない。問題は生成順序である。だからその矛盾が取れるまで末端の方だけを残す必要がある。具体的に引っかかったのは、drupal/social_auth_googleの依存でcomposerを利用すれば、末端のdrupal/social_auth_googleだけをrequireすればよいのだが、social_apiとかsocial_authとかを一緒に入れてしまうと矛盾が解決できずにcomposerが動かない。何回かトライアルして動くようになったので、自分で作ったサブテーマのhagiblogとサイト固有のイメージファイルなどを含むweb/sites/default/filesを新ディレクトリ($1)の下にコピーするスクリプトを加えた。仕上げに権限を調整している。
これでDrupal 8.9.11でcomposer2が自然に使えるプロジェクトディレクトリが完成した。
次のステップは、D9へのアップグレードである。アップグレード手順は、Upgrading from Drupal 8 to Drupal 9 (or higher)に書かれているので、その手順に沿って実行する。DBイメージも移行して、アップグレードはあっけなく成功した。
次のステップは、動作確認である。ページを閲覧する限り問題点は見つからない。ところが、コンテンツを書こうとしたり、既存コンテンツを修正しようとすると動作しない。早速調べると、UID base field override configs can still have old default value callbacksというissue(課題)にたどり着いた。どうやら、https://www.drupal.org/project/drupal/issues/3153455#comment-13769781が私の問題と一致しているように見えたので、https://www.drupal.org/project/drupal/issues/3153455#comment-13797624の手順に従って手で行うと問題は無事解決した。
これで完璧と思ったが、世の中そんなに甘くない。linkitモジュールはD9対応版で機能が落とされていて、コンテンツ編集画面でアイコンがでなくなっている。それだけでなく、コンテンツの編集画面からの依存性は消えていないのでモジュールのアンインストールもできない。これに対応しないといけない。
もう一つの問題はform_mode_managerである。これはまだD9に対応していないが、代替案として提示されているform_mode_controlというモジュールで私の要件はカバーできる。form_mode_managerは互換性がまだ確保できていないので、元サイトでモジュールをアンインストールしておかないと移行ができない。そのため、モジュールのアンインストールだけをしてデータベースを移行した。
動作確認の段階では上記の2つの問題を解決することで問題なく動作するようになった。
今回得られた知見は、バージョン間で互換性がないモジュールや、互換リリースが存在していても機能が縮小されているケースには注意が必要ということである。
これからアップグレードを行う方へのアドバイスは以下の通りである。
- まずD8の最新クリーンリリースに移行して動作確認する
- 上記クリーンリリースでupgrade_statusモジュールで互換性の確認を行う
D9対応のリリースノートはよく読んで新バージョンが自分が必要とする機能をカバーしているか確認する(私はLinkitで確認を怠った) - できるだけ、2の環境でD9に行った時の環境適応を終了しておく
- ここで、復活の呪文用にバックアップを確保する
- D9へのアップグレードを行って動作検証する
特に機能変更があるモジュールは要注意で、可読確認だけでなく編集も試す(私は編集の段階で問題が発生した) - 問題解決を行う
- 概ね確信がもてたら、バックアップを確保する
- 本番移行手順を確立する
mysqldump 旧データベース|mysql 新データベース と vendor/bin/drush updb と cp -r sites/default/files 新プロジェクト/sites/default だけで何度でもできるようにしておくのが望ましい - 本番のプロジェクトディレクトリを切り替える
以上で、恐らくなんとかなる。
実際に2020年12月7日14:30過ぎに切り替え作業を実施した。