mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-05 16:34:00 +01:00
stack-tests: only bun test files count as new tests, passed as paths
TEST_FILE matched every .ts under test/, so a PR whose only added file was a helper or fixture ran 'bun test test/helpers/x.ts', which exits 1 (the filter matches no test file) and was reported QUEUE_TRAIN_STACK_RED. A bare positional is also a substring filter that picks up unrelated files. The rule is now bun's own (.test, _test_, .spec, _spec_ in the name) and each file is passed as ./<path>, which bun treats as the exact file. The fixture PR 3 now adds a helper and is still 'no new test files'. Co-authored-by: capy-ai[bot] <230910855+capy-ai[bot]@users.noreply.github.com>
This commit is contained in:
1 parent
f25b22b0d4
commit
84f924f7df
2 files changed
+6
-5
No files matched your search
@@ -20,7 +20,8 @@ import { git } from './ship-queue-gate';
|
||||
import type { TrainPrefix, TrainSlot } from './ship-queue-train-record';
|
||||
|
||||
export const DEFAULT_STACK_TEST_COMMAND = ['bun', ...bunIsolationArgs(), 'test'];
|
||||
const TEST_FILE = /(?:^|\/)(?:tests?|__tests__|spec)\/.*\.[cm]?[jt]sx?$|\.(?:test|spec)\.[cm]?[jt]sx?$/;
|
||||
/** Bun's own test-file rule (`.test`, `_test_`, `.spec` or `_spec_` in the name); a helper or fixture under test/ is not a test file and would make `bun test <file>` exit 1 for matching nothing. */
|
||||
const TEST_FILE = /(?:\.(?:test|spec)|_(?:test|spec)_)[^/]*\.[cm]?[jt]sx?$/;
|
||||
|
||||
export interface StackTestResult { pr: string; prefix: number; files: string[]; ok: boolean; detail: string }
|
||||
|
||||
@@ -44,7 +45,7 @@ export function stackTests(repoRoot: string, baseSha: string, slots: TrainSlot[]
|
||||
const modules = path.join(repoRoot, 'node_modules');
|
||||
if (fs.existsSync(modules) && !fs.existsSync(path.join(dir, 'node_modules'))) fs.symlinkSync(modules, path.join(dir, 'node_modules'), 'dir');
|
||||
const [bin, ...args] = command;
|
||||
const run = spawnSync(bin!, [...args, ...files], { cwd: dir, encoding: 'utf8', timeout: timeoutMs, env: { ...process.env, CI: process.env.CI ?? '1' }, maxBuffer: 64 * 1024 * 1024 });
|
||||
const run = spawnSync(bin!, [...args, ...files.map(f => `./${f}`)], { cwd: dir, encoding: 'utf8', timeout: timeoutMs, env: { ...process.env, CI: process.env.CI ?? '1' }, maxBuffer: 64 * 1024 * 1024 });
|
||||
const tail = `${run.stdout ?? ''}\n${run.stderr ?? ''}`.split('\n').filter(l => /^\(fail\)|^\s*\d+ (pass|fail)$|^error:/.test(l)).slice(-6).join('; ');
|
||||
results.push({ pr: slot.pr, prefix: prefix.index, files, ok: run.status === 0, detail: run.status === 0 ? 'pass' : run.error ? `${run.error.message}` : tail || `exit ${run.status}` });
|
||||
} finally {
|
||||
|
||||
@@ -442,12 +442,12 @@ describe('ready --dispatch-ci', () => {
|
||||
|
||||
describe('train build --dry-run --stack-tests', () => {
|
||||
// Value: protects=a PR whose new tests pass on its own branch but fail once stacked behind another PR's change is caught before the train spends a gate (#3460 on #3451, 2026-10-26);
|
||||
// fails_when=the new test files run against the PR head instead of the integrated prefix, a failing prefix still dry-runs green, or a PR without new tests is misreported; why_new=no pre-dispatch stack check existed; seam=bun test in a scratch worktree; no_claim=the repo's full suite on the prefix
|
||||
test('runs each PR\'s new test files on its integrated prefix T<k>: a pass and a no-tests PR are reported, a failure refuses the dry run and names the prefix, and the ordinary dry run skips it', () => {
|
||||
// fails_when=the new test files run against the PR head instead of the integrated prefix, a failing prefix still dry-runs green, or a PR without new tests (a helper under test/ included: bun exits 1 when a positional filter matches no test file) is misreported; why_new=no pre-dispatch stack check existed; seam=bun test in a scratch worktree; no_claim=the repo's full suite on the prefix
|
||||
test('runs each PR\'s new test files on its integrated prefix T<k>: a pass and a helper-only PR are reported, a failure refuses the dry run and names the prefix, and the ordinary dry run skips it', () => {
|
||||
const fx = make();
|
||||
const h1 = openPr(fx, '1', { file: 'test/pr-1.test.ts', text: "import { expect, test } from 'bun:test';\ntest('pr-1', () => { expect(1).toBe(1); });\n" });
|
||||
const h2 = openPr(fx, '2', { file: 'test/pr-2.test.ts', text: "import { existsSync } from 'node:fs';\nimport { expect, test } from 'bun:test';\ntest('pr-2 wants no pr-1 test beside it', () => { expect(existsSync('test/pr-1.test.ts')).toBe(false); });\n" });
|
||||
const h3 = openPr(fx, '3');
|
||||
const h3 = openPr(fx, '3', { file: 'test/helpers/pr-3-helper.ts', text: 'export const three = 3;\n' });
|
||||
readyReceipt(fx, '1', h1);
|
||||
readyReceipt(fx, '2', h2);
|
||||
readyReceipt(fx, '3', h3);
|
||||
|
||||
Reference in new issue
Block a user