agent-skills/gitops-app-onboarding/SKILL.md
2026-03-31 16:18:47 +08:00

420 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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
这个 skill 是 Baizhi GitOps 平台的接入入口与执行摘要。
执行不应依赖用户重复解释平台规则;按本 skill 与当前仓库约定直接推进即可。
目标是让 agent 能独立完成以下工作:
- 为应用仓库补齐或恢复 `.gitlab-ci.yml`
- 生成或修复 `deploy/helm/<app>/` Chart
- 生成或修复 `deploy/release/` release bundle
- 在发版链路中将当前应用自己的 release 结果推送到固定 GitOps 仓库
## 平台固定常量
除非用户明确要求修改,否则默认使用以下常量:
- GitOps 仓库主机:`deploy.baizhi.cloud`
- OCI Registry 主机:`registry.baizhi.cloud`
- Helm OCI 仓库:`oci://registry.baizhi.cloud/helm`
- GitOps 仓库克隆地址:`https://deploy.baizhi.cloud/gitops-admin/argodeploy.git`
- Registry 用户名:`registry-ci`
- 共享镜像拉取 Secret`registry-pull-secret`
- GitOps 控制器Argo CD
- Chart 分发方式OCI Registry
- 源代码托管GitLab
应用仓库 CI 默认依赖以下 GitLab 变量:
- `GITEA_USER`
- `GITEA_TOKEN`
- `REGISTRY_PASSWORD`
通常直接把 `REGISTRY_USER` 写成 `registry-ci`
## 真相来源与读取顺序
开始改代码前,按下面顺序建立上下文:
1. 先读目标应用仓库 `README.md`
2. 再读 Dockerfile、包管理文件、构建脚本、现有 deploy 文件
3. 如果用户给了额外设计文档,一并读取
判断规则:
- 目标应用仓库自己的 `README.md` 是应用运行架构的真相来源
- 本 skill 定义平台接入流程、约束和执行重点
- 如果应用 README 与平台约定冲突,优先识别是“应用设计差异”还是“平台硬约束”
- 如果冲突会直接改变最终实现且无法安全推断,再问用户;否则优先按已有代码和文档做最小偏差实现
在生成任何文件前,先推断出:
- 组件列表
- 每个组件的构建上下文
- 容器入口
- 对外暴露模型
- 运行时配置结构
- 哪些依赖属于平台共享,哪些是应用私有
不要假设每个项目都长得和现有项目一样。
## 先判断修改范围
先区分任务属于哪一种:
1. 补齐或修复应用仓库中的 CI、Chart、release 模板
2. 修复应用仓库中的发版链路,使其在发版时推送当前应用自己的 release 结果
边界约束:
- 本 skill 只处理应用仓库侧接入
- 不读取、不判断、不修改 GitOps 仓库中的 `Application`、`AppProject` 或其他发布侧清单
- 对 GitOps 的唯一动作,是在应用仓库 CI 中推送当前应用自己的 release 结果或版本引用
## 交付模型
平台采用两个仓库协同交付:
- 应用仓库负责源码、Docker 构建、`.gitlab-ci.yml`、Helm Chart 源码、release bundle 模板
- 当前 GitOps 仓库负责 Argo CD `Application`、`AppProject`、平台 bootstrap、已发布 release bundle、共享配置
标准发布流程:
1. 分支或 MR 只跑测试
2.`vX.Y.Z` tag 后构建并推送镜像
3.`vX.Y.Z` tag 后打包并推送 Helm Chart
4.`vX.Y.Z` tag 后更新当前 GitOps 仓库中该应用的版本引用
5. 推送当前 GitOps 仓库提交
6. Argo CD 感知当前 GitOps 仓库变更后自动同步
关键约束:
- CI 不能直接调用 `kubectl`
- CI 不能调用 `argocd app sync`
- CI 不能把 hard refresh 当常规步骤
- 当前 GitOps 仓库的提交才是 Argo 的同步信号
如果线上故障需要 hard refresh那是运维例外不属于通用模板。
## 应用仓库通常需要生成什么
通常需要创建或修复:
- `.gitlab-ci.yml`
- `deploy/helm/<app-name>/Chart.yaml`
- `deploy/helm/<app-name>/values.yaml`
- `deploy/helm/<app-name>/templates/*`
- `deploy/release/metadata.yaml`
- `deploy/release/values.yaml`
- `deploy/release/secret.yaml`
如果应用还有不适合放进 Chart 的静态清单,可以在后续发布结果中导出到当前 GitOps 仓库的 `releases/<app>/manifests/`
## GitLab CI 规则
### stages
使用这三个 stage
- `test`
- `build`
- `release`
### test job
test job 应运行在分支和 MR 上,并执行目标项目自己的标准测试命令。
要求:
- 安装该语言栈所需的最小依赖
- 如果依赖私有代码仓库,补齐认证
- 使用项目本身的标准测试入口,不要擅自发明新的测试命令
示例:
- Go`go mod download`、`go test ./...`
- Node`npm ci`、`npm test`
### release 触发条件
发布链路只应在 `vX.Y.Z` 这种语义化 tag 上触发。
### build-images job
这个 job 必须:
- 登录 `registry.baizhi.cloud`
- 构建项目所有需要发布的运行时镜像
- 将镜像推送到 `registry.baizhi.cloud/<app-name>/<component>:<version>`
如果仓库已经使用 BuildKit 或多构建上下文,优先使用 `docker buildx`
如果镜像构建依赖私有 Git 仓库:
- 用 CI 凭据生成 `.netrc`
- 通过 Docker build secret 传入
- 如需额外 CA 证书,也通过 build secret 传入
- 不要通过全局关闭 TLS 校验规避问题
不要使用:
- `http://registry...`
- `--plain-http`
- `--insecure-skip-tls-verify`
### package-chart job
这个 job 必须:
- 执行 `helm registry login registry.baizhi.cloud`
- 将 Chart 的 `version``appVersion` 更新为 tag 去掉前缀 `v` 后的版本号
- 执行 `helm package`
- 推送到 `oci://registry.baizhi.cloud/helm`
### update-gitops-repo job
这个 job 必须:
- 克隆 `https://${GITEA_USER}:${GITEA_TOKEN}@deploy.baizhi.cloud/gitops-admin/argodeploy.git`
- 只同步当前应用自己的 release 结果或版本引用
- 提交并推送到 `main`
通常需要更新:
- `releases/<app-name>/values.yaml`
- `releases/<app-name>/metadata.yaml`
- `releases/<app-name>/manifests/` 下由当前应用导出的发布结果
不要在这个 job 中加入集群部署逻辑。
## Helm Chart 规则
Chart 必须反映应用的真实运行架构。
推荐结构:
```text
deploy/helm/<app-name>/
├── Chart.yaml
├── values.yaml
└── templates/
├── _helpers.tpl
├── deployment-<component>.yaml
├── service-<component>.yaml 或 services.yaml
└── 按职责拆分的其他资源
```
规则:
- 按职责拆文件,不要堆成一个巨大模板
- 模板中不要硬编码生产镜像 tag
- 所有镜像名都从 values 读取
- 所有 Service 暴露方式都从 values 读取
- nginx 对外 Service 固定使用 `NodePort`
- 后端 Service 默认使用集群内访问类型,不对外暴露 `NodePort`
- 如果应用运行时依赖某个不属于平台 shared 的私有服务Chart / release bundle 必须把该依赖的来源表达清楚:要么生成应用自带资源,要么明确引用用户已提供的外部地址;不要只留下一个指向不存在服务的 host
- `NodePort` 必须来自用户或平台已分配值agent 不得自行猜测或默认分配端口
- 不要生成 Ingress 模板或 Ingress values
- 设置 `enableServiceLinks: false`
- 支持 `imagePullSecrets`
- 环境变量注入保持可读
- 健康检查要符合真实应用行为
`_helpers.tpl` 一般至少提供:
- chart name
- fullname
- namespace
- labels
- selector labels
只有当项目本身确实有 path 推导的 URL 时,才增加 URL helper。
## 对外暴露模型
对外暴露模型使用固定方式,不再按项目自由选择。
- 固定使用 nginx 作为统一入口,代理前端与后端路径
- 对外只暴露 nginx 入口,并通过 `NodePort` 提供入口访问
- 后端服务默认只在集群内通信
- 每个应用对外只保留一个 nginx `NodePort` 入口
- 不生成 Ingress 资源,也不要在 values 中保留 Ingress 开关
- 不要因为应用有多个内部服务,就擅自发明多个公网 host
如果项目当前没有现成的前端代理层,也应按这个固定模型为对外入口预留 nginx 代理方案,而不是改成 Ingress。
`NodePort` 处理规则:
- 如果用户或项目文档已经提供了分配好的 `NodePort`,直接使用
- 如果没有提供,先完成所有非阻塞工作,最后只问用户一个最小必要问题来索取该端口
- 不要擅自写入示例端口或看起来顺手的默认值,例如 `30080`、`30081`
- 如果用户暂时没有提供,最终输出中必须明确说明 nginx 对外 `NodePort` 尚未分配,因此外部访问配置未完成
## Release Bundle 规则
应用仓库中的 `deploy/release/` 是导出给当前 GitOps 仓库的标准模板。
### `metadata.yaml`
至少应包含:
- 应用名
- Kubernetes release 名
- namespace
- chart 名
- chart 版本
- chart 仓库
- 镜像 tag
- 源码仓库地址
### `values.yaml`
必须是可用于部署的默认值,而不是示例值。
至少应满足:
- 镜像地址指向 `registry.baizhi.cloud/<app-name>/...`
- Secret 名符合平台约定
- 私有镜像拉取时包含 `imagePullSecrets`
- 与 Chart schema 保持一致
- nginx 对外入口使用 `NodePort`
- `NodePort` 值来自用户或平台已分配结果,而不是模板内置默认值
- 不包含 Ingress 配置项
### `secret.yaml`
用于放应用私有 Secret 模板key 名必须与 Chart 读取的 key 对齐。
规则:
- 不要为了“看起来完整”而伪造假的生产值
- 先区分“外部集成凭据”和“应用自带私有依赖的内部口令”
- 如果是外部集成凭据,应在完成所有非阻塞工作后主动向用户索取,而不是只在最后留警告
- 如果是应用自带私有依赖的内部口令,优先由生成流程一次性生成并写入 release secret而不是要求用户手填
- 如果用户暂时没有提供,不要造占位内容冒充可部署配置
- 对部署阻塞项,按最小必要粒度逐项提问,优先直接问“这一项应填什么”
- 只有当用户明确暂不提供、或本轮对话结束时仍未补齐,才在最终输出中保留缺失项警告
- 可以只保留结构,或暂不生成具体 secret 内容,但必须在最终输出中明确警告缺失项与影响
release bundle 只负责导出当前应用自己的发布结果,不负责维护 GitOps 仓库中的其他对象。
## 平台共享配置契约
`shared/` 目录只放平台级共享配置。
共享资源:
- `platform-runtime-config`
- `platform-shared-secrets`
- `registry-pull-secret`
当前 `platform-runtime-config` 提供:
- `LLM_BASE_URL`
- `EMBEDDER_BASE_URL`
当前 `platform-shared-secrets` 提供:
- `POSTGRES_USER`
- `POSTGRES_PASSWORD`
- `REDIS_PASSWORD`
- `QDRANT_API_KEY`
- `MINIO_ACCESS_KEY`
- `MINIO_SECRET_KEY`
shared 边界:
- shared 只负责共享基础设施和通用运行时地址
- `Neo4j` 不再作为平台共享基础设施提供;如应用需要图数据库,应由应用自己部署和维护
- 只要应用运行时配置仍引用某个应用私有依赖,就应在应用 Chart / release bundle 中把它一并表达出来,而不是只在 values 里保留连接参数
- 不要把某个厂商的客户端证书、私钥、应用专属 `app_id`、tenant id、client id、namespace id、应用独有 webhook 签名密钥放进 `shared/`
- 镜像拉取默认使用 `registry-pull-secret`,不要随便为每个应用再造一个 pull secret除非平台模型发生变化
## 百智云用户鉴权接入
平台接入要求百智云用户鉴权。
处理规则:
- 不要把这类鉴权材料当成平台共享配置
- 不要擅自生成生产值
- 先完成所有非阻塞工作
- `env` 与鉴权材料均为必填项
- 鉴权材料按固定顺序向用户索取:`app_id` -> `app.crt` -> `app.key` -> `ca.crt` -> `public.key`
- 如果用户还没提供完整值,不要写伪造占位内容;在最终输出中明确警告缺失了哪些字段以及可能影响
提问方式要求:
- 只在真正阻塞最终可部署结果时才问
- 先做完不依赖这些值的工作
- 按必填项收集百智云配置
- 先索取 `env`,再按固定顺序逐项索取 `app_id`、`app.crt`、`app.key`、`ca.crt`、`public.key`
- 对外部集成字段,应在非阻塞工作完成后逐项索取,而不是直接跳到最终缺失项警告
- 对应用自带私有依赖内部口令,优先自动生成;只有用户明确要求自定义时才向用户索取
- 不要用“把需要的都给我”这种模糊问法
- 缺少任一必填项时,要明确指出当前卡在哪一项
## 执行流程
建议按下面顺序推进:
1. 读取应用 README 与构建文件,梳理组件和暴露模型
2. 判断任务是补齐应用仓库接入,还是修复发版链路
3. 生成或修复 `.gitlab-ci.yml`
4. 生成或修复 Chart 与 values
5. 生成或修复 release bundle
6. 完成非阻塞工作后,再逐项补齐百智云必填字段
7. 自检并在最终输出中说明风险点
## 自检要求
完成后尽量执行:
- `git status --short`
- `git diff --check`
- `helm template`,前提是 Chart 与 values 已能渲染
至少确认:
- 应用仓库不再缺少接入文件
- `.gitlab-ci.yml` 包含 test、镜像构建、chart 发布、release 结果同步逻辑
- release values 指向 `registry.baizhi.cloud`
- GitOps 仓库更新 job 指向 `https://deploy.baizhi.cloud/gitops-admin/argodeploy.git`
- CI 中没有直接调用 Argo
- 没有继续使用旧域名
- 没有继续使用不安全的 HTTP registry 访问方式
- 如果存在用户未提供的必填私有配置,最终输出中已明确列出缺失项和潜在影响
## 最终输出要求
默认按下面结构汇报:
1. 修改了哪些文件
2. 关键设计决策
3. 最值得人工复核的 3 个点
如果存在用户未提供的必填私有配置,额外增加“缺失项警告”,明确列出:
- 缺少哪些字段
- 因此哪些配置尚未完成
- 不补齐会影响什么例如无法直接部署、某功能未启用、secret 仍为空
## 常见错误
以下都属于接入错误:
- 把应用私有鉴权材料放进 `shared/`
- 在 CI 里直接刷新 Argo
- 重新引入已废弃的旧域名
- 在 HTTPS 已恢复后仍使用 insecure registry 参数
- 生成的 Chart 与应用真实组件不匹配
- 在生产 release values 中写 `registry.example.com` 这类示例地址
- 应用没有这个设计却擅自发明新的公网 host
- 在用户没有提供必填私有值时,仍然伪造占位内容并假装可以直接部署