furniture-3d-system-Wu/scripts/yydd-prod-release-guards.sh
WuYongJie a308eb6c81 以图搜图粘贴与放大体验修复;部署脚本补齐 onnxruntime 原生库
- ProductArchiveImageSearchDialog:弹窗打开期间监听 document 级 paste,页面任意位置 Ctrl+V 直接粘贴图片(点击上传区仍是文件选择);搜索结果小图可点击,复用 ProductArchiveImagePreview 放大核对
- yydd-prod-release-guards.sh:prepare_standalone_runtime 补齐 Turbopack standalone 产物遗漏的 onnxruntime-node 原生二进制(libonnxruntime.so.*),根治部署后本地图索层加载失败;符号链接场景自动跳过
2026-10-07 09:57:08 +08:00

122 lines
4.1 KiB
Bash

# Embedded by both official deployment entry points; no remote helper dependency.
assert_release_ready() {
local app_root="$1"
local runtime="$app_root/.next/standalone"
if [ ! -s "$runtime/server.js" ] || [ ! -d "$runtime/.next/static" ]; then
echo "Incomplete standalone release: $app_root" >&2
return 1
fi
if [ -z "$(find "$runtime/.next/static" -type f -size +0c -print -quit)" ]; then
echo "Empty standalone static assets: $app_root" >&2
return 1
fi
}
prepare_standalone_runtime() {
local app_root="$1"
local runtime="$app_root/.next/standalone"
if [ ! -s "$runtime/server.js" ] || [ ! -d "$app_root/.next/static" ]; then
echo "Missing build output: $app_root" >&2
return 1
fi
if [ -z "$(find "$app_root/.next/static" -type f -size +0c -print -quit)" ]; then
echo "Empty build static assets: $app_root" >&2
return 1
fi
mkdir -p "$runtime/.next"
rm -rf -- "$runtime/.next/static" "$runtime/public"
cp -a "$app_root/.next/static" "$runtime/.next/static"
if [ -d "$app_root/public" ]; then
cp -a "$app_root/public" "$runtime/public"
fi
# Turbopack standalone tracing may omit onnxruntime-node native binaries;
# restore them or @huggingface/transformers fails to load libonnxruntime at runtime.
local ort_real="$app_root/node_modules/onnxruntime-node"
local ort_runtime="$runtime/node_modules/onnxruntime-node"
if [ -d "$ort_real/bin" ] && [ ! -L "$ort_runtime" ]; then
mkdir -p "$ort_runtime"
rm -rf -- "$ort_runtime/bin"
cp -a "$ort_real/bin" "$ort_runtime/bin"
fi
assert_release_ready "$app_root"
}
acquire_deploy_lock() {
command -v python3 >/dev/null || return 1
exec 9>"$BASE/.deploy.lock"
if ! flock -n 9; then
echo "Another production deployment is running" >&2
return 1
fi
}
verify_release_http() {
python3 - "$1" <<'PY'
import json
import sys
import time
from html.parser import HTMLParser
from urllib.parse import urljoin, urlparse
from urllib.request import urlopen
base = sys.argv[1].rstrip('/')
def get(url):
with urlopen(url, timeout=15) as response:
if response.status != 200:
raise RuntimeError('HTTP %s: %s' % (response.status, url))
return response.read(), response.headers.get_content_type(), response.url
for attempt in range(10):
try:
payload, _, _ = get(base + '/api/health')
result = json.loads(payload)
health = result.get('data', {}).get('services', {})
if not result.get('success'):
raise RuntimeError('Health request failed')
if health.get('database') != 'connected' or health.get('api') != 'running':
raise RuntimeError('Unhealthy database or API')
break
except Exception:
if attempt == 9:
raise
time.sleep(2)
class Assets(HTMLParser):
def __init__(self):
super().__init__()
self.urls = set()
def handle_starttag(self, tag, attrs):
attrs = dict(attrs)
if tag == 'script' and attrs.get('src'):
self.urls.add(attrs['src'])
if tag == 'link' and 'stylesheet' in attrs.get('rel', '').split() and attrs.get('href'):
self.urls.add(attrs['href'])
assets = set()
for path in ['/', '/installation-demo-workbench']:
content, kind, final_url = get(base + path)
if kind != 'text/html':
raise RuntimeError('Expected HTML: ' + path)
parser = Assets()
parser.feed(content.decode('utf-8'))
found = {urljoin(final_url, item) for item in parser.urls}
found = {item for item in found if urlparse(item).path.startswith('/_next/static/')}
if not found:
raise RuntimeError('No Next static references: ' + path)
assets.update(found)
for url in sorted(assets):
content, kind, _ = get(url)
if not content or kind == 'text/html':
raise RuntimeError('Invalid static asset: ' + url)
print('200 ' + url, flush=True)
if not any(urlparse(url).path.endswith('.css') for url in assets):
raise RuntimeError('No stylesheet verified')
if not any(urlparse(url).path.endswith('.js') for url in assets):
raise RuntimeError('No JavaScript verified')
print('Health and %d static assets verified at %s' % (len(assets), base), flush=True)
PY
}