拆分成多个文件的 Structurizr 工作区,现在可以导入 Archyl 了
有些 Structurizr 工作区几乎什么都不放在 workspace.dsl 里。一个头部、一个 model 块,再加一列 !include 行,每个系统一行,真正的模型分散在这些行指向的文件里。
直到本周,Archyl 都无法导入这种工作区。我们 8 月 4 日关于 Structurizr Cloud 关停的文章用一句话提过:多文件工作区必须先合并成一个文件。这就把每个系统单独放在一个文件里的工作区排除在外了。Structurizr Cloud 将于 9 月 30 日关停,也就是两周之后。
现在你可以把工作区作为 .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
这些警告是准确的,但它们也就是全部结果:那六个文件的内容一点都没有进来。自成一体的单个 .dsl 文件仍然和以前完全一样地导入。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
或者,如果工作区在某个仓库里,直接从一个 commit 打包:
git archive --format=zip -o workspace.zip HEAD:docs/architecture
这个区别很重要,因为归档最多只能有 500 个条目,而且这个数量是在做任何过滤之前检查的。把整个仓库连同 .git 文件夹一起打包,可能还没读到一个 .dsl 文件就已经超出上限。归档顶层多一层外包文件夹没有问题,因为 include 是相对于发起 include 的那个文件来解析的。
上传之后会发生什么
在导入弹窗里,Structurizr DSL 标签页上的按钮现在显示为 上传 .dsl 或 .zip。选择一个归档后,代码编辑器会被一张显示其名称和大小的卡片取代。点击 验证,卡片上会再加上文件数量和它选定的根文件。
无论是导入到已有项目,还是新建项目,都可以这样用。新项目的名称取自工作区头部,所以 workspace "Payments Platform" { ... } 可以创建项目,而不带名称的 workspace { ... } 不行。
在服务器端,归档会经过四个步骤:
- 选定根文件。 如果归档里有
workspace.dsl就用它,否则用层级最浅的.dsl文件。当需要在多个文件之间选择、而且没有一个叫workspace.dsl时,会有一条警告写明它用了哪个文件。 - 在解析之前,以文本方式展开 include。 被 include 的文件内容会替换
!include那一行,这和 Structurizr 自己做的内联是同一种方式。路径相对于发起 include 的文件,所以systems/index.dslincludeshared/platform.dsl时,找到的是systems/shared/platform.dsl。 - 解析目录 include。
!include systems会按名称顺序引入systems/下直接包含的每个.dsl文件。不会遍历子目录。 - 在边界处停下。 如果某个文件最终 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 日之前
- 确认源文件在你手里。 用
!include拆分的工作区本来就是以文件形式编写的,所以把它们找出来。如果有东西只存在于云端副本里,比如在浏览器里微调过的布局,或者在那里写的文档,8 月 4 日的文章讲了怎么把它们导出来。 - 把包含
workspace.dsl的目录打成 zip,而不是它外面的整个仓库。 - 上传并验证。 打开 Import Project,或者已有项目内的导入弹窗,选择 Structurizr DSL,上传 zip,然后点击 验证。导入之前,检查它选定的根文件,并逐条阅读警告。
- 把这个目录 commit 到一个仓库里,如果它还不在仓库中的话,这样下一个人就不必去你的笔记本电脑上找它了。
导入器的完整行为,包括新项目的命名规则,请见 Architecture as Code 文档。关于 Archyl 能导入的其他格式,请参阅导入 Structurizr、LikeC4 和 IcePanel 项目。