PlantUML + CI:让架构图不会过期的 4 个办法

puml.online

「我们画的架构图过期了」是每个团队的痛。这篇讲怎么用 CI 让图永远跟得上代码 —— 自动检查、自动重渲染、过期提醒、PR 自动出图。

反模式:写一张图就忘

1
2
3
docs/architecture/
flow.png # 2023 年画的,没人维护
README.md

半年后服务下线了、新服务上线了,这张 flow.png 还是 2023 年的样子。架构图活在真空里。

正确做法是 CI 把图「绑死」在仓库里。

技巧 1:CI 自动渲染

.github/workflows/uml.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
name: Render PlantUML
on:
push:
paths:
- 'docs/**/*.puml'
- 'docs/**/*.uml'
pull_request:
paths:
- 'docs/**/*.puml'
- 'docs/**/*.uml'

jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: temurin
- name: Download PlantUML
run: curl -L -o plantuml.jar https://github.com/plantuml/plantuml/releases/download/v1.2024.7/plantuml-1.2024.7.jar
- name: Render .puml to .svg
run: |
find docs -name '*.puml' -o -name '*.uml' | while read f; do
java -jar plantuml.jar -tsvg -failfast2 -nometadata "$f"
done
- name: Check for changes
run: |
git diff --quiet docs/ || (
echo "::warning::SVG files differ. Re-render locally and commit."
git diff --stat docs/
exit 1
)

每次有人提交 .puml 改动,CI 自动重新渲染 SVG。如果 SVG 有变化(说明本地忘跑了),CI 报警。

更友好的版本:自动 commit 回来。

1
2
3
4
5
6
7
8
9
- name: Auto-commit regenerated SVG
run: |
if [[ -n "$(git status --porcelain docs/)" ]]; then
git config user.name github-actions
git config user.email github-actions@github.com
git add docs/**/*.svg
git commit -m "render: regenerate SVG [skip ci]"
git push
fi

技巧 2:在 PR 中出图

.github/workflows/uml-pr-comment.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
name: PR PlantUML comment
on:
pull_request:
paths:
- 'docs/**/*.puml'

jobs:
comment:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: temurin
- run: |
curl -L -o plantuml.jar https://github.com/plantuml/plantuml/releases/latest/download/plantuml.jar
mkdir -p rendered
find docs -name '*.puml' | while read f; do
base=$(basename "$f" .puml)
java -jar plantuml.jar -tsvg -pipe < "$f" > "rendered/${base}.svg"
done
- name: Comment on PR
uses: marocchino/sticky-pull-request-comment@v2
with:
header: plantuml-preview
message: |
📐 PlantUML diagrams in this PR:
${{ join(steps.render.outputs.diagram_links, ', ') }}

这样 PR 里直接看到所有 .puml 渲染出的 SVG 缩略图。Reviewer 改图、改文档时能立刻比对。

技巧 3:过期检查(防止图腐化)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
name: Check diagram staleness
on:
schedule:
- cron: '0 9 * * 1' # 每周一早上 9 点

jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Find diagrams older than 6 months
run: |
stale=$(find docs -name '*.puml' -mtime +180)
if [[ -n "$stale" ]]; then
echo "::warning::Stale diagrams (>180 days):"
echo "$stale"
exit 1
fi
- name: Open issue if stale
if: failure()
uses: actions/github-script@v7
with:
script: |
const files = `$(find docs -name '*.puml' -mtime +180)`.trim();
await github.rest.issues.create({
owner: context.repo.owner,
repo: context.repo.repo,
title: '[stale] architecture diagrams older than 180 days',
body: `需要回看和更新的图:\n\n\`\`\`\n${files}\n\`\`\``
});

每周一早晨跑一次脚本,任何 .puml 超过 180 天没动就自动开一个 issue。

技巧 4:在 README 中强制引用图

不需要的技术债:

1
2
3
# 项目

我们的架构图请见 Confluence。

CI 加 lint:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
name: Lint README
on:
pull_request:
paths:
- 'README.md'

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check README references repo diagrams
run: |
if ! grep -q 'docs/architecture' README.md; then
echo "::error::README.md must link to docs/architecture/"
exit 1
fi

强制 README 里贴出仓库内的图,禁止「图在某个外部 wiki」式漂移。

完整工作流

把这 4 个技巧合起来:

  1. PR 提交时:CI 自动重新渲染所有 SVG(图过期 = 失败 PR)
  2. PR 评论里:自动贴所有 .puml 的 SVG 缩略图(评审者看得见)
  3. 每周一早晨:扫描 180 天没动的图,自动开 issue 提醒维护
  4. 任何 README.md 改动:强制引用仓库内的图
触发 CI 任务 作用
push to main render + auto-commit 自动更新 SVG
pull_request render + PR comment 评审可见图
每周一 9 点 cron staleness check 提醒维护
修改 README.md lint 防外部漂移

实战踩坑

  • CI 卡在 plantuml.jar 下载:仓库内提前 curl 一份 jar,作为 Git LFS 资产或 base64 嵌入 Vendor 目录。
  • Java 启动慢:用 temurin 而非 default-jdk,install 阶段只用 30 秒。
  • -failfast2-failfast 严格,遇到第一个错误就停止。一个文件出错不阻塞整个 build,加 || true 容错,但要 warn。
  • CJK 字体加载:CI 跑在 Ubuntu 上默认字体只有 OpenJDK 自带的,CJK 字符都成方块。装 fonts-noto-cjk:
    1
    2
    - name: Install CJK fonts
    run: sudo apt-get update && sudo apt-get install -y fonts-noto-cjk
  • PR 自动 commit SVG 触发下一轮 CI:加 [skip ci] 到 commit message,或者设 path 过滤让 SVG 改动不触发 build:
    1
    2
    3
    4
    on:
    push:
    paths:
    - 'docs/**/*.puml'

一键启用的模板

直接复制到你的仓库:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# .github/workflows/uml-ci.yml
name: PlantUML CI
on:
push:
paths: ['docs/**/*.puml', 'docs/**/*.uml']
branches: [main]
pull_request:
paths: ['docs/**/*.puml', 'docs/**/*.uml']

jobs:
render:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with: { java-version: '21', distribution: temurin }
- run: sudo apt-get install -y fonts-noto-cjk
- run: curl -L -o plantuml.jar https://github.com/plantuml/plantuml/releases/latest/download/plantuml.jar
- run: |
find docs -name '*.puml' -o -name '*.uml' | while read f; do
java -jar plantuml.jar -tsvg -failfast2 -nometadata "$f"
done
- name: Check or auto-commit
run: |
if [[ -n "$(git status --porcelain docs/)" ]]; then
git config user.name github-actions[bot]
git config user.email 41898282+github-actions[bot]@users.noreply.github.com
git add docs/
git commit -m "render: regenerate SVG [skip ci]" || echo "no changes"
git push
fi

粘贴 5 秒开张。

  • 标题: PlantUML + CI:让架构图不会过期的 4 个办法
  • 作者: puml.online
  • 创建于 : 2026-07-29 14:45:00
  • 更新于 : 2026-08-14 21:34:29
  • 链接: https://puml.online/blog/plantuml-ci-stale-diagrams/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。