--- name: gitops-app-onboarding description: 面向当前 Baizhi GitOps 平台的项目接入工作流,只适用于 `deploy.baizhi.cloud`、`registry.baizhi.cloud`、GitLab + Argo CD 这套固定交付模型。只要用户提到“给当前平台接入新项目”“恢复 .gitlab-ci.yml / deploy 目录”“补齐当前平台的 Helm chart / release bundle”“修当前平台的发版链路”“让应用仓库在发版时推送自己的 release 结果”,就应优先使用这个 skill;如果只是通用 CI、通用 Helm 或通用 GitOps 任务而未指向当前平台,不应触发。 --- # GitOps 项目接入 Skill ## 目标 让 agent 能独立完成下面四件事: - 生成或修复 `.gitlab-ci.yml` - 生成或修复 `deploy/helm//` - 生成或修复 `deploy/release/` - 让发版链路把当前应用的发布结果同步到固定 GitOps 仓库 ## 平台固定常量 除非用户明确要求修改,否则固定使用: - GitOps 主机:`deploy.baizhi.cloud` - Registry 主机:`registry.baizhi.cloud` - Helm OCI 仓库:`oci://registry.baizhi.cloud/helm` - GitOps 仓库地址:`https://deploy.baizhi.cloud/gitops-admin/argodeploy.git` - Registry 用户名:`registry-ci` - 共享 pull secret:`registry-pull-secret` - GitOps 控制器:Argo CD - 代码托管:GitLab GitLab CI 默认依赖这些变量: - `GITEA_USER` - `GITEA_TOKEN` - `REGISTRY_PASSWORD` ## 开始前先做什么 先按这个顺序读仓库: 1. `README.md` 2. Dockerfile、包管理文件、构建脚本、已有 deploy 文件 3. 用户提供的额外设计文档 在动手前先确定: - 组件列表 - 每个组件的构建上下文与入口 - 对外暴露方式 - 运行时配置结构 - 平台共享依赖与应用私有依赖 - 是否检测到私有 Git 依赖(例如 `git.in.chaitin.net/ai/baizhiyun/opensdk`) 应用仓库自己的 `README.md` 是应用运行架构的真相来源;本 skill 只定义平台接入规则。 ## 边界 - 只处理应用仓库侧接入 - 不修改与当前应用无关的 GitOps 清单 - 对 GitOps 的唯一动作,是在应用仓库 CI 中同步当前应用自己的 release 结果与版本引用 - 如果当前应用的 `Application` 已存在,只允许更新 `apps//application.yaml` 中当前应用 chart source 的 `targetRevision` - 不修改 `AppProject`、bootstrap、其他应用的 `Application` ## 应用仓库必须产出哪些文件 ### CI - `.gitlab-ci.yml` ### Chart - `deploy/helm//Chart.yaml` - `deploy/helm//values.yaml` - `deploy/helm//templates/*` ### release 作者源 - `deploy/release/metadata.yaml` - `deploy/release/values.yaml` - `deploy/release/secret.yaml` ## GitOps 仓库里最终应该有哪些文件 CI 导出结果固定为: - `deploy/release/metadata.yaml` -> `releases//metadata.yaml` - `deploy/release/values.yaml` -> `releases//values.yaml` - `deploy/release/secret.yaml` -> `releases//manifests/secret.yaml` - `apps//application.yaml` -> 只更新 chart source 的 `targetRevision` 固定规则: - 不导出 `releases//secret.yaml` - 不生成或覆盖 `db-secret.yaml`、 `kustomization.yaml` 这类 GitOps 仓库里已有的文件 ## GitLab CI 规则 ### 私有 Git 依赖判定口径 下文中的“检测到私有 Git 依赖”统一指:仓库在 `go.mod`、`go.sum`、源码 import、构建脚本或 Dockerfile 构建流程中,实际引用了需要认证访问的私有 Git 仓库(例如 `git.in.chaitin.net/ai/baizhiyun/opensdk`)。 只有在检测到这类依赖时,才启用 `.netrc`、私有仓库认证,以及 `GOPRIVATE`、`GONOSUMDB`、`GONOPROXY`、`GOINSECURE`、`GIT_SSL_NO_VERIFY` 这一组私有 Go 变量;否则不要添加这些配置。 ### stages 固定使用: - `test` - `build` - `release` ### runner tags 只要 job 使用 Docker、DinD 或 `docker buildx`,就必须带: - `docker` - `network` ### test job 用途:只做测试,不改 GitOps,不推镜像。 要求: - 运行在分支和 MR 上 - 安装当前语言栈的最小依赖 - 只有检测到私有 Git 依赖时才补齐认证;否则不要引入 `.netrc` - 使用项目原生测试入口 Go 项目默认变量写在 `.gitlab-ci.yml` 的 `variables:`: - `GOPROXY=https://goproxy.cn,direct` - `GOSUMDB=sum.golang.google.cn` 只有检测到私有 Git 依赖时,才额外设置这些变量: - `GOPRIVATE=git.in.chaitin.net` - `GONOSUMDB=git.in.chaitin.net` - `GONOPROXY=git.in.chaitin.net` - `GOINSECURE=git.in.chaitin.net` - `GIT_SSL_NO_VERIFY="true"` ### release 触发条件 只在 `vX.Y.Z` tag 上触发发布链路。 ### build-images job 输入:源码、Dockerfile、多组件构建上下文。 输出:推送到 `registry.baizhi.cloud//:` 的运行时镜像。 要求: - 登录 `registry.baizhi.cloud` - 优先使用 `docker buildx` - 只有检测到私有 Git 依赖时,才通过 `.netrc` 和 build secret 传入;否则不要生成 `.netrc` 相关步骤 - 如需额外 CA,也通过 build secret 传入 - 如果 Dockerfile 中使用 Docker Hub 源作为 `FROM` 基础镜像或其他拉取来源,需改写为 `registry-mirrors.dev.in.chaitin.net` 对应镜像源;不要保留对 Docker Hub 的直接拉取 - 如果 Dockerfile 中使用 `apk`,需要将 apk 软件源切换为中科大源后再安装依赖 - 如果 Dockerfile 内会执行 `go mod download`、`go build` 等 Go 构建命令,必须通过 `--build-arg` 透传 Go 构建变量,不要只写在 `.gitlab-ci.yml` 的 `variables:` 里 - 无论是否检测到私有 Git 依赖,至少透传:`GOPROXY`、`GOSUMDB` - 只有检测到私有 Git 依赖时,才额外透传:`GOPRIVATE`、`GONOSUMDB`、`GONOPROXY`、`GOINSECURE` - Dockerfile 中对应变量必须有 `ARG`,并让构建命令实际使用传入值,而不是退回默认值 禁止: - `http://registry...` - `--plain-http` - `--insecure-skip-tls-verify` - 不要假设 `.gitlab-ci.yml` 中的环境变量会自动进入 `docker build` / `docker buildx build` ### package-chart job 输入:`deploy/helm//Chart.yaml`、`deploy/helm//values.yaml`、`deploy/helm//templates/*` 输出:推送到 `oci://registry.baizhi.cloud/helm` 的 Chart 包。 要求: - `helm registry login registry.baizhi.cloud` - 在临时目录复制 `deploy/helm//` - 把复制品中的 `version` 和 `appVersion` 改成 tag 版本 - `helm package` - `helm push` ### update-gitops-repo job 输入:`deploy/release/*`、当前 tag 版本、GitOps 仓库中的 `apps//application.yaml` 输出: - `releases//metadata.yaml` - `releases//values.yaml` - `releases//manifests/` 下的发布结果 - `apps//application.yaml` 中当前应用 chart source 的 `targetRevision` 处理顺序固定为: 1. 克隆 `https://${GITEA_USER}:${GITEA_TOKEN}@deploy.baizhi.cloud/gitops-admin/argodeploy.git` 2. 确保 `releases//` 与 `releases//manifests/` 存在,不要整体清空目录 3. 将应用仓库中的 `deploy/release/metadata.yaml` 和 `deploy/release/values.yaml` 复制到 GitOps 仓库的 `releases//metadata.yaml` 与 `releases//values.yaml`,覆盖已有内容 4. 保留已有的 `releases//manifests/kustomization.yaml` 与 `releases//manifests/db-secret.yaml` 5. 将 `deploy/release/secret.yaml` 物化为 `releases//manifests/secret.yaml` 6. 替换 `releases//metadata.yaml` 和 `releases//values.yaml` 中的 `__VERSION__` 7. 更新 `apps//application.yaml` 中当前应用 chart source 的 `targetRevision` 8. 只有存在 diff 时才提交并推送 `main` 禁止: - 在 CI 中调用 `kubectl` - 在 CI 中调用 `argocd app sync` - 把 hard refresh 当常规发布步骤 ## Helm Chart 规则 Chart 必须反映应用的真实运行架构。 固定要求: - 按职责拆文件,不堆一个大模板 - 模板中不硬编码生产 tag - 所有镜像名从 values 读取 - 所有 Service 暴露方式从 values 读取 - nginx 对外 Service 固定使用 `NodePort` - 后端 Service 只做集群内访问 - 不生成 Ingress 模板,也不保留 Ingress values - `NodePort` 必须来自用户或平台已分配值,不能猜 - 设置 `enableServiceLinks: false` - 支持 `imagePullSecrets` - 环境变量注入保持可读 - 如果镜像内带 nginx / 反向代理配置,upstream service 名必须与 Chart 渲染出的 Service 名一致 - 生成 chart 时要确认应用是否包含需要经 nginx 转发的静态文件;如果有,必须明确静态资源目录、挂载方式和 nginx 路由,不要只配后端 upstream - 不要依赖 Kubernetes 不支持的 `$(OTHER_ENV)` 展开 - 对 Neo4j 这类镜像,不要注入不存在的 `NEO4J_*` 配置名,例如 `NEO4J_PASSWORD` 如果应用依赖平台 shared 之外的私有服务,必须明确表达依赖来源: - 要么由 Chart 生成应用自带资源 - 要么明确引用用户提供的外部地址 不能只留一个指向不存在服务的 host。 如果应用自带依赖同时需要业务连接口令和依赖自身启动口令,Secret key 要同时表达两种消费方式,例如: - `neo4j_password` - `neo4j_auth` ## 对外暴露模型 固定使用: - nginx 作为统一入口 - 对外只暴露一个 nginx `NodePort` - 后端服务只在集群内通信 - 不生成 Ingress `NodePort` 处理规则: - 用户或文档已提供时直接使用 - 没提供时,在生成到这一项时立即索取 - 不要写示例端口或默认端口 ## Release Bundle 规则 ### `metadata.yaml` 至少包含: - 应用名 - release 名 - namespace - chart 名 - chart 版本 - chart 仓库 - 镜像 tag - 源码仓库地址 ### `values.yaml` 必须是可部署默认值,不是示例值。 至少满足: - 应用自建镜像使用 `registry.baizhi.cloud//...` - 第三方镜像保持真实来源 - Secret 名与 Chart 约定一致 - PostgreSQL 连接读取应用自己的 `databaseSecret` - 私有镜像包含 `imagePullSecrets` - 与 Chart schema 一致 - nginx 对外入口使用 `NodePort` - `NodePort` 值来自用户或平台分配结果 - 不包含 Ingress 配置项 ### `manifests/db-secret.yaml` 这是 deploy 仓库注册应用阶段生成的数据库源,secret 名称格式为 `-db` 不是应用仓库侧要生成的文件。至少包含: - `host` - `port` - `database` - `username` - `password` 固定规则: - chart 如果依赖 Postgres 则必须消费这个 secret ### `secret.yaml` 只放应用私有 Secret,key 名必须与 Chart 读取的 key 对齐。 规则: - 不伪造生产值 - 外部集成凭据在生成到对应配置时逐项索取 - 应用自带私有依赖的内部口令优先自动生成 - 组合型鉴权字段优先直接写成完整 key 值 - 缺值时停在当前项继续问,不要留看似可部署的假配置 ## 平台共享配置契约 `shared/` 只放平台级共享配置。 共享资源: - `platform-runtime-config` - `platform-shared-secrets` - `registry-pull-secret` `platform-runtime-config` 提供: - `LLM_BASE_URL` - `EMBEDDER_BASE_URL` - `OSS_BUCKET` `platform-shared-secrets` 提供: - `REDIS_PASSWORD` - `QDRANT_API_KEY` - `OSS_ACCESS_KEY` - `OSS_SECRET_KEY` 平台共享基础设施固定为: - `PostgreSQL` - `Redis` - `Qdrant` - `OSS` 固定 FQDN 与对象存储约定: - `redis.infra.svc.cluster.local` - `qdrant.infra.svc.cluster.local` 固定规则: - 不要写成当前应用 namespace 下的裸服务名 - 不默认为 `Redis`、`Qdrant`、`OSS` 生成应用私有实例 - 如果应用当前使用的是 `MinIO` / S3 兼容配置,优先沿用现有对象存储配置结构接入平台对象存储;但不要默认假设 `MinIO` 客户端可直接连接平台 `OSS`,需根据仓库实际使用的 SDK 与平台提供的协议兼容性确认 - `Neo4j` 不属于 shared;如应用需要,由应用自己部署 - 不要把应用私有鉴权材料放进 `shared/` - 如果 Chart 依赖的运行时资源不是由 Chart 直接创建,就必须确保 `releases//manifests/` 仍会把这些资源 apply 到目标 namespace ## 百智云用户鉴权接入 只有在检测到私有 Git 依赖,且该依赖就是 `git.in.chaitin.net/ai/baizhiyun/opensdk` 时才需要接入。 识别规则: - 先按上文“私有 Git 依赖判定口径”检查仓库,再确认私有依赖中是否实际包含 `git.in.chaitin.net/ai/baizhiyun/opensdk` - 只有确认包含这个依赖或导入时,才进入本节并索取百智云相关材料 - 如果仓库里没有这个包,就跳过整段,不要要求接入百智云,也不要生成对应配置 固定规则: - 不要把鉴权材料放进 `shared/` - 不要伪造生产值 - 按固定顺序逐项索取:`app_id` -> `app.crt` -> `app.key` -> `ca.crt` -> `public.key` - 缺少哪一项,就停在那一项继续问 挂载规则: - 固定挂载目录:`/app/ssl` - 固定文件路径:`/app/ssl/app.crt`、`/app/ssl/app.key`、`/app/ssl/ca.crt` - 不要改成其他自定义目录 - `public.key` 如果保留,应明确其用途,不要混同为 mTLS 必需文件 ## 提问方式 - 只问当前步骤真正阻塞的值 - 逐项问,不要一次性要一大串 - 对外部集成字段,在写到对应配置时就问 - 对应用自带私有依赖内部口令,优先自动生成 - 如果当前正在等补值,回复重点只放当前这一项 ## 执行顺序 按下面顺序推进: 1. 读 README 与构建文件 2. 梳理组件、依赖、暴露模型 3. 生成或修复 `.gitlab-ci.yml` 4. 生成或修复 Chart 5. 缺少必填值时停在当前项索取 6. 生成或修复 `deploy/release/` 7. 自检并汇报风险点 ## 自检 完成后尽量执行: - `git status --short` - `git diff --check` - `helm template`(前提是 Chart 与 values 已能渲染) 至少确认: - 接入文件齐全 - `.gitlab-ci.yml` 包含 test、镜像构建、Chart 发布、GitOps 同步 - release values 指向 `registry.baizhi.cloud` - 第三方镜像没有被错误改写到平台 registry - 如果 Dockerfile 原本使用 Docker Hub 源,已切换到 `registry-mirrors.dev.in.chaitin.net`,且未误改其他非 Docker Hub 镜像源 - 如果 Dockerfile 中使用 `apk`,已切换到中科大源 - GitOps update job 指向 `https://deploy.baizhi.cloud/gitops-admin/argodeploy.git` - CI 中没有直接调用 Argo - 只使用 `deploy.baizhi.cloud` 与 `registry.baizhi.cloud` - 没有使用不安全的 registry 访问方式 - 如果 `Application` 仍引用 `releases//manifests/`,该 path 在发布结果中实际存在 - 如果镜像内包含固定 upstream 配置,upstream service 名与 Chart 渲染结果一致 - Neo4j 一类自带依赖的启动环境变量不依赖 `$(OTHER_ENV)` 展开 - 如果检测到的私有 Git 依赖中包含 `git.in.chaitin.net/ai/baizhiyun/opensdk`,缺少必填百智云私有配置时交互停在当前项继续索取 ## 最终输出 默认按这个顺序汇报: 1. 修改了哪些文件 2. 关键决定 3. 最值得人工复核的点 ## 常见错误 - 把应用私有鉴权材料放进 `shared/` - 在 CI 里直接刷新 Argo - 重新引入旧域名 - 使用 insecure registry 参数 - Chart 与应用真实组件不匹配 - 在生产 release values 中写示例地址 - 擅自发明新的公网 host - 在未检测到私有 Git 依赖中的 `git.in.chaitin.net/ai/baizhiyun/opensdk` 时仍强行接入百智云 - Dockerfile 明明使用了 Docker Hub / `apk` 默认源,却没有切到 `registry-mirrors.dev.in.chaitin.net` / 中科大源,或误改了原本不在 Docker Hub 的镜像源 - 用户未提供必填值时伪造占位内容