fix(ci): OTA 私钥改为写文件签名, 修正配置中心存储的坏密钥
- 配置中心原 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 公钥验签通过
This commit is contained in:
parent
84fb01b8a3
commit
47db85d01d
@ -43,6 +43,8 @@ jobs:
|
|||||||
run: sudo apt-get update && sudo apt-get install -y minisign
|
run: sudo apt-get update && sudo apt-get install -y minisign
|
||||||
|
|
||||||
- name: Fetch config center (minisign key)
|
- name: Fetch config center (minisign key)
|
||||||
|
# 私钥直接写文件 (build-ota.mjs 默认 KEY_PATH 即 ota-package/hotswap.key),
|
||||||
|
# 绕开 GITHUB_ENV 多行值在 Gitea Actions 下不可靠的问题
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
export CONFIG_CENTER_URL="${CONFIG_CENTER_URL:-$REGISTRY_URL_FALLBACK}"
|
export CONFIG_CENTER_URL="${CONFIG_CENTER_URL:-$REGISTRY_URL_FALLBACK}"
|
||||||
@ -55,19 +57,15 @@ jobs:
|
|||||||
req.add_header("Authorization", "Bearer " + token)
|
req.add_header("Authorization", "Bearer " + token)
|
||||||
with urllib.request.urlopen(req, timeout=20) as r:
|
with urllib.request.urlopen(req, timeout=20) as r:
|
||||||
data = json.load(r).get("data", [])
|
data = json.load(r).get("data", [])
|
||||||
wanted = {}
|
key_val = next((c.get("value", "") for c in data if c.get("key") == "MINISIGN_PRIVATE_KEY"), None)
|
||||||
for cfg in data:
|
if not key_val:
|
||||||
if cfg.get("key") == "MINISIGN_PRIVATE_KEY":
|
|
||||||
wanted[cfg["key"]] = cfg.get("value", "")
|
|
||||||
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as f:
|
|
||||||
for k, v in wanted.items():
|
|
||||||
if "\n" in v or v.startswith("untrusted comment"):
|
|
||||||
f.write(f"{k}<<EOF\n{v}\nEOF\n")
|
|
||||||
else:
|
|
||||||
f.write(f"{k}={v}\n")
|
|
||||||
if "MINISIGN_PRIVATE_KEY" not in wanted:
|
|
||||||
raise SystemExit("配置中心缺少 MINISIGN_PRIVATE_KEY (service-wardrobe/ota)")
|
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
|
PYEOF
|
||||||
|
echo "hotswap.key lines=$(wc -l < ota-package/hotswap.key)"
|
||||||
|
|
||||||
- name: Build & sign OTA package
|
- name: Build & sign OTA package
|
||||||
# 每次主分支提交生成 OTA 升级包, sequence 默认时间戳 (单调递增)
|
# 每次主分支提交生成 OTA 升级包, sequence 默认时间戳 (单调递增)
|
||||||
@ -76,7 +74,8 @@ jobs:
|
|||||||
OTA_NOTES: ${{ github.sha }}
|
OTA_NOTES: ${{ github.sha }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
node scripts/build-ota.mjs --out ota-package --notes ${OTA_NOTES}
|
# --key 显式指定 (默认路径相同); 私钥已由上一步写入该文件
|
||||||
|
node scripts/build-ota.mjs --out ota-package --key ota-package/hotswap.key --notes ${OTA_NOTES}
|
||||||
echo "===== latest.json ====="
|
echo "===== latest.json ====="
|
||||||
cat ota-package/latest.json
|
cat ota-package/latest.json
|
||||||
echo "===== bundle sha256 ====="
|
echo "===== bundle sha256 ====="
|
||||||
|
|||||||
@ -63,14 +63,15 @@ jobs:
|
|||||||
url = os.environ["CONFIG_CENTER_URL"]
|
url = os.environ["CONFIG_CENTER_URL"]
|
||||||
token = os.environ.get("CONFIG_CENTER_TOKEN", "") or ""
|
token = os.environ.get("CONFIG_CENTER_TOKEN", "") or ""
|
||||||
wanted = {}
|
wanted = {}
|
||||||
|
minisign_key = None
|
||||||
req = urllib.request.Request(f"{url}/api/projects/{os.environ['CFG_PROJECT_SIGNING']}/configs")
|
req = urllib.request.Request(f"{url}/api/projects/{os.environ['CFG_PROJECT_SIGNING']}/configs")
|
||||||
if token:
|
if token:
|
||||||
req.add_header("Authorization", "Bearer " + token)
|
req.add_header("Authorization", "Bearer " + token)
|
||||||
with urllib.request.urlopen(req, timeout=20) as r:
|
with urllib.request.urlopen(req, timeout=20) as r:
|
||||||
data = json.load(r).get("data", [])
|
data = json.load(r).get("data", [])
|
||||||
for cfg in data:
|
for cfg in data:
|
||||||
if cfg.get("key") in ("MINISIGN_PRIVATE_KEY",):
|
if cfg.get("key") == "MINISIGN_PRIVATE_KEY":
|
||||||
wanted[cfg["key"]] = cfg.get("value", "")
|
minisign_key = cfg.get("value", "")
|
||||||
req = urllib.request.Request(f"{url}/api/projects/{os.environ['CFG_PROJECT_R2']}/configs")
|
req = urllib.request.Request(f"{url}/api/projects/{os.environ['CFG_PROJECT_R2']}/configs")
|
||||||
if token:
|
if token:
|
||||||
req.add_header("Authorization", "Bearer " + token)
|
req.add_header("Authorization", "Bearer " + token)
|
||||||
@ -79,26 +80,29 @@ jobs:
|
|||||||
for cfg in data:
|
for cfg in data:
|
||||||
if cfg.get("key") in ("CF_API_TOKEN", "CF_R2_PUBLIC_URL"):
|
if cfg.get("key") in ("CF_API_TOKEN", "CF_R2_PUBLIC_URL"):
|
||||||
wanted[cfg["key"]] = cfg.get("value", "")
|
wanted[cfg["key"]] = cfg.get("value", "")
|
||||||
# GITHUB_ENV 多行值需用 heredoc 语法; 单行值直接 NAME=value
|
# 私钥直接写文件 (绕开 GITHUB_ENV 多行值问题); R2 单行值仍走 GITHUB_ENV
|
||||||
|
if not minisign_key:
|
||||||
|
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(minisign_key if minisign_key.endswith("\n") else minisign_key + "\n")
|
||||||
|
os.chmod("ota-package/hotswap.key", 0o600)
|
||||||
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as f:
|
with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as f:
|
||||||
for k, v in wanted.items():
|
for k, v in wanted.items():
|
||||||
if "\n" in v or v.startswith("untrusted comment"):
|
f.write(f"{k}={v}\n")
|
||||||
f.write(f"{k}<<EOF\n{v}\nEOF\n")
|
missing = [k for k in ("CF_API_TOKEN", "CF_R2_PUBLIC_URL") if k not in wanted]
|
||||||
else:
|
|
||||||
f.write(f"{k}={v}\n")
|
|
||||||
missing = [k for k in ("MINISIGN_PRIVATE_KEY", "CF_API_TOKEN") if k not in wanted]
|
|
||||||
if missing:
|
if missing:
|
||||||
raise SystemExit("配置中心缺少: " + ", ".join(missing))
|
raise SystemExit("配置中心缺少: " + ", ".join(missing))
|
||||||
PYEOF
|
PYEOF
|
||||||
|
echo "hotswap.key lines=$(wc -l < ota-package/hotswap.key)"
|
||||||
|
|
||||||
- name: Build & sign OTA package
|
- name: Build & sign OTA package
|
||||||
# MINISIGN_PRIVATE_KEY 由上一步写入 GITHUB_ENV, 已是本步的真实环境变量,
|
# 私钥已由上一步写入 ota-package/hotswap.key, --key 显式指定
|
||||||
# build-ota.mjs 直接读 process.env.MINISIGN_PRIVATE_KEY, 无需再映射
|
|
||||||
env:
|
env:
|
||||||
OTA_NOTES: ${{ inputs.notes }}
|
OTA_NOTES: ${{ inputs.notes }}
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
ARGS="--out ota-package"
|
ARGS="--out ota-package --key ota-package/hotswap.key"
|
||||||
if [ -n "${{ inputs.sequence }}" ]; then ARGS="${ARGS} --sequence ${{ inputs.sequence }}"; fi
|
if [ -n "${{ inputs.sequence }}" ]; then ARGS="${ARGS} --sequence ${{ inputs.sequence }}"; fi
|
||||||
if [ -n "${OTA_NOTES}" ]; then ARGS="${ARGS} --notes ${OTA_NOTES}"; fi
|
if [ -n "${OTA_NOTES}" ]; then ARGS="${ARGS} --notes ${OTA_NOTES}"; fi
|
||||||
node scripts/build-ota.mjs ${ARGS}
|
node scripts/build-ota.mjs ${ARGS}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user