feat: add guarded portal canary release
Memind CI / Test, build, and release guards (push) Failing after 2m14s

This commit is contained in:
john
2026-07-26 19:51:44 +08:00
parent 058d646b32
commit 286069449b
33 changed files with 2161 additions and 53 deletions
+40
View File
@@ -136,6 +136,26 @@ async function bundleServer() {
await run(esbuildBin, args);
}
async function bundleCanaryProxy() {
if (!(await exists(esbuildBin))) {
throw new Error(`未找到 esbuild: ${esbuildBin}`);
}
console.log('==> 打包用户级灰度路由器');
const args = [
'memind-canary-proxy.mjs',
'--bundle',
'--platform=node',
'--format=esm',
`--target=${runtimeNodeTarget}`,
'--outfile=.runtime/portal/memind-canary-proxy.mjs',
'--banner:js=import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);',
];
for (const pkg of externalPackages) {
args.push(`--external:${pkg}`);
}
await run(esbuildBin, args);
}
async function bundleSandboxMcp() {
if (!(await exists(esbuildBin))) {
throw new Error(`未找到 esbuild: ${esbuildBin}`);
@@ -386,6 +406,21 @@ async function writeMetadata() {
} else {
throw new Error(`缺少 Portal 启动脚本: ${prodStartScript}`);
}
for (const scriptName of [
'run-memind-portal-candidate.sh',
'run-memind-canary-proxy-prod.sh',
]) {
const source = path.join(root, 'scripts', scriptName);
if (!(await exists(source))) {
throw new Error(`缺少灰度运行脚本: ${source}`);
}
await fs.copyFile(source, path.join(runtimeScriptsDir, scriptName));
await fs.chmod(path.join(runtimeScriptsDir, scriptName), 0o755);
}
await fs.copyFile(
path.join(root, 'scripts', 'goosed-canary.compose.yml'),
path.join(runtimeScriptsDir, 'goosed-canary.compose.yml'),
);
await fs.copyFile(
path.join(root, 'scripts', 'load-env.mjs'),
@@ -491,6 +526,7 @@ async function writeMetadata() {
' tkmind-search-mcp.mjs (esbuild bundle; required when MindSearch is enabled)',
' tkmind-excel-mcp.mjs (esbuild bundle; required when Excel Analyst is enabled)',
' wechat-mp.bundle.mjs (esbuild bundle; hot-swappable WeChat MP module)',
' memind-canary-proxy.mjs (immutable-identity stable/candidate router)',
'',
'Post-deploy validation (scripts/check-mindspace-public-links.mjs):',
' Scans MindSpace/*/public/*.html for missing relative href/src/cover targets.',
@@ -516,6 +552,7 @@ async function writeMetadata() {
' Current public path: m.tkmind.cn -> 105 nginx -> 103 Portal :8081',
' No separate public test domain remains; use explicit local/test overrides only when needed.',
' Production H5 and WeChat links should use m.tkmind.cn unless a test rollout explicitly overrides H5_PUBLIC_BASE_URL.',
' Canary layout: stable :8081, candidate :18081, identity router :18080, candidate goosed :18015.',
'',
'Streaming runtime operations:',
' node scripts/check-stream-runtime.mjs',
@@ -560,6 +597,7 @@ async function main() {
await buildFrontend();
await copyRuntimeAssets();
await bundleServer();
await bundleCanaryProxy();
await bundleWechatMp();
await bundleSandboxMcp();
await bundleMindSearchMcp();
@@ -571,6 +609,8 @@ async function main() {
await copyMindspacePublicLinkTools();
await writeMetadata();
await fs.chmod(path.join(runtimeRoot, 'scripts', 'run-memind-portal-prod.sh'), 0o755);
await fs.chmod(path.join(runtimeRoot, 'scripts', 'run-memind-portal-candidate.sh'), 0o755);
await fs.chmod(path.join(runtimeRoot, 'scripts', 'run-memind-canary-proxy-prod.sh'), 0o755);
await fs.chmod(path.join(runtimeRoot, 'scripts', 'wechat-mp-menu.mjs'), 0o755);
await fs.chmod(path.join(runtimeRoot, 'scripts', 'check-stream-runtime.mjs'), 0o755);
await fs.chmod(path.join(runtimeRoot, 'scripts', 'runtime-worker-drain.mjs'), 0o755);