#!/usr/bin/env bash # 把签名清单放进镜像仓库:ci/publish-manifest.sh <镜像仓库> <通道> <清单目录> # 清单目录里是 release-manifest.sh 产出的 manifest.json 和 manifest.sig。这里把它们装进一个没有任何文件层的小镜像的标签里, # 推到 <镜像仓库>-manifest:<通道>(例如 registry/moshiro-dev/moshiro-backend-manifest:dev)。 # 宿主机更新器和 deploy-node.sh 直接从仓库取这个镜像、用本机的发布公钥验签,所以更新不依赖面板在线,也不依赖 Release 页面; # 仓库只是存放处,被篡改只会让验签失败。需要登录过仓库(buildah login),或设置 ZOT_USERNAME / ZOT_SECRET。 set -euo pipefail repository="${1:?usage: publish-manifest.sh }" channel="${2:?channel}" dir="${3:?manifest dir}" [[ "$repository" =~ ^[a-z0-9./_:-]+$ && "$channel" =~ ^[a-z0-9._-]+$ ]] || { echo "unexpected characters in repository or channel" >&2; exit 2; } [[ -s "$dir/manifest.json" && -s "$dir/manifest.sig" ]] || { echo "$dir needs manifest.json and manifest.sig" >&2; exit 2; } ref="${repository}-manifest:${channel}" local_name="localhost/moshiro-manifest-build:$$" container="$(buildah from scratch)" trap 'buildah rm "$container" >/dev/null 2>&1 || true; buildah rmi "$local_name" >/dev/null 2>&1 || true' EXIT manifest_b64="$(base64 < "$dir/manifest.json" | tr -d '\n')" signature="$(tr -d '\n' < "$dir/manifest.sig")" buildah config \ --label "org.moshiro.manifest=$manifest_b64" \ --label "org.moshiro.signature=$signature" \ --label "org.opencontainers.image.title=MoShiro signed release manifest ($channel)" \ "$container" buildah commit --format oci "$container" "$local_name" >/dev/null creds=() if [[ -n "${ZOT_USERNAME:-}" && -n "${ZOT_SECRET:-}" ]]; then creds=(--creds "$ZOT_USERNAME:$ZOT_SECRET"); fi for attempt in 1 2 3; do if buildah push --tls-verify=true ${creds[@]+"${creds[@]}"} "$local_name" "docker://$ref" >/dev/null; then echo "published the signed manifest at $ref" exit 0 fi if [[ "$attempt" -lt 3 ]]; then echo "manifest push attempt $attempt failed; retrying in 5 seconds" >&2; sleep 5; fi done echo "could not publish the manifest at $ref" >&2 exit 1