Skip to content
Merged
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
8 changes: 5 additions & 3 deletions docs/product/command-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ Behavior:
- deploy progress uses short stage copy (`Building locally...`, `Built <size>`, `Uploading...`, `Uploaded`, `Deploying...`, `Deployed`) and never prints `Status: running` or `Deployment is running at ...`
- success human output prints `Live in <duration>`, the URL on its own line, and `Logs prisma-cli app logs`
- accepts repeated `--env NAME=VALUE` flags
- supports `--db` for preview Branches to create a new empty Prisma Postgres database, apply the local Prisma schema when one exists, and write branch-scoped `DATABASE_URL` and `DIRECT_URL` overrides through the existing `project env` storage
- supports `--db` for preview Branches to create a new empty Prisma Postgres database, apply a supported local Prisma schema source when one exists, and write branch-scoped `DATABASE_URL` and `DIRECT_URL` overrides through the existing `project env` storage
- supports `--no-db` to suppress automatic database prompting for the deploy
- `--db` and `--no-db` are mutually exclusive; passing both is rejected
- `--yes` alone never creates a database; CI must pass `--db --yes` to create and wire one
Expand All @@ -638,8 +638,10 @@ Behavior:
- when only `DIRECT_URL` exists on the branch, explicit `--db` treats it as partial setup and repairs the pair by writing fresh branch database env values
- if schema setup or branch env-var wiring fails after database creation, the CLI deletes the newly created database before returning the error
- branch database setup does not clone or infer schema from another database; it only creates an empty database and optionally applies schema from local code
- when `prisma/migrations` exists next to `schema.prisma`, schema setup runs `prisma migrate deploy`; otherwise a found `schema.prisma` runs `prisma db push`
- when no `schema.prisma` is found, `--db` still creates the database and env overrides but skips schema setup
- Prisma Next config (`prisma-next.config.*`) is preferred over `schema.prisma`; setup runs `prisma-next contract emit` and then `prisma-next db init`
- for Prisma ORM `schema.prisma`, setup runs `prisma migrate deploy` when `prisma/migrations` exists next to the schema, otherwise it runs `prisma db push`
- when no supported Prisma schema source is found, `--db` still creates the database and env overrides but skips schema setup
- known non-Postgres Prisma sources do not trigger automatic database prompting; explicit `--db` is rejected because the created database is Prisma Postgres
- if schema setup fails, deploy stops before the app build/deploy starts
- inline `--env DATABASE_URL=...` or `--env DIRECT_URL=...` suppresses automatic database prompting; combining those inline env vars with `--db` is rejected
- maps user-facing framework names to deploy build strategies
Expand Down
2 changes: 1 addition & 1 deletion docs/product/error-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ Recommended meanings:
- `REPO_CONNECTION_FAILED`: the Management API repository connection operation failed
- `BUILD_FAILED`: build failed before a healthy deployment existed
- `BRANCH_DATABASE_SETUP_FAILED`: preview Branch database creation or branch env-var wiring failed before deployment started
- `SCHEMA_SETUP_FAILED`: local Prisma schema setup against a newly created Branch database failed before deployment started
- `SCHEMA_SETUP_FAILED`: local Prisma schema source setup against a newly created Branch database failed before deployment started
- `RUN_FAILED`: local framework run command could not be started or exited unsuccessfully
- `DEPLOY_FAILED`: deployment or post-build health failed
- `VERSION_UNAVAILABLE`: CLI could not read its own bundled package metadata to report a version (defensive; not expected in normal installs)
Expand Down
8 changes: 5 additions & 3 deletions docs/product/resource-model.md
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,18 @@ resource.

The beta package does not expose a standalone database command group yet. The
current database surface is limited to `app deploy --db`, which can create an
empty Prisma Postgres database for a preview Branch, apply the local
`schema.prisma` shape when available, and write normal branch-scoped
environment variable overrides.
empty Prisma Postgres database for a preview Branch, apply a supported local
Prisma schema source when available, and write normal branch-scoped environment
variable overrides.

Rules:

- database wiring uses the existing environment-variable model
- `DATABASE_URL` is written as a preview Branch override, not a separate app binding
- branch database setup never overwrites an existing branch-scoped `DATABASE_URL`
- schema setup is sourced only from local code; the CLI does not clone or infer schema from another database
- Prisma Next config (`prisma-next.config.*`) is preferred over `schema.prisma`
- known non-Postgres Prisma sources are treated as unsupported for automatic Prisma Postgres setup
- production database configuration is managed through explicit environment-variable commands

## Relationships
Expand Down
92 changes: 82 additions & 10 deletions packages/cli/src/lib/app/branch-database-deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@ import {
hasBranchDatabaseSignal,
inspectBranchDatabaseSignal,
runBranchDatabaseSchemaSetup,
type BranchDatabaseSchema,
type BranchDatabaseSchemaSetupResult,
type BranchDatabaseSignal,
type UnsupportedBranchDatabaseSchema,
} from "./branch-database";

export interface BranchDatabaseDeployBranch {
Expand Down Expand Up @@ -113,6 +115,14 @@ export async function maybeSetupBranchDatabase(
};
}

if (localSignal.unsupportedSchema) {
if (options.db === true) {
throw unsupportedBranchDatabaseSchemaError(localSignal.unsupportedSchema, branch.name, context);
}

return emptyBranchDatabaseSetupOutcome();
}

const hasSignal = hasBranchDatabaseSignal(localSignal) || Boolean(envState.previewDatabaseUrl);
if (options.db !== true) {
if (!hasSignal) {
Expand Down Expand Up @@ -175,11 +185,11 @@ async function setupBranchDatabase(
databaseUrl: database.databaseUrl,
directUrl: database.directUrl,
}).catch((error) => {
throw schemaSetupFailedError(error, signal.schema!, branch.name);
throw schemaSetupFailedError(error, signal.schema!, branch.name, context.runtime.cwd);
});
emitBranchDatabaseProgress(context, "success", "Applied database schema");
} else {
skippedSchemaWarning = "No schema.prisma file was found. Branch database env vars were created, but schema setup was skipped.";
skippedSchemaWarning = "No supported Prisma schema source was found. Branch database env vars were created, but schema setup was skipped.";
}

const envVars = await upsertBranchDatabaseEnvVars(context, provider, projectId, branch, database, envState);
Expand All @@ -200,6 +210,7 @@ async function setupBranchDatabase(
schema: schemaSetup
? {
command: schemaSetup.command,
source: schemaSetup.source,
path: schemaSetup.schemaPath,
}
: null,
Expand Down Expand Up @@ -341,7 +352,7 @@ function maybeRenderBranchDatabaseSignal(

const rows = [
signal.schema
? ` Schema ${path.relative(context.runtime.cwd, signal.schema.path) || "schema.prisma"}`
? ` Schema ${path.relative(context.runtime.cwd, signal.schema.path) || defaultSchemaSourcePath(signal.schema)}`
: null,
signal.databaseUrlReferences.length > 0
? ` Code ${signal.databaseUrlReferences.slice(0, 3).join(", ")}`
Expand Down Expand Up @@ -388,9 +399,14 @@ function emptyBranchDatabaseSetupOutcome(): BranchDatabaseSetupOutcome {
}

function formatSchemaSetupCommand(command: BranchDatabaseSchemaSetupResult["command"]): string {
return command === "migrate-deploy"
? "prisma migrate deploy"
: "prisma db push";
switch (command) {
case "migrate-deploy":
return "prisma migrate deploy";
case "db-push":
return "prisma db push";
case "prisma-next-db-init":
return "prisma-next db init";
}
}

function branchDatabaseSetupFailedError(summary: string, error: unknown, branchName: string): CliError {
Expand Down Expand Up @@ -467,8 +483,9 @@ function branchDatabaseCleanupFailedError(

function schemaSetupFailedError(
error: unknown,
schema: NonNullable<BranchDatabaseSignal["schema"]>,
schema: BranchDatabaseSchema,
branchName: string,
cwd: string,
): CliError {
return new CliError({
code: "SCHEMA_SETUP_FAILED",
Expand All @@ -480,18 +497,73 @@ function schemaSetupFailedError(
meta: {
branch: branchName,
schemaPath: schema.path,
source: schema.kind,
command: schema.command,
},
exitCode: 1,
nextSteps: [
schema.command === "migrate-deploy"
? "npx --no-install prisma migrate deploy"
: "npx --no-install prisma db push --skip-generate",
...formatSchemaSetupNextSteps(schema, cwd),
`prisma-cli app deploy --branch ${formatCommandArgument(branchName)} --db`,
],
});
}

function unsupportedBranchDatabaseSchemaError(
schema: UnsupportedBranchDatabaseSchema,
branchName: string,
context: CommandContext,
): CliError {
const sourcePath = path.relative(context.runtime.cwd, schema.path) || defaultUnsupportedSchemaSourcePath(schema);
return usageError(
"Branch database setup is not available for this Prisma schema",
`${sourcePath} targets ${formatUnsupportedSchemaTarget(schema.target)}, but --db creates Prisma Postgres databases.`,
"Use project env commands to provide a database URL for this branch, or switch the Prisma schema source to PostgreSQL before using --db.",
[
`prisma-cli project env add DATABASE_URL=<value> --branch ${formatCommandArgument(branchName)}`,
`prisma-cli app deploy --branch ${formatCommandArgument(branchName)}`,
],
"app",
);
}

function formatSchemaSetupNextSteps(schema: BranchDatabaseSchema, cwd: string): string[] {
const sourcePath = path.relative(cwd, schema.path) || defaultSchemaSourcePath(schema);
switch (schema.command) {
case "migrate-deploy":
return [`npx --no-install prisma migrate deploy --schema ${formatCommandArgument(sourcePath)}`];
case "db-push":
return [`npx --no-install prisma db push --schema ${formatCommandArgument(sourcePath)}`];
case "prisma-next-db-init":
return [
`npx --no-install prisma-next contract emit --config ${formatCommandArgument(sourcePath)}`,
`npx --no-install prisma-next db init --config ${formatCommandArgument(sourcePath)} --db <DATABASE_URL>`,
];
}
}

function defaultSchemaSourcePath(schema: BranchDatabaseSchema): string {
return schema.kind === "prisma-next" ? "prisma-next.config.ts" : "schema.prisma";
}

function defaultUnsupportedSchemaSourcePath(schema: UnsupportedBranchDatabaseSchema): string {
return schema.kind === "prisma-next" ? "prisma-next.config.ts" : "schema.prisma";
}

function formatUnsupportedSchemaTarget(target: UnsupportedBranchDatabaseSchema["target"]): string {
switch (target) {
case "cockroachdb":
return "CockroachDB";
case "mongodb":
return "MongoDB";
case "mysql":
return "MySQL";
case "sqlite":
return "SQLite";
case "sqlserver":
return "SQL Server";
}
}

function formatDebugDetails(error: unknown): string | null {
if (error instanceof Error) {
return error.stack ?? error.message;
Expand Down
Loading
Loading