Files
skills/skills/gitea-actions/SKILL.md
T

17 KiB
Raw Blame History

name, description
name description
gitea-actions 按统一规范给项目生成或评审优化 Gitea Actions 构建部署工作流(.gitea/workflows/docker-deploy.yaml):推 v 开头 tag 触发 → buildx 构建推 Gitea Packages → 本机 docker 重建容器 → 清理本机与注册表旧版本;零第三方 action、INNEV_ 前缀变量/密钥、凭证回退链、基础镜像强制网络检测选址(内网 livebook:8418 / 外网 code.innev.cn),FROM 未命中 {registry}/images 时自动拉官方源推送落盘后再改写。不带任何输入调用本 skill = 审查当前项目 CI/CD 是否符合本规范。凡用户要求「给项目加构建工作流 / 加个 CI / 配发版流水线 / 加 Gitea Actions / 生成 docker-deploy.yaml / 打 tag 自动构建部署 / 这个项目怎么自动发版 / 看看这个 workflow 规范不规范 / 帮我评审一下这个流水线」,或出现 推了 tag Actions 没动静 / workflow 不触发 / push 镜像 denied / unauthorized / 健康检查超时 / 拉基础镜像超时 等症状,或提到 .gitea/workflows / workflow_dispatch / buildx / Gitea Packages / self-hosted runner / INNEV_ 变量 时,务必使用本 skill——即使用户没说「Gitea Actions」这几个字。Use whenever the user wants to add, review, or standardize a Gitea Actions build/deploy workflow for a project. 边界:写/改 Dockerfile 用 runtime-image;提交推送代码+写日报用 push-and-report;手工推镜像发版用 xgent-image-push。

gitea-actions — 按统一规范给项目装构建部署工作流

把实战中固化下来的 docker-deploy 流水线规范安装到任意项目。核心理念(推理链,所有约束都挂在这上面):

  • 版本号即镜像 tag:发布 = 打 v 开头 git tag,镜像 tag 与之一一对应,可回溯;推 main 不发版
  • runner 与部署目标同机:self-hosted 实例级 runner 直连宿主 docker,构建完即本机部署
  • 零外部依赖:不用任何第三方 action,run 步骤直连 git/docker,内网 runner 无需访问 github.com
  • 基础镜像内网落盘:FROM 命中 {registry}/images 直接改写为内部引用;未命中则由流水线把官方源镜像拉下来、推送进 images 命名空间后再改写——新基础镜像一次构建即落盘,后续构建全部内网命中、越构建越快。拉取/推送失败回退官方源不硬失败;拉取前强制网络检测选址——内网 livebook:8418、外网 code.innev.cn,写死任一地址换网络环境必挂;改写只落在 CI 克隆副本,仓库 Dockerfile 保持任意网络可构建

默认流程(不带任何附加提示词也照此执行)

用户不带任何附加输入调用本 skill = 审查当前项目 CI/CD 是否符合本规范:走评审优化模式的只读审计——已有 workflow 逐条对照审计清单;连 .gitea/workflows/ 都没有则如实报告"未配置 CI/CD"并给出新建建议,不默认动手生成。

带明确意图输入(如"加个 CI""生成 workflow")时,检测项目是否存在 .gitea/workflows/ 下的工作流文件(yml/yaml),自动分流:

  • 不存在 → 新建模式:按规范从零生成 docker-deploy.yaml
  • 已存在 → 评审优化模式:对照规范逐条审计,差异摊开,用户确认后按规范改写优化(默认不直接覆盖)

总流程

第 0 步 探测项目(绝不可跳过)→ 第 1 步 槽位定参 → 第 2 步 生成/改写(确认闸)
→ 第 3 步 验证 → 第 4 步 汇报

除非用户明确只要聊聊思路,完整走全部 5 步。

第 0 步:探测项目(绝不可跳过)

不许凭用户一句话生成——读项目文件坐实,缺料就停下来问,不猜、不翻别的项目抄。

探测项 怎么探 判定/用途
已有 workflow(最先做,决定模式) glob .gitea/workflows/*.yml、.yaml 有 → 评审优化模式;无 → 新建模式
项目名 git remote basename → package.json name → 目录名,用户确认 {{PROJECT}}:镜像名/容器名/builder 名
Dockerfile glob 项目内 Dockerfile* 无 → die:先走 runtime-image 生成 Dockerfile——流水线对着空气构建无意义
启动模型 读 Dockerfile 的 FROM runtime-node 系(容器启动时 install+build)→ 健康检查窗口放宽 ~7.5 分钟;预构建产物 → 窗口可缩短
端口 Dockerfile EXPOSE / 项目配置 / 问用户 {{APP_PORT}} 容器内端口 + {{HOST_PORT}} 对外端口默认值
健康检查端点 grep 代码里 /health、/healthz、/api/health 等路由 有 → {{HEALTH_PATH}};无 → warn:不虚构,生成时整块省略健康检查步,汇报大字声明
必需 .env key 读 .env.example 渲染 deploy 步的 env key 检查行;无 .env.example → 整块省略
特殊预构建 问用户(如从源码构建工具二进制) 对应模板 [OPTIONAL:PRE_BUILD] 块,插入"构建并推送镜像"步之前
额外运行参数 读 Dockerfile/运行时要求(如 runtime-node 的 APP_ENTRY)、.env 是否引用宿主主机名 对应 [OPTIONAL:EXTRA_ENV] / [OPTIONAL:ADD_HOST] 块

→ 验收:模式(新建/评审优化)有 glob 结论背书;每个槽位有文件证据(路径)或用户确认,拿不准的在生成前问清。

第 1 步:槽位定参

读 references/docker-deploy-template.yaml(模板即规范,含全部机制与尾部人工准备清单),把探测结论映射到槽位:

槽位/可选块 来源 无对应值时
{{PROJECT}} / {{APP_PORT}} / {{HOST_PORT}} / {{HEALTH_PATH}} 第 0 步探测 前三个必给(问用户);HEALTH_PATH 无 → 删 [OPTIONAL:HEALTH_CHECK] 整块
[OPTIONAL:ENV_KEY_CHECKS] .env.example 渲染,每个必需 key 一行 grep 检查 整块删除
[OPTIONAL:PRE_BUILD] 用户确认的特殊预构建步骤 整块删除
[OPTIONAL:EXTRA_ENV] / [OPTIONAL:ADD_HOST] 运行时/依赖拓扑要求 整块删除

槽位写作 {{SLOT}}(无 $ 前缀),与 Gitea 表达式 ${{ ... }} 区分;渲染后模板里不应残留任何 {{...}}。

→ 验收:槽位对照表逐项有值或有"整块删除"结论,摊开给用户过目。

第 2 步:生成/改写(确认闸)

默认动作:先把渲染后的 workflow 全文摊给用户确认,再落盘到 .gitea/workflows/docker-deploy.yaml;改写已有文件时给 diff。已有 workflow 里与规范不冲突的定制(额外 job、项目专用步骤)保留,并在汇报里列出。

→ 验收:用户确认后文件落盘;保留的定制逐项在汇报出现,不静默丢弃(红线)。

评审优化模式(第 0 步发现已有 workflow 时走此分支)

先做完第 0、1 步得出"应该长什么样",再拿现状逐条对照审计。只读审计,审计报告出来之前不改任何文件。

审计清单(依据列挂着硬约束编号)

# 检查项 依据 级别
B1 出现 uses:(第三方 action) ① 必须修
B2 触发不是 push v* tag(如推 main 即构建部署) ② 必须修
B3 缺 workflow_dispatch job 单跑选项 ② 建议修
B4 buildx 未经 buildkitd.toml 注入 registry http=true + docker.io mirrors ③ 必须修
B5 凭证写死,或无 INNEV_* → gitea.actor/GITHUB_TOKEN 回退链 ④ 必须修
B6 cleanup 全局 prune,或容器 name 过滤无 ^...$ 锚点 ⑤ 必须修
B7 镜像只打 latest、无版本 tag ⑥ 必须修
B8 明文密钥 / clone 日志未 grep -v 过滤 token / docker login 未走 --password-stdin ⑦ 必须修(安全项,优先处理)
B9 健康检查缺失或窗口与启动模型不匹配(runtime-node 首启数分钟) ⑧ 建议修
B10 自定义变量/密钥未用 INNEV_ 前缀 命名约定 建议修
B11 缺基础镜像同步落盘(无强制网络检测选址步 / FROM 未命中 {registry}/images 时未先拉取推送落盘再改写、仅被动回退官方源) ⑩ 必须修

级别定义:必须修 = 会挂/泄密/误删邻项目产物;建议修 = 能跑但稳定性/可维护性受损。

审计报告格式(固定)

  • 结论一行:当前流程 → 规范流程差距概述(一致则明说"已符合规范")
  • 问题表:级别 | 行号 | 问题 | 依据(约束编号) | 修法
  • 已过项也要逐条报"已过"(B1-B11 逐条过,漏报和误报一样有害)

报告摊开、用户确认要修 → 转第 2 步给 diff,再进第 3 步验证。用户说"只评审不动手" → 报告即交付物。

第 3 步:验证

  1. bash scripts/check-workflow.sh <生成的 workflow 路径> 规范自检 10 项,全过(SKIP 项人工知悉)
  2. YAML 语法由脚本第 ⑧ 项覆盖(pyyaml 可用时)
  3. 真触发(打 tag 发版)不在授权范围——显式声明"未真机验证",给出手动验证路径:仓库 Actions → Run workflow 单跑 image 任务,绿了再全链路

完成定义 = 规范自检全过 + 用户拿到可执行的首次发布步骤;不是"文件写完了"。

→ 验收:check-workflow.sh 输出全 PASS;未验证项在汇报显式声明。

第 4 步:汇报

固定结构:

  • 模式:新建 / 评审优化
  • 探测结论:项目名 / Dockerfile / 启动模型 / 端口 / 健康端点 / env key(附证据文件路径)
  • 【评审优化】审计结果:必须修 N 条 / 建议修 N 条 / 已过 N 条(附问题表),用户是否授权修正
  • 写了什么:workflow 文件路径(新建 / 修改 diff);保留的项目定制清单
  • 被跳过/未做的:如无健康端点省略健康检查步、无 .env.example 省略 key 检查
  • 验证做到哪一步:check-workflow.sh 结果;真触发没做就说没做
  • 待人工补:runner 实例级登记 / 宿主 daemon.json insecure-registries 登记并重启 docker / 仓库 Units 启用 Actions / 服务器按 .env.example 建 .env / 仓库 Variables+Secrets 配置(清单在生成的 workflow 尾部注释)/ 首次打 tag 发布

硬约束

  • ① 零第三方 action。为什么:self-hosted runner 在内网,访问不了 github.com,uses: 一出现 workflow 直接跑不起来;run 步骤直连 git/docker 即可。
  • ② 仅 push v tag 触发全链路,推 main 不触发*。为什么:版本号即镜像 tag 的模型——每次提交都发版会让 Packages 堆满无版本意义的镜像,且无法回溯;手动兜底用 workflow_dispatch 的 job 选项单跑。
  • ③ buildx 必须经 buildkitd.toml 注入 registry http=true 与 docker.io mirrors。为什么:docker-container 驱动的 buildkitd 不继承宿主 daemon.json 的 insecure-registries/registry-mirrors——不声明 http=true 推送阶段必失败,不注入 mirrors 拉基础镜像超时。
  • ④ 凭证回退链 INNEV_REGISTRY_USER/INNEV_REGISTRY_TOKEN → gitea.actor/GITHUB_TOKEN,INNEV_CI_TOKEN → GITHUB_TOKEN。为什么:内置 token 同命名空间够用,配了 INNEV_* 即覆盖生效——不强制每个仓库都配密钥,也不许把凭证写死。
  • ⑤ cleanup 只动本项目名下的镜像 tag 与 ^<项目名>$ 锚点过滤的容器。为什么:部署机上还跑着其他项目的镜像与容器,全局 prune 或无锚点过滤(名字包含项目名的 buildx_buildkit_* 容器)就是误删事故。
  • ⑥ 镜像 tag = git tag 版本号 + latest,禁 latest-only。为什么:latest 无法回溯版本;部署出问题想回退时,没有版本 tag 就没有可拉的历史镜像。
  • ⑦ 密钥全部走 secrets 引用,clone 日志 grep -v "$GIT_TOKEN" 过滤,docker login 走 --password-stdin。为什么:明文 token 进 workflow 文件 = 进 git 历史;密码进 argv 会留在日志与进程列表。
  • ⑧ 健康检查窗口按启动模型放宽。为什么:runtime-node 系容器首启要 install+build 数分钟,窗口太短会把正常启动当失败杀掉(spms 实测放宽到 ~7.5 分钟);项目没有健康端点时不虚构——省略该步并显式声明。
  • ⑨ 生成/改写前先摊全文或 diff 给用户确认。为什么:workflow 直接决定发布行为,未经确认的写入超出授权;默认动作永远是"不写"。
  • ⑩ 基础镜像强制落盘内部源 {registry}/images:命中直接改写 FROM;未命中先 docker pull 官方源 → docker push 到 {registry}/images 落盘 → 再改写 FROM;仅拉取/推送失败才回退官方源(告警不硬失败)。拉取前强制网络检测选址(内网 livebook:8418 / 外网 code.innev.cn);改写只作用 CI 克隆副本。为什么:内网 runner 直连 docker.io 慢/超时——新基础镜像首次构建即同步落盘,后续构建全部命中内网源、越构建越快,不再依赖组织提前手工同步;livebook:8418 是 LAN 明文、code.innev.cn 是 WAN TLS,写死任一地址换网络环境必挂——必须运行时探测;同步失败只告警回退,不让镜像源问题阻塞发版;仓库 Dockerfile 要在任意网络可构建,不能把内网地址烙进源码。

凭证与配置

本 skill 自身无外部凭证。生成的 workflow 引用的 INNEV_* 变量/密钥由人在 Gitea「仓库 → 设置 → Actions」里配置(配置清单自动生成在 workflow 尾部注释里,照单配即可)。用户在对话中贴过来的真实令牌/密钥:不落进任何文件,并提醒轮换。

人机权责

  • 写操作:生成/覆盖 .gitea/workflows/docker-deploy.yaml——默认摊全文确认后落盘。
  • 终态是人的按钮:首次发版(git tag v0.1.0 && git push origin v0.1.0)、仓库 Variables/Secrets 配置、服务器 .env 创建,agent 一律不执行。
  • 待人工补:runner 登记、宿主 daemon.json insecure-registries、仓库 Units 启用 Actions、数据库迁移(如适用)——落成清单交付,不绕道、不假装完成。

排障对照表

症状 原因 怎么办
推 tag 后 Actions 没动静 仓库未启用 Actions Units / tag 不是 v 开头 仓库设置启用 Actions;tag 改 v 开头重打
镜像 push 阶段失败(http 相关报错) buildkitd.toml 未声明 http=true(buildkitd 不继承宿主 insecure-registries) 按约束③补齐注入(本规范模板已含)
构建拉基础镜像超时 docker-container 驱动不继承宿主 registry-mirrors 经 buildkitd.toml 注入 INNEV_DOCKERHUB_MIRRORS
同步步反复出现「同步失败」告警 宿主 pull 官方源超时(mirrors 未配)/ push 到 images 被拒(token 缺 write:package 或对 images 组织无写权限 / 宿主 daemon.json 未登记 livebook:8418 insecure-registries) 配宿主 registry-mirrors;确认 INNEV_REGISTRY_TOKEN scope 与 images 组织写权限、daemon.json 登记并重启 docker——同步失败只告警回退官方源,不阻塞构建
同步/构建拉 livebook:8418 报 http 相关错误 buildkitd.toml 缺该 registry 的 http=true 声明 模板已含条件注入;旧 workflow 按约束③⑩补齐
外网 runner 检测命中 code.innev.cn 但拉取失败 token 失效或 runner 无外网 确认 INNEV_REGISTRY_TOKEN 有效(同一 Gitea 实例内外网凭证通用)、runner 可出外网
部署机 docker pull 报 HTTP response to HTTPS client 宿主 daemon.json 未登记 LAN 明文 registry 登记 insecure-registries 并重启 docker(人工),或前缀改 TLS 地址
健康检查超时/失败 runtime-node 首启 install+build 数分钟窗口太短;或 .env 缺 key 按约束⑧放宽窗口;看容器日志确认缺哪个 key
cleanup 删注册表版本 403 token 缺 write:package scope 该步 best-effort 只告警不阻塞;补 scope 后自然恢复
容器内连宿主数据库 5432 不通 容器经 host-gateway 访问不到宿主系统服务端口 .env 改指同机 docker 发布端口(如 5433)——实测踩坑
git clone 源码失败 INNEV_CI_TOKEN 缺失或 scope 不足 配 INNEV_CI_TOKEN(read:repository),或确认内置 GITHUB_TOKEN 够用

die 消息统一三段式:是什么 + 为什么(后果) + 怎么办。

红线(任何情况下不违反)

  • 不替用户打 tag、不替用户触发首次发布——终态是人的按钮
  • 不往任何文件里写真实密钥/令牌;用户贴过来的提醒轮换
  • 不静默丢弃已有 workflow 的项目定制——差异必须摊开、保留项必须进汇报
  • 不虚构健康检查端点——探测不到就省略该步并显式声明,不写个 /api/health 假装有
  • 不擅自加第三方 action——用户坚持要加时,先复述约束①的后果再让其拍板
  • 不静默截断——被省略的可选块、被跳过的检查必须出现在汇报里

边界:这些不归本 skill 管

  • 写/改/评审项目 Dockerfile(归 runtime-image;本 skill 第 0 步发现没有 Dockerfile 时指路过去)
  • 提交推送代码并写日报(归 push-and-report)
  • 手工构建推送业务镜像发版(归 xgent-image-push / xgent-app-release)
  • 修改 runtime 基础镜像本身(归 runtime-base 仓库维护)
  • {registry}/images 命名空间的组织级批量同步与清理(本 skill 让流水线在构建时对未命中的 FROM 按需同步落盘,日常构建即自然积累;批量预同步/下架清理不归本 skill)