修复预览部署可选提交参数
修复 Checkout 阶段在严格 shell 下展开未定义 COMMIT_HASH 的失败 增加预览流水线参数归一化防回归门禁 同步预览部署参数合同与项目决策文档
This commit is contained in:
@@ -14161,3 +14161,9 @@
|
||||
- 实例与端口:分支规范化后形成稳定 `deploymentId`,同一分支换 commit 复用实例和 Web 端口;不同分支使用独立 Compose project。Web 端口在全局文件锁内从 `8400..8499` 分配,状态表与宿主监听同时空闲才可占用,卸载后释放。SpacetimeDB 与 OTLP 不映射宿主端口,Jenkins 通过受控 Compose 网络发布模块;页面只展示 Web 内网地址。
|
||||
- 来源与卸载:部署只接受 `SOURCE_BRANCH` 和可选 `COMMIT_HASH`,Jenkins 必须证明 commit 属于目标分支。卸载只接受受控状态中存在的 `deploymentId`,客户端不能传 Jenkins URL、Job、Compose project、容器名或端口。状态通过固定 `preview-result.json` artifact 返回,不解析或向浏览器暴露完整 console。
|
||||
- 关联文档:`docs/technical/【开发运维】Jenkins容器预览部署控制面技术方案-2026-08-15.md`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||
|
||||
## 2026-08-15 Jenkins 预览部署可选 commit 的跨 shell 参数合同
|
||||
|
||||
- 决策:`COMMIT_HASH` 在 Preview Deployer 全链路保持可选。控制服务正常请求显式传空字符串;Jenkins 流水线同时兼容首次参数未物化和旧构建重跑,在每个独立 `sh` 中使用 `${COMMIT_HASH:-}` 归一化,禁止依赖前一 shell 的局部变量。
|
||||
- `DEPLOY` 缺少 `SOURCE_BRANCH` 必须失败关闭;分支明确而 commit 为空时才表示选择该目标分支的远端最新提交,仍统一经过 `scripts/jenkins-checkout-source.sh`,不得改用控制器 `master`、忽略 commit 归属或关闭严格 shell。
|
||||
- 验证方式:`npm run check:preview-deployer` 必须拒绝 checkout 阶段的裸 `${COMMIT_HASH}`;现场重跑不带 commit 的 DEPLOY 后,流水线应通过 `Checkout Requested Source` 并在结果中记录目标分支解析出的 `resolvedCommit`。
|
||||
|
||||
@@ -56,6 +56,8 @@ SpacetimeDB 与 OTLP 不映射宿主端口;Jenkins 通过受控 Compose 网络
|
||||
|
||||
分支名只允许数字、字母、点、下划线、短横线和斜杠,不允许首尾斜杠或连续点号。Jenkins 必须复用 `scripts/jenkins-checkout-source.sh`,验证 commit 真实属于目标远端分支;SPA 和代理服务的输入校验不能代替流水线校验。
|
||||
|
||||
`COMMIT_HASH` 是真正可选的参数:控制服务应显式传空字符串,但 Jenkins 也必须兼容首次参数尚未物化、旧构建重跑等没有该环境变量的调用。每个独立 `sh` 步骤都要在 `set -u` 下用空值默认完成归一化,不能依赖前一个 `sh` 中的局部赋值。`DEPLOY` 缺少 `SOURCE_BRANCH` 必须在动态 checkout 前失败关闭;分支明确而 commit 为空时,仍由 `scripts/jenkins-checkout-source.sh` 解析为该目标分支的远端最新提交,不得回退到控制器 `master` 或跳过分支归属校验。
|
||||
|
||||
每次运行归档 `preview-result.json`,至少包含:
|
||||
|
||||
```json
|
||||
|
||||
@@ -52,6 +52,10 @@ pipeline {
|
||||
COMMIT_HASH="${COMMIT_HASH:-}"
|
||||
DEPLOYMENT_ID="${DEPLOYMENT_ID:-}"
|
||||
case "${ACTION}" in DEPLOY|STATUS|UNINSTALL) ;; *) exit 1 ;; esac
|
||||
if [ "${ACTION}" = 'DEPLOY' ] && [ -z "${SOURCE_BRANCH}" ]; then
|
||||
echo 'DEPLOY 必须提供 SOURCE_BRANCH。' >&2
|
||||
exit 1
|
||||
fi
|
||||
if [ -n "${SOURCE_BRANCH}" ]; then
|
||||
git check-ref-format --branch "${SOURCE_BRANCH}" >/dev/null
|
||||
fi
|
||||
@@ -93,9 +97,9 @@ pipeline {
|
||||
withCredentials([sshUserPrivateKey(credentialsId: env.GIT_REMOTE_CREDENTIAL_ID, keyFileVariable: 'GENARRATIVE_GIT_SSH_KEY')]) {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
SOURCE_BRANCH="${SOURCE_BRANCH}" \
|
||||
COMMIT_HASH="${COMMIT_HASH}" \
|
||||
GIT_REMOTE_URL="${GIT_REMOTE_URL}" \
|
||||
SOURCE_BRANCH="${SOURCE_BRANCH:-}" \
|
||||
COMMIT_HASH="${COMMIT_HASH:-}" \
|
||||
GIT_REMOTE_URL="${GIT_REMOTE_URL:-}" \
|
||||
SOURCE_COMMIT_FILE=".jenkins-source-commit" \
|
||||
GENARRATIVE_JENKINS_REUSE_EXISTING_CHECKOUT="true" \
|
||||
GIT_SSH_COMMAND="ssh -i ${GENARRATIVE_GIT_SSH_KEY} -o IdentitiesOnly=yes -o StrictHostKeyChecking=accept-new" \
|
||||
|
||||
@@ -55,6 +55,31 @@ assertIncludes(
|
||||
"string(name: 'DEPLOYMENT_ID'",
|
||||
'Jenkins 必须暴露 DEPLOYMENT_ID。',
|
||||
);
|
||||
assertIncludes(
|
||||
jenkinsfile,
|
||||
'SOURCE_BRANCH="${SOURCE_BRANCH:-}"',
|
||||
'Jenkins 目标源码 checkout 必须兼容旧构建缺少 SOURCE_BRANCH 环境变量。',
|
||||
);
|
||||
assertIncludes(
|
||||
jenkinsfile,
|
||||
'COMMIT_HASH="${COMMIT_HASH:-}"',
|
||||
'Jenkins 目标源码 checkout 必须兼容可选 COMMIT_HASH 未物化。',
|
||||
);
|
||||
assertIncludes(
|
||||
jenkinsfile,
|
||||
'GIT_REMOTE_URL="${GIT_REMOTE_URL:-}"',
|
||||
'Jenkins 目标源码 checkout 必须在严格 shell 下安全读取固定 Git 地址。',
|
||||
);
|
||||
assertExcludes(
|
||||
jenkinsfile,
|
||||
'COMMIT_HASH="${COMMIT_HASH}"',
|
||||
'Jenkins 不得在 set -u 下严格展开可选 COMMIT_HASH。',
|
||||
);
|
||||
assertIncludes(
|
||||
jenkinsfile,
|
||||
`if [ "${'${ACTION}'}" = 'DEPLOY' ] && [ -z "${'${SOURCE_BRANCH}'}" ]; then`,
|
||||
'Jenkins DEPLOY 缺少 SOURCE_BRANCH 时必须失败关闭。',
|
||||
);
|
||||
assertIncludes(
|
||||
jenkinsfile,
|
||||
"archiveArtifacts artifacts: 'preview-result.json'",
|
||||
|
||||
Reference in New Issue
Block a user