Skip to content

Commit 4ca01d1

Browse files
dcramercodex
andcommitted
fix(migrations): Preserve host state adapter identity
Pass the real core state adapter into TypeScript migrations so Redis-native index and lock detection continues to work. Add multiline import guard coverage and remove the stale generated temp-path comment from the history migration. Co-Authored-By: GPT-5.6 Codex <noreply@openai.com>
1 parent 360518a commit 4ca01d1

6 files changed

Lines changed: 45 additions & 37 deletions

File tree

packages/junior-migrations/src/journal.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ function validateTypeScriptSource(tag: string, source: string): void {
8686
}
8787
};
8888
const imports = source.matchAll(
89-
/^\s*import\s+([^;]+?)\s+from\s+["']([^"']+)["'];?/gm,
89+
/^\s*import\s+([\s\S]*?)\s+from\s+["']([^"']+)["'];?/gm,
9090
);
9191
for (const match of imports) {
9292
const clause = match[1]?.trim();
@@ -97,7 +97,7 @@ function validateTypeScriptSource(tag: string, source: string): void {
9797
validateRuntimeSpecifier(specifier);
9898
}
9999
const exports = source.matchAll(
100-
/^\s*export\s+([^;]+?)\s+from\s+["']([^"']+)["'];?/gm,
100+
/^\s*export\s+([\s\S]*?)\s+from\s+["']([^"']+)["'];?/gm,
101101
);
102102
for (const match of exports) {
103103
const clause = match[1]?.trim();

packages/junior-migrations/tests/journal.test.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,18 @@ describe("resolveMigrations", () => {
6262
);
6363
});
6464

65+
it("rejects multiline imports of Junior runtime modules", async () => {
66+
const folder = await migrationFolder(["0000_multiline"]);
67+
await writeFile(
68+
join(folder, "0000_multiline.ts"),
69+
'import {\n getChatConfig,\n getDb,\n} from "@sentry/junior/internal";\nexport default { apiVersion: 1, async up() {} };\n',
70+
);
71+
72+
await expect(resolveMigrations(folder)).rejects.toThrow(
73+
"cannot import application runtime code",
74+
);
75+
});
76+
6577
it("allows versioned Junior migration helpers", async () => {
6678
const folder = await migrationFolder(["0000_helpers"]);
6779
await writeFile(

packages/junior/migrations/0008_conversation_history_to_sql.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1034,7 +1034,6 @@ async function importConversationFromLegacy(conversationId, deps) {
10341034
return { imported };
10351035
}
10361036

1037-
// ../../../../../../private/tmp/0008-entry.ts
10381037
import {
10391038
createMigrationSqlConversationMessageStore,
10401039
createMigrationStateConversationStore,

packages/junior/src/chat/conversations/sql/migrations.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import {
1010
} from "@sentry/junior-migrations";
1111
import type { StateAdapter } from "chat";
1212
import type { RedisStateAdapter } from "@chat-adapter/state-redis";
13-
import { createMigrationStateV1 } from "@/chat/migrations/state-v1";
1413
import type { JuniorSqlMigrationExecutor } from "@/db/db";
1514
import { juniorSqlSchema as schema } from "@/db/schema";
1615

@@ -155,7 +154,7 @@ export async function migrateSchema(
155154
},
156155
}
157156
: {}),
158-
state: createMigrationStateV1(options.stateAdapter),
157+
state: options.stateAdapter,
159158
}),
160159
loadTypeScript: options.loadTypeScript,
161160
mode: "all",

packages/junior/src/chat/migrations/state-v1.ts

Lines changed: 0 additions & 32 deletions
This file was deleted.

packages/junior/tests/component/cli/upgrade-cli.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { mkdtempSync, rmSync, writeFileSync } from "node:fs";
22
import { tmpdir } from "node:os";
33
import path from "node:path";
44
import type { RedisStateAdapter } from "@chat-adapter/state-redis";
5+
import type { MigrationContextV1 } from "@sentry/junior-migrations";
56
import { createJiti } from "jiti";
67
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
78
import { getChatConfig } from "@/chat/config";
@@ -379,6 +380,35 @@ export const plugins = {
379380
}
380381
}, 15_000);
381382

383+
it("passes the host state adapter through without wrapping its identity", async () => {
384+
const stateAdapter = getStateAdapter();
385+
await stateAdapter.connect();
386+
const fixture = await createLocalJuniorSqlFixture();
387+
const observedStates: unknown[] = [];
388+
389+
try {
390+
await migrateSchema(fixture.sql, {
391+
loadTypeScript: async () => ({
392+
default: {
393+
apiVersion: 1,
394+
async up(context: MigrationContextV1) {
395+
observedStates.push(context.state);
396+
},
397+
},
398+
}),
399+
mode: "all",
400+
stateAdapter,
401+
});
402+
403+
expect(observedStates).toHaveLength(5);
404+
expect(observedStates.every((state) => state === stateAdapter)).toBe(
405+
true,
406+
);
407+
} finally {
408+
await fixture.close();
409+
}
410+
});
411+
382412
it("migrates legacy conversation work before SQL conversation backfill", async () => {
383413
const stateAdapter = getStateAdapter();
384414
await stateAdapter.connect();

0 commit comments

Comments
 (0)