Skip to content
Open
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
30 changes: 22 additions & 8 deletions packages/cli/src/commands/setup/neon/neon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,38 @@ export const description =
'Provision a Neon Postgres database and configure your project'

export function builder(yargs: Argv) {
return yargs.option('force', {
alias: 'f',
default: false,
description: 'Overwrite existing DATABASE_URL in .env',
type: 'boolean',
})
return yargs
.option('force', {
alias: 'f',
default: false,
description: 'Overwrite existing DATABASE_URL in .env',
type: 'boolean',
})
.option('migrations', {
description:
'Run Prisma migrations after setup. Omit to be prompted. Use --no-migrations to skip.',
type: 'boolean',
})
.option('verbose', {
alias: 'v',
default: false,
description: 'Show full output from migration commands (stderr → stdout)',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The description says "stderr → stdout" but the implementation uses stdio: 'inherit', which keeps stderr on the parent's stderr stream — it does not redirect it to stdout. A reader of --help output would expect the two streams to be merged, but that's not what happens.

Suggested change
description: 'Show full output from migration commands (stderr → stdout)',
description: 'Show full output from migration commands (stderr visible in terminal)',

type: 'boolean',
})
}

export interface Args {
force: boolean
migrations?: boolean
verbose: boolean
}

export async function handler({ force }: Args) {
export async function handler({ force, migrations, verbose }: Args) {
recordTelemetryAttributes({
command: 'setup neon',
force,
})

const { handler } = await import('./neonHandler.js')
return handler({ force })
return handler({ force, migrations, verbose })
}
40 changes: 34 additions & 6 deletions packages/cli/src/commands/setup/neon/neonHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import path from 'node:path'

import execa from 'execa'
import { Listr } from 'listr2'
import prompts from 'prompts'

import { colors, getPaths, installPackages } from '@cedarjs/cli-helpers'
import { addWorkspacePackages } from '@cedarjs/cli-helpers/packageManager/packages'
Expand All @@ -12,7 +13,7 @@ import type { Args } from './neon.js'

const cedarPaths = getPaths()

export async function handler({ force }: Args) {
export async function handler({ force, migrations, verbose }: Args) {
const schemaPath = path.join(cedarPaths.api.base, 'db', 'schema.prisma')
const dbTsPath = path.join(cedarPaths.api.src, 'lib', 'db.ts')
const prismaConfigPathCjs = path.join(
Expand Down Expand Up @@ -41,6 +42,24 @@ export async function handler({ force }: Args) {

const notes: string[] = []

// Resolve whether to run migrations: flag > prompt
let runMigrations = migrations
if (runMigrations === undefined) {
const response = await prompts({
type: 'toggle',
name: 'runMigrations',
message: 'Run Prisma migrations now?',
initial: true,
active: 'Yes',
inactive: 'No',
})
// prompts returns undefined for the value if the user ctrl-c's
if (response.runMigrations === undefined) {
process.exit(0)
}
runMigrations = response.runMigrations
}
Comment on lines +47 to +61

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Silent exit in non-interactive (CI) environments

When migrations is not provided and stdin is not a TTY — the typical case in CI — prompts returns an empty object {} immediately, so response.runMigrations is undefined. The code then calls process.exit(0), silently aborting setup after all earlier tasks (schema switch, adapter update, Neon provisioning, .env write) have already completed. A CI pipeline that relied on migrations running automatically will now silently exit with code 0 partway through, leaving the database un-migrated with no diagnostic output.

A safe guard would be to detect a non-TTY stdin before calling prompts and either default to true or exit with a clear error message instructing the caller to pass --migrations or --no-migrations explicitly.


const tasks = new Listr(
[
{
Expand Down Expand Up @@ -344,6 +363,10 @@ export async function handler({ force }: Args) {
return true
}

if (!runMigrations) {
return 'Skipped (--no-migrations)'
}
Comment on lines +366 to +368

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 The skip message 'Skipped (--no-migrations)' is displayed even when the user simply answered "No" to the interactive prompt rather than passing the flag. A user who answered the prompt will see a message that implies they used a command-line flag they never typed, which is confusing.

Suggested change
if (!runMigrations) {
return 'Skipped (--no-migrations)'
}
if (!runMigrations) {
return migrations === false
? 'Skipped (--no-migrations)'
: 'Skipped'
}


if (ctx.skipWithNote) {
return 'DATABASE_URL already configured — skipping migration'
}
Expand All @@ -363,7 +386,9 @@ export async function handler({ force }: Args) {
'yarn cedar prisma migrate dev --name init-neon',
{
cwd: cedarPaths.base,
stdio: ['inherit', 'inherit', 'pipe'],
stdio: verbose
? 'inherit'
: ['inherit', 'inherit', 'pipe'],
reject: false,
env: {
...process.env,
Expand All @@ -374,10 +399,13 @@ export async function handler({ force }: Args) {

if (result.exitCode !== 0) {
throw new Error(
'Prisma migration failed:\n\n' +
result.stderr +
'\n\nYou can try running it manually:\n' +
' yarn cedar prisma migrate dev --name init-neon',
verbose
? 'Prisma migration failed. You can try running it manually:\n' +
' yarn cedar prisma migrate dev --name init-neon'
: 'Prisma migration failed:\n\n' +
result.stderr +
'\n\nYou can try running it manually:\n' +
' yarn cedar prisma migrate dev --name init-neon',
)
}
},
Expand Down
Loading