Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 25 additions & 25 deletions packages/cli/src/commands/migrate/object-scope.integration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ import { copyFileSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'nod
import { tmpdir } from 'node:os';
import { dirname, join, resolve } from 'node:path';
import { fileURLToPath } from 'node:url';
import Database from 'better-sqlite3';

const HERE = dirname(fileURLToPath(import.meta.url));
const CLI_ROOT = resolve(HERE, '..', '..', '..');
Expand Down Expand Up @@ -125,26 +126,14 @@ process.exit(0);
`;

/** The repro's off-shape value, written past the write path: a location keyed the retired way. */
const OFF_SHAPE_CHILD = `
const { SqlDriver } = await import('@objectstack/driver-sql');
const raw = new SqlDriver({ client: 'better-sqlite3', connection: { filename: process.env.FIXTURE_DB }, useNullAsDefault: true });
await raw.knex('os21644_site').where({ id: 's1' }).update({ geo: JSON.stringify({ latitude: 1, longitude: 2 }) });
await raw.disconnect();
process.exit(0);
`;

/** The flag rows and the app rows, read on a connection of our own. */
const READ_STATE_CHILD = `
const { SqlDriver } = await import('@objectstack/driver-sql');
const raw = new SqlDriver({ client: 'better-sqlite3', connection: { filename: process.env.FIXTURE_DB }, useNullAsDefault: true });
const k = raw.knex;
const flags = await k('sys_migration').select('id', 'last_run_at', 'verified_at', 'blocking').orderBy('id');
const site = await k('os21644_site').select('id', 'geo').orderBy('id');
const product = await k('os21644_product').select('id', 'image').orderBy('id');
await raw.disconnect();
process.stdout.write(JSON.stringify({ flags, site, product }));
process.exit(0);
`;
function writeOffShape(db: string): void {
const conn = new Database(db);
try {
conn.prepare('UPDATE os21644_site SET geo = ? WHERE id = ?').run(JSON.stringify({ latitude: 1, longitude: 2 }), 's1');
} finally {
conn.close();
}
}

interface Run {
code: number | null;
Expand Down Expand Up @@ -186,10 +175,22 @@ function freshDb(): string {
return db;
}

/**
* The flag rows and the app rows, read on a connection of our own, in this
* process: a child `node` per read cost ~0.5 s each, sixteen times a file.
*/
function readState(db: string): State {
const out = childNode(READ_STATE_CHILD, { FIXTURE_DB: db });
if (out.status !== 0) throw new Error(`could not read the fixture database (status ${out.status})\n${out.stderr}`);
return JSON.parse(out.stdout) as State;
// Opened as the child it replaces opened it (read-write, knex's default).
const conn = new Database(db);
try {
return {
flags: conn.prepare('SELECT id, last_run_at, verified_at, blocking FROM sys_migration ORDER BY id').all() as FlagRow[],
site: conn.prepare('SELECT id, geo FROM os21644_site ORDER BY id').all() as State['site'],
product: conn.prepare('SELECT id, image FROM os21644_product ORDER BY id').all() as State['product'],
};
} finally {
conn.close();
}
}

function flagRow(state: State, id: string): FlagRow | undefined {
Expand Down Expand Up @@ -296,8 +297,7 @@ beforeAll(async () => {

// The measured repro: one off-shape value stored, then a misspelled --object --apply.
const reproDb = freshDb();
const offShape = childNode(OFF_SHAPE_CHILD, { FIXTURE_DB: reproDb });
if (offShape.status !== 0) throw new Error(`the off-shape value was not written\n${offShape.stderr}`);
writeOffShape(reproDb);
const reproRightDb = join(dir, 'data', 'repro-right.db');
copyFileSync(reproDb, reproRightDb);
reproFullDry = await runCommand('value-shapes', ['--json'], reproDb);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,14 @@ import Database from 'better-sqlite3';

const HERE = dirname(fileURLToPath(import.meta.url));
const CLI_ROOT = resolve(HERE, '..', '..', '..');
/**
* The source entry, spawned by this process's own `node`, as the family's other spawners
* (`data-commands.absent-database`, `object-scope`, `unmapped-columns`) spawn it. Not through
* the `tsx` binary: the entry, its `src/` and its pinned `NODE_ENV=development` are the same
* either way, and the wrapper only adds a second process and its own transform, ~3.4 s of
* every spawn (#23181 slice 12: `tsx bin/run-dev.js --version` 8.28-8.44 s, `node` 4.93-4.99 s).
*/
const RUN_DEV = resolve(CLI_ROOT, 'bin', 'run-dev.js');
const TSX = resolve(CLI_ROOT, '..', '..', 'node_modules', '.bin', 'tsx');
const CASE_TIMEOUT_MS = 300_000;
const NOT_AN_OBJECT = ['sys_packages'];

Expand Down Expand Up @@ -98,10 +104,10 @@ interface Reading {
function bootThenPlan(dir: string): Reading {
const dbFile = join(dir, 'boot.db');
const env = childEnv(dir, dbFile);
const boot = spawnSync(TSX, [RUN_DEV, 'serve', '--no-server', '--no-ui', '--no-console', '--port', '0'], {
const boot = spawnSync(process.execPath, [RUN_DEV, 'serve', '--no-server', '--no-ui', '--no-console', '--port', '0'], {
cwd: dir, env: { ...env, OS_MIGRATE_AND_EXIT: '1' }, encoding: 'utf8', timeout: 240_000,
});
const plan = spawnSync(TSX, [RUN_DEV, 'migrate', 'plan', '--json'], {
const plan = spawnSync(process.execPath, [RUN_DEV, 'migrate', 'plan', '--json'], {
cwd: dir, env, encoding: 'utf8', timeout: 240_000,
});
let payload: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,14 @@ import Database from 'better-sqlite3';

const HERE = dirname(fileURLToPath(import.meta.url));
const CLI_ROOT = resolve(HERE, '..', '..', '..');
/**
* The source entry, spawned by this process's own `node`, as the family's other spawners
* (`data-commands.absent-database`, `object-scope`, `unmapped-columns`) spawn it. Not through
* the `tsx` binary: the entry, its `src/` and its pinned `NODE_ENV=development` are the same
* either way, and the wrapper only adds a second process and its own transform, ~3.4 s of
* every spawn (#23181 slice 12: `tsx bin/run-dev.js --version` 8.28-8.44 s, `node` 4.93-4.99 s).
*/
const RUN_DEV = resolve(CLI_ROOT, 'bin', 'run-dev.js');
const TSX = resolve(CLI_ROOT, '..', '..', 'node_modules', '.bin', 'tsx');
const CASE_TIMEOUT_MS = 600_000;
const SPAWN_TIMEOUT_MS = 240_000;

Expand Down Expand Up @@ -134,7 +140,7 @@ async function freePort(): Promise<number> {
*/
function devBootOnce(): string {
const r = spawnSync(
TSX,
process.execPath,
[RUN_DEV, 'dev', '--port', String(port), '--compile', '--no-watch', '--no-restart', '--no-seed-admin'],
{ cwd: dir, env: env({ OS_MIGRATE_AND_EXIT: '1' }), encoding: 'utf8', timeout: SPAWN_TIMEOUT_MS },
);
Expand All @@ -145,7 +151,7 @@ function devBootOnce(): string {

/** One read-only `os migrate` door's `--json` document. */
function migrateJson(args: string[]): any {
const r = spawnSync(TSX, [RUN_DEV, 'migrate', ...args, '--json'], {
const r = spawnSync(process.execPath, [RUN_DEV, 'migrate', ...args, '--json'], {
cwd: dir, env: env(), encoding: 'utf8', timeout: SPAWN_TIMEOUT_MS,
});
expect(r.status, `os migrate ${args.join(' ')} failed:\n${`${r.stdout}\n${r.stderr}`.slice(-1500)}`).toBe(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@ import Database from 'better-sqlite3';

const HERE = dirname(fileURLToPath(import.meta.url));
const CLI_ROOT = resolve(HERE, '..', '..', '..');
/**
* The source entry, spawned by this process's own `node`, as the family's other spawners
* (`data-commands.absent-database`, `object-scope`, `unmapped-columns`) spawn it. Not through
* the `tsx` binary: the entry, its `src/` and its pinned `NODE_ENV=development` are the same
* either way, and the wrapper only adds a second process and its own transform, ~3.4 s of
* every spawn (#23181 slice 12: `tsx bin/run-dev.js --version` 8.28-8.44 s, `node` 4.93-4.99 s).
*/
const RUN_DEV = resolve(CLI_ROOT, 'bin', 'run-dev.js');
const TSX = resolve(CLI_ROOT, '..', '..', 'node_modules', '.bin', 'tsx');
const CASE_TIMEOUT_MS = 300_000;

const APP_OBJECT = 'os25134_deal';
Expand Down Expand Up @@ -93,14 +99,14 @@ function childEnv(f: Fixture, extra: NodeJS.ProcessEnv = {}): NodeJS.ProcessEnv

/** `os serve`'s own provision-and-exit: a fresh store, the full composition schema-synced into it. */
function serveBoot(f: Fixture): void {
const boot = spawnSync(TSX, [RUN_DEV, 'serve', '--no-server', '--no-ui', '--no-console', '--port', '0'], {
const boot = spawnSync(process.execPath, [RUN_DEV, 'serve', '--no-server', '--no-ui', '--no-console', '--port', '0'], {
cwd: f.dir, env: childEnv(f, { OS_MIGRATE_AND_EXIT: '1' }), encoding: 'utf8', timeout: 240_000,
});
expect(boot.status, `the serving boot did not provision the database:\n${(boot.stderr ?? '').slice(-6000)}`).toBe(0);
}

function plan(f: Fixture, json: boolean): { exit: number | null; payload: any; text: string } {
const run = spawnSync(TSX, [RUN_DEV, 'migrate', 'plan', ...(json ? ['--json'] : [])], {
const run = spawnSync(process.execPath, [RUN_DEV, 'migrate', 'plan', ...(json ? ['--json'] : [])], {
cwd: f.dir, env: childEnv(f), encoding: 'utf8', timeout: 240_000,
});
let payload: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,14 @@ import Database from 'better-sqlite3';

const HERE = dirname(fileURLToPath(import.meta.url));
const CLI_ROOT = resolve(HERE, '..', '..', '..');
/**
* The source entry, spawned by this process's own `node`, as the family's other spawners
* (`data-commands.absent-database`, `object-scope`, `unmapped-columns`) spawn it. Not through
* the `tsx` binary: the entry, its `src/` and its pinned `NODE_ENV=development` are the same
* either way, and the wrapper only adds a second process and its own transform, ~3.4 s of
* every spawn (#23181 slice 12: `tsx bin/run-dev.js --version` 8.28-8.44 s, `node` 4.93-4.99 s).
*/
const RUN_DEV = resolve(CLI_ROOT, 'bin', 'run-dev.js');
const TSX = resolve(CLI_ROOT, '..', '..', 'node_modules', '.bin', 'tsx');
const CASE_TIMEOUT_MS = 300_000;

/** The one table outside the object set (`PackageServicePlugin.start()`'s raw DDL; see the boot-parity pin). */
Expand Down Expand Up @@ -116,7 +122,7 @@ const BOOT_STREAM_TAIL = 8_000;
* there at `error`), and an assertion that failed without it left the CI log unable to confirm or refute one.
*/
function serveBoot(f: Fixture, extra: NodeJS.ProcessEnv = {}): string {
const boot = spawnSync(TSX, [RUN_DEV, 'serve', '--no-server', '--no-ui', '--no-console', '--port', '0'], {
const boot = spawnSync(process.execPath, [RUN_DEV, 'serve', '--no-server', '--no-ui', '--no-console', '--port', '0'], {
cwd: f.dir, env: childEnv(f, { ...extra, OS_MIGRATE_AND_EXIT: '1' }), encoding: 'utf8', timeout: 240_000,
});
const output =
Expand All @@ -130,7 +136,7 @@ function serveBoot(f: Fixture, extra: NodeJS.ProcessEnv = {}): string {
const afterBoot = (bootOutput: string, what: string): string => `${what}\n${bootOutput}`;

function command(f: Fixture, argv: string[], extra: NodeJS.ProcessEnv = {}): { exit: number | null; payload: any } {
const run = spawnSync(TSX, [RUN_DEV, 'migrate', ...argv], { cwd: f.dir, env: childEnv(f, extra), encoding: 'utf8', timeout: 240_000 });
const run = spawnSync(process.execPath, [RUN_DEV, 'migrate', ...argv], { cwd: f.dir, env: childEnv(f, extra), encoding: 'utf8', timeout: 240_000 });
let payload: any;
try { payload = JSON.parse(run.stdout); } catch { payload = { unparsed: `${run.stdout}\n${run.stderr}`.slice(-800) }; }
return { exit: run.status, payload };
Expand Down
Loading