- 配置中心原 MINISIGN_PRIVATE_KEY 缺首行 untrusted comment (只含 base64), minisign 报 'Error while loading the secret key file' - 已删除坏条目 (cfg-mtwmbmkd-bbiihv), 保留正确完整值 (cfg-mtwr5c2m-99r5fh) - docker-build.yml / ota-build.yml 不再用 GITHUB_ENV 多行 heredoc, 改为把私钥写入 ota-package/hotswap.key, build-ota.mjs --key 显式指定 - 本地全链路验证: 配置中心拉取 → 写文件 → 签名 → 用 tauri.conf.json 公钥验签通过
99 lines
4.0 KiB
YAML
99 lines
4.0 KiB
YAML
name: Docker Build and Push
|
|
|
|
# 仅 main 分支 push 触发 (每次提交 → 自动部署)
|
|
# 每次主分支提交: 构建前端 + 生成 OTA 升级包 (minisign 签名) → 打进 Docker 镜像 → 部署到 :3002
|
|
# OTA 随镜像发布: 容器内 OTA_PACKAGE_DIR=/app/ota-package 指向打包的 ota-package/
|
|
# 依赖配置注册中心 (bh.vps.honor3.com:8008):
|
|
# - service-wardrobe / ota : MINISIGN_PRIVATE_KEY (整段 .key 内容, 多行)
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
- master
|
|
|
|
jobs:
|
|
build-image:
|
|
runs-on: ubuntu-latest
|
|
permissions:
|
|
contents: read
|
|
env:
|
|
# VITE_API_BASE 留空 = 前端走同源 /api (OTA server 同进程托管首页 + OTA 接口)
|
|
VITE_API_BASE: ""
|
|
CONFIG_CENTER_URL: '${{ secrets.CONFIG_CENTER_URL }}'
|
|
CONFIG_CENTER_TOKEN: '${{ secrets.CONFIG_CENTER_TOKEN }}'
|
|
REGISTRY_URL_FALLBACK: 'http://bh.vps.honor3.com:8008'
|
|
CFG_PROJECT_SIGNING: 'proj-mtwjnvir-k52zvp'
|
|
|
|
steps:
|
|
- uses: https://gitea.com/actions/checkout@v4
|
|
|
|
- name: Setup Node
|
|
uses: https://gitea.com/actions/setup-node@v4
|
|
with:
|
|
node-version: 22
|
|
|
|
- name: Install deps
|
|
run: npm ci --no-audit --no-fund
|
|
|
|
- name: Build frontend
|
|
# dist/ 供 OTA 打包用 (Dockerfile 内也会构建一份)
|
|
run: npm run build
|
|
|
|
- name: Install minisign
|
|
run: sudo apt-get update && sudo apt-get install -y minisign
|
|
|
|
- name: Fetch config center (minisign key)
|
|
# 私钥直接写文件 (build-ota.mjs 默认 KEY_PATH 即 ota-package/hotswap.key),
|
|
# 绕开 GITHUB_ENV 多行值在 Gitea Actions 下不可靠的问题
|
|
run: |
|
|
set -euo pipefail
|
|
export CONFIG_CENTER_URL="${CONFIG_CENTER_URL:-$REGISTRY_URL_FALLBACK}"
|
|
python3 - <<'PYEOF'
|
|
import json, os, urllib.request
|
|
url = os.environ["CONFIG_CENTER_URL"]
|
|
token = os.environ.get("CONFIG_CENTER_TOKEN", "") or ""
|
|
req = urllib.request.Request(f"{url}/api/projects/{os.environ['CFG_PROJECT_SIGNING']}/configs")
|
|
if token:
|
|
req.add_header("Authorization", "Bearer " + token)
|
|
with urllib.request.urlopen(req, timeout=20) as r:
|
|
data = json.load(r).get("data", [])
|
|
key_val = next((c.get("value", "") for c in data if c.get("key") == "MINISIGN_PRIVATE_KEY"), None)
|
|
if not key_val:
|
|
raise SystemExit("配置中心缺少 MINISIGN_PRIVATE_KEY (service-wardrobe/ota)")
|
|
os.makedirs("ota-package", exist_ok=True)
|
|
with open("ota-package/hotswap.key", "w", encoding="utf-8") as f:
|
|
f.write(key_val if key_val.endswith("\n") else key_val + "\n")
|
|
os.chmod("ota-package/hotswap.key", 0o600)
|
|
PYEOF
|
|
echo "hotswap.key lines=$(wc -l < ota-package/hotswap.key)"
|
|
|
|
- name: Build & sign OTA package
|
|
# 每次主分支提交生成 OTA 升级包, sequence 默认时间戳 (单调递增)
|
|
# 产物 ota-package/ (tar.gz + latest.json + .minisig) 进入 docker build context, 由 Dockerfile COPY 进镜像
|
|
env:
|
|
OTA_NOTES: ${{ github.sha }}
|
|
run: |
|
|
set -euo pipefail
|
|
# --key 显式指定 (默认路径相同); 私钥已由上一步写入该文件
|
|
node scripts/build-ota.mjs --out ota-package --key ota-package/hotswap.key --notes ${OTA_NOTES}
|
|
echo "===== latest.json ====="
|
|
cat ota-package/latest.json
|
|
echo "===== bundle sha256 ====="
|
|
sha256sum ota-package/wardrobe-ota.tar.gz
|
|
|
|
- name: Build Docker image
|
|
run: docker build -t wardrobe:latest .
|
|
|
|
- name: List images
|
|
run: docker images
|
|
|
|
- name: Remove old container
|
|
run: docker rm -vf wardrobe || true
|
|
|
|
- name: Recycle container
|
|
run: docker system prune --volumes -f
|
|
|
|
- name: Run container
|
|
# 一键镜像: 前端 + OTA + 首页, 端口 3002 (与 iboard 的 3001 同机共存)
|
|
run: |
|
|
docker run -d --name wardrobe -p 3002:3002 wardrobe:latest |