複数ファイルに分割された Structurizr ワークスペースを Archyl にインポートできるようになりました

Structurizr のワークスペースの中には、workspace.dsl にほとんど何も置いていないものがあります。ヘッダーと model ブロック、そしてシステムごとに 1 行ずつ並んだ !include 行だけ。実際のモデルは、それらの行が指す先のファイルに分散しています。

今週まで、Archyl はこれをインポートできませんでした。Structurizr Cloud の終了についての 8 月 4 日の記事でも、そのことを 1 行で書いています。複数ファイルのワークスペースは、先に 1 つのファイルにまとめる必要がある、と。これでは、システムごとに 1 ファイルに分けたワークスペースは対象外でした。Structurizr Cloud は 9 月 30 日、つまり 2 週間後に終了します。

ワークスペースを .zip としてアップロードできるようになり、Archyl はすべての !include をその中のファイルに対して解決します。

単一ファイルではそもそも無理だった理由

次のような構成のワークスペースを考えます。

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

ルートファイルは、各部分をつなぎ合わせるだけです。

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

このルートファイルだけをアップロードまたは貼り付けると、インポーターにはパスを解決する手がかりがありません。手元にあるものをパースし、各 include をスキップして、次のように伝えます。

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

警告の内容は正確ですが、結果もそれですべてです。6 つのファイルの中身は何も含まれていません。自己完結した単一の .dsl ファイルは、これまでとまったく同じようにインポートされます。zip はそれ以外のすべてのためのものです。

zip にするのはリポジトリではなくワークスペースのディレクトリ

ワークスペースが !include を使っているなら、分割されたファイルはどこかにファイルとして存在しています。Structurizr の include のドキュメントは、ファイルの include を次のように説明しています:"a single local file, specified by a relative path" — 相対パスで指定された単一のローカルファイル。つまり重要なコピーはディスク上か Git にあり、クラウドにはありません。workspace.dsl を含むディレクトリを見つけて、それを zip にしてください。

ディレクトリの中から:

zip -r workspace.zip workspace.dsl model systems

ワークスペースがリポジトリにある場合は、コミットから直接:

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

この違いが重要なのは、アーカイブのエントリ数に 500 の上限があり、その数が何かを除外する前にチェックされるからです。.git フォルダーごとリポジトリ全体を zip にすると、.dsl ファイルが 1 つも読まれないうちに上限を超えることがあります。アーカイブの最上位にラッパーフォルダーがあっても問題ありません。include は、include を書いたファイルからの相対パスで解決されるためです。

アップロードすると何が起きるか

インポートモーダルの Structurizr DSL タブのボタンは、.dsl または .zip をアップロード という表示になりました。アーカイブを選ぶと、コードエディターがその名前とサイズを表示するカードに置き換わります。検証 をクリックすると、カードにファイル数と選ばれたルートファイルが追加されます。

これは既存プロジェクトへのインポートでも、新規プロジェクトの作成でも使えます。新規プロジェクトの名前はワークスペースのヘッダーから取られるため、workspace "Payments Platform" { ... } ならプロジェクトを作成できますが、名前のない workspace { ... } では作成できません。

サーバー側では、アーカイブは 4 つのステップを経ます。

  1. ルートを選ぶ。 アーカイブに workspace.dsl があればそれを、なければ最も浅い階層にある .dsl ファイルを使います。複数のファイルから選ぶ必要があり、どれも workspace.dsl という名前でない場合は、使ったファイルを警告で示します。
  2. パースの前に、include をテキストとして展開する。 include されたファイルの内容が !include 行を置き換えます。Structurizr が行うのと同じインライン展開です。パスは include を書いたファイルからの相対パスなので、systems/index.dsl が shared/platform.dsl を include すると systems/shared/platform.dsl が見つかります。
  3. ディレクトリの include を解決する。 !include systems は systems/ 直下にあるすべての .dsl ファイルを名前順に取り込みます。サブディレクトリはたどりません。
  4. 境界で止める。 直接または別のファイル経由で、結果的に自分自身を include することになったファイルは、その循環を断ち切って報告します。ネストは 10 階層で止まります。

展開されたワークスペースは、その後、単一ファイルと同じ Structurizr インポーターを通ります。忠実度も、スキップしたものについての警告リストも同じです。

見つからないファイルや、アーカイブの外を指すパスなど、解決できない include も警告になります。ワークスペースの残りの部分はそのままインポートされます。

リモートの include は意図的に拒否しています

Structurizr では、!include で HTTPS の URL を指すこともできます。Archyl はそれをたどりません。解決すれば、アップロードされた任意のファイルが、私たちのサーバーに好きなアドレスへリクエストを送らせることができてしまいます。誰がアップロードするかにかかわらず、これはサーバーサイドリクエストフォージェリの攻撃経路です。その行は警告付きでスキップされます。

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

必要なモデル要素がリモートファイルに含まれているなら、それをダウンロードしてアーカイブに入れ、その行を相対パスに書き換えてください。

制限

制限 値 超えた場合
アーカイブのサイズ 10 MiB アップロードを拒否
アーカイブ内のエントリ数 500 アップロードを拒否
展開後の合計サイズ 50 MiB アップロードを拒否
個々のファイル 5 MiB 警告付きでファイルをスキップ
include のネスト 10 階層 それより深い include を警告付きでスキップ

絶対パスや .. セグメントによってアーカイブの外に出ようとするパスを持つエントリは、警告付きでスキップされます。保持されるのはテキストファイルだけです:.dsl、.md、.json、.yaml、.yml、.txt。画像やそれ以外のファイルは、DSL インポーターでは使い道がないため、警告なしで破棄されます。

まだできないこと

Git 同期は include を解決しません。 リポジトリ同期が読むのは archyl.yaml であり、Structurizr ワークスペースではありません。そのため、Archyl が複数ファイルの DSL をリポジトリから直接取り込む経路はまだありません。DSL が Git にあるなら、当面は上の git archive コマンドがそのワークフローです。

Structurizr の忠実度について、それ以外に変わった点はありません。 レイアウト、スタイル、deployment view は以前もインポートされておらず、zip からもインポートされません。workspace.json の経路もまだありません。Archyl が読むのは DSL テキストです。Structurizr で最も価値を感じているのが手作業で調整したレイアウトなら、終了についての記事で紹介した、Structurizr 自身のツールを使い続ける選択肢のほうが引き続き適しています。

9 月 30 日までに

  1. ソースファイルを確保する。 !include で分割されたワークスペースはファイルとして書かれたものなので、そのファイルを探してください。ブラウザーで調整したレイアウトや、そこで書いたドキュメントなど、クラウド上のコピーにしかないものがあれば、8 月 4 日の記事に取り出し方があります。
  2. workspace.dsl を含むディレクトリを zip にする。それを囲むリポジトリではありません。
  3. アップロードして検証する。 Import Project、または既存プロジェクト内のインポートモーダルを開き、Structurizr DSL を選んで zip をアップロードし、検証 をクリックします。インポートする前に、選ばれたルートファイルを確認し、すべての警告に目を通してください。
  4. ディレクトリをリポジトリにコミットする。 まだリポジトリに入っていなければそうしておき、次の人があなたのノート PC の中を探さなくて済むようにしてください。

インポーターの完全な動作は、新規プロジェクトの名前のルールも含めて、Architecture as Code のドキュメントにあります。Archyl がインポートできるほかのフォーマットについては、Structurizr、LikeC4、IcePanel のプロジェクトのインポートをご覧ください。