Files
docs/测试环境Jenkins部署指南.md
T

17 KiB
Raw Blame History

测试环境 Jenkins 部署指南

最后核对:2026-08-25

本文供 Codex 对话和项目维护人员部署虫虫出海测试环境使用。只适用于测试环境,不适用于预发布或生产。

开发、测试环境内国内/海外服务同机共置,以及生产双区域 Nacos 和 Event Bridge 目标拓扑,统一见双区域部署与 Nacos 规划;本文只维护测试环境 Jenkins 操作步骤。

1. 人工部署默认与 Codex 授权边界

测试环境默认由人工部署。读取本指南、完成代码、远端联调、测试环境回归、浏览器验收或“部署后才能继续验证”都不自动授权 Codex 触发 Jenkins。

没有当前对话的明确部署授权时,Codex 工作到“可人工部署”即停止,并交付:目标仓库和分支、完整 commit SHA、受影响 Job/服务、已通过的本地门禁、必要环境前提、人工触发步骤和部署后验证清单。Codex 可以按任务需要只读检查 Jenkins 现状,但不得触发、重跑或停止构建,也不得重建远端容器。

只有用户在当前对话明确要求“由 Codex 部署”“自动部署并测试”“今晚持续部署验收”或等价表述时,Codex 才能执行。授权必须能确定环境、服务或 Job、目标提交和结束条件;只在该范围内有效,任务完成或用户叫停后自动失效。

用户明确安排夜间持续执行时,Codex 可以在授权范围内等待构建、重试同一提交的失败 Job、执行部署后健康检查和验收;不得借此新增服务、扩大到全量部署或执行数据库操作。不得根据当前时间、用户长时间未回复或用户可能已经休息自行推断夜间授权。

此授权不包含以下操作;遇到时必须单独取得用户明确确认:

  • 部署 staging 或 production。
  • 执行任何数据库写入、迁移、初始化和测试数据修改。
  • 勾选 SKIP_TESTS。
  • 无法明确影响范围时执行后端 ALL 全量部署。
  • 修改 Jenkins Job、Credentials、节点、插件、权限或系统配置。
  • 删除构建、停止他人正在执行的构建、回滚环境或清理容器/数据。

“请继续”“完成验收”“修复后验证”不单独构成部署授权;必须明确表达由 Codex 操作 Jenkins。人工已经部署后,用户要求 Codex 继续测试的,只授权测试和只读核对,不反向授权再次部署。

2. 环境与认证

项目 地址或标识
Jenkins 本机未提交环境变量 JENKINS_URL;使用已配置的 HTTPS 反向代理地址
Jenkins 用户 本机未提交环境变量 JENKINS_USER
Jenkins API Token 本机未提交环境变量 JENKINS_API_TOKEN;禁止使用账号密码代替
测试 Gateway 本机未提交环境变量 TEST_GATEWAY_URL
Admin Web 本机未提交环境变量 TEST_ADMIN_WEB_URL
Client Web 本机未提交环境变量 TEST_CLIENT_WEB_URL
后端 Git 分支 test
Admin/Client Git 分支 release/test

Jenkins 用户在个人“安全”页面生成独立 API Token。Token 只保存到本机密钥管理或未提交环境文件,不得写入仓库、命令示例、聊天记录、构建参数、日志或 Jenkinsfile。旧版明文密码调用方式已停用;历史上曾写入文档的密码必须视为泄露并完成轮换。

只有当前对话已明确授权 Codex 部署时才可使用 API;未授权时不得通过浏览器或 API 触发构建。已获部署授权时优先使用 API Token 调用,不复用浏览器 Cookie。API 用户只授予读取目标 Job、触发构建和读取构建结果所需的最小权限,不授予 Job 配置、Credentials、节点、插件或系统管理权限。

Jenkins 页面会显示“系统管理”“新建任务”“配置”“删除 Pipeline”等管理入口。即使当前账号具有管理权限,也只能执行本任务所需的构建和只读检查。

3. Jenkins HTTP API 调用

Jenkins Remote Access API 可以触发构建、读取队列、查询构建状态和获取控制台日志。API 只是人工点击的等价入口,不扩大第 1 节的授权范围,也不允许绕过部署前检查、参数门禁或部署后验收。

实现依据以 Jenkins 官方 Remote Access API 和 CSRF Protection 文档为准。

3.1 本机认证准备

以下变量只在当前受控终端设置,示例值必须替换为实际反向代理地址、用户和 API Token,不写入任何受版本控制文件:

export JENKINS_URL='https://jenkins.example.com'
export JENKINS_USER='jenkins-api-user'
export JENKINS_API_TOKEN='replace-with-local-secret'

先做只读连通性检查:

curl --fail --silent --show-error \
  --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  "${JENKINS_URL%/}/api/json?tree=nodeName,mode"

使用 API Token 的认证请求不需要 CSRF Crumb;不得关闭 Jenkins CSRF 防护。若仍返回 401/403,先检查 Token、用户权限和反向代理是否保留 Authorization 头,不要改用明文密码。只有遗留的用户名/密码脚本才需要同时维护 Cookie 与 /crumbIssuer/api/json 返回的 Crumb,本项目不再采用该方式。

3.2 触发无参数前端 Job

curl --fail-with-body --silent --show-error \
  --request POST \
  --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  --dump-header admin-web-test.headers \
  --output /dev/null \
  "${JENKINS_URL%/}/job/admin-web-test/build"

Client 将 Job 路径改为 /job/client-web-test/build。成功响应通常是 HTTP 201/302,并在 Location 响应头返回队列条目 URL。临时响应头文件使用后立即删除,不得提交。

3.3 触发参数化后端 Job

以下示例只部署测试环境的 gateway-overseas 与 lastleg-service;实际调用必须按本次授权修改服务范围:

curl --fail-with-body --silent --show-error \
  --request POST \
  --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  --dump-header backend-java.headers \
  --output /dev/null \
  --data-urlencode 'BUILD_MODE=SELECT' \
  --data-urlencode 'SERVICE_GATEWAY_OVERSEAS=true' \
  --data-urlencode 'SERVICE_LASTLEG=true' \
  --data-urlencode 'ENVIRONMENT=test' \
  --data-urlencode 'DEPLOY=true' \
  --data-urlencode 'SKIP_TESTS=false' \
  --data-urlencode 'EVENT_BRIDGE_REGION=BOTH' \
  --data-urlencode 'DOWNSTREAM_JOB_PREFIX=baiyue-firstleg-' \
  "${JENKINS_URL%/}/job/backend-java/buildWithParameters"

没有明确选择的 SERVICE_* 参数保持 Job 默认 false,不要为了省事传 ALL。调用前应从 ${JENKINS_URL%/}/job/backend-java/api/json 核对当前 Job 参数定义;参数发生变化时先更新本文,禁止让调用脚本静默依赖过期默认值。

3.4 跟踪队列与构建结果

从触发响应的 Location 头取得 QUEUE_URL,轮询队列,直到出现 executable.url:

QUEUE_URL="$(awk 'BEGIN{IGNORECASE=1} /^Location:/{gsub("\\r",""); print $2}' backend-java.headers)"
curl --fail --silent --show-error \
  --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  "${QUEUE_URL%/}/api/json?tree=id,why,cancelled,executable[number,url]"

取得返回中的 executable.url 后,用它作为 BUILD_URL 查询终态和日志:

curl --fail --silent --show-error \
  --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  "${BUILD_URL%/}/api/json?tree=number,building,result,url,duration,estimatedDuration"

curl --fail --silent --show-error \
  --user "$JENKINS_USER:$JENKINS_API_TOKEN" \
  "${BUILD_URL%/}/consoleText"

只有 building=false 且 result=SUCCESS 才算 Job 成功。后端总控还必须核对每个下游 Job 结果;HTTP POST 成功、进入队列或拿到构建号均不代表部署成功。轮询建议每 5–10 秒一次,并设置调用方总超时;未经授权不得调用队列取消、构建停止或重跑接口。

3.5 API 常见错误

  • 401:用户或 API Token 错误,或者反向代理未转发 Authorization。
  • 403:用户缺少 Job Read/Build 权限;使用 API Token 时不要通过关闭 CSRF 或改用密码规避。
  • 404:Job 名称、Folder 路径或反向代理 Jenkins Context Path 错误。
  • 400:参数名或 Choice 值与当前 Job 定义不一致。
  • 队列长期没有 executable:读取 why,检查 Job 并发限制、节点标签、部署锁和执行器,不要重复 POST 制造重复部署。

4. Job 与部署单元

部署单元 Jenkins Job 源码目录 流水线行为
Admin Web admin-web-test apps/admin-web/ 拉取 release/test,构建镜像,重建容器,执行容器内 /healthz
Client Web client-web-test apps/client-web/ 拉取 release/test,构建镜像,重建容器,执行容器内 /healthz
后端总控 backend-java baiyue-firstleg/ 选择变更服务并行调度下游 Job;测试环境使用 Jenkins 节点本机镜像

后端下游 Job:

  • baiyue-firstleg-gateway
  • baiyue-firstleg-gateway-overseas
  • baiyue-firstleg-auth
  • baiyue-firstleg-iam
  • baiyue-firstleg-firstleg
  • baiyue-firstleg-finance
  • baiyue-firstleg-order
  • baiyue-firstleg-warehouse
  • baiyue-firstleg-file
  • baiyue-firstleg-print
  • baiyue-firstleg-integration-service
  • baiyue-firstleg-lastleg-service
  • baiyue-firstleg-warehouse-overseas-service
  • baiyue-firstleg-overseas-security-service
  • baiyue-firstleg-event-bridge-service
  • baiyue-firstleg-audit-service

正常部署后端时从 backend-java 总控 Job 发起。下游 Job 主要由总控调度;只有重跑同一提交的单个失败服务且已核对全部参数时,才直接操作下游 Job。

5. 部署前强制检查

  1. 阅读目标项目及目标模块的 AGENTS.md,确认任务允许修改和部署该单元。
  2. 检查工作区状态,区分当前任务变更与用户已有变更。不得擅自提交或部署无关改动。
  3. 运行目标项目声明的测试和构建门禁:
    • Admin:至少运行受影响测试、pnpm typecheck 和 pnpm build;交付部署前优先运行 pnpm test。
    • Client:至少运行 pnpm typecheck、受影响测试和 pnpm build;交付部署前优先运行 pnpm test。
    • Backend:优先运行 mvn -pl <module> -am test;公共模块或跨服务变更按影响范围扩大验证。
  4. 确认待部署代码已经提交并推送到 Jenkins 实际拉取的远端分支。Jenkins 无法部署本地未提交或未推送的文件。
  5. 记录准备部署的仓库、分支、完整 commit SHA、Job 和后端服务列表。
  6. 触发前核对当前对话是否存在符合第 1 节的明确部署授权,并通过 commentary 告知用户即将部署的 Job、commit 和范围。没有明确授权时停止在人工部署交接,不以通知替代授权。
  7. 检查 Jenkins 构建队列和执行器。不得覆盖或中断他人构建;同一 Job 正在构建时等待其结束,再重新核对远端提交。

如果当前工作区包含其他人的未提交改动,只有在能够证明远端目标 commit 仅包含本任务变更时才可部署。无法隔离时停止并说明阻断。

6. 前端部署

Admin 和 Client Job 无部署参数,触发后会直接构建并重建对应测试容器。因此触发前必须确认远端 release/test HEAD 就是目标提交。

Admin

  1. 打开 admin-web-test。
  2. 核对最近构建、当前队列和远端 release/test 目标提交。
  3. 触发“立即构建”。
  4. 等待构建进入终态,不得只看到进入队列就结束任务。
  5. 成功后检查 ${TEST_ADMIN_WEB_URL}/healthz 返回 HTTP 200 和 ok。

Client

  1. 打开 client-web-test。
  2. 核对最近构建、当前队列和远端 release/test 目标提交。
  3. 触发“立即构建”。
  4. 等待构建进入终态。
  5. 成功后检查 ${TEST_CLIENT_WEB_URL}/healthz 返回 HTTP 200 和 ok。

前端 /healthz 只证明容器和 Nginx 正常。任务涉及登录、接口或业务页面时,还必须按当前任务执行对应 Gateway 请求或浏览器业务验收。

7. 后端部署

打开 backend-java,选择 “Build with Parameters”。测试环境常规部署使用以下参数:

参数 常规值 说明
BUILD_MODE SELECT 或已核对后的 AUTO 优先显式选择受影响服务;确认提交差异完整时可用 AUTO
SERVICE_* 仅勾选受影响服务 SELECT 模式至少选择一个
ENVIRONMENT test 本文禁止改为其他环境
DEPLOY true 否则只构建镜像,不更新测试容器
SKIP_TESTS false 未经单独确认不得跳过测试
EVENT_BRIDGE_REGION BOTH 选择事件桥时默认一次部署国内和海外实例;CN/OVERSEAS 仅用于单区故障重跑
IMAGE_REPOSITORY 保持测试默认值 test 会解析为 baiyue-firstleg-test
DOCKER_BASE_IMAGE 保持 Job 默认值 除非任务明确要求变更基础镜像
DOWNSTREAM_JOB_PREFIX baiyue-firstleg- 与现有 16 个下游 Job 对应

选择规则:

  • 单服务业务代码:选择该服务,并检查内部客户端或契约消费者是否也需要部署。
  • common-*、父 pom.xml、platform-bom/、Jenkinsfile* 或 deploy/ 中非 deploy/sql/ 的部署设施变化:AUTO 会选择全部 16 个服务。能够证明公共变更影响全部服务时可直接部署;无法证明范围时按第 1 节取得确认。
  • deploy/sql/ 变化:AUTO 只标记存在待执行的数据库迁移,不据此扩大服务范围;同一提交中的服务目录变化仍按目录选择对应服务。若提交只有 SQL 变化,则不调度服务 Job。数据库迁移必须独立审核、取得明确授权并执行,不能由普通服务部署隐式触发。
  • Gateway 路由、CORS 或访问域变化:选择 gateway,并检查受影响业务服务。
  • 海外 PDA 换仓即时失效链变化:同时选择 gateway-overseas、auth、iam;Jenkins 环境文件必须提供非空 AUTH_SESSION_VALIDATION_URL,并复用既有 INTERNAL_SERVICE_TOKEN,不得把 URL、服务令牌或 raw 用户 Token 写入源码/Nacos 明文。普通海外 Admin/Client 路径不调用该同步校验。
  • 跨服务 DTO/OpenAPI/内部客户端变化:同时选择生产者和消费者。
  • 数据库结构变化:不能仅部署服务。先按数据库变更规则取得明确授权并完成迁移,再部署依赖该结构的服务。
  • Finance 服务部署使用模块名 finance,Jenkins 下游 Job 必须命名为 baiyue-firstleg-finance;测试环境凭据 firstleg-test-env 必须包含非空 FINANCE_DB_URL、FINANCE_DB_USERNAME、FINANCE_DB_PASSWORD。
  • File 服务部署依赖 Jenkins 文件凭据 firstleg-test-env 中有效的 ROCKETMQ_NAME_SERVER,且 MQ_TOPIC_PREFIX 必须为 test-。

总控 Job 成功不应只看主任务颜色。必须核对描述或日志中的每个下游结果均为 SUCCESS。出现任一 FAILURE 时,总控可能显示 UNSTABLE;这种情况视为部署失败。

8. 部署后验证

每次部署至少完成以下检查:

  1. Jenkins Job 已进入终态,记录构建号、结果、commit 和耗时。
  2. 后端总控部署记录全部下游 Job 名称、构建号和结果。
  3. 前端健康检查:
    • GET ${TEST_ADMIN_WEB_URL}/healthz
    • GET ${TEST_CLIENT_WEB_URL}/healthz
  4. 后端入口检查:GET ${TEST_GATEWAY_URL}/actuator/health 返回 HTTP 200。
  5. 执行与变更直接相关的真实 API 或浏览器流程。健康检查不能代替业务验收。
  6. 失败响应记录 HTTP 状态、业务错误码、requestId、traceId 和阻断原因。

不得因为 Jenkins 成功就宣称业务验收通过,也不得让测试失败回退为模拟成功。

9. 失败处理

  • 构建失败:读取失败阶段和控制台日志,定位第一个有效错误;修复并完成本地验证后,用新 commit 重新部署。
  • 下游服务失败:记录失败的服务 Job 和构建号,检查 Maven 测试、镜像构建、环境凭据及 Docker Compose 输出。
  • 部署成功但健康检查失败:检查对应 Job 的容器状态和末尾日志,不切换为本地后端。
  • 健康检查成功但业务失败:记录请求证据,核对数据库迁移、Nacos 配置、服务注册和真实接口契约。
  • 不得在未确认影响的情况下通过跳过测试、初始化数据库、清理工作区外数据或全量重启来“试一下”。

失败后不要自动回滚、删除容器或修改测试数据。需要这些动作时先向用户说明具体目标、影响和恢复方案并取得确认。

10. 交付记录

部署完成后,最终回复至少包含:

  • 部署的环境、Job 和服务范围。
  • 分支与 commit SHA。
  • Jenkins 构建号及最终结果。
  • 健康检查和直接业务验证结果。
  • 任何失败、跳过项、残余风险及 requestId/traceId。

不要在回复中输出密码、Token、Cookie、Jenkins Credential 内容或环境文件内容。