PlantUML + CI/CD:GitHub Actions 自动渲染图、PR 检查与 Drift Detection
团队里 PlantUML 图越来越多,怎么保证每个人的 .puml 文件都正确渲染?PR 里的图怎么自动检查?代码变了图没同步怎么办?这一篇用 GitHub Actions 全解决。
为什么要把 PlantUML 集成到 CI
PlantUML 图是代码,但它不像普通代码那样有 lint/编译检查。常见问题:
.puml 文件有语法错误,上线了才发现图渲染不出来
- 代码改了,但忘了同步更新对应的
.puml 图(drift)
- PR review 时,图有没有变动很难看出来,要手动打开确认
CI 集成可以解决:提交代码自动渲染、自动在 PR 里显示图变化、自动检测 drift。
一、最小 GitHub Actions Workflow
在 .github/workflows/plantuml.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 35 36 37 38 39 40 41 42 43 44
| name: PlantUML Render
on: push: branches: [main] paths: - '**.puml' pull_request: paths: - '**.puml'
jobs: render: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
- name: Setup Java uses: actions/setup-java@v4 with: distribution: temurin java-version: 17
- name: Cache PlantUML uses: actions/cache@v4 with: path: ~/plantuml.jar key: plantuml-1.2024.2
- name: Download PlantUML if: steps.cache.outputs.cache-hit != 'true' run: | curl -L -o ~/plantuml.jar \ https://github.com/plantuml/plantuml/releases/download/v1.2024.2/plantuml.jar
- name: Render all .puml files run: | find . -name "*.puml" -exec java -jar ~/plantuml.jar -tsvg {} \;
- name: Upload SVG artifacts uses: actions/upload-artifact@v4 with: name: rendered-diagrams path: '**/*.svg'
|
每次 .puml 文件变动都自动渲染,产出的 SVG 作为 artifact 下载。
二、PR 检查:检测 .puml 文件变动
在 PR 里自动评论图的变化:
1 2 3 4 5 6 7 8 9 10 11 12
| - name: Comment changed diagrams on PR if: github.event_name == 'pull_request' run: | # 找到本 PR 改动的 .puml 文件 CHANGED_FILES=$(git diff --name-only origin/main...HEAD | grep '\.puml$') echo "Changed .puml files:" echo "$CHANGED_FILES" for file in $CHANGED_FILES; do echo "Rendering: $file" java -jar ~/plantuml.jar -tsvg "$file" done
|
PR review 时reviewer 直接在 GitHub 界面上看到每张图的变化,不需要本地跑命令。
三、自动生成图变更报告
用 GitHub API 在 PR 里发评论,展示哪些图变了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| - name: Post diagram changes to PR if: github.event_name == 'pull_request' env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | CHANGED=$(git diff --name-only origin/main...HEAD | grep '\.puml$') if [ -z "$CHANGED" ]; then echo "No .puml files changed" exit 0 fi COMMENT_BODY="## PlantUML 图变更报告 | 文件 | 状态 | |------|------| $(for f in $CHANGED; do echo "| \`$f\` | ⚠️ 待 review |"; done)
_这些 .puml 文件已自动渲染,SVG artifact 已上传。_" curl -s -X POST \ -H "Authorization: token $GH_TOKEN" \ -d "{\"body\": $COMMENT_BODY}" \ "https://api.github.com/repos/$GITHUB_REPOSITORY/issues/${{ github.event.pull_request.number }}/comments"
|
Reviewer 看到哪些 .puml 文件变了,直接点链接下载 SVG。
四、Drift Detection(图中文字 vs 代码不一致)
Drift 是指代码改了但图没更新的情况。最常见:函数名改了,图里的文字还是旧的。
用 grep + PlantUML 的 -checkonly 模式做轻量检测:
1 2 3 4 5 6 7 8 9 10
| - name: Check for stale diagram references run: | # 示例:检测图里是否引用了已删除的函数 GHOST_FUNCTIONS="getUserById|createOrder|deleteSession" STALE=$(grep -r "$GHOST_FUNCTIONS" diagrams/ || true) if [ -n "$STALE" ]; then echo "⚠️ 潜在 stale 引用:" echo "$STALE" # 非阻塞警告,不 fail CI fi
|
更强的 drift detection:用代码解析工具(AST parser)提取函数名/类名,和图里 note 里的文字对比:
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
| """drift_detector.py — 检测 PlantUML 图里的文字是否和代码一致""" import subprocess, re, sys
def get_functions(repo_path): """从 Python 代码提取所有函数名""" result = subprocess.run( ['grep', '-r', r'def \w+', repo_path, '--include=*.py'], capture_output=True, text=True ) return set(re.findall(r'def (\w+)', result.stdout))
def get_puml_notes(puml_dir): """从 .puml 文件提取所有 note 内容""" notes = set() for f in subprocess.run(['find', puml_dir, '-name', '*.puml'], capture_output=True, text=True).stdout.split(): with open(f) as fh: notes.update(re.findall(r'note\s+of\s+(\w+[^\n]*)', fh.read())) return notes
funcs = get_functions('.') notes = get_puml_notes('diagrams/') drift = notes & funcs if drift: print(f"⚠️ 潜在 drift: {drift}") sys.exit(1)
|
五、缓存 PlantUML JAR 加速 CI
PlantUML JAR 下载一次 50MB,每次 CI 都重下浪费。用 actions/cache 缓存:
1 2 3 4 5 6 7 8 9 10 11 12
| - name: Cache PlantUML JAR id: cache-plantuml uses: actions/cache@v4 with: path: ~/plantuml.jar key: plantuml-1.2024.2
- name: Download PlantUML (if cache miss) if: steps.cache-plantuml.outputs.cache-hit != 'true' run: | curl -L -o ~/plantuml.jar \ https://github.com/plantuml/plantuml/releases/download/v1.2024.2/plantuml.jar
|
缓存命中时 CI 耗时从 ~60s 降到 ~15s(省掉下载和 Java 启动的 jar)。
六、权限和安全
PlantUML 渲染时可以执行任意代码(通过 !include / !function)。CI 环境下:
1 2 3 4 5 6
| - name: Render with sandbox run: | # 用 -pipe 模式,不读写本地文件 java -jar ~/plantuml.jar \ -DROOT_DIR=/tmp/plantuml-sandbox \ -pipe -tsvg < diagram.puml > diagram.svg
|
ALLOW_INCLUDE 选项控制是否允许 !include:
1 2
| java -DALLOW_INCLUDE=local -jar ~/plantuml.jar -tsvg file.puml
|
CI 环境里不要用 INTERNET 安全级别(允许网络请求),用 SECURE 或 ALLOW_LIST。
七、完整 Workflow 示例
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| name: PlantUML CI Pipeline
on: push: branches: [main] paths: ['**.puml', '.github/workflows/plantuml*.yml'] pull_request: paths: ['**.puml']
jobs: plantuml-check: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 with: fetch-depth: 0
- uses: actions/setup-java@v4 with: distribution: temurin java-version: 17
- name: Cache PlantUML uses: actions/cache@v4 with: path: ~/plantuml.jar key: plantuml-1.2024.2
- name: Download PlantUML if: steps.cache.outputs.cache-hit != 'true' run: | curl -L -o ~/plantuml.jar \ https://github.com/plantuml/plantuml/releases/download/v1.2024.2/plantuml.jar
- name: Syntax check all .puml files run: | find . -name "*.puml" -print0 | \ xargs -0 -I{} sh -c 'java -jar ~/plantuml.jar -checkonly {} && echo "OK: {}"'
- name: Render to SVG run: | mkdir -p ci-artifacts find . -name "*.puml" -exec java -jar ~/plantuml.jar -tsvg -o ci-artifacts {} \;
- name: Run drift detection run: python3 scripts/drift_detector.py
- name: Upload artifacts uses: actions/upload-artifact@v4 with: name: puml-render-results path: ci-artifacts/
- name: Comment on PR if: github.event_name == 'pull_request' run: scripts/comment_on_pr.sh
|
八、效果总结
| 功能 |
集成前 |
集成后 |
| .puml 语法检查 |
手动打开渲染 |
CI 自动检查 |
| 图变更 review |
手动截图 |
PR 自动评论 |
| Drift 检测 |
无 |
自动化 |
| SVG artifact |
手动渲染 |
CI 自动产出 |
| CI 耗时 |
— |
~15s(含缓存) |
把 PlantUML 纳入 CI 后,团队协作效率提升显著——reviewer 不再需要手动确认图有没有变化,drift 在合并前就被 catch。