feat(gitea-actions): prefer internal images namespace for base images with forced network detection
This commit is contained in:
1 parent
1b9a40bdc6
commit
5737e9e66a
3 files changed
+98
-4
No files matched your search
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: gitea-actions
|
||||
description: 按统一规范给项目生成或评审优化 Gitea Actions 构建部署工作流(.gitea/workflows/docker-deploy.yaml):推 v 开头 tag 触发 → buildx 构建推 Gitea Packages → 本机 docker 重建容器 → 清理本机与注册表旧版本;零第三方 action、INNEV_ 前缀变量/密钥、凭证回退链。凡用户要求「给项目加构建工作流 / 加个 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。
|
||||
description: 按统一规范给项目生成或评审优化 Gitea Actions 构建部署工作流(.gitea/workflows/docker-deploy.yaml):推 v 开头 tag 触发 → buildx 构建推 Gitea Packages → 本机 docker 重建容器 → 清理本机与注册表旧版本;零第三方 action、INNEV_ 前缀变量/密钥、凭证回退链、基础镜像强制网络检测选址(内网 livebook:8418 / 外网 code.innev.cn)并优先 {registry}/images 内网源。凡用户要求「给项目加构建工作流 / 加个 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 — 按统一规范给项目装构建部署工作流
|
||||
@@ -10,6 +10,7 @@ description: 按统一规范给项目生成或评审优化 Gitea Actions 构建
|
||||
- **版本号即镜像 tag**:发布 = 打 v 开头 git tag,镜像 tag 与之一一对应,可回溯;推 main 不发版
|
||||
- **runner 与部署目标同机**:self-hosted 实例级 runner 直连宿主 docker,构建完即本机部署
|
||||
- **零外部依赖**:不用任何第三方 action,run 步骤直连 git/docker,内网 runner 无需访问 github.com
|
||||
- **基础镜像内网优选**:FROM 优先 `{registry}/images`(组织已把常用基础镜像同步到该命名空间),未命中回退官方源;拉取前强制网络检测选址——内网 `livebook:8418`、外网 `code.innev.cn`,写死任一地址换网络环境必挂;改写只落在 CI 克隆副本,仓库 Dockerfile 保持任意网络可构建
|
||||
|
||||
## 默认流程(不带任何附加提示词也照此执行)
|
||||
|
||||
@@ -84,6 +85,7 @@ description: 按统一规范给项目生成或评审优化 Gitea Actions 构建
|
||||
| B8 | 明文密钥 / clone 日志未 `grep -v` 过滤 token / docker login 未走 `--password-stdin` | ⑦ | 必须修(安全项,优先处理) |
|
||||
| B9 | 健康检查缺失或窗口与启动模型不匹配(runtime-node 首启数分钟) | ⑧ | 建议修 |
|
||||
| B10 | 自定义变量/密钥未用 INNEV_ 前缀 | 命名约定 | 建议修 |
|
||||
| B11 | 缺基础镜像内网优选(无强制网络检测选址步 / FROM 未优先 {registry}/images) | ⑩ | 必须修 |
|
||||
|
||||
级别定义:**必须修** = 会挂/泄密/误删邻项目产物;**建议修** = 能跑但稳定性/可维护性受损。
|
||||
|
||||
@@ -91,13 +93,13 @@ description: 按统一规范给项目生成或评审优化 Gitea Actions 构建
|
||||
|
||||
- 结论一行:当前流程 → 规范流程差距概述(一致则明说"已符合规范")
|
||||
- 问题表:级别 | 行号 | 问题 | 依据(约束编号) | 修法
|
||||
- 已过项也要逐条报"已过"(B1-B10 逐条过,漏报和误报一样有害)
|
||||
- 已过项也要逐条报"已过"(B1-B11 逐条过,漏报和误报一样有害)
|
||||
|
||||
报告摊开、用户确认要修 → 转第 2 步给 diff,再进第 3 步验证。用户说"只评审不动手" → 报告即交付物。
|
||||
|
||||
## 第 3 步:验证
|
||||
|
||||
1. `bash scripts/check-workflow.sh <生成的 workflow 路径>` 规范自检 8 项,全过(SKIP 项人工知悉)
|
||||
1. `bash scripts/check-workflow.sh <生成的 workflow 路径>` 规范自检 10 项,全过(SKIP 项人工知悉)
|
||||
2. YAML 语法由脚本第 ⑧ 项覆盖(pyyaml 可用时)
|
||||
3. 真触发(打 tag 发版)不在授权范围——**显式声明"未真机验证"**,给出手动验证路径:仓库 Actions → Run workflow 单跑 `image` 任务,绿了再全链路
|
||||
|
||||
@@ -127,6 +129,7 @@ description: 按统一规范给项目生成或评审优化 Gitea Actions 构建
|
||||
- ⑦ **密钥全部走 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`,拉取前强制网络检测选址(内网 `livebook:8418` / 外网 `code.innev.cn`),未命中回退官方源不硬失败;FROM 改写只作用 CI 克隆副本**。为什么:内网 runner 直连 docker.io 慢/超时,images 命名空间已同步常用基础镜像,优先内网源又快又稳;livebook:8418 是 LAN 明文、code.innev.cn 是 WAN TLS,写死任一地址换网络环境必挂——必须运行时探测;仓库 Dockerfile 要在任意网络可构建,不能把内网地址烙进源码。
|
||||
|
||||
## 凭证与配置
|
||||
|
||||
@@ -145,6 +148,9 @@ description: 按统一规范给项目生成或评审优化 Gitea 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 |
|
||||
| 优选步骤全部显示「内部源未命中」 | images 命名空间未同步该基础镜像 | 在 Gitea images 组织确认/同步对应镜像;流水线自动回退官方源,不阻塞 |
|
||||
| 优选/构建拉 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 后自然恢复 |
|
||||
@@ -168,3 +174,4 @@ die 消息统一三段式:是什么 + 为什么(后果) + 怎么办。
|
||||
- 提交推送代码并写日报(归 push-and-report)
|
||||
- 手工构建推送业务镜像发版(归 xgent-image-push / xgent-app-release)
|
||||
- 修改 runtime 基础镜像本身(归 runtime-base 仓库维护)
|
||||
- 基础镜像同步进 `{registry}/images` 命名空间(组织级镜像维护动作;本 skill 只管流水线侧的优选与回退)
|
||||
@@ -18,6 +18,8 @@
|
||||
# 命名约定:自定义变量/密钥一律 INNEV_ 前缀(仓库 → 设置 → Actions 配置,清单见本文件尾部注释)。
|
||||
# 凭证回退链:INNEV_REGISTRY_USER / INNEV_REGISTRY_TOKEN → gitea.actor / 内置 GITHUB_TOKEN;
|
||||
# INNEV_CI_TOKEN → GITHUB_TOKEN。加了即生效。
|
||||
# 基础镜像:拉取前强制网络检测选址(内网 livebook:8418 / 外网 code.innev.cn),FROM 优先
|
||||
# <registry>/images 命名空间,未命中回退官方源;改写只作用 CI 克隆副本,不动仓库 Dockerfile。
|
||||
# 镜像 tag = 版本号(git tag,如 v1.2.3)+ latest;手动 dispatch 无 tag 上下文时回退提交短 sha。
|
||||
name: docker-deploy
|
||||
|
||||
@@ -46,6 +48,9 @@ env:
|
||||
INNEV_HOST_PORT: ${{ vars.INNEV_HOST_PORT || '{{HOST_PORT}}' }}
|
||||
# 服务器上单独维护的 .env 绝对路径(key 与仓库 .env.example 一致);.env 不进 git/镜像
|
||||
INNEV_ENV_FILE: ${{ vars.INNEV_ENV_FILE || '/etc/{{PROJECT}}/.env' }}
|
||||
# 基础镜像内网源 registry——默认空 = 强制网络检测自动选址(内网 livebook:8418 / 外网
|
||||
# code.innev.cn);显式设置覆盖探测结果。FROM 命中 <该值>/images 即改写为内部引用,缺失回退官方源
|
||||
INNEV_IMAGES_REGISTRY: ${{ vars.INNEV_IMAGES_REGISTRY || '' }}
|
||||
|
||||
jobs:
|
||||
# 任务 1:构建镜像并推送到本机 Gitea Packages($INNEV_IMAGE_PREFIX/{{PROJECT}})
|
||||
@@ -66,6 +71,23 @@ jobs:
|
||||
# 日志开头明示推送目标,变量配错时第一时间可见
|
||||
echo "构建目标镜像:$PREFIX/{{PROJECT}}:$TAG"
|
||||
|
||||
# 从 <registry>/images 拉基础镜像之前必须强制网络检测选址:livebook:8418 是 LAN 明文 HTTP、
|
||||
# code.innev.cn 是 WAN TLS——写死任一地址,换个网络环境流水线必挂。均不可达则置空,
|
||||
# 后续优选步整体回退官方源(buildkitd.toml 的 docker.io mirrors 兜底)。
|
||||
- name: 强制网络检测(基础镜像源选址)
|
||||
run: |
|
||||
REG="${INNEV_IMAGES_REGISTRY#*://}"
|
||||
if [ -n "$REG" ]; then
|
||||
echo "仓库变量显式指定基础镜像源:$REG"
|
||||
elif curl -fsS -m 5 http://livebook:8418/api/v1/version >/dev/null 2>&1; then
|
||||
REG=livebook:8418; echo "内网探测命中,基础镜像源:$REG/images"
|
||||
elif curl -fsS -m 5 https://code.innev.cn/api/v1/version >/dev/null 2>&1; then
|
||||
REG=code.innev.cn; echo "外网探测命中,基础镜像源:$REG/images"
|
||||
else
|
||||
REG=''; echo "::warning::内网/外网镜像源均不可达,基础镜像全部回退官方源"
|
||||
fi
|
||||
echo "INNEV_IMAGES_REGISTRY=$REG" >> "$GITHUB_ENV"
|
||||
|
||||
- name: 取出源码(免 actions/checkout,纯 git)
|
||||
env:
|
||||
GIT_TOKEN: ${{ secrets.INNEV_CI_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
@@ -79,7 +101,12 @@ jobs:
|
||||
env:
|
||||
LOGIN_USER: ${{ secrets.INNEV_REGISTRY_USER || gitea.actor }}
|
||||
LOGIN_TOKEN: ${{ secrets.INNEV_REGISTRY_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
run: echo "$LOGIN_TOKEN" | docker login "$INNEV_REGISTRY" -u "$LOGIN_USER" --password-stdin
|
||||
run: |
|
||||
echo "$LOGIN_TOKEN" | docker login "$INNEV_REGISTRY" -u "$LOGIN_USER" --password-stdin
|
||||
# 基础镜像源与推送 registry 不同端点(如外网 code.innev.cn)时补登录——同一 Gitea 实例,凭证通用
|
||||
if [ -n "$INNEV_IMAGES_REGISTRY" ] && [ "$INNEV_IMAGES_REGISTRY" != "$INNEV_REGISTRY" ]; then
|
||||
echo "$LOGIN_TOKEN" | docker login "$INNEV_IMAGES_REGISTRY" -u "$LOGIN_USER" --password-stdin
|
||||
fi
|
||||
|
||||
# buildkitd.toml 里对 $INNEV_REGISTRY 声明 http=true(强制明文 HTTP):buildkitd 不继承宿主
|
||||
# daemon.json 的 insecure-registries,纯 HTTP registry 不声明会在 push 阶段失败。
|
||||
@@ -93,10 +120,49 @@ jobs:
|
||||
echo ''
|
||||
echo "[registry.\"$INNEV_REGISTRY\"]"
|
||||
echo ' http = true'
|
||||
# LAN 明文的基础镜像源与推送 registry 不同端点时补 http 声明(TLS 端点如 code.innev.cn 不需要)
|
||||
if [ "$INNEV_IMAGES_REGISTRY" = "livebook:8418" ] && [ "$INNEV_IMAGES_REGISTRY" != "$INNEV_REGISTRY" ]; then
|
||||
echo ''
|
||||
echo "[registry.\"$INNEV_IMAGES_REGISTRY\"]"
|
||||
echo ' http = true'
|
||||
fi
|
||||
} > buildkitd.toml
|
||||
cat buildkitd.toml
|
||||
docker buildx create --use --name {{PROJECT}}builder --config buildkitd.toml
|
||||
|
||||
# 基础镜像强制优选内部源:src 副本 Dockerfile 里命中 <registry>/images 的 FROM 改写为内部引用,
|
||||
# 未命中保持原样(构建时经 buildkitd.toml 的 docker.io mirrors 回退官方源),不硬失败。
|
||||
# 只改 CI 克隆出的副本,不动仓库 Dockerfile——同一 Dockerfile 在任意网络环境都要可构建。
|
||||
- name: 基础镜像优选内部源(images 命名空间,缺失回退官方源)
|
||||
run: |
|
||||
if [ -z "$INNEV_IMAGES_REGISTRY" ]; then
|
||||
echo "内部镜像源不可用,跳过优选,基础镜像全部走官方源"
|
||||
exit 0
|
||||
fi
|
||||
cd src
|
||||
# 构建阶段名(FROM ... AS <name>)不是镜像引用,收集起来跳过
|
||||
STAGES=$(awk 'toupper($1)=="FROM"{for(i=2;i<=NF;i++) if(toupper($i)=="AS") print $(i+1)}' Dockerfile)
|
||||
{ grep -niE '^[[:space:]]*FROM[[:space:]]' Dockerfile || true; } | cut -d: -f1 | while read -r N; do
|
||||
REF=$(awk -v n="$N" 'NR==n{for(i=2;i<=NF;i++){if($i ~ /^--/) continue; print $i; exit}}' Dockerfile)
|
||||
case "$REF" in ''|scratch|'$'*|*@*) echo "跳过 ${REF:-空引用}(scratch/ARG/digest)"; continue ;; esac
|
||||
W="${REF#docker.io/}" # 显式 docker.io 前缀视同官方源,纳入优选
|
||||
# 仅当含 / 时才可能带 registry:首段含 . 或 : 或是 localhost 即视为已带 registry,保持原样
|
||||
case "$W" in */*) case "${W%%/*}" in *.*|*:*|localhost) echo "跳过 $REF(已带 registry)"; continue ;; esac ;; esac
|
||||
if echo "$STAGES" | grep -qx "$W"; then echo "跳过 $REF(构建阶段名)"; continue; fi
|
||||
NAME="${W%%:*}"; if [ "$NAME" = "$W" ]; then TAG=latest; else TAG="${W##*:}"; fi
|
||||
NAME="${NAME#library/}"
|
||||
CAND="$INNEV_IMAGES_REGISTRY/images/$NAME:$TAG"
|
||||
if docker buildx imagetools inspect "$CAND" >/dev/null 2>&1; then
|
||||
ESC=$(printf '%s' "$REF" | sed 's/[.[\*^$/]/\\&/g')
|
||||
sed -i "${N}s|$ESC|$CAND|" Dockerfile
|
||||
echo "优选命中:$REF → $CAND"
|
||||
else
|
||||
echo "内部源未命中,保留官方源:$REF"
|
||||
fi
|
||||
done
|
||||
echo '--- 优选后的 FROM 行 ---'
|
||||
grep -niE '^[[:space:]]*FROM[[:space:]]' Dockerfile || true
|
||||
|
||||
# [OPTIONAL:PRE_BUILD] 项目有特殊预构建步骤(如从源码构建工具二进制)时取消注释并改写本步,
|
||||
# 否则连同标记整块删除。插入位置必须在"构建并推送镜像"步之前。
|
||||
# - name: 预构建(按项目需要改写)
|
||||
@@ -269,6 +335,10 @@ jobs:
|
||||
# host-gateway 访问不通——实测踩坑,切勿写错。
|
||||
# 7. 日常发布:git tag v1.2.3 && git push origin v1.2.3(tag 需 v 开头才会触发流水线);
|
||||
# 部署成功后 cleanup 自动删除本机与 Gitea Packages 里的旧版本镜像,无需人工干预。
|
||||
# 8. 基础镜像内网源:组织已在 Gitea images 命名空间同步常用基础镜像(如 images/golang:1.25-alpine)。
|
||||
# 构建前强制网络检测选址(内网 livebook:8418 / 外网 code.innev.cn),命中即把 src 副本
|
||||
# Dockerfile 的 FROM 改写为 <registry>/images/*,未命中自动回退官方源——全自动无需人工干预,
|
||||
# 只需保证 images 命名空间持续同步需要的基镜像。
|
||||
#
|
||||
# 仓库 → 设置 → Actions 配置清单
|
||||
# 变量(Variables):
|
||||
@@ -279,6 +349,9 @@ jobs:
|
||||
# registry.hub.docker.com,docker.1panel.live,docker.1panel.dev,docker.1ms.run
|
||||
# INNEV_HOST_PORT 容器对外发布端口,默认 {{HOST_PORT}}(容器内固定 {{APP_PORT}})
|
||||
# INNEV_ENV_FILE 服务器上 .env 的绝对路径,默认 /etc/{{PROJECT}}/.env(见上方准备 6)
|
||||
# INNEV_IMAGES_REGISTRY 基础镜像内网源 registry——默认空 = 强制网络检测自动选址
|
||||
# (内网 livebook:8418 / 外网 code.innev.cn);显式设置覆盖探测结果。
|
||||
# FROM 命中 <该值>/images 即改写为内部引用,缺失回退官方源
|
||||
# 密钥(Secrets):
|
||||
# INNEV_REGISTRY_USER docker login 账号——跨命名空间推包时必需(同命名空间可回退 gitea.actor)
|
||||
# INNEV_REGISTRY_TOKEN docker login token(scope: write:package + read:package);
|
||||
|
||||
@@ -84,6 +84,20 @@ else
|
||||
skip "⑧ python3+pyyaml 不可用,YAML 语法未校验"
|
||||
fi
|
||||
|
||||
# ⑨ 基础镜像源强制网络检测(内网 livebook:8418 / 外网 code.innev.cn 运行时选址,写死必挂)
|
||||
if grep -q 'INNEV_IMAGES_REGISTRY' "$FILE" && grep -q 'livebook:8418' "$FILE" && grep -q 'code.innev.cn' "$FILE"; then
|
||||
pass "⑨ 基础镜像源强制网络检测(内外网选址)"
|
||||
else
|
||||
bad "⑨ 缺基础镜像源强制网络检测——内网 livebook:8418 / 外网 code.innev.cn 必须运行时探测选址"
|
||||
fi
|
||||
|
||||
# ⑩ FROM 强制优选 <registry>/images 内部源,未命中回退官方源
|
||||
if grep -q 'INNEV_IMAGES_REGISTRY/images/' "$FILE"; then
|
||||
pass "⑩ FROM 优选 <registry>/images 内部源(未命中回退官方源)"
|
||||
else
|
||||
bad "⑩ 缺 FROM 优选内部源步骤——基础镜像应优先 <registry>/images,未命中回退官方源"
|
||||
fi
|
||||
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
say "---"
|
||||
say "规范自检未通过:存在 FAIL 项,逐条修正后重跑。"
|
||||
|
||||
Reference in new issue
Block a user