Composer-gestütztes Upgrade von Drupal 8.x auf Drupal 9.x. Mit dem vorliegenden Drupal 9.1.5 sind die ärgsten Kinderkrankheiten ausgemerzt und es gibt keinen Grund, es länger aufzuschieben: Das Upgrade auf Drupal-9, um auf der Höhe der Zeit zu bleiben und man von den großartigen Neuerungen profitieren kann.

Vorbedingungen:

Projekt anlegen

Alle beschriebenen Arbeitsschritte werden in einer lokalen Entwicklungsumgebung durchgeführt. In einem frischen Projekt-Ordner diese Verzeichnisse anlegen:

#!/bin/sh
mkdir assets backup config private config/sync
  • assets: Für Dinge wie Fonts, Layout-Bilder etc., die zur Website gehören, im Original-Zustand
  • backup: Für Backups der Dateien und der Datebank
  • config/sync: Für Drupals Konfiguration, wenn man eingestellt hat, dass diese in Dateien anstatt in die Datenbank geschrieben werden sollen
  • private: Private Files. Im Gegensatz zu sites/default/files liegen hier Dateien mit Zugriffsberechtigung, falls man dies wünscht

All diese Dinge liegen "außerhalb des Web"; ein anonymer Besucher kann also nie auf diese Dinge zugreifen, indem er z.B. den Pfad errät.

Als Name für den Projekt-Ordner wähle ich persönlich einfach die Domain ohne Top-Level, aus domain.tld wird also der Projektordner domain. Das hat sich in der Praxis bewährt und es gibt kein Rätselraten, zu welchem Kunden "Projekt315" wohl gehören mag.

Auch in einer verteilten Arbeitsumgebung mit mehreren Leuten ist es wichtig, super-einfache Regeln aufzustellen, an die sich jeder hält und jeder sofort versteht.

Durch das Übertragen der Website-Bestandteile in eine frisch angelegte Datei-Installation hat man die Chance, Dinge zu entrümpeln und korrekt nach aktuellen Empfehlungen zu lösen.

Weist die Website-Struktur bereits die der empfohlenen Drupal-Installation auf, kann dieser Schritt auch übersprungen werden. Alle Websites, die zuvor nicht mit composer sondern per Direktdownload von drupal.org erzeugt wurden, sollten die Umstellung auf die neue Ordner-Struktur durchlaufen, sonst funktionieren auch die weiteren Schritte nicht.

Frisches Drupal-Projekt 8.x

Mittels

#!/bin/sh
composer create-project drupal/recommended-project:8.8 --no-dev new_dir

ein frisches Drupal-Projekt innerhalb des Projektordners anlegen. Falls diese Fehlermeldung erscheint...

Your lock file does not contain a compatible set of packages. Please run composer update.

... einfach ins Verzeichnis new_dir wechseln und mit composer update auf Stand bringen. Diese Fehlermeldung scheint daher zu kommen, dass composer selbst grade einen Versionssprung von 1.x auf 2.x hatte, so daß viele composer.json Dateien nicht mehr ganz aktuell sind.

Sobald composer mit dem Erzeugen fertig ist, kann der Inhalt von new_dir eine Ebene hochgeschoben und new_dir gelöscht werden.

#!/bin/sh
### vom Projektordner aus aufgerufen

# dot-files eine Ebene höher
mv new_dir/.* .

# alles andere eine Ebene höher
# und new_dir (jetzt leer) löschen
mv new_dir/* . && rmdir new_dir

Somit sieht der Projektordner nun wie folgt aus:

  • .editorconfig
  • .gitattributes
  • assets/
  • backup/
  • composer.json
  • composer.lock
  • config/
    • config/sync/
  • private/
  • vendor/
  • web/

Website-Dateien umschieben

Die Bestandteile, die die Website ausmachen, aus dem alten Projektordner in den neuen schieben. Zu bewegen sind: files, theme(s), module, libraries und ggf. weitere Dinge wie favicons, spezielle .htaccess-Direktiven etc., z.B.

alter_ordner/sites/default/files --> projektordner/sites/default/files

Randnotiz Datei-Cache

Diese Verzeichnisse

  • /sites/default/files/php
  • /sites/default/files/css
  • /sites/default/files/js

kann man gefahrlos löschen. Diese werden im laufenden Betrieb von Drupal automatisch angelegt und enthalten gecachte Dateien.

auch /sites/default/files/styles kann gefahrlos gelöscht werden. Hier werden die durch die Bildstile definierten Kopien der Original-Bilder abgelegt. Wenn hier etwas fehlt, wird es automatisch neu angelegt.

Gerade vor Übertragung oder dem Einpacken (zip, tgz, bzip, ...) sollte man daran denken, diese Verzeichnisse zu entsorgen, um die Dateigröße insgesamt klein zu halten.

Drupal Settings

Die Zugangsdaten zur Datenbank/Local und Datenbank/Hoster sollte man zur Hand haben, um die settings.php und settings.local.php zu erzeugen.

#!/bin/sh
cp sites/default/default.settings.php sites/default/settings.php
cp sites/default/default.services.yml sites/default/services.yml
cp sites/example.settings.local.php sites/default/settings.local.php

Gerade die settings.php ist eine sehr lange Datei mit sehr detaillierten Kommentaren als Hilfe zur Anwendung der verschiedenen Dinge in den Settings. Ich persönlich lösche alle Kommentare aus der settings.php und schiebe diejenigen Dinge, die Umgebungs-abhängig sind, in eine durch einen Kommentar abgetrennte Sektion.

Als Referenz zum Nachlesen der Einstellungsmöglichkeiten verbleibt default.settings.php.

Umgebungs-abhängig sind z.B. Datenbank-Verbindung, Fehleranzeige, Trusted Hosts und ggf. weitere.

In der settings.local.php verfahre ich ebenso. Die Umgebungs-abhängigen Dinge stehen unten in einem Segment zusammen. Mir erleichtert das die Übersicht und ich weiß, wo ich hinspringen muß, um etwas zu ändern. Ich muß nicht suchen.

Solange wir uns auf der lokalen Web-Umgebung bewegen, kommentieren wir die letzten Zeilen der settings.php Datei aus, damit settings.local.php geladen wird und aktiv ist.

In settings.php und settings.local.php nun auch die extra angelegten Verzeichnisse eintragen:

$settings['config_sync_directory'] = '../config/sync';
$settings['file_private_path'] = '../private';

Diese hier nicht vergessen und entsprechend ihrer Umgebung in settings.php und settings.local.php entsprechende Werte eintragen:

$settings['file_public_path'] = 'sites/default/files';
$settings['file_temp_path'] = '/tmp';

Datenbank importieren

Mit einem Tool zur Datenbankverwaltung die Datenbank zur Website importieren und bereitstellen. Z.B. mit phpmyadmin, per Kommandozeile direkt mit SQL-Befehlen oder einem Programm mit GUI.

Website prüfen

Website im Browser aufrufen. Je nachdem, wie die lokale Entwicklungsumgebung realisiert ist, mit vagrant, Docker, einem Virtualbox Image, homebrew, mampp, xampp o.a., differiert dies etwas.

In meinem Fall aktuell mit homebrew unter Mac OS X, dnsmasq/resolver, Apache 2.4 (homebrew) und MariaDB. Alle Web/Drupal Projekte liegen bei mir in einem Ordner sites auf einem NAS. Mittels dnsmasq/resolver aufgelöst und durch Apache ausgeliefert ergibt sich immer die Web-URL projektname.sites.test, was ich sehr praktisch finde.

Das Ablegen der Website-Dateien auf dem NAS ist nicht die schnellste Lösung, aber mir geht es primär um den Platz.

In einer Bearbeitungsschleife alle Fehler beheben; Warnungen können meist ignoriert werden.

Abschließend einem die Datenbank Aktualisierung durchführen, damit die Datenbank auch auf aktuellem Stand ist.

Upgrade Vorbereitung

Modul: upgrade_status

Quelle: https://www.drupal.org/project/upgrade_status

#!/bin/sh
composer info | grep -r "drupal/core"
# -> versionsnummer

# core-dev anfordern
composer require --dev drupal/core-dev:versionsnummer

# modul installieren
composer require 'drupal/upgrade_status:^3.0'

Das Modul aktivieren. Modul update_manager wird als Abhängigkeit mit aktiviert, falls inaktiv. Dieses Modul ist das Werkzeug für die Vorbereitung zum Upgrade.

Drupal-9 Tauglichkeit der Module

Schleife mit Prüfung der Drupal-9-Tauglichkeit aller vorhandenen Module der Website.

/admin/reports/upgrade_status aufrufen und einzelne Module updaten, falls möglich. Anderenfalls Deaktivieren/Deinstallieren.

Module, die auch nach einem Update auf die neueste Version nicht Drupal-9-ready sind, via Erweitern/Modul Deinstallieren entfernen. Nach Deaktivierung kann auch der zugehörige Modul-Ordner unter /modules gelöscht werden.

Das Upgrade ist auch eine Möglichkeit, ein bisschen aufzuräumen und nicht genutzte Module zu deaktivieren und zu löschen.

upgrade_status zeigt in tabellarischen Übersichten alle Module nach ihrem Status an. Man kann nun entweder alle Module, die nicht in Drupal 9 laufen werden, einzeln deinstallieren und löschen oder stumpf alle genannten Module mit composer require hinzufügen, um sie später mit composer remove zu entfernen. Das Ergebnis ist dasselbe.

Website Module updaten

Durch das Aufrufen von

#!/bin/sh
composer require drupal/modul_name

ohne Versionsnummer wird automatisch die aktuellste Version, die auf drupal.org verfügbar ist, in die Datei composer.json eingetragen und installiert. composer lädt blitzschnell die Version gepackt herunter und entpackt den Modul-Ordner an die richtige Stelle (/modules/contrib). Es verbleiben keine Artefakte älterer Versionen desselben Moduls.

Um die vom gewünschten Modul abhängigen anderen Dinge kümmert sich composer automatisch und updated ggf. auch Dinge im /vendor Verzeichnis.

Anstatt jedes Modul einzeln anzufordern, kann auch eine lange Befehlszeile gebaut werden, mit der dann alles auf Schlag aktualisiert wird:

#!/bin/sh
### das zeichen \ verbindet die zeilen, man kann auch alles in 1 zeile schreiben
composer require \
    drupal/admin_toolbar \
    drupal/better_exposed_filters \
    drupal/ctools \
    drupal/dropzonejs \
    drupal/entity_embed \
    drupal/entity_reference_revisions \
    drupal/eu_cookie_compliance \
    drupal/field_group \
    drupal/file_browser \
    drupal/paragraphs \
    drupal/pathauto \
    drupal/superfish \
    drupal/video_embed_field \
    drupal/metatag \
    drupal/schema_metatag

Website Theme "updaten"

Das genutzte Theme wird wahrscheinlich für Drupal-8 entwickelt worden sein. Hier muss eine entsprechende Zeile in die Datei /themes/custom/theme_name/theme_name.info.yml eingefügt werden:

core_version_requirement: ^8 || ^9

am besten direkt nach dem core-Eintrag. Den Eintrag solchermaßen bearbeiteter Theme-Einträge in der Übersicht von upgrade_status markieren und "scannen" (Button ganz unten), damit diese Änderung übernommen und das Theme als Drupal-9-tauglich markiert wird.

Datenbank aktualisieren

Durch das Updaten der Module (genauer: der Dateien der Module) muß nun final auch nochmal die Datenbank auf Stand gebracht werden, hierzu einfach "Aktualisierungen durchführen" aufrufen.

Modul upgrade_status entfernen

Wenn die Status-Anzeige von upgrade_status 100% angzeigt und nun alle Module und Themes geprüft sind, als letzten Schritt das Modul upgrade_status deaktivieren und deinstallieren, es wird für die weiteren Schritte nicht mehr gebraucht.

#!/bin/sh
### erst deaktiveren, dann dies
composer remove drupal/upgrade_status

Drupal 9 Upgrade durchführen

Quelle: https://www.drupal.org/docs/upgrading-drupal/upgrading-from-drupal-8-to…

Jetzt geht es ans Eingemachte.

#!/bin/sh
composer require drupal/core-recommended:^9.0.0 drupal/core-composer-scaffold:^9.0.0 drupal/core-project-message:^9.0.0 --update-with-dependencies --no-update

# If you have drupal/core-dev installed.
composer require drupal/core-dev:^9.0.0 --dev --update-with-dependencies --no-update

Dies aktualisiert erst die composer.json Datei, es passiert noch nichts. Erst wenn wir den nächsten Befehl ausführen lassen, sehen wir, ob alles geklappt hat.

#!/bin/sh
composer update

Composer löst nun wieder alle Abhängigkeiten auf, lädt Fehlendes nach und ersetzt alte Bestandteile. Kurzum: Composer bringt unsere Website auf Drupal-9.

Der Prozess nimmt ggf. etwas Zeit in Anspruch; währenddessen kann man gespannt das Terminal beobachten, wie viele Zeilen dort vorbeirauschen. Oder man macht sich einen Kaffee.

Finaler Check der Website

Der nächste Aufruf von /admin/reports/status sollte nun anzeigen, dass hier eine Drupal-9 Version werkelt. Zum jetzigen Zeitpunkt ist es grad Drupal 9.1.5.

Nun noch ein Datenbankupdate via /update.php und diese Website ist auf Stand.

Anschließend kann diese Website deployed werden. Mit git, (s)ftp oder welche Möglichkeiten beim gewählten Hoster zulässig sind.

Kurzform für Copy-Paste im Terminal

#!/bin/sh
mkdir projektordner
cd projektordner
mkdir assets backup config private config/sync
###
composer create-project drupal/recommended-project:8.8 --no-dev new_dir
### fehlermeldung "Your lockfile..."
cd new_dir
composer update
cd ..
####
### dot-files eine ebene hoeher
mv new_dir/.* .
### alles andere eine ebene höher
### und new_dir (jetzt leer) löschen
mv new_dir/* . && rmdir new_dir
###
# alte installation files, theme(s), module, libraries
# und ggf. weitere dinge wie favicons, spezielle .htaccess direktiven etc.
# in projektordner verschieben
###
# können gelöscht werden:
/sites/default/files/php
/sites/default/files/css
/sites/default/files/js
/sites/default/files/styles
###
# settings
cp sites/default/default.settings.php sites/default/settings.php
cp sites/default/default.services.yml sites/default/services.yml
cp sites/example.settings.local.php sites/default/settings.local.php
# werte in settings eintragen.
###
# datenbank zur website importieren
###
# seite im browser aufrufen http://projektname.sites.test
###
composer require drupal/composer_deploy
# modul aktivieren
###
composer info | grep -r "drupal/core"
# -> versionsnummer
composer require --dev drupal/core-dev:# versionsnummer
composer require 'drupal/upgrade_status:^3.0'
###
# ungenutzte module deaktivieren + deinstallieren
###
composer require drupal/admin_toolbar drupal/better_exposed_filters drupal/ctools drupal/dropzonejs drupal/entity_embed drupal/entity_reference_revisions drupal/eu_cookie_compliance drupal/field_group drupal/file_browser drupal/paragraphs drupal/pathauto drupal/superfish drupal/video_embed_field drupal/metatag drupal/schema_metatag
###
# in /themes/custom/theme_name/theme_name.info.yml:
core_version_requirement: ^8 || ^9
# theme "scannen"
###
# wenn alles auf 100%
# upgrade_status deaktivieren
composer remove drupal/upgrade_status
###
# db update
###
composer require drupal/core-recommended:^9.0.0 drupal/core-composer-scaffold:^9.0.0 drupal/core-project-message:^9.0.0 --update-with-dependencies --no-update
composer require drupal/core-dev:^9.0.0 --dev --update-with-dependencies --no-update
# update d-9
composer update
###
# db update
###
# db export in projektordner/backup
# projektordner deployen

 

Sektor