P4 Swarm 部署与使用
P4 Swarm 部署与使用
Swarm 是 Perforce 官方的代码评审 Web 系统,和 Helix Core(P4)集成做 pre-commit / post-commit review。这篇从概念用法讲到部署:在 P4V 里怎么发起和处理 review、Docker 怎么起一个新 Swarm、config.php 怎么配、Nginx 怎么套 HTTPS、一个 Swarm 怎么连多台 P4、怎么触发 Jenkins 构建、API 怎么用、再到接 Claude 做 AI Review,最后是卸载和排错。下文所有内部主机、IP、账号密码都用占位符代替,换成你自己的值即可。
Review 工作流(P4V 端)
Swarm 网址登录用的账号密码和 P4 一致。P4V 连上启用了 Swarm 集成的 P4 服务后,会在 submitted 和 pending changelist 标签页加上 Review Id 和 Review State 两列;看不到就在表头右键勾选这两个字段。如果 P4V 里没有 Swarm 连接成功的日志输出,重启 P4V。
发起 review(Requester)
- 右键某个具体的 pending changelist(不能是 default pending changelist),选
Request New Swarm Review。 - 在弹窗里填 reviewer:知道用户名直接输,不知道用
Browse找。支持多个 reviewer,但至少要有一个是 Required。弹窗还有几个选项:Revert checked out files after they are shelved:shelve 后直接取消该 changelist 文件的 checkout。想在提交 review 后保留本地修改就别勾这个。Remove files that are opened for add:直接删本地新增的文件。Don't shelve unchanged files:不 shelve 未改动的文件。
- 点 OK。创建成功后自动跳到 Swarm 网站,pending changelist 会带上一个 Swarm 小标签,并自动把待 review 的文件 shelve。Swarm 会自动给 Requester 和 Reviewer 发邮件。
关于 +l(exclusive lock)状态文件,有个坑要特别注意:
- 文件在 P4 上是
+l状态时,必须勾选Revert checked out files after they are shelved,且二进制文件在 Swarm 上不可视。 - 如果是
+l状态却没勾这个选项,那么没人会收到 request 通知,后续即使所有 reviewer 同意也无法在 Swarm 上提交。 - 已经对
+l文件创建了异常的 request,可以先把文件 revert(取消 checkout),再点Update Swarm Review ...修复。
如果 request 提交不规范导致 Request 异常,将没人收到邮件,后续会影响提交。
处理 review(Reviewer)
收到 Requester 邮件,所有待 review 的单子在 Swarm 的
/reviews/页面能看到。多人投票:每个 reviewer 在单子页面投票,通过
Vote Up,不通过Vote Down。只有一个 reviewer 时跳过这步。只有所有 reviewer 都 Vote Up,Need Review下拉框里才会出现Approve、Approve and Commit按钮。点开单子,右上角
Need Review下拉框里选对应回复。各选项含义:操作 含义 Needs Revision 要求修改 review 中的文件 Needs Review 要求进一步评审 Approve 批准(满足投票要求时才可用) Commit 提交(已批准的 pre-commit review 才可用) Approve and Commit 一步批准并提交(未批准但满足投票要求的 pre-commit review) Reject 拒绝,单子移到 closed Archive 归档 Obliterate Review 抹除(默认仅 admin/super 用户可用)
点 Approve 单子状态变为已批准并邮件通知双方;点 Approve and Commit 会自动提交该 pending changelist。
reviewer 同意后,由 reviewer 或 requester 在 Swarm 上点 commit,Requester 不要在 P4V 上手动提交,否则 Swarm 上没有 review 记录。
更新 review
高版本 P4V 有 bug,直接右键 update Swarm Review 'XXX' 可能用不了。可靠做法:
- 新建一个 pending changelist,把改动的文件放进去。
- 右键这个新 changelist →
update Swarm Review 'XXX'→ 输入 Review 编号。
对于 post-commit review、或不是你作者的 review:fetch review 的文件到新 changelist → 改文件 → 在 changelist 描述里加上 #review-12345(和其他文字用空白分隔,或单独一行)→ shelve。
从 review 取文件
作为 reviewer 想拿一份本地副本:review id 对应 P4 里一个含这些文件的 pending changelist。在 P4V 用 Go To Spec 对话框输入 review id → P4V 弹出 Pending Changelist 对话框 → 选要 unshelve 的文件 → 右键 Unshelve → 选目标 changelist → Unshelve,文件就拉到本地了。
评论
支持对文件、对文件中的某一行评论,以及图片评论(把图拖进输入框,单图上限 8MB)、回复评论、给 request/reviewer/评论者发邮件。删错误的 review 也在评论相关菜单里。
Docker 部署
下面是在一台宿主机上用 Docker 起多个 Swarm 实例的流程。每个实例占一个宿主机端口,记得维护一份端口分配表避免冲突。
宿主机环境
系统用 CentOS。先装 Docker(找 IT 开网络权限),设开机自启:
systemctl enable docker.service
确保 P4 服务器和 Swarm 宿主机能互通。再装 docker-compose,直接下二进制最省事:
# 从 https://github.com/docker/compose/releases/ 下载后
cp docker-compose-linux-x86_64 /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
docker-compose -v
起一个新 Swarm
建项目目录(同宿主机多 Swarm,命名保持统一):
cd ~
mkdir projectName-swarm
cd projectName-swarm
.env 文件(只改下面这些。/opt/perforce/swarm/data/ 下没有 config.php 时才用 .env):
project=<project-name> # 项目名
port=<swarm-port> # Swarm 端口
image=perforce/helix-swarm:2023 # Swarm 镜像版本
hostip=<swarm-host> # Swarm 宿主机 IP
P4D_PORT=<P4SERVER>:1666 # P4 server 端口
P4D_SUPER=<p4-super-user> # P4 超级用户,登录设为永不过期!!!
P4D_SUPER_PASSWD=<P4-PASSWORD> # P4 超级用户密码
SWARM_USER=<p4-super-user> # P4 超级用户,登录设为永不过期!!!
SWARM_PASSWD=<P4-PASSWORD> # P4 超级用户密码
SWARM_HOST=$hostip:$port
SWARM_MAILHOST=smtp.office365.com
SWARM_REDIS=helix-redis-$project
SWARM_REDIS_PORT=7379
# 设为 'y' 则即使扩展已存在也会重装并覆盖现有配置
SWARM_FORCE_EXT=y
docker-compose.yml(无需改动):
version: '2.11'
networks:
default:
driver: bridge
name: swarm-${project}
services:
swarm:
image: ${image}
container_name: helix-swarm-${project}
domainname: helix
volumes:
- $PWD/swarm-data:/opt/perforce/swarm/data
ports:
- 0.0.0.0:${port}:${port}
working_dir: /opt/perforce/swarm
depends_on:
- redis
tty: false
env_file: $PWD/.env
restart: always
redis:
image: "redis"
container_name: helix-redis-${project}
domainname: helix
command: redis-server --protected-mode no --port 7379 --appendonly yes
volumes:
- $PWD/redis-data:/data
restart: always
crontab 文件:改了 Swarm 端口后 worker cron 会失效,所以单独建一个 cron job。从 /etc/crontab 拷个模板,末尾加上这一行:
* * * * * root [ -x /opt/perforce/swarm/p4-bin/scripts/swarm-cron.sh ] && /opt/perforce/swarm/p4-bin/scripts/swarm-cron.sh
start-new-swarm.sh(无需改动):起容器、等 5 分钟初始化、改 Apache 站点和 cron 配置里的端口、重启、再把 crontab 拷进容器:
set -a
source $PWD/.env
set +a
mkdir -p redis-data
mkdir -p swarm-data
docker-compose up -d
sleep 5m
sed -i "1i\Listen $port" swarm-data/docker/sites-available/perforce-swarm-site.conf
sed -i "s/80/$port/g" swarm-data/docker/sites-available/perforce-swarm-site.conf
sed -i "s/80/$port/g" swarm-data/docker/swarm-cron-hosts.conf
docker-compose down
docker-compose up -d
docker cp crontab $(docker ps -aqf "name=helix-swarm-$project"):/etc/crontab
启动并等约 5 分钟:
chmod +x ./start-new-swarm.sh
./start-new-swarm.sh
P4 用 SSL 时,进容器建立信任:
docker ps -a
docker exec -it <container-id> /bin/bash
p4 -p ssl:<P4SERVER>:1666 trust
重启 Swarm:
docker-compose stop
docker-compose start
不要删容器。如果删了容器再重启,需要重新拷一次 crontab,否则网页会显示没有 worker、导致 Swarm 不可用:
docker cp crontab $(docker ps -aqf "name=helix-swarm-$project"):/etc/crontab
最后建一个名为 .swarm 的 P4 depot,用于图片评论附件存储。如果 P4V 连不上 Swarm,检查并设置 Swarm URL:
p4 property -l -A
p4 -p "<P4SERVER>:1666" property -a -n P4.Swarm.URL -v "http://<swarm-host>:<port>"
升级 Swarm 版本
切到 projectName-swarm 目录:
docker-compose down删当前容器。docker pull perforce/helix-swarm:<新版本>下镜像(机器上没有时)。- 备份当前
projectName-swarm目录,准备新起一个。 - 更新
.env里的image版本。 ./start-new-swarm.sh起新 Swarm。- 重新改
config.php,在网页 reload 配置。
配置文件 config.php
config.php 是 Swarm 的配置文件,位于 /opt/perforce/swarm/data/config.php。Docker 部署时改 swarm-data/config.php。改完后在网页 System Information → Cache Info → Reload Configuration 使配置生效(Swarm 会缓存这个文件,不 reload 不会被读取)。
基本结构如下,把所有密钥/主机替换成你自己的值:
<?php
/* WARNING: The contents of this file is cached by Swarm. Changes to
* it will not be picked up until the cached versions are removed.
*/
return array(
'environment' => array(
'hostname' => '<swarm-host>:<port>',
),
'p4' => array(
'port' => '<P4SERVER>:1666',
'user' => '<p4-super-user>',
'password' => '<P4-PASSWORD>', // P4 ticket 或密码
),
'mail' => array(
'sender' => '<sender@example.com>',
'transport' => array(
'host' => 'smtp.office365.com',
'port' => 587,
'connection_class' => 'login',
'connection_config' => array(
'username' => '<mail-user>',
'password' => '<SMTP-PASSWORD>',
'ssl' => 'tls',
),
),
),
'queue' => array(
'workers' => 8, // 默认 3
'worker_lifetime' => 595, // 默认 10 分钟少 5 秒
'worker_task_timeout' => 1800, // 默认 30 分钟
'worker_memory_limit' => '1G', // 默认 1G
),
'reviews' => array(
'cleanup' => array(
'mode' => 'auto', // auto 跟随默认 / user 展示勾选框
'default' => true, // commit 时清理 pending changelist
'reopenFiles' => false, // 把打开的文件重开到 default changelist
),
),
'log' => array(
'priority' => 3,
'reference_id' => true,
),
'redis' => array(
'options' => array(
'server' => array(
'host' => 'helix-redis-<project>',
'port' => 7379,
),
),
),
// notifications 各事件的 is_self/is_author/is_reviewer/is_moderator 开关按需配置
);
几点说明:
queue块控制 worker。workers是 worker 进程数(默认 3),cron job 会按需拉起新 worker,达到上限就不再起;worker_lifetime是单个 worker 运行时长上限(默认 595 秒),超时会做完当前任务再退出,不会中途打断任务;worker_task_timeout是单任务处理上限(默认 1800 秒),用来终结卡死的 worker;worker_memory_limit是单 worker 内存上限(默认 1G)。改 P4 server IP 后,清缓存重新配置:
rm -r /opt/perforce/swarm/data/cache rm /opt/perforce/swarm/data/config.php.* sudo /opt/perforce/swarm/sbin/configure-swarm.sh邮件用 Office365 时,要联系 IT 把 Swarm 机器 IP 加进新邮件服务器白名单;并确保配置的邮箱账号能正常发邮件。
从包安装(非 Docker)
如果不用 Docker,Swarm 也有 Debian(.deb,Ubuntu)和 RPM(.rpm,CentOS/RHEL)包。P4 服务器和 Swarm 服务器分开,Swarm 建议装在 Ubuntu 上,且 P4 服务器要先装好。装前先 telnet <P4SERVER> 1666 确认能连到 P4。
大致步骤:配 Perforce 包仓库 → 导入签名 key → apt-get install helix-swarm(主包)、helix-swarm-triggers(在 P4 服务器上装)、helix-swarm-optional(可选包)。装完跑交互式配置:
sudo /opt/perforce/swarm/sbin/configure-swarm.sh
配置脚本会依次问:P4PORT(形如 my-helix-core-server:1666)、一个有 admin 权限的普通 P4 用户的 userid 和登录 ticket/密码(默认 userid 是 swarm)、Swarm UI 的 hostname(域名,找 IT 要)、邮件 relay 主机。
如果 P4 服务器不能用包(比如跑 Windows),要把 trigger 脚本 /opt/perforce/swarm/p4-bin/scripts/swarm-trigger.pl 拷到 P4 服务器,提交到 //.swarm/triggers/swarm-trigger.pl,并把 /opt/perforce/etc/swarm-trigger.conf 提交到 //.swarm/triggers/swarm-trigger.conf,从 Swarm 取 SWARM_TOKEN 填进去。trigger 依赖 perl 5.08+,Windows 上 JSON 模块随 Strawberry Perl 自带。还要让 P4 把所有 shelved change 都 promote(pre-commit review 的前提):
p4 configure set dm.shelve.promote=1
HTTPS:Nginx 反向代理
让 Swarm 走 HTTPS 的思路是用 Nginx 做反向代理:浏览器访问 https://<swarm-url>:8443,Nginx 用 SSL 证书加密通信,再把请求代理到本地 Swarm 服务 http://localhost:<swarm-port>,响应原路加密返回。
装 Nginx(CentOS,配官方仓库):
sudo vi /etc/yum.repos.d/nginx.repo
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true
sudo yum clean all && sudo yum makecache
sudo yum install nginx -y
sudo systemctl start nginx && sudo systemctl enable nginx
sudo systemctl status nginx
上传证书和私钥到安全目录并设权限(只 root 可读私钥):
sudo mkdir -p /etc/ssl/private
sudo cp wildcard.pem /etc/ssl/private/
sudo cp wildcard.key /etc/ssl/private/
sudo chmod 600 /etc/ssl/private/wildcard.key
配置反向代理(/etc/nginx/conf.d/swarm.conf):
server {
listen 8443 ssl;
server_name <swarm-url>; # 替换为你的域名
ssl_certificate /etc/ssl/private/wildcard.pem;
ssl_certificate_key /etc/ssl/private/wildcard.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256';
ssl_prefer_server_ciphers on;
location / {
proxy_pass http://localhost:<swarm-port>; # Swarm 容器内部地址端口
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
验证并 reload:
sudo nginx -t
sudo systemctl reload nginx
一个 IP 上多实例就配多个 server 块,用不同的 listen 端口(如 8443→8130、9443→8132)各自 proxy_pass 到对应 Swarm 端口即可。
一个 Swarm 连多台 P4
官方文档:多 Helix Core 实例配置。
在全局 config.php 里给每台 P4 加一个 label,填各自连接信息:
<?php
return array(
'p4' => array(
'serverA' => array(
'port' => '<p4d-A>:1666',
'user' => '<admin-user-A>',
'password' => '<P4-PASSWORD>',
'sso' => 'disabled', // disabled|optional|enabled
),
'serverB' => array(
'port' => '<p4d-B>:1666',
'user' => '<admin-user-B>',
'password' => '<P4-PASSWORD>',
'sso' => 'disabled',
),
);
要单独配某台 P4,在 <swarm_root>/data/servers/<serverid> 目录加一个 config.php。注意:
- 必须有全局
config.php来声明这些 P4 实例。 - 单台 P4 的专属配置里不能含
p4项,否则会被静默忽略(不报错)。
每台 P4 都要用 Helix Core 扩展(推荐)或 trigger 通知 Swarm 事件,两者不能混用,且要给每台设好 trigger token 和 Swarm host 变量。配置里要用完整 URL,例如 https://<swarm-url>:<port>/serverA。
给每台 P4 配 cron job,把所有 server url 加进去:
http://localhost:<port>/serverA
http://localhost:<port>/serverB
如果 worker cron 不工作,手动建一个 /etc/crontab job:
* * * * * root [ -x /opt/perforce/swarm/p4-bin/scripts/swarm-cron.sh ] && /opt/perforce/swarm/p4-bin/scripts/swarm-cron.sh
登录 Swarm 后点 serverA 或 serverB 即可进各自的 Swarm 页面。
worker / cron 排查
worker 处理队列任务(建/更新 review、评论、发邮件)。任务文件在 /opt/perforce/swarm/data/queue,完成即删。如果文件数持续增长而非稳定,就调大 config.php 里的 workers。
/etc/cron.d/helix-swarm 指向 swarm-cron.sh,内容应为:
* * * * * nobody [ -x /opt/perforce/swarm/p4-bin/scripts/swarm-cron.sh ] && /opt/perforce/swarm/p4-bin/scripts/swarm-cron.sh
swarm-cron.sh 用 wget 或 curl 拉 worker:
wget --quiet --no-check-certificate --output-document /dev/null --timeout 1 "http://<swarm-url>/queue/worker"
curl --silent --insecure --output /dev/null --max-time 1 "http://<swarm-url>/queue/worker"
/opt/perforce/etc/swarm-cron-hosts.conf 指定连接类型、hostname 和端口,格式 [http[s]://]<swarm-host>[:<port>](默认 http、端口 80,hostname 必填)。
最重要的一步是手动跑一次 swarm-cron.sh 验证。如果报 Error (4) starting a worker ... via [wget],先手动跑那条 wget 命令,再看队列状态:
curl http://<swarm-url>/queue/status
# {"tasks":0,"futureTasks":0,"workers":6,"maxWorkers":8,...}
workers 数不为 0 就正常。用 grep CRON /var/log/syslog 确认 cron 在跑。cron 还是不行就重启:service cron restart。
触发 Jenkins 构建
让 Swarm review 触发 Jenkins job 做 CI。
生成 Jenkins API token:在 Jenkins 用户配置里生成。
在 Swarm 里建一个 test:
- URL:Jenkins job 的 url。
- Body:传给 Jenkins job 的参数。
- Iterate tests for affected projects and branches:为每个关联的 branch/project 各建一个 test run,
{projects}、{branches}、{branch}参数会用在 test 名上。 - Header:
name=value形式传给 test suite。
Authorization 值怎么来:把用户名和 Jenkins API token 用冒号拼接后做 base64。
# test.txt 内容为 <jenkins-user>:<api-token>
cat test.txt | base64 -w 0
填进 Header 时别忘了前面加 Basic 。
Jenkins job 参数:按需接收,但必须有 pass 和 fail 参数,否则 Swarm 拿不到构建结果。
把 test 加进 workflow,When 选项:
On Update:review 创建、提交且内容有变、更新且内容有变时触发。On Submit:pre-commit review 提交或 post-commit review 创建时触发。On Demand:不自动跑,在 review 页 Tests 对话框手动跑。
Blocks 选项:Nothing(失败不挡批准)、Approve(失败则不能批准)。
最后在项目里启用 workflow、配好 branch。注意:如果中止 Jenkins 构建,Swarm 上的 test 结果是 failed。
Swarm 回调 URL(可选)
Jenkins 把结果回写 Swarm 的几种方式:
{update}:POST JSON 到{update}URL,把 test 结果消息写回。status取running/pass/fail;最多 10 条 message,每条最多 80 字符(超出截断)。2019.3+ 推荐这个。curl -v -X POST -H "Content-Type:application/json" \ http://<swarm-url>/serverA/api/v10/testruns/6/<run-uuid>/ -d @D:\swarm.json{pass}/{fail}:GET 或 POST 都行,直接置结果。curl http://<swarm-url>/serverA/api/v10/testruns/8/pass/<run-uuid>/ curl http://<swarm-url>/serverA/api/v10/testruns/8/fail/<run-uuid>/
自动提交 API(可选)
文档:Swarm API。先取 ticket:
p4 -p <P4SERVER>:1666 -u <user> login -p
提交(transition):
curl -H "Content-Type: application/json" -X POST \
-u "<swarm-user>:<api-token>" -d @swarm.json \
"http://<swarm-url>/api/v11/reviews/${params.review}/transitions"
{
"transition": "approved:commit",
"fixStatus": "closed",
"cleanup": true
}
${params.review} 来自 {review}。
Jenkins HTTPS URL 报错
如果触发时 Swarm 日志报 stream_socket_enable_crypto(): SSL operation failed,通常是 Jenkins 那端证书链不全——需要用完整链的证书:服务器证书 + 中间证书 + 根证书。
API
参考 Swarm API 文档。查版本:
http://<swarm-url>:<port>/api/version
手动安装 helix-swarm.p4-extension
helix-swarm.p4-extension 是 Swarm 和 Helix Core 集成的扩展,影响 update review、review 提交后自动关闭等功能。装 Swarm 时会自动装这个扩展,如果不小心删了可以手动重装。
缺点:提交很多文件时会被这个扩展限制,需要把限制设为 false 才行。
扩展文件在 Swarm 宿主机的 /opt/perforce/swarm/p4-bin/extensions/,拷出来:
docker cp <container-id>:/opt/perforce/swarm/p4-bin/extensions/helix-swarm.p4-extension /root/projectName-swarm/helix-swarm.p4-extension
删旧扩展、装新扩展(确保当前目录有该文件):
p4 extension --delete Perforce::helix-swarm --yes
p4 extension --yes --install helix-swarm.p4-extension
建全局配置(若不存在):
p4 extension --configure Perforce::helix-swarm
spec 文件里关键是 ExtConfig 段——填 Swarm-Token(从 Swarm 取)和 Swarm-URL,ExtEnabled 设 true。
建实例配置启用扩展、验证、查看:
p4 extension --configure Perforce::helix-swarm --name projectName-swarm
p4 extension --run projectName-swarm ping # 返回 OK 即正常
p4 extension --list --type instance
禁用扩展:把 ExtEnabled 改成 false(p4 extension --configure Perforce::helix-swarm)。
进阶:接 Claude 做 AI Review
这是个进阶玩法:当 Jenkins 经 Swarm Workflow 的 test 阶段触发构建时,脚本自动用 Claude 对 review 的代码变更做 review,并把结果以 inline comment 的形式回写 Swarm。代码与示例 review 见内部仓库。
功能
脚本会自动:
- 取本次 review 最新版本文件的 diff。
- 把每个文件的 diff 发给 Claude 做代码审查。
- 在 Swarm review 页面发两类 comment:Summary comment(所有文件问题汇总,先发)和 Inline comment(定位到具体文件行号的建议,后发)。
二进制文件、美术资源(.uasset、.fbx、.png 等)会自动跳过,不发给 AI。
环境与配置(exe 运行可忽略环境部分)
pip install p4python==2024.1.* # 版本需与 P4 Server API 匹配
pip install requests # 需 Python >= 3.10
编辑同目录的 swarm_ai_review.ini:
[swarm]
url = http://<swarm-host>:<port>/
user = <swarm-user>
ticket = <p4-ticket>
[p4]
port = <P4SERVER>:1666 ; 例如 ssl:<P4SERVER>:1666
user = <p4-user>
ticket = <p4-ticket>
[claude]
url = <claude-api-url>/v1/messages
model = claude-opus-4-6
max_tokens = 4096
Claude API Key 通过环境变量传入,不写进配置文件:
export ClaudeKey="<your-api-key>"
在 Jenkins 里设成 Secret Text 类型的 Credential,用 withCredentials 注入。
运行与 Jenkins 集成
python swarm_ai_review.py --review-id 10129
# 或通过环境变量(Jenkins 自动注入)
export SWARM_REVIEW_ID=10129
python swarm_ai_review.py
Jenkinsfile 的 test 阶段:
stage('AI Code Review') {
environment {
SWARM_REVIEW_ID = "${params.SWARM_REVIEW}" // Swarm 注入的参数
ClaudeKey = credentials('claude-api-key')
}
steps {
sh 'python3 /path/to/swarm_ai_review.py'
}
}
整体流程
Jenkins Trigger (SWARM_REVIEW_ID)
→ [1] GET /api/v11/reviews/{id},取 versions[] 中 time 最大的版本,得 shelved CL
→ [2] P4Python: describe -du -S {changelist},按文件块拆分 diff、构建 {新行号→行内容} 映射
→ [3] 逐文件 POST Claude API(跳过二进制/资源),要求返回 JSON array
[{"line": N, "severity": "...", "comment": "..."}]
→ [4] POST /api/v9/comments(Summary,无 context)
→ [5] POST /api/v9/comments × N(inline,含 file + rightLine + content)
几个关键实现点
取 shelved diff:P4Python 默认 tagged 模式返回结构化 dict,describe -du 的 diff 文本在 tagged 模式下输出不完整。临时关掉 tagged,行为就和 CLI 一致,返回 list[str]:
p4.tagged = False
lines = p4.run("describe", "-du", "-S", str(changelist))
p4.tagged = True
拆分 diff:按 ==== //depot/path/file ==== 头部正则拆文件块,跳过 SKIP_EXTENSIONS,超过 MAX_DIFF_CHARS(默认 12000)截断。
hunk map:解析 unified diff 的 @@ -a,b +c,d @@,追踪新文件行号,返回 {int: str} 映射,给 inline comment 提供 context[content] 做行定位。
调 Claude:发 diff,要求返回 JSON array,字段 line(新文件行号)、severity(error/warning/info)、comment(建议)。Claude 偶尔会用 ```json ``` 包裹,用正则清理后再解析。
inline comment API:
POST /api/v9/comments
topic = reviews/{review_id}
body = **[AI Review] [ERROR]** ...
context[file] = //depot/mainline/Source/GameManager.cpp
context[rightLine] = 42
context[content] = return ptr->GetValue(); // 行内容(≤200 字符)
context[rightLine] 对应 diff 右侧(新文件)行号,Swarm 用 context[content] 做行定位校验。
取最新版本:Swarm review 每次更新文件会新增一条 version。用 max(versions, key=lambda v: v.get("time", 0)) 而非 versions[-1],避免依赖 Swarm 返回顺序。
配置扩展点:SKIP_EXTENSIONS(跳过的文件类型)、MAX_DIFF_CHARS(单文件 diff 上限)、SYSTEM_PROMPT(审查规则)、ini 里的 max_tokens。
卸载与排错
卸载
参考官方卸载文档。删 P4.Swarm.URL 属性时如果报 No such property 'P4.Swarm.URL':
p4 property -l -A
# :: >> P4.Swarm.URL = http://HelixSwarmHost (any) #none
p4 property -d -n P4.Swarm.URL -s 0
常见问题
打开页面报 ticket 错误(p4 admin 账号 ticket 过期)。 原因:在 Swarm 上建组时,Swarm 会建一个密码 12 小时过期的组,导致 p4 admin 账号 ticket 失效。建组后立刻把过期设为 unset。临时修复——进容器手动生成 ticket,更新到 config.php 再重启容器:
docker exec -it <container-id> /bin/bash
p4 -p <P4SERVER>:1666 -u <user> login -p
:: 把 ticket 写进 config.php
vim swarm-data/config.php
docker restart <container-id>
页面提示没有 worker(各种操作都可能出问题)。 进容器检查 /etc/crontab 是否有那行 swarm-cron.sh,没有就 docker cp 拷一份进去;有的话检查 swarm-data/docker/swarm-cron-hosts.conf 里的 Swarm 地址是否正确,改对后重启。
页面打不开、端口不通。 检查 Apache 配置 swarm-data/docker/sites-available/perforce-swarm-site.conf,改对后重启 Swarm。
通过 Swarm 提交后 review 无法自动关闭。 依次检查:有没有 worker(按上面方法处理)→ p4 extension --list --type instance 看扩展实例,没输出说明扩展没了,手动重装 → 检查扩展配置是否被禁用(p4 extension --configure Perforce::helix-swarm 全局、--name <配置名> 实例),禁用了就打开。