Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1112937
Add undefined target handling for deploy/revert/verify operations
pyramation Jul 21, 2025
e3e02f0
Fix redundant condition logic in moduleToChange assignment
pyramation Jul 21, 2025
06d5576
Remove unnecessary parentheses from ternary condition
pyramation Jul 21, 2025
85b5749
Refactor module selection and extension collection logic
pyramation Jul 21, 2025
3aa8c04
Fix moduleToChange logic: remove incorrect null handling
pyramation Jul 22, 2025
c5beb57
Refactor getAllWorkspaceExtensions to use proper dependency ordering
pyramation Jul 24, 2025
a072b28
Refactor workspace dependency ordering to use virtual module pattern
pyramation Jul 24, 2025
a0a9092
Add CHANGES.md with detailed summary
pyramation Jul 25, 2025
d86bcd1
Add tests for getWorkspaceExtensionsInDependencyOrder
pyramation Jul 25, 2025
190da0c
Fix duplicate entries in getWorkspaceExtensionsInDependencyOrder
pyramation Jul 28, 2025
e0d15b2
Rename extDeps to resolveExtensionDependencies
pyramation Jul 28, 2025
39d67c0
Simplify getWorkspaceExtensionsInDependencyOrder to use filtered reso…
pyramation Jul 28, 2025
861574b
Add RECOMMENDATION.md with simplification analysis
pyramation Jul 28, 2025
8895a52
Rename method to resolveWorkspaceExtensionDependencies
pyramation Jul 28, 2025
d2ca7ef
Fix CI failure: Update test references to renamed method
pyramation Jul 28, 2025
6d8b7d2
rm
pyramation Jul 28, 2025
8d60b31
rm
pyramation Jul 28, 2025
2cd5ba7
Add comprehensive documentation to findTopDependentModule method
pyramation Jul 28, 2025
69a9b6d
Add EXPLAIN_FIND_TOP.md with analysis of findTopDependentModule
pyramation Jul 29, 2025
b5f3329
Remove findTopDependentModule and replace with consistent dependency …
pyramation Jul 29, 2025
6cb2806
Fix inconsistent reverse() usage in revert logic
pyramation Jul 29, 2025
b50586b
reverse
pyramation Jul 29, 2025
7fa3955
Fix revert logic to match verify pattern
pyramation Jul 29, 2025
bc02627
Fix CI failure: Restore toChange special case in revert for proper de…
pyramation Jul 29, 2025
c130a55
Add comprehensive documentation for toChange special case in revert
pyramation Jul 29, 2025
a5f777e
Add revert truncation logic and tests
pyramation Jul 29, 2025
e7e38f5
Fix truncation example in documentation
pyramation Jul 29, 2025
bf7dc1f
Add revert truncation logic and tests
pyramation Jul 29, 2025
aff9620
Fix pg-cache lifecycle issue in test cleanup
pyramation Jul 29, 2025
c7815bf
Fix revert logic to always use workspace-wide resolution
pyramation Jul 29, 2025
edc4eb8
comment
pyramation Jul 30, 2025
a1bb992
rm
pyramation Jul 30, 2025
dc995d1
no need for method
pyramation Jul 30, 2025
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`getWorkspaceExtensionsInDependencyOrder with complex existing fixtures handles different fixture types consistently 1`] = `
{
"external": [
"citext",
"plpgsql",
"pgcrypto",
],
"resolved": [
"citext",
"plpgsql",
"pgcrypto",
"my-first",
"my-second",
"my-third",
],
}
`;

exports[`getWorkspaceExtensionsInDependencyOrder with complex existing fixtures returns extensions in dependency order for complex workspace 1`] = `
{
"external": [
"plpgsql",
"uuid-ossp",
"pgcrypto",
],
"resolved": [
"plpgsql",
"uuid-ossp",
"pg-utilities",
"pg-verify",
"pgcrypto",
"totp",
"utils",
"secrets",
],
}
`;

exports[`getWorkspaceExtensionsInDependencyOrder with complex existing fixtures verifies dependency ordering properties 1`] = `
{
"external": [
"citext",
"plpgsql",
"pgcrypto",
],
"resolved": [
"citext",
"plpgsql",
"pgcrypto",
"my-first",
"my-second",
"my-third",
],
}
`;

exports[`getWorkspaceExtensionsInDependencyOrder with existing fixtures handles workspace with minimal modules 1`] = `
{
"external": [
"citext",
"plpgsql",
"pgcrypto",
],
"resolved": [
"citext",
"plpgsql",
"pgcrypto",
"my-first",
"my-second",
"my-third",
],
}
`;

exports[`getWorkspaceExtensionsInDependencyOrder with existing fixtures returns extensions in dependency order for launchql workspace 1`] = `
{
"external": [
"plpgsql",
"uuid-ossp",
"pgcrypto",
],
"resolved": [
"plpgsql",
"uuid-ossp",
"pg-utilities",
"pg-verify",
"pgcrypto",
"totp",
"utils",
"secrets",
],
}
`;

exports[`getWorkspaceExtensionsInDependencyOrder with existing fixtures returns extensions in dependency order for simple-w-tags workspace 1`] = `
{
"external": [
"citext",
"plpgsql",
"pgcrypto",
],
"resolved": [
"citext",
"plpgsql",
"pgcrypto",
"my-first",
"my-second",
"my-third",
],
}
`;
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
process.env.LAUNCHQL_DEBUG = 'true';

import { LaunchQLProject } from '../../src/core/class/launchql';
import { TestFixture } from '../../test-utils';

let fixture: TestFixture;

beforeAll(() => {
fixture = new TestFixture('sqitch');
});

afterAll(() => {
fixture.cleanup();
});

describe('getWorkspaceExtensionsInDependencyOrder', () => {
describe('with existing fixtures', () => {
it('returns extensions in dependency order for simple-w-tags workspace', () => {
const workspacePath = fixture.getFixturePath('simple-w-tags');
const project = new LaunchQLProject(workspacePath);

const result = project.resolveWorkspaceExtensionDependencies();
expect(result).toMatchSnapshot();
});

it('returns extensions in dependency order for launchql workspace', () => {
const workspacePath = fixture.getFixturePath('launchql');
const project = new LaunchQLProject(workspacePath);

const result = project.resolveWorkspaceExtensionDependencies();
expect(result).toMatchSnapshot();
});

it('handles workspace with minimal modules', () => {
const workspacePath = fixture.getFixturePath('simple');
const project = new LaunchQLProject(workspacePath);

const result = project.resolveWorkspaceExtensionDependencies();
expect(result).toMatchSnapshot();

expect(result).toHaveProperty('resolved');
expect(result).toHaveProperty('external');
});
});

describe('with complex existing fixtures', () => {
it('returns extensions in dependency order for complex workspace', () => {
const workspacePath = fixture.getFixturePath('launchql');
const project = new LaunchQLProject(workspacePath);

const result = project.resolveWorkspaceExtensionDependencies();
expect(result).toMatchSnapshot();

expect(Array.isArray(result.resolved)).toBe(true);
expect(Array.isArray(result.external)).toBe(true);
});

it('verifies dependency ordering properties', () => {
const workspacePath = fixture.getFixturePath('simple-w-tags');
const project = new LaunchQLProject(workspacePath);

const result = project.resolveWorkspaceExtensionDependencies();
expect(result).toMatchSnapshot();

expect(result).toHaveProperty('resolved');
expect(result).toHaveProperty('external');
expect(Array.isArray(result.resolved)).toBe(true);
expect(Array.isArray(result.external)).toBe(true);

expect(result.resolved.length).toBeGreaterThanOrEqual(0);
expect(result.external.length).toBeGreaterThanOrEqual(0);
});

it('handles different fixture types consistently', () => {
const workspacePath = fixture.getFixturePath('simple');
const project = new LaunchQLProject(workspacePath);

const result = project.resolveWorkspaceExtensionDependencies();
expect(result).toMatchSnapshot();

expect(result.resolved.length).toBeGreaterThan(0);
});
});
});
51 changes: 51 additions & 0 deletions packages/core/__tests__/projects/deployment-scenarios.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
process.env.LAUNCHQL_DEBUG = 'true';

import { TestDatabase } from '../../test-utils';
import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture';

describe('Deployment Scenarios with Undefined Targets', () => {
let fixture: CoreDeployTestFixture;
let db: TestDatabase;

beforeEach(async () => {
fixture = new CoreDeployTestFixture('sqitch', 'simple-w-tags');
db = await fixture.setupTestDatabase();
});

afterEach(async () => {
await fixture.cleanup();
});

test('handles undefined target scenarios for deploy, revert, and verify operations', async () => {
await fixture.deployModule(undefined as any, db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(true);
expect(await db.exists('table', 'metaschema.customers')).toBe(true);

await expect(
fixture.verifyModule(undefined as any, db.name, ['sqitch', 'simple-w-tags'])
).resolves.not.toThrow();

await fixture.revertModule(undefined as any, db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(false);
expect(await db.exists('table', 'metaschema.customers')).toBe(false);

await fixture.deployModule('my-third', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(true);
expect(await db.exists('table', 'metaschema.customers')).toBe(true);

await fixture.revertModule('my-first:@v1.0.0', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(false);
expect(await db.exists('table', 'metaschema.customers')).toBe(false);

await fixture.deployModule(undefined as any, db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(true);
expect(await db.exists('table', 'metaschema.customers')).toBe(true);

await fixture.verifyModule(undefined as any, db.name, ['sqitch', 'simple-w-tags']);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
process.env.LAUNCHQL_DEBUG = 'true';

import { TestDatabase } from '../../test-utils';
import { CoreDeployTestFixture } from '../../test-utils/CoreDeployTestFixture';

describe('Revert Truncation Scenarios', () => {
let fixture: CoreDeployTestFixture;
let db: TestDatabase;

beforeEach(async () => {
fixture = new CoreDeployTestFixture('sqitch', 'simple-w-tags');
db = await fixture.setupTestDatabase();
});

afterAll(async () => {
await fixture.cleanup();
});

test('deploys my-third and reverts to my-first with toChange - should revert all dependent modules', async () => {
await fixture.deployModule('my-third', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'myapp')).toBe(true); // my-first
expect(await db.exists('table', 'myapp.products')).toBe(true); // my-first @v1.1.0
expect(await db.exists('schema', 'otherschema')).toBe(true); // my-second
expect(await db.exists('table', 'otherschema.users')).toBe(true); // my-second @v2.0.0
expect(await db.exists('schema', 'metaschema')).toBe(true); // my-third
expect(await db.exists('table', 'metaschema.customers')).toBe(true); // my-third

await fixture.revertModule('my-first:@v1.0.0', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(false);
expect(await db.exists('table', 'metaschema.customers')).toBe(false);
expect(await db.exists('schema', 'otherschema')).toBe(false);
expect(await db.exists('table', 'otherschema.users')).toBe(false);

expect(await db.exists('schema', 'myapp')).toBe(true);
expect(await db.exists('table', 'myapp.users')).toBe(true);
expect(await db.exists('table', 'myapp.products')).toBe(false); // @v1.1.0 change reverted
});

test('deploys my-third and reverts my-second without toChange - should use module-specific resolution', async () => {
await fixture.deployModule('my-third', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(true);
expect(await db.exists('table', 'metaschema.customers')).toBe(true);
expect(await db.exists('schema', 'otherschema')).toBe(true);
expect(await db.exists('table', 'otherschema.users')).toBe(true);

await fixture.revertModule('my-second', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'otherschema')).toBe(false);
expect(await db.exists('table', 'otherschema.users')).toBe(false);

expect(await db.exists('schema', 'myapp')).toBe(true);
expect(await db.exists('table', 'myapp.products')).toBe(true);

expect(await db.exists('schema', 'metaschema')).toBe(false);
});

test('null name with cwd inside my-second calling revert - should revert all modules', async () => {
await fixture.deployModule('my-third', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(true);
expect(await db.exists('schema', 'otherschema')).toBe(true);
expect(await db.exists('schema', 'myapp')).toBe(true);

await fixture.revertModule(undefined as any, db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(false);
expect(await db.exists('schema', 'otherschema')).toBe(false);
expect(await db.exists('schema', 'myapp')).toBe(false);
});

test('verifies workspace-wide resolution with toChange ensures proper dependency handling', async () => {

await fixture.deployModule('my-third', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'myapp')).toBe(true); // my-first
expect(await db.exists('schema', 'otherschema')).toBe(true); // my-second
expect(await db.exists('schema', 'metaschema')).toBe(true); // my-third

await fixture.revertModule('my-first:@v1.0.0', db.name, ['sqitch', 'simple-w-tags']);

expect(await db.exists('schema', 'metaschema')).toBe(false);
expect(await db.exists('schema', 'otherschema')).toBe(false);

expect(await db.exists('schema', 'myapp')).toBe(true);
expect(await db.exists('table', 'myapp.users')).toBe(true);
expect(await db.exists('table', 'myapp.products')).toBe(false); // @v1.1.0 change reverted
});
});
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { listModules } from '../../src/modules/modules';
import { extDeps,resolveDependencies } from '../../src/resolution/deps';
import { resolveExtensionDependencies, resolveDependencies } from '../../src/resolution/deps';
import { TestFixture } from '../../test-utils';

let fixture: TestFixture;
Expand Down Expand Up @@ -47,7 +47,7 @@ it('sqitch package dependencies [simple/3rd]', async () => {
it('launchql project extensions dependencies', async () => {
const modules = listModules(fixture.getFixturePath('launchql'));

const utils = await extDeps('utils', modules);
const utils = await resolveExtensionDependencies('utils', modules);
expect(utils).toEqual({
external: ['plpgsql', 'uuid-ossp', 'pgcrypto'],
resolved: [
Expand All @@ -61,7 +61,7 @@ it('launchql project extensions dependencies', async () => {
]
});

const secrets = await extDeps('secrets', modules);
const secrets = await resolveExtensionDependencies('secrets', modules);
expect(secrets).toEqual({
external: ['plpgsql', 'uuid-ossp', 'pgcrypto'],
resolved: [
Expand All @@ -75,7 +75,7 @@ it('launchql project extensions dependencies', async () => {
]
});

const totp = await extDeps('totp', modules);
const totp = await resolveExtensionDependencies('totp', modules);
expect(totp).toEqual({
external: ['plpgsql', 'uuid-ossp', 'pgcrypto'],
resolved: [
Expand Down
Loading