Zum Inhalt springen
duxt

Was der Build prüft

Die stillen Fehlschläge dieser Ebene, in Meldungen verwandelt.

Jeder Fehler, den diese Ebene tatsächlich hatte, war lautlos: eine Collection, die Content verwarf, weil ihr Name kein JavaScript-Bezeichner war; eine Seite, die 404te, weil ein Link veraltet war; eine Navigation, die leer zurückkam. Keiner der drei sagte etwas — der Build war grün und die Seite falsch. Also laufen nach dem Build Prüfungen, die alle dasselbe lesen: den Parse-Cache, den Content hinterlässt.

PrüfungSchweregrad
Eine Collection ohne SeitenFehler
Ein Ordner, der mit einem URL-Segment kollidiertFehler
Ein fehlender title oder descriptionWarnung
Ein toter interner Link oder AnkerWarnung
Was eine generierte Sektion nicht lesen konnteWarnung
Was jede Sprache trägt und was stehen geblieben istHinweis

Warum der Schweregrad nicht einheitlich ist

Ein Fehler kostet eine Seite, die niemand erreichen kann und die nichts auf der Website je erklären würde — eine leere Collection ist ein 404 auf jeder Seite einer Version. Eine Warnung kostet Qualität: Die Seite rendert weiterhin, und eine entfernte Quelle kann zwischen zwei Releases veralten, ohne dass das die Schuld dieses Builds wäre. Den Build scheitern zu lassen, weil das Repository eines anderen weitergezogen ist, würde einen grünen Build von einem Dritten abhängig machen.

Ein Hinweis kostet gar nichts: Er ist ein Zustand der Website, kein Mangel an ihr. Eine unübersetzte Seite ist kein Fehler, und sie als Warnung zu melden würde allen beibringen, über die Warnungen hinwegzulesen.

Generierte Sektionen

Eine generierte Sektion wird geprüft wie jede andere Collection, in ihren eigenen Worten. Was in diesem Bericht landet, ist eines von drei Dingen:

  • Das Artefakt war an diesem Ref nicht da, die Sektion wurde also nicht gebaut;
  • der Typ hat nichts daraus gelesen, die Sektion beansprucht also URLs und liefert keine aus;
  • der Typ ist über etwas hinweggegangen — ein nicht auflösbares $ref in einem OpenAPI-Dokument, eine Changelog-Überschrift, die wie ein Release aussieht, sich aber nicht als eines parsen lässt und deshalb Teil des Releases darüber wurde.

Alle drei sind Warnungen, und das ist kein Kompromiss. Alles, was ein lokales Artefakt falsch machen kann — ein Pfad, der nicht da ist, eine Datei, die der Typ überhaupt nicht lesen kann, eine Option, die er nicht kennt —, lässt den Build bereits beim Laden der Konfiguration scheitern, lange bevor es diesen Bericht gibt: Die eigene Konfiguration der Website ist ein Fehler, den der Build nicht mittragen darf. Was hier übrig bleibt, ist entweder ein entferntes Artefakt, das zwischen zwei Releases legitim veraltet sein kann, oder eine Seite, die gerendert wurde und in der etwas fehlt.

Der Übersetzungsbericht

Eine Zeile je Sprache, in jedem Build:

[duxt] translations
[duxt]   de: 118/121 pages, 3 behind the original
[duxt]     "docs/guides/deploying.md" has no de translation.
[duxt]     "docs/de/concepts/sources.md" has not moved since the original changed.

Die zweite Zahl braucht history: true an der Quelle — die Daten kommen aus git, und eine Quelle, die ihre Historie nicht angefordert hat, hat keine. Ohne sie zählt der Bericht die Abdeckung und sagt nichts über Veralten, statt aus dem Fehlen zu raten.

Es gibt ihn wegen eines konkreten Fehlschlags. OpenCode übersetzte seine Dokumentation mit einem Agenten in CI in siebzehn Sprachen, schaltete den Workflow ab, und nirgends stand, dass die Übersetzungen sich nicht mehr bewegten. Die Ebene weiß pro Seite ohnehin, welche Sprachen sie tragen und wann jede Datei sich zuletzt geändert hat; ein Bericht macht daraus etwas, das jemand sieht.

Derselbe Bericht als Befehl

Die Befunde liegen an zwei Orten, die sich schlecht jemandem in die Hand drücken lassen: in einem Build-Log, das weggescrollt ist, und in Devtools-Panels, die es nur in einem laufenden Dev-Server gibt. duxt-report ist der dritte — dieselben Daten als Markdown auf stdout. Er kommt mit dem Paket, die Ebene zu erweitern ist also alles, was es dafür braucht.

pnpm exec duxt-report            # Markdown
pnpm exec duxt-report --json     # the same data, unrendered

Er liest die app.config.ts der Website, die Artefakte daneben und die Seiten aus dem Parse-Cache von Content — kein Server, er läuft also in CI und in einer Pipe. Er endet mit 1 bei einem Fehler und mit 0 bei Warnungen, also nach derselben Schweregradregel, der auch der Build folgt.

Drei Panels haben hier keine Entsprechung, und das mit Absicht: Der Suchindex, der Pfad-Debugger und die Cache-Auflistung sind Fragen an einen laufenden Prozess, und sie von außen zu beantworten hieße raten.

Was die Prüfungen wissen und du nicht

  • Eine Ordnerkollision ist nur ein Problem, solange ein Präfix aktiv ist. Ein Doku-Ordner namens v2 ist auf einer unversionierten Seite in Ordnung und auf einer versionierten unerreichbar, weil das Präfix gewinnt. Der Build weiß, welcher Fall vorliegt, und die Meldung benennt die Datei und bietet die Lösung an.
  • Ein Link wird so aufgelöst, wie das Theme ihn auflöst. Ein absoluter Pfad in einer Seite ist relativ zur eigenen Quelle dieser Seite, wird also zuerst unter dem Präfix der Quelle probiert und danach nackt. Eine Prüfung, die nur die nackte Form kennt, würde auf einer Multi-Repo-Seite jeden korrekten Link melden.
  • Ein Link wird in seiner eigenen Sprache aufgelöst. Jede Sprache einer Quelle liefert identische Inhaltspfade — die Locale steht vor der URL, nicht im Inhaltsbaum —, und Anker werden aus dem Überschriftentext abgeleitet, eine deutsche Überschrift hat also einen deutschen Anker. Eine Prüfung, die nur über den Pfad auflöst, würde einen deutschen Link gegen englische Überschriften prüfen und auf einer übersetzten Seite jeden korrekten Anker melden. Ein Link auf eine Seite, die eine Sprache nicht trägt, fällt auf das Original zurück — genau wie die Website selbst.
  • Externe URLs werden nicht geprüft. Eine zu verifizieren hieße, das Netz in den Build zu holen, und ein nicht erreichbarer fremder Host ist kein Grund, warum deine Dokumentation nicht ausgeliefert wird.

/concepts/sources, nicht ../2.concepts/2.sources.md. Unter welchem Präfix eine Seite ausgeliefert wird, entscheidet sich zur Build-Zeit — Pfade ohne Präfix zu schreiben ist deshalb genau das, was dasselbe Markdown auf einer Seite /guides/deploying und auf einer anderen /acme/v2.0.0/guides/deploying bedienen lässt. Es ist außerdem die einzige Form, die die Linkprüfung sieht.

War diese Seite hilfreich?