Apache Gump live r1939132 快速入门与集成示例

基于实测快照 Apache Gump live r1939132 的快速入门:从编写最小 module/project/repository 元数据、DTD 校验、Python 加载自检,到离线 integrate 生成 HTML/RSS 报告,再到真实 git 检出 commons-io 并构建的全流程,所有命令与回显均在 Ubuntu 22.04 + Python 3.10.12 实测通过。

Apache GumpApache Gump2026/10/15

Apache Gump live r1939132 快速入门与集成示例

目标:在一台装好 Gump(第 1 篇方案 A/B 均可)的机器上,从零写出第一批自定义元数据,用官方工具完成 DTD 校验与 Python 加载自检,跑通一次离线集成并产出 HTML/RSS 报告,最后把元数据指向真实 Git 仓库体验完整「更新→构建→报告」流水线;本文全部命令与回显均在 Apache Gump live r1939132 + Ubuntu 22.04.5 LTS + Python 3.10.12 实测通过。

先建立心智模型:Gump 的输入只有两样——workspace(描述这一轮跑什么、在哪跑)和 module/project 元数据(描述聚合哪些仓库、每个项目的构建方式与依赖);输出也主要两样——日志站 HTML 与 RSS/Atom 联合分发。bin/integrate.py 是把这两头串起来的执行器,它会依次执行环境检查、元数据加载、SCM 更新、逐项目构建、依赖图统计与文档生成。理解了这一点,下面的每个步骤就都是在「喂元数据、读输出」。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS,x86_64
  • Python:3.10.12;SVN:1.14.1;xmllint:libxml 20913;xsltproc:libxslt 10134
  • JDK:OpenJDK 11.0.32.1;Ant:1.10.12
  • 组件:Apache Gump live,SVN r1939132(2026-08-31 提交),内部版本串 2.3
  • 安装方式:第 1 篇方案 A + B,源码位于 /root/gump
  • 实验目录:元数据工作区 /root/gump-meta-test(下文第 2 步创建)

进入环境前先确认三件事(实时回显):

cd /root/gump && ./gump help | head -3

     _____
    |   __|_ Apache_ ___
    |  |  | | |     | . |
python3 --version && svn --version --quiet
Python 3.10.12
1.14.1
echo "GUMP_HOME=$GUMP_HOME"; hostname -s
GUMP_HOME=/root/gump
gump-ubuntu

💡 技术拓展:本文所有实测在两种入口上做过对比——

入口实测结果适用
bin/integrate.py(集成运行器)离线运行退出码 0,完整产出报告本文采用
bin/update.py / bin/build.py(独立运行器)初始化阶段崩溃 Not Implemented on TextResolver: getFile不可用(r1939132 已知缺陷)

官方服务端跑的正是 integrate(cron/gump.py 调 python/gump/integrate.py),独立 update/build 入口在当前快照的 Python 3 运行时下不可用,本文统一采用 bin/integrate.py。

二、10 分钟跑通第一个集成

本节四步走:建目录与元数据 → 官方 DTD 校验 → Python 加载自检 → 离线集成出报告。全程不联网(SCM 更新一步关闭)。

2.1 第 1 步:搭建独立元数据工作区

不在官方 metadata/ 里直接改动,而是在 /root/gump-meta-test 建独立工作区,只引用官方 DTD 与校验脚本:

mkdir -p /root/gump-meta-test/{project,repository,profile,tmp}
cp -r /root/gump/metadata/dtd /root/gump-meta-test/
cp /root/gump/metadata/validate /root/gump-meta-test/
mkdir -p /root/gump-meta-test/tools
cp /root/gump/metadata/tools/*.xslt /root/gump-meta-test/tools/

三个核心文件的职责:repository/ 定义代码托管源,project/ 定义模块与项目(一个 module 是一个仓库单元,内含一至多个 project),dtd/ 是校验依据。

写入第一个仓库定义 /root/gump-meta-test/repository/myrepo.xml:

<?xml version="1.0" encoding="ISO-8859-1"?>
<repository name="myrepo" type="git">
  <title>My Demo Repository</title>
  <home-page>http://gitbox.apache.org/repos/asf/</home-page>
  <url>http://gitbox.apache.org/repos/asf/</url>
  <redistributable/>
</repository>

写入第一个模块 /root/gump-meta-test/project/hello-gump.xml,包含两个项目和一个 core → test 依赖:

<?xml version="1.0" ?>
<module name="hello-gump">

  <url href="http://gump.apache.org"/>
  <description>
    Minimal Gump module for validation testing.
  </description>

  <git repository="myrepo" dir="hello-gump.git"/>

  <project name="hello-gump-core">
    <package>org.example.hellogump</package>
    <ant target="jar">
      <property name="debug" value="on"/>
    </ant>
    <depend project="xml-xerces"/>
    <home nested="dist"/>
    <jar name="dist/hello-gump-core.jar" id="hello-gump-core"/>
    <license name="LICENSE.txt"/>
  </project>

  <project name="hello-gump-test">
    <package>org.example.hellogump.test</package>
    <ant target="test"/>
    <depend project="hello-gump-core"/>
    <option project="junit"/>
  </project>

</module>

逐段解读:<git repository="myrepo" dir="hello-gump.git"/> 声明该模块由 myrepo 仓库的 hello-gump.git 检出;<ant target="jar"> 声明用 Ant 目标 jar 构建,可带 <property>;<depend> 是强依赖(被依赖项目失败则本项不构建),<option> 是软依赖(仅做顺序排序);<jar id> 给产出的构件命名,供下游 <depend project="..."/> 引用。完整元素表见第 4 篇。

2.2 第 2 步:官方 DTD 校验

直接复用官方校验脚本(它逐个用 xmllint 校验 repository/profile/project 三类文件):

cd /root/gump-meta-test && bash validate 2>&1 | head -8
 ======== Processing Repositories ============
 ======== Processing Profiles ============
 ======== Processing Local Projects ============
 ======== Processing External Projects ============

本地项目阶段没有输出任何 validity error,即 myrepo.xml 与 hello-gump.xml 都通过校验(脚本对通过者静默、对失败者打印行号与原因)。

反向验证——故意写一个非法元素 <bogus-element value="x"/> 再校验:

sed 's|<depend project="xml-xerces"/>|<depend project="xml-xerces"/>\n    <bogus-element value="x"/>|' project/hello-gump.xml > project/bad.xml && cp project/bad.xml project/hello-gump.xml && bash validate 2>&1 | grep -c "validity error"
3

xmllint 报出的 3 条 validity error 均指向 <bogus-element>(元素未声明及连带的项目内容校验失败),删除该元素恢复原文件后校验归零。这证明校验链对自定义元数据真实有效。

2.3 第 3 步:Python 加载自检

DTD 校验只证明「格式合法」,不证明「能被 Gump 读进内存」。用仓库自带的 WorkspaceLoader 写一个 10 行的自检脚本 /root/load-test.py:

import sys, os
sys.path.insert(0, os.path.abspath("python"))
sys.path.insert(0, os.path.abspath("."))
from gump.core.gumpinit import gumpinit
from gump.core.loader.loader import WorkspaceLoader

gumpinit()
wsfile = sys.argv[1]
ws = WorkspaceLoader(False).load(wsfile)
print("WORKSPACE name:", ws.getName())
mods = list(ws.getModules())
print("MODULES:", [m.getName() for m in mods])
projs = list(ws.getProjects())
for p in projs:
    print("PROJECT:", p.getName(), "| depends:",
          [d.getProject().getName() for d in p.directDependencies.depends])
print("LOAD_OK")

同时写入对应 workspace /root/gump-meta-test/my-workspace.xml(注意 version 属性,大小写坑见 4.1 节):

<?xml version="1.0"?>
<workspace
    name="mytest"
    basedir="work/workspace"
    pkgdir="work/packages"
    jardir="work/jars"
    logdir="work/logs"
    version="0.4">
  <property name="build.sysclasspath" value="only"/>
  <module href="project/hello-gump.xml"/>
  <repository href="repository/myrepo.xml"/>
</workspace>

执行自检:

cd /root/gump && python3 /root/load-test.py /root/gump-meta-test/my-workspace.xml 2>&1 | tail -5
WORKSPACE name: mytest
MODULES: ['hello-gump']
PROJECT: hello-gump-core | depends: []
PROJECT: hello-gump-test | depends: ['hello-gump-core']
LOAD_OK

验证点:workspace 名称、模块列表、两个项目的依赖边全部按元数据还原,说明元数据已被 Gump 对象模型完整解析。

2.4 第 4 步:离线集成,产出报告

GUMP_WORK_OFFLINE=true 关闭 SCM 更新(hello-gump.git 本就不存在),让流水线走完「加载→构建尝试→统计→文档→联合分发」全链:

cd /root/gump
export PYTHONPATH=/root/gump/python:/root/gump GUMP_HOME=/root/gump
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64 GUMP_WORK_OFFLINE=true
python3 bin/integrate.py -w /root/gump-meta-test/my-workspace.xml all > /tmp/integ.log 2>&1
echo "EXIT=$?"
EXIT=0

运行末尾的完整回显:

Document run using [XDocDocumenter]
Document run using [TextDocumenter]
Syndicate run using [<gump.actor.syndication.rss.RSSSyndicator object at 0x7a3b031886d0>]
Syndicate run using [<gump.actor.syndication.atom.AtomSyndicator object at 0x7a3b03188670>]
Wipe Directory ['/root/gump/work/workspace/mvnlocalrepo']
Synchronize work->log, and clean-up...
Wipe Directory ['/root/gump/work/workspace/xdocs-work']
Gump Integration complete. Exit code [0=SUCCESS] : 0

关键解读:Unable to register RDF Describer : cannot import name 'TYPE' from 'rdflib' 出现在日志中(含 1 处 Traceback)——这是 rdflib 新版 API 不兼容所致,Gump 打印警告后跳过该描述器,不影响退出码 0,如实记录。

产出的日志站结构:

ls /root/gump/work/logs/
atom.xml
buildLog.html
context.html
css
diffsLog.html
favicon.ico
gump_icons
gump_repo
gump_work
hello-gump
images
index.html
module_fixes.html
module_todos.html
notesLog.html
packages.html
project_fixes.html
project_prereqs.html
project_todos.html
repositories.html

运行首页记录的运行标识(实时提取):

Apache Gump(TM) Run GUID    gump-ubuntu:mytest:20261015084708
Gump Version    2.3

两个项目各有一套 logs/hello-gump/<项目名>/ 报告(含 rss.xml、atom.xml、状态详情),project_prereqs.html 汇总了依赖前置图。到这一步,元数据 → 校验 → 加载 → 集成 → 报告的最小闭环已经全部走通。

三、集成真实项目:从 GitBox 实时检出 commons-io

本节把元数据指向真实存在的仓库,验证 SCM 更新与构建尝试两个阶段。选择 commons-io 是因为它体量适中且发布在 GitBox。

3.1 指向真实仓库的元数据

新增模块 /root/gump-meta-test/project/commons-io-live.xml:

<?xml version="1.0" ?>
<module name="commons-io-live">
  <url href="https://commons.apache.org/proper/commons-io/"/>
  <description>Live update test against commons-io git.</description>
  <git repository="myrepo" dir="commons-io.git"/>
  <project name="commons-io-live">
    <package>org.apache.commons.io</package>
    <ant target="jar"/>
    <home nested="target"/>
    <jar name="commons-io-*.jar" id="commons-io"/>
  </project>
</module>

对应 workspace /root/gump-meta-test/ws-live.xml(basedir 等相对路径实测落在 $GUMP_HOME 下而非 workspace 文件旁,产物出现在 /root/gump/work-live/):

<?xml version="1.0"?>
<workspace
    name="wslive"
    basedir="work-live/workspace"
    pkgdir="work-live/packages"
    jardir="work-live/jars"
    logdir="work-live/logs"
    version="0.4">
  <property name="build.sysclasspath" value="only"/>
  <module href="project/commons-io-live.xml"/>
  <repository href="repository/myrepo.xml"/>
</workspace>

3.2 跑完整集成(在线)

这次不设 GUMP_WORK_OFFLINE,让更新阶段真实执行 Git 操作:

cd /root/gump
export PYTHONPATH=/root/gump/python:/root/gump GUMP_HOME=/root/gump
export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
python3 bin/integrate.py -w /root/gump-meta-test/ws-live.xml commons-io-live > /tmp/integ-live.log 2>&1
echo "EXIT=$?"
EXIT=0

3.3 更新阶段实测:真实 Git 检出成功

模块级更新报告 work-live/logs/commons-io-live/gump_work/update_commons-io-live.html 的关键内容(实时提取):

Details State: Success For: Module: commons-io-live
Working Directory: /root/gump/work-live/workspace/cvs/commons-io-live
Exit Code: 0   Elapsed Time: 2 secs
Command Line: git fetch --quiet --no-tags origin +refs/heads/master:refs/remotes/origin/master

首次运行(目录为空时)执行的是完整克隆,命令为 git clone --quiet --recursive --branch master http://gitbox.apache.org/repos/asf/commons-io.git,实测 State: Success。检出的真实源码:

ls /root/gump/work-live/workspace/commons-io-live | head -5
CODE_OF_CONDUCT.md
CONTRIBUTING.md
LICENSE.txt
NOTICE.txt
ls /root/gump/work-live/workspace/commons-io-live/build.xml 2>&1
ls: cannot access '/root/gump/work-live/workspace/commons-io-live/build.xml': No such file or directory

更新阶段结论:Gump 的 Git 更新器对 GitBox 仓库真实可用(clone 与后续 fetch 均退出码 0);同时如实记录一个发现——当前 commons-io 主干只有 Maven 的 pom.xml,没有 build.xml,Gump 元数据里按旧式 <ant> 构建会注定失败,这正是下一阶段实测到的结果。

3.4 构建阶段实测:失败也是流水线的正常输出

项目级构建报告 gump_work/build_commons-io-live_commons-io-live.html 实时提取:

Details State: Failed For: Project: commons-io-live
Working Directory: /root/gump/work-live/workspace/commons-io-live
Exit Code: 1

构建输出文件 work-live/workspace/tmp/build_commons-io-live_commons-io-live.txt 的全部内容:

Error: Could not find or load main class org.apache.tools.ant.Main
Caused by: java.lang.ClassNotFoundException: org.apache.tools.ant.Main

两层原因叠加:Gump 以 java org.apache.tools.ant.Main 方式调起 Ant,本环境 Ant 类路径未被解析;且该项目本无 build.xml。项目状态如实落盘(项目详情页 index.html 提取):

Project : commons-io-live
State   Current State:  Failed
Reason: Build Failed

模块级状态仍为 Success(SCM 检出成功),项目级 Failed(构建失败)——这正是 Gump 的设计语义:模块状态只反映源码获取,项目状态反映构建,聚合报告把两者分开呈现。

3.5 联合分发产物实测

运行结束后,模块日志目录同时生成 RSS 与 Atom:

ls /root/gump/work-live/logs/commons-io-live/*.xml
/root/gump/work-live/logs/commons-io-live/atom.xml
/root/gump/work-live/logs/commons-io-live/rss.xml
head -c 280 /root/gump/work-live/logs/commons-io-live/rss.xml
<rss version="2.0"  xmlns:gump="http://gump.apache.org/"   xmlns:admin="http://webns.net/mvcb/"   xmlns:dc="http://purl.org/dc/elements/1.1/"   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"   xmlns:sy="http://purl.org/rss/1.0/modules/syndication/">  <channel>  <title>Apache Gump(TM):

另有 changes_to_commons-io-live.txt 记录本次更新的源码变更清单。整套「HTML 报告 + RSS/Atom + 变更清单」就是 Gump 对外联合分发的标准产物,订阅方按 URL 轮询即可获知每次聚合运行的结果。

四、快速上手中的实测要点

4.1 workspace 的 version 大小写坑

workspace.dtd 声明的是大写属性,而官方样例与 Python 加载器都用小写,实测现象完全一致:

  • 用大写 VERSION="0.4" 写 workspace:DTD 校验通过,但 Python 加载后 getVersion() 为 None,bin/build.py 在 runner.py 第 105 行抛 TypeError: '>=' not supported between instances of 'NoneType' and 'str'(Python 2 时代 None 可比较,Python 3 报错);
  • 用小写 version="0.4":加载正常,integrate 退出码 0。

结论与做法:统一用小写 version="0.4",与官方 metadata/minimal-workspace.xml 保持一致;这正是 r1939132 快照里 DTD 与实现不同步的现状,遵循实现即可。

4.2 命令行参数顺序

bin/integrate.py 的 -w 解析只识别紧跟位置参数的形态(handleArgv 中 -w/--workspace 作为首参处理),实测 -X -w <file> 会报 No workspace defined with -w。习惯写法固定为:

python3 bin/integrate.py -w <workspace 文件> <项目表达式>

项目表达式实测可用 all(全部)或单个项目名(如 commons-io-live)。

4.3 依赖在元数据里不声明就等于不存在

hello-gump 元数据里 <depend project="xml-xerces"/> 引用的项目既不在官方 profile 关联范围内、也没在本工作区定义,integrate 运行实测会按「不存在的依赖」处理并继续(该依赖边只参与排序,不触发构建)。首次写元数据的建议:先把 <depend> 清单写真实存在的项目,再逐步扩展,避免把排序关系写空。

五、技术拓展与选型说明

💡 技术拓展:Gump 与常规 CI(Jenkins/GitHub Actions)的定位差异——

维度Apache Gump常规 CI
调度单位跨仓库依赖图(模块/项目)单仓库流水线
元数据独立 XML,仓库与项目分离声明每仓库一份配置
价值提前发现上游改动破坏下游保障自身分支质量
报告形态HTML 日志站 + RSS/Atom 订阅Web UI + 通知

本文选用 Gump live r1939132 的 bin/integrate.py:它与环境检查、元数据校验、真实 SCM 更新、联合分发四个环节都打通,且是官方服务端同款入口。

六、常见问题(FAQ)

Q1:离线 integrate 的退出码 0 但日志里有 Traceback,算成功吗? 算。退出码 0 表示流水线各阶段完成;日志里的 Traceback 是 RDF 描述器导入失败(rdflib API 变更),该描述器被跳过,其余功能不受影响。项目构建失败也不会改变整合运行的退出码——看结果要读 logs/index.html 与各项目状态页。

Q2:为什么我的项目全部 Failed with reason Build Failed? 大概率是元数据声明了 <ant> 但项目里没有 build.xml,或本机 Ant 未随 Gump 的调用方式正确解析(本文 3.4 节即实测到了 ClassNotFoundException: org.apache.tools.ant.Main)。先确认源码树里的构建文件与元数据声明一致,再排查 java org.apache.tools.ant.Main 能否手工执行。

Q3:产物目录总变来变去? workspace 的 basedir/logdir 等相对路径实测按 $GUMP_HOME 解析。固定写法:要么给绝对路径,要么认清产物落在 /root/gump/work*/ 下再到日志站里找 HTML。

Q4:怎么只跑一个项目? 命令行最后的项目表达式控制范围:all 跑全部,写单个项目名(如 commons-io-live)则只跑该项目及其依赖链(实测有效)。

Q5:Python 3.6(CentOS 8)也能照本文操作吗? 能。第 2 篇已实测同一套流程在 Python 3.6.8 下结果一致(单测 6/6、离线 integrate 退出码 0),仅需先按该篇 4.6 节补 python 软链。

七、参考链接

  1. 官方元数据对象模型:https://gump.apache.org/metadata/index.html
  2. 官方 workspace XML 说明:https://gump.apache.org/metadata/workspace.html
  3. Python Gump 命令用法:https://gump.apache.org/python/usage.html
  4. 官方运行示例脚本:https://svn.apache.org/repos/asf/gump/live/demo-gump-run
  5. 官方 vmgump 运行实例(真实运行报告样例):http://vmgump.apache.org/