fix(gstack2): harden integrated runtime verification

This commit is contained in:
Sinabina
2026-07-21 12:29:01 -07:00
parent 09492d34b4
commit 37144e8b05
24 changed files with 2032 additions and 3313 deletions
+6 -1
View File
@@ -8,7 +8,12 @@ import {
} from '../../runtime/install.js';
const ROOT = path.resolve(import.meta.dir, '../..');
const REQUIRED_CAPABILITIES = ['browse', 'gstack-design', 'make-pdf'] as const;
const REQUIRED_CAPABILITIES = [
'browse',
'gstack-design',
'make-pdf',
...(process.platform === 'darwin' ? ['gstack-ios-qa-daemon', 'gstack-ios-qa-mint'] : []),
] as const;
export interface RuntimePayloadEntry {
path: string;
+22
View File
@@ -0,0 +1,22 @@
#!/usr/bin/env bun
import { collectFreeTestFiles } from '../test-free-shards';
import { runStrictTestShard } from '../test-free-strict';
const GSTACK2_TEST_TIMEOUT_MS = 30_000;
const files = collectFreeTestFiles().filter((file) => /^test\/gstack2-.*\.test\.ts$/.test(file));
if (files.length === 0) {
throw new Error('No GStack 2 test files were discovered.');
}
console.log(`[test:gstack2] ${files.length} files across ${files.length} isolated processes`);
for (let index = 0; index < files.length; index += 1) {
const file = files[index];
console.log(`[test:gstack2] file ${index + 1}/${files.length}: ${file}`);
const exitCode = await runStrictTestShard([file], GSTACK2_TEST_TIMEOUT_MS);
if (exitCode !== 0) {
process.exitCode = exitCode;
break;
}
}
+5 -2
View File
@@ -302,8 +302,11 @@ export function planBoundedFreeTestShards(
return shards;
}
export function buildShardArgs(files: string[]): string[] {
return ['test', ...files, '--max-concurrency=1', `--timeout=${FREE_TEST_TIMEOUT_MS}`];
export function buildShardArgs(files: string[], timeoutMs = FREE_TEST_TIMEOUT_MS): string[] {
if (!Number.isInteger(timeoutMs) || timeoutMs <= 0) {
throw new Error(`Test timeout must be a positive integer. Received: ${timeoutMs}`);
}
return ['test', ...files, '--max-concurrency=1', `--timeout=${timeoutMs}`];
}
type CliOptions = {
+5 -2
View File
@@ -261,9 +261,12 @@ export async function runDefaultFreeTests(): Promise<number> {
return slopSignal === null ? 0 : terminationSignalExitCode(slopSignal);
}
export async function runStrictTestShard(files: string[]): Promise<number> {
export async function runStrictTestShard(
files: string[],
timeoutMs?: number,
): Promise<number> {
if (files.length === 0) throw new Error('Cannot run an empty free-test shard.');
const child = spawn(process.execPath, buildShardArgs(exactTestFileSelectors(files)), {
const child = spawn(process.execPath, buildShardArgs(exactTestFileSelectors(files), timeoutMs), {
cwd: ROOT,
env: process.env,
stdio: ['inherit', 'pipe', 'pipe'],