Skip to content

Commit c704293

Browse files
committed
test(projects): skip archive repair suite when Redis is unset
1 parent 1e4499e commit c704293

1 file changed

Lines changed: 66 additions & 61 deletions

File tree

‎apps/sim/lib/projects/__integration__/backfill-repair.integration.ts‎

Lines changed: 66 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,16 @@ const name = `project_repair_test_${generateId().replaceAll('-', '')}`
1717
const url = new URL(readTestDatabaseUrl())
1818
url.pathname = `/${name}`
1919
const client = postgres(url.toString(), { max: 1, onnotice: () => {} })
20-
const directory = await mkdtemp(join(tmpdir(), 'project-repair-test-'))
21-
const manifest = join(directory, 'manifest.json')
22-
const report = join(directory, 'report.json')
20+
let directory: string
21+
let manifest: string
22+
let report: string
2323
const redisUrl = readTestRedisUrl()
24-
if (!redisUrl) throw new Error('Archive repair integration requires TEST_REDIS_URL')
25-
const cache = new Redis(redisUrl)
26-
const subscriber = new Redis(redisUrl)
24+
const describeWithRedis = describe.runIf(Boolean(redisUrl))
25+
let cache: Redis
26+
let subscriber: Redis
2727
const mcpServerId = generateId()
2828
const cacheKey = `mcp:tools:workspace:env:server:${mcpServerId}`
2929
const published: unknown[] = []
30-
subscriber.on('message', (_channel, message) => published.push(JSON.parse(message)))
3130
const releaseNotifications = createDeferred<void>()
3231
let tailNotified = false
3332
const realtime = createServer(async (request, response) => {
@@ -64,63 +63,69 @@ const run = (command: string, artifacts = { manifest, report }) =>
6463
}
6564
)
6665

67-
beforeAll(async () => {
68-
await new Promise<void>((resolve) => realtime.listen(0, '127.0.0.1', resolve))
69-
const address = realtime.address()
70-
if (!address || typeof address === 'string') throw new Error('Realtime fixture failed to bind')
71-
environment.SOCKET_SERVER_URL = `http://127.0.0.1:${address.port}`
72-
await subscriber.subscribe('mcp:workflow_tools_changed')
73-
await admin.unsafe(`CREATE DATABASE "${name}"`)
74-
await client.unsafe(
75-
'CREATE EXTENSION vector; CREATE EXTENSION btree_gin; CREATE EXTENSION pg_trgm'
76-
)
77-
const folder = join(directory, 'migrations')
78-
await mkdir(join(folder, 'meta'), { recursive: true })
79-
const expansion = journal.entries.find((entry) => entry.tag === '0404_workspace_project_column')
80-
if (!expansion) throw new Error('Missing expansion migration')
81-
const entries = journal.entries.filter((entry) => entry.when <= expansion.when)
82-
const source = new URL('../../../../../packages/db/migrations/', import.meta.url)
83-
for (const entry of entries)
84-
await copyFile(new URL(`${entry.tag}.sql`, source), join(folder, `${entry.tag}.sql`))
85-
await writeFile(join(folder, 'meta/_journal.json'), JSON.stringify({ ...journal, entries }))
86-
await execute(
87-
'bun',
88-
[
89-
'--no-env-file',
90-
'-e',
91-
`
92-
import postgres from 'postgres';
93-
import { drizzle } from 'drizzle-orm/postgres-js';
94-
import { migrate } from 'drizzle-orm/postgres-js/migrator';
95-
import { runScriptMigrations, scriptMigrations } from '@sim/db/script-migrations/index';
96-
const sql = postgres(process.env.MIGRATION_DATABASE_URL,{max:1,onnotice:()=>{}});
97-
try { await migrate(drizzle(sql),{migrationsFolder:process.env.FIXTURE_MIGRATIONS}); await runScriptMigrations(sql, scriptMigrations.filter((item) => item.name !== '0031_project_membership')); }
98-
finally { await sql.end(); }
99-
`,
100-
],
101-
{
102-
cwd: new URL('../../../../../packages/db/', import.meta.url),
103-
env: { ...environment, FIXTURE_MIGRATIONS: folder },
104-
timeout: 120000,
105-
}
106-
)
107-
}, 120000)
66+
describeWithRedis('Operator archive repair against the full compatible schema', () => {
67+
beforeAll(async () => {
68+
directory = await mkdtemp(join(tmpdir(), 'project-repair-test-'))
69+
manifest = join(directory, 'manifest.json')
70+
report = join(directory, 'report.json')
71+
cache = new Redis(redisUrl!)
72+
subscriber = new Redis(redisUrl!)
73+
subscriber.on('message', (_channel, message) => published.push(JSON.parse(message)))
74+
await new Promise<void>((resolve) => realtime.listen(0, '127.0.0.1', resolve))
75+
const address = realtime.address()
76+
if (!address || typeof address === 'string') throw new Error('Realtime fixture failed to bind')
77+
environment.SOCKET_SERVER_URL = `http://127.0.0.1:${address.port}`
78+
await subscriber.subscribe('mcp:workflow_tools_changed')
79+
await admin.unsafe(`CREATE DATABASE "${name}"`)
80+
await client.unsafe(
81+
'CREATE EXTENSION vector; CREATE EXTENSION btree_gin; CREATE EXTENSION pg_trgm'
82+
)
83+
const folder = join(directory, 'migrations')
84+
await mkdir(join(folder, 'meta'), { recursive: true })
85+
const expansion = journal.entries.find((entry) => entry.tag === '0404_workspace_project_column')
86+
if (!expansion) throw new Error('Missing expansion migration')
87+
const entries = journal.entries.filter((entry) => entry.when <= expansion.when)
88+
const source = new URL('../../../../../packages/db/migrations/', import.meta.url)
89+
for (const entry of entries)
90+
await copyFile(new URL(`${entry.tag}.sql`, source), join(folder, `${entry.tag}.sql`))
91+
await writeFile(join(folder, 'meta/_journal.json'), JSON.stringify({ ...journal, entries }))
92+
await execute(
93+
'bun',
94+
[
95+
'--no-env-file',
96+
'-e',
97+
`
98+
import postgres from 'postgres';
99+
import { drizzle } from 'drizzle-orm/postgres-js';
100+
import { migrate } from 'drizzle-orm/postgres-js/migrator';
101+
import { runScriptMigrations, scriptMigrations } from '@sim/db/script-migrations/index';
102+
const sql = postgres(process.env.MIGRATION_DATABASE_URL,{max:1,onnotice:()=>{}});
103+
try { await migrate(drizzle(sql),{migrationsFolder:process.env.FIXTURE_MIGRATIONS}); await runScriptMigrations(sql, scriptMigrations.filter((item) => item.name !== '0031_project_membership')); }
104+
finally { await sql.end(); }
105+
`,
106+
],
107+
{
108+
cwd: new URL('../../../../../packages/db/', import.meta.url),
109+
env: { ...environment, FIXTURE_MIGRATIONS: folder },
110+
timeout: 120000,
111+
}
112+
)
113+
}, 120000)
108114

109-
afterAll(async () => {
110-
releaseNotifications.resolve()
111-
await new Promise<void>((resolve, reject) => {
112-
realtime.close((error) => (error ? reject(error) : resolve()))
113-
realtime.closeAllConnections()
115+
afterAll(async () => {
116+
releaseNotifications.resolve()
117+
await new Promise<void>((resolve, reject) => {
118+
realtime.close((error) => (error ? reject(error) : resolve()))
119+
realtime.closeAllConnections()
120+
})
121+
await cache.del(cacheKey)
122+
await Promise.all([cache.quit(), subscriber.quit()])
123+
await client.end({ timeout: 2 })
124+
await admin.unsafe(`DROP DATABASE IF EXISTS "${name}" WITH (FORCE)`)
125+
await admin.end()
126+
await rm(directory, { recursive: true, force: true })
114127
})
115-
await cache.del(cacheKey)
116-
await Promise.all([cache.quit(), subscriber.quit()])
117-
await client.end({ timeout: 2 })
118-
await admin.unsafe(`DROP DATABASE IF EXISTS "${name}" WITH (FORCE)`)
119-
await admin.end()
120-
await rm(directory, { recursive: true, force: true })
121-
})
122128

123-
describe('Operator archive repair against the full compatible schema', () => {
124129
it.each(['workspace', 'project', 'row'] as const)(
125130
'defers a busy %s lock, repairs unrelated environments and resumes without losing progress',
126131
async (lock) => {

0 commit comments

Comments
 (0)