Migration V14 > V15: Problem bei "bench start"

Hallo alle,

ich versuche mich gerade an der Migration von V14 auf V15 und habe hier ein sehr seltsames Problem. Ich habe die Prerequisites installiert:
Node 18.19.0
Bench 5.19.0
Python 3.11.7
Pip 23.3.1
MariaDB 10.6.16

Und die bench auf Python3.11 migriert:

bench pip install --upgrade pip
bench migrate-env python3.11

Beim Schwenk auf V15 treten dann die ersten Probleme auf:
bench switch-to-branch version-15 --upgrade frappe erpnext hrms

Die laufende bench wird dabei gestoppt, im Log tauchen Fehler auf:

14:46:50 watch.1          | ✘ [ERROR] Could not resolve "/home/frappe/frappe-bench/apps/frappe/frappe/public/js/recorder.bundle.js"
14:46:50 watch.1          | 
14:46:50 watch.1          | ✘ [ERROR] Could not resolve "./file_uploader"
14:46:50 watch.1          | 
14:46:50 watch.1          |     frappe/public/js/frappe/upload.js:4:25:
14:46:50 watch.1          |       4 │ import FileUploader from "./file_uploader";
14:46:50 watch.1          |         ╵                          ~~~~~~~~~~~~~~~~~
14:46:50 watch.1          | 
14:46:50 watch.1          | ✘ [ERROR] Could not resolve "./reminders"
14:46:50 watch.1          | 
14:46:50 watch.1          |     frappe/public/js/frappe/form/toolbar.js:5:32:
14:46:50 watch.1          |       5 │ import { ReminderManager } from "./reminders";
14:46:50 watch.1          |         ╵                                 ~~~~~~~~~~~~~
14:46:50 watch.1          | 
14:46:50 web.1            |  * Detected change in '/home/frappe/frappe-bench/apps/frappe/frappe/desk/doctype/notification_settings/notification_settings.py', reloading
14:46:51 web.1            |  * Restarting with stat
14:46:51 web.1            | Traceback (most recent call last):
14:46:51 web.1            |   File "<frozen runpy>", line 189, in _run_module_as_main
14:46:51 web.1            |   File "<frozen runpy>", line 112, in _get_module_details
14:46:51 web.1            |   File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 1407, in <module>
14:46:51 web.1            |     @whitelist(methods=["POST", "PUT"])
14:46:51 web.1            |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14:46:51 web.1            |   File "/home/frappe/frappe-bench/apps/frappe/frappe/__init__.py", line 819, in innerfn
14:46:51 web.1            |     from frappe.utils.typing_validations import validate_argument_types
14:46:51 web.1            |   File "/home/frappe/frappe-bench/apps/frappe/frappe/utils/typing_validations.py", line 7, in <module>
14:46:51 web.1            |     from pydantic import ConfigDict
14:46:51 web.1            | ModuleNotFoundError: No module named 'pydantic'
14:46:51 system           | web.1 stopped (rc=1)

Dann wird es seltsam. Beim erneuten bench start tritt dieser Fehler auf:

15:40:30 system           | socketio.1 started (pid=28325)
15:40:30 socketio.1       | /home/frappe/frappe-bench/apps/frappe/node_modules/@redis/client/dist/lib/client/index.js:35
15:40:30 socketio.1       |             modules: extensions?.modules,
15:40:30 socketio.1       |                                 ^
15:40:30 socketio.1       | 
15:40:30 socketio.1       | SyntaxError: Unexpected token '.'
15:40:30 socketio.1       |     at wrapSafe (internal/modules/cjs/loader.js:915:16)
15:40:30 socketio.1       |     at Module._compile (internal/modules/cjs/loader.js:963:27)
15:40:30 socketio.1       |     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
15:40:30 socketio.1       |     at Module.load (internal/modules/cjs/loader.js:863:32)
15:40:30 socketio.1       |     at Function.Module._load (internal/modules/cjs/loader.js:708:14)
15:40:30 socketio.1       |     at Module.require (internal/modules/cjs/loader.js:887:19)
15:40:30 socketio.1       |     at require (internal/modules/cjs/helpers.js:74:18)
15:40:30 socketio.1       |     at Object.<anonymous> (/home/frappe/frappe-bench/apps/frappe/node_modules/@redis/client/dist/index.js:18:18)
15:40:30 socketio.1       |     at Module._compile (internal/modules/cjs/loader.js:999:30)
15:40:30 socketio.1       |     at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
15:40:30 system           | socketio.1 stopped (rc=1)

Offensichtlich versteht die node-Version, die von bench start verwendet wird, noch kein optional chaining. Dies wäre bei node <= V12 der Fall. Ich habe aber kein node <= V12 mehr auf meinem Rechner, siehe nvm list:

frappe@my_erpnext:~/frappe-bench$ nvm list
->     v18.19.0
         system
default -> 18 (-> v18.19.0)
node -> stable (-> v18.19.0) (default)
stable -> 18.19 (-> v18.19.0) (default)
iojs -> N/A (default)
lts/* -> lts/iron (-> N/A)
lts/argon -> v4.9.1 (-> N/A)
lts/boron -> v6.17.1 (-> N/A)
lts/carbon -> v8.17.0 (-> N/A)
lts/dubnium -> v10.24.1 (-> N/A)
lts/erbium -> v12.22.12 (-> N/A)
lts/fermium -> v14.21.3 (-> N/A)
lts/gallium -> v16.20.2 (-> N/A)
lts/hydrogen -> v18.19.0
lts/iron -> v20.10.0 (-> N/A)

Ich verstehe nicht, was hier passiert. Den Source Code von bench verstehe ich leider auch nicht.
Habt Ihr eine Idee, was die Ursache sein könnte?

Vielleicht Empfehlungen für strategisch geschickte print()-Statements, mit denen man den Ablauf von bench start überprüfen kann?

Hier ist ein zuverlässigerer Weg für das Upgrade:

  1. Setze einen neuen Server oder Container mit den nötigen Abhängigkeiten auf.
  2. Erstelle eine neue Bench und Site. Vergewissere dich, dass alles funktioniert.
  3. Erstelle ein vollständiges Backup deiner „alten“ Instanz (Datenbank, hochgeladene Dateien, Site Config)
  4. Stelle das Backup auf der neuen Bench wieder her und führe danach bench migrate aus. Vergewissere dich, dass alles funktioniert.
1 Like

Vielen Dank für die schnelle Antwort.

Das mag ja für Entwicklungsinstanzen machbar sein, aber das ist doch nicht wirklich der Weg für produktive Instanzen?

Ich versuche aus meinen Erfahrungen bei der Migration im Dev einen sicheren Weg für die Migration unserer Prod-Instanzen zu erarbeiten, und diese Lösung wird von meinen Chefs nicht akzeptiert werden.

Was genau stört euch daran?

1 Like

Wie Raffael beschreibt ist das eigentlich Gold-richtig. Erstmal npm, node, python, yarn, honcho und das ganze Zeug drauf und dann frappe mit php3 oder pipx installieren, bench update, bench migrate etc. Wenn man sich nach bench start dann mit localhost:8000 verbinden kann, halbe Miete!

Jetzt mariadb configurieren und mit bench get-app die ganzen Apps installieren, eine davon ist dann erpnext, site erzeugen, site-Namen in die hosts oder dns und per 8000 verbinden. Hat das alles geklappt, sehr gut! Jetzt noch die richtige Datenbank unterschieben und bench migrate. Brauchst du vielleicht eher neue Chefs? :slight_smile:

Was ihr beschreibt ist zu 100% machbar, aber unerwartet aufwändig für ein Update von einer Software-Version.

Zunächst mal brauchen wir einen eigenen neuen Server fürs ERP. Der muss dann komplett neu aufgesetzt werden. Kostest Zeit, kostet Geld.

Das ganze mindestens mal drei: Entwicklung, Test, Prod, in unserem Fall mal fünf. Kostest Zeit, kostet Geld.

Die Hardwarekosten ließen sich durch den Einsatz von Docker-Containern begrenzen. Haben wir bisher nicht gemacht, müssen wir Knowhow aufbauen. Kostest Zeit, kostet Geld.

Ich persönlich habe Spaß an Frickeleien und lerne gern neue Sachen, wie Ihr wahrscheinlich auch. Die Finanzen macht aber jemand anders, und der wird nicht glücklich über diese Lösung sein. Es ist auch nicht so, das der Betrieb des ERP zum Nulltarif erfolgen muss, aber fünf neue Rechner anschaffen und aufsetzen, um auf eine neue Version migrieren zu können…?

Oder anfangen mit Docker, und den Aufwand für Einarbeitung tragen. Klingt interessant, wird aber eine Weile dauern, bis das richtig läuft. In der Zeit bleiben dann andere bereits geplante Sachen liegen, was die Anwender unglücklich macht.

Alles zusammenfassend möchte ich nur sagen, das der Aufwand für die Migration auf V15 derzeit unerwartet hoch ist, und wesentlich höher als er sein sollte.

Das ist nunmal der offizielle Weg. Warum aber 5x neue Hardware? Für eine reine Migration sollte virtualisierung ja Standard sein.

Zumal? Kostet diese Fehlerbereinigung und das probieren aktuell nicht auch Zeit/Geld?

In meiner Testumgebung habe ich das Update (war aber auf die Beta) so aber hinbekommen:

bench switch-to-branch version-15 --upgrade frappe erpnext hrms

Ja ein simpler Schalter “Upgrade” wäre wünschenswert - denke da sind aber genug Gründe weshalb dies aktuell nicht möglich ist.

Hi Lucas,
ich beneide Dich, das bench switch-to-branch version-15 bei dir reibungslos durchgelaufen ist :wink:
Ich habe bereits die Migrationen V12 > V13 > V14 mitgemacht und bin dabei immer recht gut durchgekommen, ohne neue Server aufzusetzen.

Ich denke, das dies auch mit V15 klappen müsste.

Wenn mach sich den Fehler anschaut: Syntax Error bei "extensions?.modules," ist eigentlich alles gesagt:
Die JS-Laufzeitumgebung node versteht noch kein optional chaining. Dies ist bei node V12 der Fall. Nun habe ich mir große Mühe gegeben, node V12 von der Platte zu putzen, trotzdem schafft bench start es noch irgendwie, eine alte Version zu benutzen.

Wie ein allseits bekannter Vulkanier sagen würde: Unlogisch, aber faszinierend.

Ein Vorteil scheint mir zu sein, dass man nahtlos zurück-switchen könnte, falls erforderlich, weil das bisherige Setup erstmal nicht angerührt wird.

Und das neue Setup erstmal unabhängig zu testen, könnte auch erheblich günstiger sein, als ein Totalausfall des System wegen irgendeines blöden Fehlers, der jedem jederzeit mal passieren könnte.

Dann wird die Buchhaltung vielleicht fragen, wieso denn das Update nicht resilient und mit Redundanz durchgeführt wurde.
(Danach wird vielleicht das Budget für besseres Ops angepasst werden, oder mal eine Schulung genehmigt, damit einem das Containerei-Jonglieren flüssiger und sicherer von der Hand geht.)

Problem gelöst. Ich habe herausgefunden, das bench start die Datei /usr/bin/node verwendet, dies ist bei mir V12. Das damals von mir installierte node lag in meinem Home-Verzeichnis, wurde aber von der bench nicht verwendet.

Unter How To Install Node.js on Debian 10 | DigitalOcean habe ich eine Anleitung gefunden, mit der ich node aktualisieren konnte.

Das Erstellen eines neuen Servers/Containers hätte das Problem nicht gelöst, da ich wieder Debian Buster als Basis verwendet hätte, was mir wiederum /usr/bin/node V12 bereitgestellt hätte.

Vielen Dank für die Anregungen bezüglich Container und Virtualisierung, ich werde dem nachgehen. Der Einsatz einer neuen Debian Distro macht bestimmt auch Sinn.

Auf einer anderen Instanz konnte ich das Problem noch einfacher lösen:

nvm install 20
nvm alias default 20

node V20 war zu diesem Zeitpunkt der aktuelle stable release, für Frappe hätte es auch V18 getan.
Das Entscheidende ist, die richtige Version als Default zu setzen.