Skip to content

Commit f105f02

Browse files
committed
chore: wip
1 parent 1f87d46 commit f105f02

File tree

4 files changed

+215
-92
lines changed

4 files changed

+215
-92
lines changed

packages/launchpad/src/binary-downloader.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ Thanks for helping us make Launchpad better! 🙏
486486
}
487487

488488
if (config.verbose) {
489-
console.log(`⬇️ Downloading precompiled PHP ${binary.php_version} (${binary.configuration})...`)
489+
console.log(`⬇️ Downloading precompiled PHP ${binary.php_version} (${binary.configuration})...`)
490490
console.log(`📊 Size: ${Math.round(binary.size / 1024 / 1024 * 10) / 10}MB`)
491491
}
492492

packages/launchpad/src/dev/dump.ts

Lines changed: 86 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,13 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
322322

323323
const { findBinaryInPath } = await import('../utils')
324324
const pgIsReady = findBinaryInPath('pg_isready') || 'pg_isready'
325+
if (process.env.LAUNCHPAD_DEBUG === '1') {
326+
try {
327+
process.stderr.write(`🐞 waitForPostgresIfNeeded: PATH=${process.env.PATH}\n`)
328+
process.stderr.write(`🐞 waitForPostgresIfNeeded: host=${host} port=${port} pg_isready=${pgIsReady}\n`)
329+
}
330+
catch {}
331+
}
325332
let ready = false
326333
// First pass: pg_isready
327334
for (let i = 0; i < 20 && !ready; i++) {
@@ -333,12 +340,24 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
333340
p.on('error', () => resolve(false))
334341
})
335342
ready = ok
343+
if (process.env.LAUNCHPAD_DEBUG === '1') {
344+
try {
345+
process.stderr.write(`🐞 pg_isready attempt ${i + 1}: ${ok ? 'ok' : 'fail'}\n`)
346+
}
347+
catch {}
348+
}
336349
if (!ready)
337350
await new Promise(r => setTimeout(r, 250 + i * 150))
338351
}
339352
// Fallback: TCP probe
340353
if (!ready) {
341354
const net = await import('node:net')
355+
if (process.env.LAUNCHPAD_DEBUG === '1') {
356+
try {
357+
process.stderr.write('🐞 pg_isready not ready, falling back to TCP probe\n')
358+
}
359+
catch {}
360+
}
342361
for (let i = 0; i < 20 && !ready; i++) {
343362
const ok = await new Promise<boolean>((resolve) => {
344363
const socket = net.connect({ host, port: Number(port), timeout: 1000 }, () => {
@@ -352,6 +371,12 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
352371
})
353372
})
354373
ready = ok
374+
if (process.env.LAUNCHPAD_DEBUG === '1') {
375+
try {
376+
process.stderr.write(`🐞 TCP probe attempt ${i + 1}: ${ok ? 'ok' : 'fail'}\n`)
377+
}
378+
catch {}
379+
}
355380
if (!ready)
356381
await new Promise(r => setTimeout(r, 250 + i * 150))
357382
}
@@ -363,6 +388,12 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
363388
// Final verification using psql simple query if available
364389
const psqlBin = findBinaryInPath('psql') || 'psql'
365390
if (psqlBin) {
391+
if (process.env.LAUNCHPAD_DEBUG === '1') {
392+
try {
393+
process.stderr.write(`🐞 using psql binary: ${psqlBin}\n`)
394+
}
395+
catch {}
396+
}
366397
for (let i = 0; i < 8; i++) {
367398
const ok = await new Promise<boolean>((resolve) => {
368399
// eslint-disable-next-line ts/no-require-imports
@@ -371,6 +402,12 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
371402
p.on('close', (code: number) => resolve(code === 0))
372403
p.on('error', () => resolve(false))
373404
})
405+
if (process.env.LAUNCHPAD_DEBUG === '1') {
406+
try {
407+
process.stderr.write(`🐞 psql SELECT 1 attempt ${i + 1}: ${ok ? 'ok' : 'fail'}\n`)
408+
}
409+
catch {}
410+
}
374411
if (ok)
375412
break
376413
await new Promise(r => setTimeout(r, 300 + i * 200))
@@ -429,6 +466,15 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
429466
}
430467
}
431468
catch {}
469+
// Also set PG* vars for libpq tools and frameworks that honor them
470+
if (!execEnv.PGHOST)
471+
execEnv.PGHOST = execEnv.DB_HOST
472+
if (!execEnv.PGPORT)
473+
execEnv.PGPORT = execEnv.DB_PORT
474+
if (!execEnv.PGUSER)
475+
execEnv.PGUSER = execEnv.DB_USERNAME || execEnv.DB_USER || 'postgres'
476+
if (!execEnv.PGPASSWORD && execEnv.DB_PASSWORD !== undefined)
477+
execEnv.PGPASSWORD = execEnv.DB_PASSWORD
432478

433479
if (command.runInBackground) {
434480
execSync(command.command, {
@@ -446,12 +492,47 @@ async function executepostSetup(projectDir: string, commands: PostSetupCommand[]
446492
}
447493
catch {}
448494
await waitForPostgresIfNeeded()
495+
// final short grace period
496+
await new Promise(r => setTimeout(r, 500))
497+
}
498+
try {
499+
execSync(command.command, {
500+
cwd: projectDir,
501+
env: execEnv,
502+
stdio: inShell ? (['ignore', 2, 2] as any) : 'inherit',
503+
})
504+
}
505+
catch (err) {
506+
// Deep diagnostics on failure
507+
try {
508+
process.stderr.write('🐞 Migration failed; collecting diagnostics...\n')
509+
process.stderr.write(`🐞 PATH=${execEnv.PATH}\n`)
510+
process.stderr.write(`🐞 DB env: HOST=${execEnv.DB_HOST} PORT=${execEnv.DB_PORT} USERNAME=${execEnv.DB_USERNAME || execEnv.DB_USER || ''} DATABASE_URL=${execEnv.DATABASE_URL || ''}\n`)
511+
}
512+
catch {}
513+
try {
514+
const { spawnSync } = await import('node:child_process')
515+
const pgReady = spawnSync(execEnv.PG_ISREADY || 'pg_isready', ['-h', execEnv.DB_HOST || '127.0.0.1', '-p', execEnv.DB_PORT || '5432'])
516+
process.stderr.write(`🐞 pg_isready exit=${pgReady.status} stdout=${(pgReady.stdout || '').toString()} stderr=${(pgReady.stderr || '').toString()}\n`)
517+
}
518+
catch {}
519+
try {
520+
const { spawnSync } = await import('node:child_process')
521+
const psql = spawnSync('psql', ['-h', execEnv.DB_HOST || '127.0.0.1', '-p', execEnv.DB_PORT || '5432', '-U', 'postgres', '-tAc', 'SELECT 1'])
522+
process.stderr.write(`🐞 psql check exit=${psql.status} stdout=${(psql.stdout || '').toString()} stderr=${(psql.stderr || '').toString()}\n`)
523+
}
524+
catch {}
525+
try {
526+
const logPath = path.join(homedir(), '.local', 'share', 'launchpad', 'logs', 'postgres.log')
527+
if (fs.existsSync(logPath)) {
528+
const content = fs.readFileSync(logPath, 'utf8')
529+
const tail = content.split(/\r?\n/).slice(-100).join('\n')
530+
process.stderr.write(`🐞 tail -100 postgres.log:\n${tail}\n`)
531+
}
532+
}
533+
catch {}
534+
throw err
449535
}
450-
execSync(command.command, {
451-
cwd: projectDir,
452-
env: execEnv,
453-
stdio: inShell ? (['ignore', 2, 2] as any) : 'inherit',
454-
})
455536
results.push(`✅ ${command.description}`)
456537
}
457538
}

packages/launchpad/src/services/definitions.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,11 @@ export const SERVICE_DEFINITIONS: Record<string, ServiceDefinition> = {
4444
// Ensure default postgres role exists for framework defaults
4545
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = \'postgres\') THEN CREATE ROLE postgres SUPERUSER LOGIN; END IF; END $$;'],
4646
// Create project-specific user idempotently
47-
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = \'{dbUsername}\') THEN CREATE ROLE {dbUsername} LOGIN PASSWORD \'{dbPassword}\'; ELSE ALTER ROLE {dbUsername} WITH PASSWORD \'{dbPassword}\'; END IF; END $$;'],
47+
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'DO $$ BEGIN IF NOT EXISTS (SELECT FROM pg_roles WHERE rolname = \'{appUser}\') THEN CREATE ROLE {appUser} LOGIN PASSWORD \'{appPassword}\'; ELSE ALTER ROLE {appUser} WITH PASSWORD \'{appPassword}\'; END IF; END $$;'],
4848
// Grant permissions and set ownership
49-
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'ALTER DATABASE {projectDatabase} OWNER TO {dbUsername}; GRANT ALL PRIVILEGES ON DATABASE {projectDatabase} TO {dbUsername};'],
50-
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'GRANT CREATE ON SCHEMA public TO {dbUsername};'],
51-
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'GRANT USAGE ON SCHEMA public TO {dbUsername};'],
49+
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'ALTER DATABASE {projectDatabase} OWNER TO {appUser}; GRANT ALL PRIVILEGES ON DATABASE {projectDatabase} TO {appUser};'],
50+
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'GRANT CREATE ON SCHEMA public TO {appUser};'],
51+
['psql', '-h', '127.0.0.1', '-p', '5432', '-d', 'postgres', '-c', 'GRANT USAGE ON SCHEMA public TO {appUser};'],
5252
],
5353
supportsGracefulShutdown: true,
5454
config: {

0 commit comments

Comments
 (0)