Keep the complete MySQL 8.4 integration profile and per-fork isolation. Retain JDBC precision and CAS coverage on the supported database and align workflow guards and documentation. Co-authored-by: Qwen-Coder <[email protected]>
11 KiB
verify 通道的 Java 工具链
状态:随本次改动实现。对应 issue #13741。
问题
.github/workflows/qwen-triage.yml 里的沙箱 verify 任务是维护者对 PR 做
A/B 结论的通道。它跑在每次新建的 node:22-bookworm 容器里,不安装 JDK 或
Maven。改动了 packages/sdk-java/ 的 PR,Java 侧有没有被执行,取决于那一轮
代理肯不肯花自己的时间去下载工具链。有的轮次会下载,有的不会,后一轮还可能
悄悄停掉前一轮已经执行过的 Java。
sdk-java.yml 定义了 Java 构建和测试通道。这里的缺口是 verify 代理自己的结论。
现状
- verify 容器每个 job 新建。
$RUNNER_TEMP从宿主机挂载,跨 job 保留,所以 每个消费者在使用前都会删掉自己的子目录。 - 代理以
env -i启动,HOME是$RUNNER_TEMP下的新目录。~/.m2永远是 空的。代理该看到的东西必须放进这组环境变量。 - Java 模块发布的是固定版本(
0.1.0-alpha,acp-sdk为0.0.1-alpha),不是 SNAPSHOT。qwen-managed-agent-server依赖qwencode-sdk;Broker 源码和测试在 Server 模块内编译。本地仓库里留下的旧 jar 就是 Maven 会解析到的那一个。 actions/cache用path的字面量加上压缩方式来识别一条缓存。这个镜像没有zstd。已经走通的先例是.github/workflows/pnpm-store.yml:在main上 跑的可信生产者,加上只恢复的消费者,两边的runs-on、容器和path相同。- verify 任务的预算注释按 180 分钟计算,对应
timeout-minutes: 190。
目标
PR diff 碰到 packages/sdk-java/ 或 packages/managed-agent-server/ 时,代理一开始就有 JDK 21、Maven 3.9.11、
预热过的本地仓库,以及按合并引用装好的 qwencode。其他
PR 不付代价。技能的环境约定写明通道提供什么。
不做的事
在技能里列为 Not covered,仍由 sdk-java.yml 负责:
- MySQL 8.4 的 failsafe 集成测试和 hosted harness。它们需要数据库和
打包好的
dist/cli.js。 - Java 11 和 Java 17 矩阵。
- 用抖动门重跑 Java 测试。
方案
resolver 在 checkout 之前已经把完整的改动文件列表分页取进 $files。列表匹配
^packages/(sdk-java|managed-agent-server)/ 时,输出 java=true。后面的步骤同时要求
decision == 'run' 和 java == 'true'。
flowchart TD
resolve["Resolve PR 设置 java"] --> tools[Install verify runner tools]
tools --> jdk["Install Java toolchain 写入 /opt/verify-java"]
jdk --> checkout[Wipe checkout pin record]
checkout --> pnpm[Restore pnpm store]
pnpm --> m2["清空并恢复 verify Maven repo"]
m2 --> build[Install and build PR app]
build --> flake[Flakiness gate]
flake --> mods[Install Java modules]
mods --> browser[Install evidence browser]
browser --> agent["仅当 ready 存在时注入代理环境"]
root 步骤都在任何 PR 代码之前。执行 PR POM 的步骤以 node 运行,并剥离
GitHub 和 Actions 凭据。
工具链
Install Java toolchain 以 root 运行,位于 Install verify runner tools
之后、Checkout PR merge ref 之前。它下载钉死版本的 Temurin 21 x64 压缩包
(sha256),以及 repo.maven.apache.org 上的 Maven 3.9.11(sha512,与
sdk-java.yml 的 MAVEN_VERSION、MAVEN_SHA512 相同)。两份归档解压到
/opt/verify-java/{jdk,maven},权限 a+rX,属主为 root。只有两份校验和
java -version / mvn -version 都成功之后才写 /opt/verify-java/ready。
mvn -version 之前会导出 JAVA_HOME 和 PATH:Maven 启动脚本不会自己去找刚解压的
JDK,否则它会在 ready 写出来之前退出。
curl 使用 --max-time 300 并重试。失败时删掉前缀、打出 warning、以 0
退出。
/opt 在容器本地且属 root,node 用户不能投放 ready。容器每个 job 都是
新的,ready 不会从上一次运行漏过来。
Maven 仓库缓存
.github/workflows/verify-maven-repo.yml 是生产者。它在推送到 main 且
packages/sdk-java/*/pom.xml、packages/managed-agent-server/pom.xml 或该工作流文件本身变化时触发,也支持
workflow_dispatch。它使用 verify 任务的 runs-on 和 node:22-bookworm,
选项为 --init --user node,并用与 pnpm store 相同的 SHA 钉住
actions/cache/save,保存 ${{ runner.temp }}/verify-maven-repo。key 为
verify-maven-repo-${{ hashFiles('packages/sdk-java/*/pom.xml', 'packages/managed-agent-server/pom.xml') }}。
生产者对 qwencode 做 -DskipTests 的 install,再对
managed-agent-server 和 client 做 -DskipTests verify,把编译、测试和
生命周期插件拉进仓库。保存前删除 packages/sdk-java/*/pom.xml 和 packages/managed-agent-server/pom.xml 每个模块对应的
com/alibaba/<artifactId>。这些版本不是 SNAPSHOT;把 main 的 jar 留在缓存里,
同级模块安装失败时就会解析到 main 的构建。
verify 任务在 Install and build PR app 之前清空
$RUNNER_TEMP/verify-maven-repo,并用只恢复的 actions/cache/restore
恢复(没有 save 步骤)。restore-keys: verify-maven-repo- 覆盖改了 POM 的
PR。恢复步骤设置 continue-on-error,缓存服务故障时退化为冷仓库,而不是让
验证失败。
同级模块
Install Java modules 放在抖动门之后、Install evidence browser 之前,仅当
安装/构建还没有写下 verdict 时运行。没有 ready 就 warning 并 exit 0。否则
把仓库交给 node,每条命令包在 timeout -k 30 300 和 runuser -u node
里,并剥离凭据:
mvn -f packages/sdk-java/qwencode/pom.xml -DskipTests -Dgpg.skip=true -Dmaven.javadoc.skip=true install
该命令带 -Dmaven.repo.local=$RUNNER_TEMP/verify-maven-repo。root 把
qwencode=<exit> 追加到
$RUNNER_TEMP/verify-context/java-prepare.log,并把缓存是否命中写入步骤摘要。
这一步总是以 0 退出,从不写 verdict。
代理环境
Run verification agent 只在 /opt/verify-java/ready 存在时,于现有
Chromium 代码块之后向 QWEN_ENV 追加。后面的 PATH 生效,因为 env 从左到右
应用赋值:
PATH前面加上/opt/verify-java/jdk/bin和/opt/verify-java/maven/binJAVA_HOME=/opt/verify-java/jdkMAVEN_ARGS=-Dmaven.repo.local=$RUNNER_TEMP/verify-maven-repoQWEN_VERIFY_JAVA=1
.qwen/skills/verify-pr/SKILL.md 告诉代理不要自己下载 JDK 或 Maven,如何读
java-prepare.log,A/B 的 base 一侧如何重装同级模块(仓库里只有一份非
SNAPSHOT),以及把依赖数据库的集成测试写进 Not covered。Java diff 存在但没有
QWEN_VERIFY_JAVA,表示工具链安装失败。
超时
预算注释为工具链、恢复和两次封顶的 mvn install 增加最多约 20 分钟,且只在
Java diff 上发生。最坏情况从约 180 分钟变为约 200 分钟。timeout-minutes
改为 210,仍留 10 分钟余量。
设计决定
- 路径开关覆盖
packages/sdk-java/和packages/managed-agent-server/。sdk-java.yml还会在很宽的 core 和 CLI 路径上触发。给那些 diff 准备 Java,会让大多数 core PR 都去下载工具链, 而它们的跨语言测试仍然需要 MySQL 和本通道不提供的 bundle。 - checkout 之前以 root 下载,不用
actions/setup-java。 那个 action 的 toolcache 在共享宿主机上,cache: maven还会在 post 步骤回写。bookworm 的 apt 钉不住 Temurin 21。checkout 之前的步骤没有 PR 输入,与Install verify runner tools相同。 - 只恢复的缓存加上可信生产者。 verify 任务里的 save 会让 PR 控制的 POM
解析写入共享缓存。生产者只在
main上跑。缓存的验收是第二次运行命中,不是 YAML 形状检查:这个镜像没有zstd,以前就有 key 相同却永远命不中的缓存。 - 保存前剥离本仓库的产物。 固定版本让旧 jar 和合并引用的构建无法区分。
- 同级模块安装尽力而为,并且放在 TypeScript 构建之后。 Maven 失败不能把
TypeScript 验证变成
fail。日志里的退出码告诉代理要不要重装。
约束
issue_comment工作流跑的是默认分支上的 YAML。这套行为只有在改动进入main之后才生效。- 功能分支写入的缓存只有该分支能读到。verify 任务要能命中,生产者必须先在
main上跑过。 - 7 天没人访问的缓存会被淘汰。下一次生产者运行或
workflow_dispatch会重写。 未命中仍然能用,只是更慢。 qwen-triage.yml受工作流体积棘轮约束。新的生产者是单独文件,需要自己的.size-baseline行。
风险
- Maven Central 或 Temurin 下载可能不可达。Java 侧退化为 Not covered; 验证的其余部分照常跑。
- 容器多出解压后的 JDK(约 0.5 GB)。宿主机的
$RUNNER_TEMP多出仓库(约 200 MB),下一次 Java verify 运行时删掉。 - #13732 第 11 条在工具链就位之前要求把 Java 视为未覆盖。本通道开始设置
QWEN_VERIFY_JAVA之后,那一条应只在变量不存在时生效。如果 #13732 先合并, 本次改动一并修改它。
验证
scripts/tests/qwen-triage-workflow.test.js钉住路径开关、步骤顺序、校验和、 与sdk-java.yml及生产者共享的 Maven 钉子、只恢复的缓存(相同的 path、 key、runner 和容器)、被剥离的 artifact 集合、runuser加timeout、 有条件的代理环境,以及 210 分钟的任务上限。.github/scripts/qwen-triage-workflow.test.mjs要求timeout-minutes >= 210。- 本地
node:22-bookworm演练跑下载、以node安装同级模块,以及只用代理 环境变量跑mvn test。 - 合并之后:对同一个 Java PR 连续两次
/verify。第二次的步骤摘要显示verify Maven repo: hit=true,报告执行了 Java 侧,代理没有下载 JDK。
验收标准
packages/sdk-java/和packages/managed-agent-server/以外的 diff 不下载 JDK、不恢复 Maven 仓库、不安装同级模块。- Java diff 到达代理时已设置
QWEN_VERIFY_JAVA=1、JAVA_HOME和MAVEN_ARGS;下载失败时则没有这些变量,并有 warning。任务仍然运行代理。 - verify 任务从不保存 Maven 缓存。
- 生产者剥离的 artifact id 恰好等于
packages/sdk-java/*/pom.xml和packages/managed-agent-server/pom.xml的 artifact id。 - 生产者在
main上保存之后,第二次 verify 运行报告缓存命中。