#!/usr/bin/env bash # 测试环境发布:从干净的提交构建并替换 app 容器。 # 用法:bash scripts/release.sh 版本取根 deno.json # bash scripts/release.sh --no-build 只用已有镜像重建容器 # 前提:工作区干净、CHANGELOG.md 已写好本版本条目、所有成员包版本号一致。 # 做的事:打 tag v<版本>(已存在则须指向 HEAD)→ 写 .env.deploy 的 APP_VERSION / SOURCE_REVISION # → 构建镜像 → 只替换 app(启动时自动迁移)→ 等 healthy 并核对健康接口版本。 set -euo pipefail cd "$(dirname "$0")/.." ENV_FILE=.env.deploy BUILD=1 [ "${1:-}" = "--no-build" ] && BUILD=0 die() { echo "✗ $*" >&2; exit 1; } [ -f "$ENV_FILE" ] || die "缺少 $ENV_FILE" [ -z "$(git status --porcelain)" ] || die "工作区有未提交的改动,先提交再发布(git status)" version=$(deno eval --quiet 'console.log(JSON.parse(Deno.readTextFileSync("deno.json")).version)') tag="v$version" for f in apps/*/deno.json apps/web/package.json packages/*/deno.json; do v=$(deno eval --quiet "console.log(JSON.parse(Deno.readTextFileSync('$f')).version ?? '')") [ -z "$v" ] || [ "$v" = "$version" ] || die "$f 版本 $v 与根 deno.json $version 不一致" done grep -q "^## \[$version\]" CHANGELOG.md || die "CHANGELOG.md 还没有 ## [$version] 条目" head=$(git rev-parse --short HEAD) if git rev-parse -q --verify "refs/tags/$tag" >/dev/null; then [ "$(git rev-parse --short "$tag^{commit}")" = "$head" ] || die "$tag 已存在但不指向 HEAD($head)" else git tag -a "$tag" -m "$tag" echo "已打 tag $tag → $head" fi set_env() { if grep -q "^$1=" "$ENV_FILE"; then sed -i "s|^$1=.*|$1=$2|" "$ENV_FILE"; else echo "$1=$2" >>"$ENV_FILE"; fi } set_env APP_VERSION "$tag" set_env SOURCE_REVISION "$head" compose() { docker compose --env-file "$ENV_FILE" "$@"; } if [ $BUILD -eq 1 ]; then echo "▶ 构建 uhd-media-tool:$tag" compose build app fi echo "▶ 替换 app" compose up -d --no-deps app echo "▶ 等待 healthy" cid=$(compose ps -q app) for _ in $(seq 1 90); do st=$(docker inspect -f '{{.State.Health.Status}}' "$cid" 2>/dev/null || echo starting) [ "$st" = healthy ] && break [ "$st" = unhealthy ] && die "app unhealthy;看日志:docker compose --env-file $ENV_FILE logs --tail 100 app" sleep 2 done [ "$st" = healthy ] || die "等待 healthy 超时" port=$(grep -E '^UMT_PORT=' "$ENV_FILE" | cut -d= -f2) health=$(curl -fsS "http://127.0.0.1:${port:-4380}/api/v1/health") echo "$health" | grep -q "\"version\":\"$version\"" || die "健康接口版本不对:$health" echo "✓ 已发布 $tag($head):$health"