From 6b1dfc77d9e58c70d908a71ace4694dd60a7be0a Mon Sep 17 00:00:00 2001 From: kdletters Date: Sat, 8 Aug 2026 16:09:54 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8DJenkins=E8=B7=A8=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E4=BA=A7=E7=89=A9=E5=A4=8D=E5=88=B6=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 为Stdb、API、Web与数据库导出任务精确授权产物消费者 增加Copy Artifact Production模式权限静态门禁 补充跨任务产物复制排障与生效流程文档 --- docs/project-memory/shared-memory/pitfalls.md | 8 +++++++ ...发运维】本地开发验证与生产运维-2026-05-15.md | 2 ++ jenkins/Jenkinsfile.production-api-build | 1 + .../Jenkinsfile.production-database-export | 1 + .../Jenkinsfile.production-stdb-module-build | 1 + jenkins/Jenkinsfile.production-web-build | 1 + scripts/check-production-ops-guardrails.mjs | 22 +++++++++++++++++++ 7 files changed, 36 insertions(+) diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index 460565737..5de23e6b6 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -2300,6 +2300,14 @@ - 验证:deploy 工作区应直接出现 `build//web.tar.gz` 与 `web.tar.gz.sha256`;后续仍由 `scripts/deploy/production-web-deploy.sh` 执行 checksum 校验和解压 smoke。 - 关联:`jenkins/Jenkinsfile.production-web-deploy`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。 +## Copy Artifact Production 模式下来源 Job 必须显式授权 + +- 现象:Deploy / Publish / Import 在 `copyArtifacts` 立即报 `Unable to find project for artifact copy: `,但 Jenkins 中的来源 Job、指定构建号和归档产物都存在。 +- 原因:Copy Artifact 已启用推荐的 `Production` 模式,但产物生产者的 Jenkinsfile 没有 `copyArtifactPermission`;插件会把权限不足伪装成“找不到项目”。 +- 处理:在产物生产者的 Declarative Pipeline `options` 内精确授权固定消费者:Stdb Build 授权 Stdb Publish,API Build 授权 API Deploy,Web Build 授权 Web Deploy,Database Export 授权 Database Import。不使用 `*`,不通过全局 `Job/Read` 扩权,不把插件退回 Migration 模式规避。 +- 验证:运行 `npm run check:production-ops`;上线后先运行一次四个产物生产者中本次需要的 Job,确认 live `config.xml` 出现 `CopyArtifactPermissionProperty`,再重跑消费者。 +- 关联:`jenkins/Jenkinsfile.production-stdb-module-build`、`jenkins/Jenkinsfile.production-api-build`、`jenkins/Jenkinsfile.production-web-build`、`jenkins/Jenkinsfile.production-database-export`、`scripts/check-production-ops-guardrails.mjs`。 + ## Jenkins 生产流水线拉 Git 统一走本机 SSH - 后续更新:2026-07-14 起所有生产 Job 的 `Pipeline script from SCM` 和 Jenkinsfile 内部 checkout 统一使用本机 SSH 地址 `ssh://git@127.0.0.1:2222/GenarrativeAI/Genarrative.git` 与凭据 `genarrative-local-gitea-ssh`,不再保留局域网 IP、HTTP 内网地址或公网 fallback。 diff --git a/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md b/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md index 10e9b5a79..c94b27c14 100644 --- a/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md +++ b/docs/【开发运维】本地开发验证与生产运维-2026-05-15.md @@ -579,6 +579,8 @@ cat /var/lib/genarrative/health-patrol/status.json 如需接外部告警,可在 `/etc/genarrative/health-patrol.env` 配置 `GENARRATIVE_HEALTH_PATROL_WEBHOOK_URL`;脚本只会在 `WARNING` 或 `CRITICAL` 时向该 webhook 发送 JSON。未配置 webhook 时,告警来源是 systemd 失败状态、journal 和状态文件。 +Jenkins Copy Artifact 必须保持 `Production` 权限模式;产物生产者要在 Jenkinsfile 中用 `copyArtifactPermission` 精确授权消费者,不能依赖 Migration 模式或全局 `Job/Read`。固定映射为 `Genarrative-Stdb-Module-Build` → `Genarrative-Stdb-Module-Publish`、`Genarrative-Api-Build` → `Genarrative-Api-Deploy`、`Genarrative-Web-Build` → `Genarrative-Web-Deploy`、`Genarrative-Database-Export` → `Genarrative-Database-Import`。如果 `copyArtifacts` 报 `Unable to find project for artifact copy`,但来源 Job、指定构建号和归档都实际存在,先检查来源 Job 的 `CopyArtifactPermissionProperty`;修复 Jenkinsfile 后必须先运行一次产物生产者,让 Declarative Pipeline 把 Job property 写回 Jenkins,再重跑 Deploy / Publish / Import。`npm run check:production-ops` 会防止四条白名单再次丢失。 + `Genarrative-Web-Build` 的主站构建失败若出现 Rollup 报错 `"xxx" is not exported by "src/services/publicWorkCode.ts"`,优先按前端公开作品号工具缺失处理,而不是排查 Jenkins 节点环境。修复时要让 `publicWorkCode.ts` 的 `buildPublicWorkCode` 与 `isSamePublicWorkCode` 成对导出,并补 `src/services/publicWorkCode.test.ts` 覆盖对应玩法前缀;随后用 `npm run build:production-release -- --component web --name <临时名>` 复现 Jenkins web 构建路径。 `Genarrative-Web-Build` 会把 `build//web.tar.gz`、`web.tar.gz.sha256`、`release-manifest.json` 和 `scripts/deploy/production-web-deploy.sh` 直接归档为 Jenkins 构建产物;`Genarrative-Web-Deploy` 只通过 `copyArtifacts` 从指定上游构建复制这些产物和部署脚本,不再在目标机器 checkout Git,再执行随构建归档的 `scripts/deploy/production-web-deploy.sh`。Web 发布不再读取构建机本地缓存目录,也不再通过 release agent `rsync` 回构建机拉取大包;如果 deploy 找不到 `web.tar.gz`,应先检查上游 Web Build 是否按同一 `BUILD_VERSION` 成功归档产物。 diff --git a/jenkins/Jenkinsfile.production-api-build b/jenkins/Jenkinsfile.production-api-build index c3e8d7608..05849573c 100644 --- a/jenkins/Jenkinsfile.production-api-build +++ b/jenkins/Jenkinsfile.production-api-build @@ -7,6 +7,7 @@ pipeline { disableConcurrentBuilds() skipDefaultCheckout(true) buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20')) + copyArtifactPermission('Genarrative-Api-Deploy') } environment { diff --git a/jenkins/Jenkinsfile.production-database-export b/jenkins/Jenkinsfile.production-database-export index cf2574bd6..442ab0e83 100644 --- a/jenkins/Jenkinsfile.production-database-export +++ b/jenkins/Jenkinsfile.production-database-export @@ -5,6 +5,7 @@ pipeline { disableConcurrentBuilds() skipDefaultCheckout(true) buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20')) + copyArtifactPermission('Genarrative-Database-Import') } environment { diff --git a/jenkins/Jenkinsfile.production-stdb-module-build b/jenkins/Jenkinsfile.production-stdb-module-build index 6d748c4ef..c326c9cb7 100644 --- a/jenkins/Jenkinsfile.production-stdb-module-build +++ b/jenkins/Jenkinsfile.production-stdb-module-build @@ -7,6 +7,7 @@ pipeline { disableConcurrentBuilds() skipDefaultCheckout(true) buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20')) + copyArtifactPermission('Genarrative-Stdb-Module-Publish') } environment { diff --git a/jenkins/Jenkinsfile.production-web-build b/jenkins/Jenkinsfile.production-web-build index 9a543a9a6..200483d69 100644 --- a/jenkins/Jenkinsfile.production-web-build +++ b/jenkins/Jenkinsfile.production-web-build @@ -7,6 +7,7 @@ pipeline { disableConcurrentBuilds() skipDefaultCheckout(true) buildDiscarder(logRotator(numToKeepStr: '20', artifactNumToKeepStr: '20')) + copyArtifactPermission('Genarrative-Web-Deploy') } environment { diff --git a/scripts/check-production-ops-guardrails.mjs b/scripts/check-production-ops-guardrails.mjs index 5c85def1a..05b816928 100644 --- a/scripts/check-production-ops-guardrails.mjs +++ b/scripts/check-production-ops-guardrails.mjs @@ -23,6 +23,11 @@ const checks = [ includes: 'cargo check -p api-server --all-targets --manifest-path server-rs/Cargo.toml', reason: 'API 生产构建必须执行 api-server 全 target 编译检查。', }, + { + file: 'jenkins/Jenkinsfile.production-api-build', + includes: "copyArtifactPermission('Genarrative-Api-Deploy')", + reason: 'Copy Artifact Production 模式下,API Build 必须显式授权 API Deploy 读取归档。', + }, { file: 'jenkins/Jenkinsfile.production-stdb-module-build', includes: 'npm run check:rustfmt', @@ -38,6 +43,12 @@ const checks = [ includes: 'npm run check:admin-account-procedures', reason: 'Stdb module 生产构建必须执行管理员 procedure smoke。', }, + { + file: 'jenkins/Jenkinsfile.production-stdb-module-build', + includes: "copyArtifactPermission('Genarrative-Stdb-Module-Publish')", + reason: + 'Copy Artifact Production 模式下,Stdb Build 必须显式授权 Stdb Publish 读取归档。', + }, { file: 'jenkins/Jenkinsfile.production-web-build', includes: 'npm run check:production-ops', @@ -63,6 +74,17 @@ const checks = [ includes: 'npm run test', reason: 'Web 生产构建必须执行当前维护范围内的 Vitest。', }, + { + file: 'jenkins/Jenkinsfile.production-web-build', + includes: "copyArtifactPermission('Genarrative-Web-Deploy')", + reason: 'Copy Artifact Production 模式下,Web Build 必须显式授权 Web Deploy 读取归档。', + }, + { + file: 'jenkins/Jenkinsfile.production-database-export', + includes: "copyArtifactPermission('Genarrative-Database-Import')", + reason: + 'Copy Artifact Production 模式下,Database Export 必须显式授权 Database Import 读取归档。', + }, { file: 'server-rs/crates/spacetime-module/src/migration.rs', includes: