chore: 一键检查、发布脚本与开发环境约定
- deno task test:all(scripts/test-all.sh):逐包跑完再汇总,连不上测试库直接失败, web 用 Node 跑 vitest;deno task ci 改用它 - deno task release(scripts/release.sh):工作区不干净、CHANGELOG 无本版条目即拒绝; 打 tag、构建、只替换 app、核对健康接口版本 - deno task dev:up:起开发库并迁移到最新;开发 API 端口改 4390(4380 留给本机部署版) - CLAUDE.md:命令、提交与发布约定、文档放哪 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
ceb66f8c77
commit
11ca2f01ff
200 files changed
+191
-23061
No files matched your search
@@ -0,0 +1,63 @@
|
||||
#!/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"
|
||||
@@ -0,0 +1,54 @@
|
||||
#!/usr/bin/env bash
|
||||
# 全量测试:逐个包跑完(不在第一个失败处停),最后汇总;连不上测试库直接失败,不让数据库用例静默跳过。
|
||||
# 用法:sh scripts/test-all.sh [包目录...] 缺省跑全部 workspace 成员
|
||||
# web 用 Node 跑 vitest(Deno 跑 web 的 vitest 有兼容问题)。
|
||||
set -u
|
||||
cd "$(dirname "$0")/.."
|
||||
ROOT=$PWD
|
||||
|
||||
if [ -f .env ]; then set -a; . ./.env; set +a; fi
|
||||
DB_URL=${DATABASE_URL:-postgres://umt:umt@localhost:55433/umt}
|
||||
|
||||
if [ "${UMT_SKIP_DB_TESTS:-}" != "1" ]; then
|
||||
if ! deno eval --quiet "
|
||||
import pg from 'npm:[email protected]';
|
||||
const c = new pg.Client({ connectionString: '$DB_URL', connectionTimeoutMillis: 3000 });
|
||||
await c.connect(); await c.end();" >/dev/null 2>&1; then
|
||||
echo "✗ 连不上测试库($DB_URL)。先 deno task dev:up;确实不跑数据库用例时设 UMT_SKIP_DB_TESTS=1" >&2
|
||||
exit 2
|
||||
fi
|
||||
fi
|
||||
|
||||
members=("$@")
|
||||
[ ${#members[@]} -eq 0 ] && members=(packages/adapters packages/agent packages/contracts packages/db packages/domain
|
||||
packages/mapping packages/tasks packages/testkit apps/server apps/web)
|
||||
|
||||
LOG_DIR=${TEST_LOG_DIR:-$ROOT/.local/test-logs}
|
||||
mkdir -p "$LOG_DIR"
|
||||
failed=()
|
||||
summary=()
|
||||
for m in "${members[@]}"; do
|
||||
log="$LOG_DIR/$(echo "$m" | tr / -).log"
|
||||
printf '▶ %-20s ' "$m"
|
||||
if [ "$m" = apps/web ]; then
|
||||
(cd "$m" && "$ROOT/node_modules/.bin/vitest" run) >"$log" 2>&1
|
||||
else
|
||||
(cd "$m" && deno run -A npm:vitest run) >"$log" 2>&1
|
||||
fi
|
||||
code=$?
|
||||
line=$(sed 's/\x1b\[[0-9;]*m//g' "$log" | grep -E '^\s+Tests ' | tail -1 | tr -s ' ')
|
||||
if [ $code -eq 0 ]; then echo "✓ ${line:-}"; else echo "✗ ${line:-退出码 $code}"; failed+=("$m"); fi
|
||||
summary+=("$m:${line:-exit $code}")
|
||||
done
|
||||
|
||||
echo
|
||||
if [ ${#failed[@]} -eq 0 ]; then
|
||||
echo "全部通过(日志 $LOG_DIR)"
|
||||
else
|
||||
echo "失败:${failed[*]}"
|
||||
for m in "${failed[@]}"; do
|
||||
echo "── $m"
|
||||
sed 's/\x1b\[[0-9;]*m//g' "$LOG_DIR/$(echo "$m" | tr / -).log" | grep -E '(FAIL|×) ' | head -10
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
Reference in new issue
Block a user