Auf mehrere Dateien verteilte Structurizr-Workspaces lassen sich jetzt in Archyl importieren

Manche Structurizr-Workspaces enthalten in workspace.dsl fast nichts. Einen Header, einen model-Block und eine Spalte von !include-Zeilen, eine pro System, während das eigentliche Modell über die Dateien verteilt ist, auf die sie verweisen.

Bis diese Woche konnte Archyl das nicht importieren. Unser Beitrag vom 4. August zur Abschaltung von Structurizr Cloud sagte das in einer Zeile: Workspaces aus mehreren Dateien mussten erst zu einer Datei zusammengeführt werden. Damit fielen Workspaces weg, die jedes System in einer eigenen Datei halten. Structurizr Cloud wird am 30. September abgeschaltet, in zwei Wochen.

Du kannst den Workspace jetzt als .zip hochladen, und Archyl löst jedes !include gegen die Dateien darin auf.

Warum eine einzelne Datei nie funktionieren konnte

Nimm einen Workspace mit diesem Aufbau:

workspace.dsl
model/
  people.dsl
  relationships.dsl
systems/
  ledger.dsl
  notifications.dsl
  payments.dsl

mit einer Wurzeldatei, die nur die Teile zusammenfügt:

workspace "Payments Platform" "Card payments and settlement" {
    model {
        !include model/people.dsl
        !include systems
        !include model/relationships.dsl
    }
}

Lädst du diese Wurzeldatei allein hoch oder fügst sie ein, hat der Importer nichts, gegen das er die Pfade auflösen kann. Er parst, was er hat, überspringt jedes Include und meldet dir:

line 3: directive '!include' is not supported and was skipped
line 4: directive '!include' is not supported and was skipped
line 5: directive '!include' is not supported and was skipped

Die Warnungen stimmen, und sie sind zugleich das gesamte Ergebnis: Nichts aus diesen sechs Dateien ist darin enthalten. Eine einzelne, in sich geschlossene .dsl-Datei wird weiterhin genau wie bisher importiert. Das Zip ist für alles andere.

Zippe das Workspace-Verzeichnis, nicht das Repository

Wenn dein Workspace !include verwendet, existieren die aufgeteilten Dateien irgendwo als Dateien. Structurizrs Dokumentation zu Includes beschreibt ein Datei-Include als "a single local file, specified by a relative path" — eine einzelne lokale Datei, angegeben über einen relativen Pfad. Die Kopie, auf die es ankommt, liegt also auf einer Festplatte oder in Git, nicht in der Cloud. Such das Verzeichnis, das workspace.dsl enthält, und zippe genau das.

Aus dem Verzeichnis heraus:

zip -r workspace.zip workspace.dsl model systems

Oder, wenn der Workspace in einem Repository liegt, direkt aus einem Commit:

git archive --format=zip -o workspace.zip HEAD:docs/architecture

Der Unterschied ist wichtig, weil das Archiv auf 500 Einträge begrenzt ist und diese Zahl geprüft wird, bevor irgendetwas herausgefiltert wird. Zippst du ein ganzes Repository samt .git-Ordner, kannst du die Grenze überschreiten, bevor auch nur eine .dsl-Datei gelesen wird. Ein umschließender Ordner auf oberster Ebene des Archivs ist kein Problem, denn Includes werden relativ zur einbindenden Datei aufgelöst.

Was beim Hochladen passiert

Im Import-Dialog heißt der Button im Structurizr-DSL-Tab jetzt .dsl oder .zip hochladen. Wählst du ein Archiv, wird der Code-Editor durch eine Karte mit dessen Namen und Größe ersetzt. Klick auf Validieren, und die Karte zeigt zusätzlich die Anzahl der Dateien und die gewählte Wurzeldatei.

Das funktioniert beim Import in ein bestehendes Projekt ebenso wie beim Anlegen eines neuen. Ein neues Projekt übernimmt seinen Namen aus dem Workspace-Header, also kann workspace "Payments Platform" { ... } ein Projekt anlegen, ein bloßes workspace { ... } dagegen nicht.

Auf dem Server durchläuft das Archiv vier Schritte:

  1. Die Wurzel wählen. workspace.dsl, wenn das Archiv eine enthält, sonst die am wenigsten tief liegende .dsl-Datei. Muss zwischen mehreren Dateien gewählt werden und heißt keine davon workspace.dsl, nennt eine Warnung die verwendete Datei.
  2. Includes als Text expandieren, vor dem Parsen. Der Inhalt der eingebundenen Datei ersetzt die !include-Zeile, dasselbe Inlining, das Structurizr macht. Pfade sind relativ zur einbindenden Datei, also findet systems/index.dsl, das shared/platform.dsl einbindet, die Datei systems/shared/platform.dsl.
  3. Verzeichnis-Includes auflösen. !include systems zieht jede .dsl-Datei direkt in systems/ herein, sortiert nach Namen. Unterverzeichnisse werden nicht durchlaufen.
  4. An den Rändern stoppen. Bindet eine Datei am Ende sich selbst ein, direkt oder über eine andere Datei, wird der Zyklus unterbrochen und gemeldet. Die Verschachtelung endet nach 10 Ebenen.

Der expandierte Workspace läuft danach durch denselben Structurizr-Importer wie eine einzelne Datei, mit derselben Genauigkeit und derselben Warnliste für alles, was übersprungen wird.

Ein Include, das sich nicht auflösen lässt, etwa eine fehlende Datei oder ein Pfad, der aus dem Archiv hinauszeigt, wird ebenfalls zur Warnung. Der Rest des Workspace wird trotzdem importiert.

Remote-Includes werden bewusst abgelehnt

Structurizr erlaubt auch, dass !include auf eine HTTPS-URL zeigt. Archyl folgt diesen nicht. Sie aufzulösen hieße, dass jede hochgeladene Datei unsere Server eine Adresse ihrer Wahl anfragen lassen könnte, und das ist ein Einfallstor für Server-Side Request Forgery, egal wer hochlädt. Die Zeile wird mit einer Warnung übersprungen:

!include: remote target "https://example.com/shared/identity.dsl" is not supported and was skipped

Enthält die Remote-Datei Modellelemente, die du brauchst, lade sie herunter, leg sie ins Archiv und ändere die Zeile auf einen relativen Pfad.

Die Limits

Limit Wert Bei Überschreitung
Archivgröße 10 MiB Upload abgelehnt
Einträge im Archiv 500 Upload abgelehnt
Gesamtgröße nach dem Entpacken 50 MiB Upload abgelehnt
Jede einzelne Datei 5 MiB Datei übersprungen, mit Warnung
Include-Verschachtelung 10 Ebenen Tieferes Include übersprungen, mit Warnung

Einträge, deren Pfad aus dem Archiv auszubrechen versucht, über einen absoluten Pfad oder ..-Segmente, werden mit einer Warnung übersprungen. Nur Textdateien werden behalten: .dsl, .md, .json, .yaml, .yml und .txt. Bilder und alles andere werden ohne Warnung verworfen, da der DSL-Importer nichts damit anfangen kann.

Was weiterhin nicht geht

Git-Sync löst keine Includes auf. Die Repository-Synchronisierung liest archyl.yaml, keinen Structurizr-Workspace, es gibt also noch keinen Weg, auf dem Archyl ein DSL aus mehreren Dateien direkt aus einem Repository holt. Liegt dein DSL in Git, ist der git archive-Befehl oben vorerst der Workflow.

Sonst hat sich an der Structurizr-Genauigkeit nichts geändert. Layout, Styles und Deployment-Views wurden vorher nicht importiert und werden auch aus einem Zip nicht importiert. Einen Weg über workspace.json gibt es ebenfalls weiterhin nicht: Archyl liest DSL-Text. Wenn dir an Structurizr vor allem das von Hand abgestimmte Layout wichtig ist, passen die Optionen aus dem Beitrag zur Abschaltung, bei denen du beim eigenen Tooling von Structurizr bleibst, weiterhin besser.

Vor dem 30. September

  1. Stell sicher, dass du die Quelldateien hast. Ein mit !include aufgeteilter Workspace wurde als Dateien geschrieben, also such sie. Liegt etwas nur in der Cloud-Kopie, etwa im Browser zurechtgerücktes Layout oder dort geschriebene Dokumentation, erklärt der Beitrag vom 4. August, wie du es herausbekommst.
  2. Zippe das Verzeichnis mit workspace.dsl, nicht das Repository drumherum.
  3. Hochladen und validieren. Öffne Import Project oder den Import-Dialog in einem bestehenden Projekt, wähle Structurizr DSL, lade das Zip hoch und klick auf Validieren. Prüfe die gewählte Wurzeldatei und lies jede Warnung, bevor du importierst.
  4. Committe das Verzeichnis in ein Repository, falls es noch in keinem liegt, damit die nächste Person es nicht auf deinem Laptop suchen muss.

Das vollständige Verhalten des Importers, einschließlich der Namensregeln für neue Projekte, steht in der Architecture-as-Code-Dokumentation. Für die anderen Formate, die Archyl importiert, siehe Structurizr-, LikeC4- und IcePanel-Projekte importieren.