#!/usr/bin/env bash # CI 发布:镜像已推送成功后,签名清单,并发布出去。ci/publish-release-offer.sh <组件> <镜像仓库> <通道> <输出目录> # 1. 清单放进镜像仓库(<镜像仓库>-manifest:<通道>):更新器和首次部署都从这里取,不依赖面板,必须成功; # 2. 面板在线时再登记一份(/api/release/offer,面板验 CI 签名,不需要令牌)让在线的节点更快收到:只是加速,失败只警告,不让构建失败。 # 面板不会因此自动重启 Backend。 set -euo pipefail component="${1:?component}"; repository="${2:?repository}"; digest="${3:?digest}"; tag="${4:?tag}"; channel="${5:?channel}"; outdir="${6:?outdir}" [[ -n "${RELEASE_SIGNING_KEY:-}" ]] || { echo "release signing is not configured; no update offer published"; exit 0; } root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" bash "$root/ci/release-manifest.sh" "$component" "$repository" "$digest" "$tag" "$channel" "$outdir" bash "$root/ci/publish-manifest.sh" "$repository" "$channel" "$outdir" if [[ -n "${RELEASE_API_URL:-}" ]]; then python3 -c 'import json,sys; print(json.dumps({"manifest": open(sys.argv[1]).read(), "signature": open(sys.argv[2]).read()}))' \ "$outdir/manifest.json" "$outdir/manifest.sig" > "$outdir/payload.json" response="$outdir/response.json" status="$(curl --silent --show-error --retry 3 --max-time 30 -o "$response" -w '%{http_code}' -X POST "${RELEASE_API_URL%/}/api/release/offer" \ -H 'Content-Type: application/json' --data-binary "@$outdir/payload.json" 2>/dev/null || true)" if [[ "$status" == 2* ]]; then echo "also registered the signed $component release with the panel ($channel)" else echo "warning: the panel did not take the $component offer (HTTP ${status:-none}); updaters still get it from the registry" >&2 fi fi