| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 5 天前 | ||
| 4 天前 | ||
| 5 天前 | ||
| 5 天前 | ||
| 5 天前 | ||
| 4 天前 | ||
| 5 天前 | ||
| 5 天前 | ||
| 5 天前 | ||
| 4 天前 | ||
| 2 天前 | ||
| 4 天前 | ||
| 5 天前 |
xwcode 的 xuanwu-ci-bot 配置
本目录由 xuanwu-ci-bot 在 MR / Push 时扫描。每个匹配的 Dockerfile 对应一次并行 pr-check:镜像构建成功 = 检查通过(产物不推 Harbor)。
相关文件:
| 文件 | 作用 |
|---|---|
Dockerfile.*(本目录根下) |
默认 pr-check 门禁 |
release/Dockerfile.* |
仅 tag release 前并行跑(见 release/README.md) |
nightly/Dockerfile.* |
日调度深测(NIGHTLY_REPOS + 最新 v* tag 上有这些文件;见 ci-bot docs/nightly.md) |
push-image.yaml |
★ 已启用(v1.9.6 M3③ · 2026-10-17):master 推送 ⇒ 构建根目录 Dockerfile 并推 Harbor(xuanwu/xwcode) |
release.yaml + 仓根外 docker/Dockerfile.release |
打 v* tag:先跑 release/ checks,再构建并上传资产(含 10MB 体积硬闸) |
产品镜像的构建上下文排除见仓根 Dockerfile.dockerignore;pr-check 共用仓根 .dockerignore。
Bot 会递归扫描 .xuanwu/ 做 pr-check,但跳过 optional/、nightly/、release/。.xuanwu/release/ 仅在 tag release job 中执行;.xuanwu/nightly/ 由 bot 日调度触发。
CI 优化(Phase 1–4)
| Phase | 内容 | 状态 |
|---|---|---|
| 1 | 重门禁移出默认 PR(现为 release/ tag 门) |
已做 |
| 2 | 默认 PR 0 次 cargo build --release(release build 在 tag / release/) |
已做 |
| 3 | 公共 snippets/setup-rust-ci.sh、manifest→cargo fetch 层、BuildKit registry/git cache、botgate-artifacts 导出 .botgate/(报告不 tee 进控制台)、CARGO_TERM_COLOR、统一 crates (prod) mirror |
已做 |
| 4 | 默认路径 cargo-hack / cargo-audit(及 release 的 deny/machete)改 GitHub 预编译包,避免 cargo install |
已做(publish 仍 install dist/cyclonedx) |
| 5 | 默认 Rust 通用门禁(fmt/clippy/build/nextest/audit)收敛为 botgate(bot-gate run pr --locked --strict) |
已做 |
| 6 | 简单仓用 .xuanwu/botgate.yaml;Jenkins 从 ci-bot 标准模板合成 Dockerfile |
已做 |
Botgate 门禁脚本在共享 L0(run-botgate-pr);本仓用 .xuanwu/botgate.yaml(无拷贝 Dockerfile)。.xuanwu/snippets/ 仅留给非 botgate 检查。仓根 botgate.toml 配置 BotGate pr 档。
构建缓存分层(L0 / L1 / L2)与 SLA
默认 PR 调度到 Jenkins HA 的 warm agent(label xuanwu-docker,hostPath warm-<hostname>/)。Burst 仅作队列溢出;burst 上 botgate 无持久 target 缓存(pod 删除即清空)。
| 层 | 内容 | 存放 | 失效 |
|---|---|---|---|
| L0 基镜像 | apt、rustup 组件、bot-gate / bot-metric / cargo-audit | 组织共享 Harbor xuanwu/ci-cache/rust-botgate-base:<channel>(权威源:xuanwu-ci-bot/ci-cache) |
在 ci-bot 仓改 ci-cache/ 后 ./ci-cache/build-push.sh;channel / 工具版本变更 |
| L1 层缓存 | Dockerfile 各 RUN / COPY 层 |
本机 DinD + Harbor type=registry cache(…/xwcode-botgate:buildcache) |
对应指令输入变更;DinD prune 后可从 Harbor 拉回 |
| L2 mounts | crates.io registry、git deps、/src/target |
仅 warm agent DinD(BuildKit cache mount) | lock / 源码 / 工具链变则增量;节点销毁则丢 |
约定:
- registry / git:全局共享
id=cargo-registry、id=cargo-git,均sharing=locked(并行检查串行化写入,避免 git checkout 竞态)。 - target:按仓+检查隔离,
id=<repo>-<check>-target,sharing=locked(避免 botgate / hack 互踩)。 - 不把
/src/target推 Harbor;无「跨节点共享 target」承诺。
SLA(文档承诺)
| 场景 | 期望 |
|---|---|
| Warm 命中(同 warm 节点二次 PR) | botgate 墙钟为增量量级(分钟级,视改动面) |
| 冷启动(新 warm 节点 / DinD 被清空) | 可拉 L0 + L1 registry cache,无 L2 target → 首次仍接近全量编译 |
| Burst | 冷缓存,可接受变慢;不计入 warm SLA |
L0 推送(组织共享,不在本仓)
- 权威:xuanwu-ci-bot
ci-cache/;main上改ci-cache/→ Jenkins push-image 自动推rust-botgate-base:<channel>(与 bot 应用镜像同 job、按 path 过滤) - 手工兜底:ci-bot
./ci-cache/build-push.sh;本仓 helper 默认docker pull - pr-check 只
FROM该镜像,不 push base。 新仓脚手架见 ci-botexamples/.xuanwu/botgate/。
Warm DinD 定期 docker builder prune --filter until=168h(见 jenkins-ha Terraform)。
验收:
- 静态:
.xuanwu/snippets/verify-ci-cache.sh - L0:Harbor 存在
…/rust-botgate-base:<channel>(与RUST_CHANNEL/ toolchain 一致) - 墙钟:同 warm 节点连续两次 PR 对比 botgate;换节点一次确认冷启动仍能命中 L0/L1(无跨节点 target)
默认 PR 门禁(P0 / P1)
| 检查名 | Dockerfile | 来源(GHA) | 档 |
|---|---|---|---|
| botgate | botgate.yaml(Jenkins 合成 Dockerfile) |
check(fmt/clippy/build/test)+ audit → BotGate pr |
P0 |
| env-inherit | Dockerfile.env-inherit |
GHA env-inherit 的 Docker 对等:cargo-fetch Dockerfile 须齐 CARGO_NET_* / GIT_CONFIG_*(或 FROM rust-botgate-base) |
P0 |
| lint | Dockerfile.lint |
lint-extra | P0 |
| python | Dockerfile.python |
python-test | P0 |
| secret-scan | Dockerfile.secret-scan |
gitleaks 全历史 + AC12 腿(shallow=false;与 tag release/Dockerfile.secret-scan 同门) |
P0 |
| hack | Dockerfile.hack |
cargo-hack + AC8 | P1 |
| msrv | Dockerfile.msrv |
msrv | P1 |
botgate 替代原独立的 fmt / clippy / build / nextest / audit。语义上测试步为 BotGate 默认 cargo test(非 nextest)。hack / msrv / lint / python / secret-scan / env-inherit 仍并行独立门禁。PR 不再跑 cargo doc(已去掉 Dockerfile.doc)。PR secret-scan 与 tag 一样扫全历史并跑 AC12 腿(shallow=false;乙表持红且无【新】命中 ⇒ 绿)。该声明会把整个 pr-check 的克隆放宽成非浅克隆。env-inherit 跳过不拉 cargo 的检查(lint / python / secret-scan / gate-selftest);botgate 认 L0 rust-botgate-base。
Tag release 门禁(.xuanwu/release/)
打 v* tag 且存在 release.yaml 时,Jenkins release job 在上传资产前并行跑这些检查(失败则不发 Release):
| 检查名 | 路径 | 说明 |
|---|---|---|
| secret-scan | release/Dockerfile.secret-scan |
gitleaks 全历史 + AC12 腿(shallow=false;乙表持红为设计态) |
| memory | release/Dockerfile.memory |
release 编译 + 探针 |
| tui | release/Dockerfile.tui |
release 编译 + pytest |
| publish | release/Dockerfile.publish |
cargo-dist / SBOM + AC11 changelog(全历史 + tag) |
| verify-release | release/Dockerfile.verify-release |
scripts/verify_release.sh 全量(本地 master/dev + release 二进制) |
| supply-chain | release/Dockerfile.supply-chain |
deny / machete / audit |
| gate-selftest | release/Dockerfile.gate-selftest |
门禁自测子集 |
资产构建:docker/Dockerfile.release(含 10MB 体积硬闸)→ /out/...。
Nightly 深测(.xuanwu/nightly/)
bot 按 NIGHTLY_CRON(默认 UTC 47 21 * * * ≈ CST 05:47)对白名单仓跑 Jenkins …/nightly:只测最新 v* tag(L5),不测 branch HEAD。失败发 SMTP。
| 检查名 | Dockerfile | 来源(GHA nightly-deep) |
|---|---|---|
| miri | nightly/Dockerfile.miri |
miri + AC1 腿 |
| fuzz-corpus | nightly/Dockerfile.fuzz-corpus |
fuzz 语料回归 + AC2 腿 |
| mutants | nightly/Dockerfile.mutants |
cargo-mutants + AC3 腿 |
| perf | nightly/Dockerfile.perf |
criterion + AC4/AC5 腿 |
手工:POST /hooks/nightly + X-Xuanwu-Callback-Secret,body {"owner":"…","repo":"…","force":true}。稳定前与 GHA nightly-deep.yml 双跑。
本地冒烟示例:
# L0:pull 组织共享 base(重建/推送在 xuanwu-ci-bot:./ci-cache/build-push.sh)
docker pull registry.xuanwu.openatom.cn/xuanwu/ci-cache/rust-botgate-base:$(sed -nE 's/^[[:space:]]*channel[[:space:]]*=[[:space:]]*"([^"]+)".*/\1/p' rust-toolchain.toml | head -1)
# 本机已装 bot-gate 时可直接(推荐;与 CI 门禁同配置):
# bot-gate run pr --locked
# bot-gate run fast
# CI 由 .xuanwu/botgate.yaml 合成 Dockerfile;本地 docker 对等可对照
# xuanwu-ci-bot/src/templates/Dockerfile.botgate
docker build --network=host -f .xuanwu/release/Dockerfile.memory -t xwcode-memory .
怎么从 GitHub Actions CI 转写到 xuanwu CI
GHA 的「一个 job / 若干 run:」在 xuanwu-ci 里变成「一个 .xuanwu/Dockerfile.<名>」。Jenkins 对每个 Dockerfile 执行 docker build,成功即绿。
1. 对应关系
| GitHub Actions | xuanwu-ci-bot |
|---|---|
.github/workflows/*.yml 里的 job / step |
.xuanwu/Dockerfile.<检查名> |
| job 内装工具 + 跑命令 | Dockerfile 的 RUN(装依赖 + 执行原命令) |
| 构建成功 / 命令 exit 0 | docker build 成功 |
| 推镜像(若有) | .xuanwu/push-image.yaml + 仓根(或指定)Dockerfile |
| 打 tag 发 Release 资产 | .xuanwu/release.yaml + docker/Dockerfile.release(勿放 .xuanwu/) |
| 仓库 Webhook / Actions secrets | GitCode Webhook → bot;凭证在 Jenkins / bot 侧,不要写进 YAML |
命名约定(任选其一):
.xuanwu/Dockerfile.<name>→ 检查名<name>(如Dockerfile.fmt→fmt).xuanwu/<name>.Dockerfile.xuanwu/Dockerfile→ 检查名default- 重/慢、仅发版跑的门禁放
.xuanwu/release/→ tag release 前并行跑
2. 转写步骤(建议顺序)
-
抽出命令
打开.github/workflows/ci.yml(或其它 workflow),记下该门禁真正要跑的命令(例如cargo fmt --all -- --check),忽略actions/checkout、rust-cache、artifact 上传等 GHA 专属步骤。 -
选基镜
- Rust:与
rust-toolchain.toml对齐(本仓用rust:1.98-bookworm)。 - 纯脚本 / Python:可用
debian:*/python:*。
Jenkins 拉 Docker Hub 慢时,可设RUSTUP_DIST_SERVER/RUSTUP_UPDATE_ROOT指向https://mirror.xuanwu.openatom.cn(见本目录现有 Dockerfile)。
- Rust:与
-
补齐构建前件(本仓必做)
GHA 顶层env在 Docker 里不会自动继承,须在 Dockerfile 中显式写入,与install.sh/ci.yml一致:CARGO_NET_GIT_FETCH_WITH_CLI=true- gitcode 的
GIT_CONFIG_*insteadOf(ssh /git@→ https) .cargo/config.toml:crates.io →sparse+https://crates.xuanwu.openatom.cn/api/v1/cratesio/apt安装git、ca-certificates,以及 clippy/build 所需的pkg-config、libssl-dev等
-
写成 Dockerfile 骨架
FROM rust:1.98-bookworm # ENV:mirror + CARGO_NET_GIT_FETCH_WITH_CLI + GIT_CONFIG_* … # RUN apt-get … && 写 .cargo/config.toml WORKDIR /src COPY . . RUN <原 CI 中的命令> -
拆分粒度
一个 Dockerfile = 一个可并行的检查名。重/慢、仅发版需要的门禁放release/,避免默认 PR 被拖垮。 -
对照本仓差异再改写
GHA 写法 Docker / Jenkins 上怎么处理 actions/download-artifact依赖上游 job在同一 Dockerfile 内先 cargo build再跑后续(见release/Dockerfile.tui)taiki-e/install-actioncargo install …或curl预编译二进制(见Dockerfile.lint)continue-on-error/if:Docker 无法表达「软失败」;要么硬门禁,要么别迁 ::notice::/ PR 评论无对应;只保留 exit code 门禁 fetch-depth: 0/ 全历史Dockerfile 声明 # xuanwu-ci-clone: shallow=false(PR 与 tag 的 secret-scan 都这样);bot 对同一次 checkout 取最宽。全 tag 集门禁仍见下节 -
可选:推镜像 / Release
- Harbor:本仓已启用 push-image(
.xuanwu/push-image.yaml·branch: master· 指根目录产品Dockerfile·harbor_repo: xuanwu/xwcode·v1.9.6M3③)。 - Release:
.xuanwu/release/checks →docker/Dockerfile.release+release.yaml;镜像内/out/...;strip 后 >10MB 则构建失败。
- Harbor:本仓已启用 push-image(
-
接入 Webhook
GitCode → Settings → Webhooks →https://<bot-host>/hooks/gitcode,勾选 Push 与 Merge Request。首次触发后 Jenkins 出现xuanwu-ci/<owner>/<repo>/pr-check等任务。
3. 仍留在 GitHub Actions 的门禁
Jenkins pr-check 默认浅克隆(depth=1、不拉 tag)。检查可声明 # xuanwu-ci-clone: depth=N / shallow=false / fetch_tags=true(bot 取最宽)。本仓 PR secret-scan 声明了 shallow=false,因此整次 pr-check 按全历史克隆。
仍留在 GHA(需全 tag 集 / GitHub 专属 / 软门禁)的:
| GHA job | 原因 |
|---|---|
| verify-release-dev-safe | 已确认留在 GHA:开发期子集,放进默认 PR 会把浅克隆改成全历史 |
| CodeQL | 已确认留在 GHA:GitHub CodeQL Action,Jenkins 无对等平台 |
| env-inherit(GHA job) | 已确认留在 GHA:断言的是 workflow 顶层 env: 继承;Docker 侧 Dockerfile.env-inherit 查的是另一件事 |
| coverage | 已确认留在 GHA:软门禁 + PR 评论;members = [] 时 0 测试,迁进 docker build 会变成空跑 |
| nightly-deep | 已转 .xuanwu/nightly/;GHA schedule 仍双跑,稳定后可停 |
需要全 tag 时保持 GHA 的 fetch-depth: 0,不要为「迁完」而迁成假绿。