- 作者帖子
背景
薇晓朵商城 (mall.weixiaoduo.com) 的产品更新链路长期断裂——dl1 上 83% 的文件是 2017-2022 年上传的,feicode 仓库有 457 个有代码但 0 个 release 。手动更新一个产品需要:下载源码 → 打包 zip → 上传 dl1 → 创建 Release → 更新 WooCommerce 下载链接 → 更新本地 YAML,6 个步骤,容易出错且耗时。
Elementor Pro 试点手动跑通全流程后,我们把它固化成了
fei publish命令。架构
采用混合委托模式:
~/bin/fei(Bash) 加了一个cmd_publish()薄壳,exec python3委托给 Python 脚本~/Projects/mall-products/feicode/fei-publish.py(Python) 承载主逻辑- 复用现有数据:
repos.json(530 个仓库映射) 、product.yaml(371 个产品定义) 、.env.secrets(凭证)
这样 fei CLI 保持统一入口,Python 处理复杂逻辑 (API 调用、 zip 操作、 YAML 读写) 。
单个产品发布流程 (8 步)
fei publish <slug>- 查找映射 — repos.json 找到 org/repo,product.yaml 找到 WooCommerce product_id 、当前版本、 zip_top_dir
- 提取版本号 — 通过 Gitea raw API 远程读取 (不需要 clone),按优先级尝试:
metadata.main_file指定的文件 →Version:header{slug}.php→Version:headerstyle.css→Version:header(主题)readme.txt→Stable tag:- 过滤无效值 (trunk/stable/dev/master/main)
- 打包 zip — Gitea archive API 下载 main.zip → 解压 → 重命名顶层目录为 zip_top_dir → 重新打包排除 .git* → 输出
{slug}-{version}.zip - 创建 Gitea Release — POST /repos/{org}/{repo}/releases,tag=v{version},上传 zip 为附件。已存在则跳过创建
- 上传到 dl1 — SCP 到 weixiaoduo-prod:/www/wwwroot/dl1.weixiaoduo.com/{YYYY}/{MM}/
- 更新 WooCommerce — PUT /wp-json/wc/v3/products/{id},替换 downloads 中名称含” 原版” 的条目 URL 和版本号,保留其他下载项 (中文语言包等)
- 更新本地 product.yaml — upstream_version 、 downloads URL/name 、 date_modified
- (可选) 触发客户通知 —
--notify参数,通过 prod-query 调用 wdpum 排队通知
批量操作
fei publish --check # 并发扫描所有产品版本差异 (20 线程,297 个产品 3 秒完成) fei publish --auto --limit 10 # 自动发布前 10 个有差异的产品 fei publish <slug> --dry-run # 模拟运行,不实际执行 fei publish <slug> --force # 强制发布 (即使版本相同)踩过的坑
1. 版本提取的 「trunk」 陷阱
部分插件的 readme.txt 里
Stable tag: trunk,这不是真实版本号。解决:维护一个无效版本黑名单{trunk, stable, dev, master, main},匹配到就跳过继续尝试下一个候选文件。2. 并发扫描的连接池溢出
--check用 20 个线程并发调 Gitea API,但 requests.Session 默认连接池只有 10,导致大量 「Connection pool is full, discarding connection」 警告。解决:挂载自定义 HTTPAdapter,pool_connections=20, pool_maxsize=20 。3. zip 顶层目录名不一致
Gitea archive API 下载的 zip 顶层目录是
{repo}/,但 WordPress 插件/主题要求顶层目录名与 slug 一致 (有些产品还有特殊的 zip_top_dir,比如 astra 主题的子主题目录是astra-wei) 。解决:解压后根据 product.yaml 的metadata.zip_top_dir重命名。4. WooCommerce 下载项的精确替换
一个产品可能有多个下载项 (原版插件包、中文语言包、子主题等),更新时只替换名称含” 原版” 的条目,保留其他不变。如果没有” 原版” 条目则插入一个新的。
数据依赖关系
repos.json (530 仓库) ↓ slug → org/repo product.yaml (371 产品) ↓ id, downloads, metadata.upstream_version, metadata.zip_top_dir .env.secrets ↓ FEICODE_TOKEN, WC_CONSUMER_KEY/SECRET, WC_STORE_URL日志和回滚
- 每次发布写 JSON 日志到
publish-log/{date}-{slug}.json - WooCommerce 更新前备份当前下载列表到日志
- dl1 上传是追加式的 (新文件新路径),WC 更新失败不会丢失已上传的文件
下一步
- 当仓库有新代码推送时,考虑 Gitea webhook 触发自动发布
--check可以做成定时任务,每天扫描一次,有更新就通知- 批量发布加上速率限制,避免短时间内大量 API 请求
- 作者帖子
Cyberforums · 原文 · Markdown
想回复或继续讨论?请到 Cyberforums 赛博论坛参与。
参与讨论 / 回复