修复AI游戏创作壳跨平台启动
Project CI / Frontend tests (pull_request) Successful in 2m28s
Project CI / Repository checks (pull_request) Successful in 3m17s
Project CI / Backend tests (pull_request) Successful in 10m26s
Project CI / Native shell tests (pull_request) Failing after 6m19s

修复 macOS 下 Unix 文件身份比较和临时目录测试兼容
隔离 AI 游戏创作本地数据库与发布身份并阻止旧 schema 降级启动
完善 Tauri 开发栈错误传播和 POSIX 子进程树清理
跳过 macOS 不支持的进程指标回调以消除周期告警
补充开发调度测试、技术方案和团队排障记忆
This commit is contained in:
2026-07-22 15:21:33 +08:00
parent 017e956724
commit 034a7f6651
10 changed files with 150 additions and 22 deletions
+77 -9
View File
@@ -1513,12 +1513,11 @@ class DevRunner {
await this.publishSpacetimeModule();
} catch (error) {
if (isSpacetimePublishPermissionError(error)) {
console.warn(
`[dev:spacetime] 本地发布被当前 identity 拒绝,保留已启动的 standalone: ${error.message}`,
throw new Error(
`本地数据库不属于当前隔离 identity,已停止启动以避免 API 使用旧 schema 后持续重试订阅。请改用独立本地数据目录,或在确认无需保留旧开发数据后重建该目录。详情: ${error.message}`,
);
} else {
throw error;
}
throw error;
}
}
}
@@ -1645,8 +1644,10 @@ class DevRunner {
async publishSpacetimeModule() {
const env = buildLocalRustProcessEnv(this.baseEnv);
this.prepareMigrationBootstrapSecret(env);
const cliConfigPath = await this.prepareLocalSpacetimeCliIdentity(env);
const args = buildSpacetimePublishArgs({
cliConfigPath,
database: this.options.database,
preserveDatabase: this.options.preserveDatabase,
server: this.state.spacetimeServer,
@@ -1660,6 +1661,48 @@ class DevRunner {
});
}
async prepareLocalSpacetimeCliIdentity(env) {
if (!isLoopbackSpacetimeServer(this.state.spacetimeServer)) {
return '';
}
await this.ensureApiServerSpacetimeToken();
const cliConfigPath = resolve(
this.options.spacetimeDataDir,
'dev-cli',
'cli.toml',
);
ensureParentDir(cliConfigPath);
if (
existsSync(cliConfigPath) &&
resolveCurrentSpacetimeCliToken(cliConfigPath) === this.spacetimeApiToken
) {
chmodSync(cliConfigPath, 0o600);
console.log('[dev:spacetime] 已复用隔离的本地发布 identity');
return cliConfigPath;
}
await runForeground(
'spacetime',
[
'--config-path',
cliConfigPath,
'login',
'--token',
this.spacetimeApiToken,
],
{
cwd: serverRsDir,
env,
label: 'spacetime-login',
},
);
if (existsSync(cliConfigPath)) {
chmodSync(cliConfigPath, 0o600);
}
console.log('[dev:spacetime] 已配置隔离的本地发布 identity');
return cliConfigPath;
}
prepareMigrationBootstrapSecret(env) {
let runtimeServiceBootstrapSecret = '';
switch (this.options.migrationBootstrapSecretMode) {
@@ -2814,8 +2857,14 @@ function isLoopbackSpacetimeServer(serverUrl) {
}
}
function resolveCurrentSpacetimeCliToken() {
const result = spawnSync('spacetime', ['login', 'show', '--token'], {
function resolveCurrentSpacetimeCliToken(cliConfigPath = '') {
const args = [
...(cliConfigPath ? ['--config-path', cliConfigPath] : []),
'login',
'show',
'--token',
];
const result = spawnSync('spacetime', args, {
cwd: repoRoot,
encoding: 'utf8',
shell: process.platform === 'win32',
@@ -2839,13 +2888,21 @@ function trimPreview(text, maxLength = 300) {
function runForeground(command, args, { cwd, env, label }) {
return new Promise((resolveRun, rejectRun) => {
let capturedOutput = '';
const capture = (chunk, target) => {
target.write(chunk);
capturedOutput = `${capturedOutput}${String(chunk)}`.slice(-32_768);
};
const child = spawn(command, args, {
cwd,
env,
stdio: 'inherit',
stdio: ['inherit', 'pipe', 'pipe'],
shell: process.platform === 'win32',
});
child.stdout?.on('data', (chunk) => capture(chunk, process.stdout));
child.stderr?.on('data', (chunk) => capture(chunk, process.stderr));
child.on('error', rejectRun);
child.on('exit', (code, signal) => {
if (signal) {
@@ -2854,7 +2911,12 @@ function runForeground(command, args, { cwd, env, label }) {
}
if (code !== 0) {
rejectRun(new Error(`[dev:${label}] 退出码: ${code}`));
const detail = trimPreview(capturedOutput, 2_000);
rejectRun(
new Error(
`[dev:${label}] 退出码: ${code}${detail ? `: ${detail}` : ''}`,
),
);
return;
}
@@ -2914,8 +2976,14 @@ function isDirectModuleExecution(argv1, moduleUrl, resolvePath = safeRealpath) {
}
}
function buildSpacetimePublishArgs({ database, server, preserveDatabase }) {
function buildSpacetimePublishArgs({
cliConfigPath = '',
database,
server,
preserveDatabase,
}) {
const args = [
...(cliConfigPath ? ['--config-path', cliConfigPath] : []),
'publish',
database,
'--server',