ci: 修复NapCat运行时镜像验证

This commit is contained in:
sunlei 2026-06-26 18:05:19 +08:00
parent aa6e81f4c2
commit 0c6eed7539
3 changed files with 34 additions and 2 deletions

View File

@ -61,7 +61,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
- `ci/jenkins/KT-NapCatQQ-Upstream-Sync.Jenkinsfile` 是 NapCatQQ 上游审计入口,默认只调用 ktWorkflow 的 `napcat-upstream-audit` dry-run保留人工审查边界。
- Codex 上游审计必须同时设置 `RUN_CODEX_AUDIT=true` 并填写 `CONFIRM_CODEX_WORKSPACE_WRITE=RUN_CODEX_WORKSPACE_WRITE_AUDIT`;这是因为 Codex runner 使用 workspace-write sandbox不能作为定时任务默认行为。
- `ci/jenkins/KT-NapCatQQ-Runtime-Release.Jenkinsfile` 是运行时发布入口,先调用 `napcat-runtime-release-readiness`,再通过显式参数触发运行时镜像构建和 API promotion下游 job 使用白名单 choice避免任意 Jenkins job 名被传入,并把 upstream release commit / NapCat base image digest 透传到镜像构建证据。
- `ci/jenkins/KT-NapCatQQ-Runtime-Image-Build.Jenkinsfile` 是运行时镜像构建下游,只从 NAS 本地裸仓库 clone 经过审查的 NapCatQQ fork ref构建 `NapCat.Shell`,调用 API 仓库 `scripts/napcat-desktop-cn-stage-build.mjs` 生成 staged context执行 `docker build` 和容器内 `/ci/napcat-desktop-cn/verify.sh`;它不触发 API promotion、不执行 `kubectl`、不合并或推送 Git。
- `ci/jenkins/KT-NapCatQQ-Runtime-Image-Build.Jenkinsfile` 是运行时镜像构建下游,只从 NAS 本地裸仓库 clone 经过审查的 NapCatQQ fork ref构建 `NapCat.Shell`先要求 NAS API 工作区 clean并从 Jenkins API main checkout 的只读 `.git` reference 做 `fetch + merge --ff-only`,再调用 API 仓库 `scripts/napcat-desktop-cn-stage-build.mjs` 生成 staged context执行 `docker build` 和容器内 `/ci/napcat-desktop-cn/verify.sh`由于该下游需要访问挂载的宿主 Docker socket内层 runner 固定 `--user 0:0`,镜像验证容器按账号容器同款 `SYS_ADMIN` / seccomp / apparmor 参数和 `NAPCAT_REQUIRE_DEVICE_PROFILE=1` 启动,但它不触发 API promotion、不执行 `kubectl`、不合并或推送 Git。
- 生产 API promotion 除了 `PROMOTE_API_RUNTIME=true` 和明确 image/profile 参数外,还必须填写 `CONFIRM_API_PROMOTION_TARGET=PROMOTE_KT_TEMPLATE_API_MAIN`
- 三个模板默认使用 NAS 工作区 `/vol1/docker/kt-codex/workspace/KT`,运行证据落在 `/vol1/docker/kt-codex/artifacts` 下。
- 模板只保存入口和参数形状,不记录 Jenkins credential、Token、SSH key 或其他真实凭据。

View File

@ -22,6 +22,8 @@ pipeline {
environment {
KT_WORKSPACE_ROOT = '/vol1/docker/kt-codex/workspace/KT'
API_ROOT = '/vol1/docker/kt-codex/workspace/KT/Node/kt-template-online-api'
API_GIT_REFERENCE_HOST = '/vol1/docker/volumes/kt-node-agent-workdir/_data/workspace/KT-Template_KT-Template-API_main/.git'
API_GIT_REFERENCE = '/ci/kt-template-online-api-main.git'
NAPCAT_GIT_REPOSITORY = '/vol1/docker/kt-codex/git/NapCatQQ.git'
KT_WORKFLOW_RUNNER_IMAGE = 'kt-jenkins-node-agent:current'
}
@ -51,6 +53,7 @@ pipeline {
set -e
docker run --rm \
-e API_ROOT="$API_ROOT" \
-e API_GIT_REFERENCE="$API_GIT_REFERENCE" \
-e BUILD_TAG="$BUILD_TAG" \
-e BUILD_URL="$BUILD_URL" \
-e COREPACK_HOME=/vol1/docker/kt-codex/runtime/corepack \
@ -64,7 +67,9 @@ pipeline {
-e UPSTREAM_RELEASE_COMMIT="$UPSTREAM_RELEASE_COMMIT" \
-e UPSTREAM_RELEASE_TAG="$UPSTREAM_RELEASE_TAG" \
-v /vol1/docker/kt-codex:/vol1/docker/kt-codex \
-v "$API_GIT_REFERENCE_HOST":"$API_GIT_REFERENCE":ro \
-v /var/run/docker.sock:/var/run/docker.sock \
--user 0:0 \
--entrypoint bash "$KT_WORKFLOW_RUNNER_IMAGE" -lc '
set -euo pipefail
source /vol1/docker/kt-codex/runtime/nvm/nvm.sh
@ -91,8 +96,19 @@ pipeline {
trap cleanup EXIT
git config --global --add safe.directory "$NAPCAT_GIT_REPOSITORY"
git config --global --add safe.directory "$API_ROOT"
rm -rf "$ARTIFACT_DIR" "$BUILD_WORKDIR"
mkdir -p "$ARTIFACT_DIR" "$BUILD_WORKDIR"
if [ -n "$(git -C "$API_ROOT" status --short)" ]; then
echo "API_ROOT must be clean before runtime image build: $API_ROOT" >&2
git -C "$API_ROOT" status --short >&2
exit 2
fi
test -d "$API_GIT_REFERENCE"
git -C "$API_ROOT" fetch "$API_GIT_REFERENCE" refs/remotes/origin/main
git -C "$API_ROOT" checkout main
git -C "$API_ROOT" merge --ff-only FETCH_HEAD
git -C "$API_ROOT" rev-parse HEAD > "$ARTIFACT_DIR/api-root-commit.txt"
git clone "$NAPCAT_GIT_REPOSITORY" "$NAPCAT_ROOT"
cd "$NAPCAT_ROOT"
git checkout --detach "$NAPCAT_FORK_REF"
@ -118,7 +134,12 @@ pipeline {
-t "$QQBOT_NAPCAT_IMAGE_OVERRIDE" \
-f "$STAGE_OUT/ci/napcat-desktop-cn/Dockerfile" \
"$STAGE_OUT"
docker run -d --name "$VERIFY_NAME" "$QQBOT_NAPCAT_IMAGE_OVERRIDE" >/dev/null
docker run -d --name "$VERIFY_NAME" \
--cap-add SYS_ADMIN \
--security-opt apparmor=unconfined \
--security-opt seccomp=unconfined \
-e NAPCAT_REQUIRE_DEVICE_PROFILE=1 \
"$QQBOT_NAPCAT_IMAGE_OVERRIDE" >/dev/null
sleep 3
docker exec "$VERIFY_NAME" sh /ci/napcat-desktop-cn/verify.sh
docker image inspect "$QQBOT_NAPCAT_IMAGE_OVERRIDE" \

View File

@ -811,6 +811,17 @@ export async function runSelfTest(): Promise<void> {
"requireRuntimeImageParameters(",
"requireImageProfileMatch(",
"-v /var/run/docker.sock:/var/run/docker.sock",
"--user 0:0",
"API_GIT_REFERENCE_HOST",
"API_GIT_REFERENCE",
"-v \"$API_GIT_REFERENCE_HOST\":\"$API_GIT_REFERENCE\":ro",
"--cap-add SYS_ADMIN",
"--security-opt apparmor=unconfined",
"--security-opt seccomp=unconfined",
"-e NAPCAT_REQUIRE_DEVICE_PROFILE=1",
"git -C \"$API_ROOT\" fetch \"$API_GIT_REFERENCE\" refs/remotes/origin/main",
"git -C \"$API_ROOT\" merge --ff-only FETCH_HEAD",
"\"$ARTIFACT_DIR/api-root-commit.txt\"",
"git clone \"$NAPCAT_GIT_REPOSITORY\" \"$NAPCAT_ROOT\"",
"BUILD_WORKDIR=\"$ARTIFACT_ROOT_REAL/runtime-image-build-workspace/$BUILD_ID_SAFE\"",
"KT_ARTIFACT_ROOT must stay under /vol1/docker/kt-codex/artifacts",