Ein Schutz für die Fehler, die nur auf der Plattform auftreten

Zwei Dinge hatten die Produktion lahmgelegt, und keines von beiden konnte lokal scheitern: ein Import ohne Endung, den ein Bundler verdeckt und Node verweigert, und ein Muster in vercel.json, das überhaupt keine Bereitstellung erzeugt. Beides wird jetzt vor dem Build geprüft, und der Schutz wurde bewiesen, indem jeder der beiden Fehler noch einmal eingebaut wurde.

Die Typen stimmen, der Bundler baut, der Entwicklungsserver liefert aus — und die Bereitstellung antwortet auf jede Anfrage mit 500. Für genau diesen Abstand gibt es dieses Skript. Alle drei Werkzeuge lösen Module auf und lesen Konfiguration so, wie ein Bundler es tut; die ausgelieferte Funktion tut beides nicht, und das Skript prüft genau den Unterschied. Es steckt in npm run build und endet mit einem Fehlercode, damit keiner der beiden Fehler noch einmal bis zu einem Push kommt.

Was es abweist

Einen relativen Import ohne Endung. Die API läuft als ESM auf Node, wo ./faq nicht auflöst und ./faq.js schon. Eine einzige solche Zeile, erreichbar aus dem Importgraphen des Servers, beantwortete jede /api-Route mit FUNCTION_INVOCATION_FAILED.

Einen .json-Import in diesem Graphen. import { version } from '../package.json' besteht die Typprüfung, baut und läuft im Entwicklungsserver. Das ausgelieferte Bündel trägt Module und nicht das Repository, die Datei ist also einfach nicht da, und der Import scheitert beim Laden des Moduls — und das ist jede Anfrage, weshalb die ganze API 500 lieferte.

Ein source-Muster, das der Router der Plattform nicht liest. Das Symptom ist hier keine fehlgeschlagene Auslieferung: Ein ungültiges Muster wird abgewiesen, bevor ein Build beginnt, es gibt also überhaupt keine Bereitstellung, und die Produktion bleibt still auf dem vorherigen Commit. Die Muster werden mit derselben Bibliothek gelesen, mit der die Plattform sie liest.

Eine Version, die sich selbst widerspricht. shared/version.ts muss mit package.json übereinstimmen. Es ist eine Kopie, eben weil ein JSON-Import der Fehler von oben ist, und eine Kopie, die niemand prüft, veraltet; das Manifest der Erweiterung und das Release-Tag lesen die eine, der Connector die andere.

Wie es entscheidet, wohin es schaut

Die Regel gilt für die Dateien, die die ausgelieferte Funktion wirklich lädt, und diese Menge ist nicht „alles unter server/“ — sie folgt den Importen, wohin sie führen, und genau so wurde eine Datei unter src/lib überhaupt Teil des Servers. Es beginnt deshalb am Eingangspunkt der Funktion und läuft von dort. Ein Import, der nur Typen holt, wird übersprungen: Er wird beim Kompilieren getilgt, seine Angabe muss also nie zur Laufzeit aufgelöst werden.

Was es nicht ist

Keine Testsuite und kein Linter. Es kennt vier bestimmte Unterschiede zwischen der Plattform und einem Laptop und sonst nichts; einen Denkfehler bemerkt es nicht, und wenn die Bibliothek zum Lesen der Muster fehlt, warnt es statt zu scheitern — denn der Zweck ist, den Fehler auf der Maschine zu fangen, auf der er gemacht wird. Jede Regel wurde bewiesen, indem ihr Fehler wieder eingebaut wurde und die Prüfung fiel.

Weiter: Dokumentation, die im Repository lebt und Markdown aus GitHub Actions veröffentlichen.