Deploy admin web with release bundle
Some checks failed
CI / verify (push) Has been cancelled

This commit is contained in:
kdletters
2026-05-01 17:56:16 +08:00
parent 8718472dbd
commit 443a7781e5
9 changed files with 189 additions and 51 deletions

View File

@@ -310,6 +310,7 @@ fi
TARGET_DIR="${BUILD_ROOT}/${BUILD_NAME}"
WEB_DIR="${TARGET_DIR}/web"
ADMIN_WEB_DIR="${WEB_DIR}/admin"
API_BINARY_SOURCE="${SERVER_RS_DIR}/target/x86_64-unknown-linux-gnu/release/api-server"
WASM_SOURCE="${SERVER_RS_DIR}/target/wasm32-unknown-unknown/release/spacetime_module.wasm"
@@ -364,6 +365,12 @@ if [[ "${SKIP_WEB_BUILD}" -ne 1 ]]; then
cd "${REPO_ROOT}"
node scripts/vite-cli.mjs build --outDir "${WEB_DIR}" --emptyOutDir
)
echo "[deploy:rust] 构建后台 Vite release -> ${ADMIN_WEB_DIR}"
(
cd "${REPO_ROOT}"
MSYS2_ARG_CONV_EXCL="--base=" node scripts/admin-web-build.mjs build --base=/admin/ --outDir "${ADMIN_WEB_DIR}" --emptyOutDir
)
fi
if [[ "${SKIP_API_BUILD}" -ne 1 ]]; then
@@ -421,11 +428,14 @@ import {fileURLToPath} from 'node:url';
const releaseDir = path.dirname(fileURLToPath(import.meta.url));
const webRoot = path.join(releaseDir, 'web');
const adminWebRoot = path.join(webRoot, 'admin');
const webHost = process.env.GENARRATIVE_WEB_HOST || '127.0.0.1';
const webPort = Number(process.env.GENARRATIVE_WEB_PORT || '3000');
const apiTarget = new URL(process.env.GENARRATIVE_API_TARGET || 'http://127.0.0.1:8082');
const indexPath = path.join(webRoot, 'index.html');
const adminIndexPath = path.join(adminWebRoot, 'index.html');
const proxyPrefixes = [
'/admin/api',
'/api/',
'/api',
'/generated-character-drafts',
@@ -466,11 +476,11 @@ function sendFile(response, filePath) {
.pipe(response);
}
function serveStatic(request, response, pathname) {
function serveStaticFromRoot(response, pathname, rootDir, fallbackIndexPath) {
const decodedPath = decodeURIComponent(pathname);
const relativePath = decodedPath === '/' ? '/index.html' : decodedPath;
const filePath = path.normalize(path.join(webRoot, relativePath));
const safeRelativePath = path.relative(webRoot, filePath);
const filePath = path.normalize(path.join(rootDir, relativePath));
const safeRelativePath = path.relative(rootDir, filePath);
if (safeRelativePath.startsWith('..') || path.isAbsolute(safeRelativePath)) {
response.writeHead(403, {'content-type': 'text/plain; charset=utf-8'});
@@ -480,12 +490,21 @@ function serveStatic(request, response, pathname) {
const resolvedFilePath = fs.existsSync(filePath) && fs.statSync(filePath).isFile()
? filePath
: indexPath;
: fallbackIndexPath;
response.writeHead(200, {'content-type': contentTypeFor(resolvedFilePath)});
sendFile(response, resolvedFilePath);
}
function serveStatic(request, response, pathname) {
serveStaticFromRoot(response, pathname, webRoot, indexPath);
}
function serveAdminStatic(response, pathname) {
const adminPath = pathname === '/admin/' ? '/' : pathname.replace(/^\/admin/u, '');
serveStaticFromRoot(response, adminPath, adminWebRoot, adminIndexPath);
}
function proxyToApi(request, response) {
const targetUrl = new URL(request.url || '/', apiTarget);
const proxyRequest = http.request(
@@ -522,6 +541,17 @@ const server = http.createServer((request, response) => {
return;
}
if (url.pathname === '/admin') {
response.writeHead(301, {location: '/admin/'});
response.end();
return;
}
if (url.pathname === '/admin/' || url.pathname.startsWith('/admin/')) {
serveAdminStatic(response, url.pathname);
return;
}
serveStatic(request, response, url.pathname);
});
@@ -1189,7 +1219,7 @@ cat >"${TARGET_DIR}/README.md" <<'EOF'
## 内容
- \`.env\` / \`.env.local\`:从仓库根目录复制的环境文件,同时各保留一份到 \`web/\`
- \`web/\`Vite release 静态资源
- \`web/\`主前端 Vite release 静态资源\`web/admin/\` 为后台管理前端静态资源
- \`api-server\`x86_64-unknown-linux-gnu release 可执行文件
- \`spacetime_module.wasm\`wasm32-unknown-unknown release 模块
- \`migration-bootstrap-secret.txt\`:本发布包 wasm 编译时注入的迁移引导密钥;服务器 \`start.sh\` 发布时会显示,迁移授权完成后可删除
@@ -1211,6 +1241,11 @@ cat >"${TARGET_DIR}/README.md" <<'EOF'
默认启动会先尝试无清库发布;如果 SpacetimeDB 返回 schema 冲突,\`start.sh\` 会把旧库导出到 \`database-migrations/<database>/\`,随后清库发布新 wasm并用 \`--replace-existing\` 导入回灌。
## 入口
- 主站:\`http://<web-host>:<web-port>/\`
- 后台:\`http://<web-host>:<web-port>/admin/\`
## 环境变量
- 启动时会先加载发布目录根部的 \`.env\` 与 \`.env.local\`,再回退到脚本内默认值。