Skip to content

Commit 98a82e6

Browse files
authored
Merge pull request #63 from prisma/feat/config-app-config-file
feat(config): introduce app config file
2 parents acb39c6 + 9392e54 commit 98a82e6

15 files changed

Lines changed: 1668 additions & 22 deletions

docs/product/command-spec.md

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Out of scope for the current beta:
5858
non-TTY stderr, and when `NO_UPDATE_NOTIFIER` is set. When shown, update
5959
notifications are stderr-only human output and do not change the original
6060
command result.
61-
- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for Project -> Branch -> App resolution. `.prisma/local.json` is a gitignored local pin/cache, not a declarative repo config file.
61+
- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for Project -> Branch -> App resolution. `.prisma/local.json` is a gitignored local pin/cache, not a declarative repo config file. `prisma.app.json` is only for app build settings.
6262
- Remote commands do not silently change local context.
6363

6464
## Authentication
@@ -627,6 +627,11 @@ Behavior:
627627
- writes `.prisma/local.json` after Project binding succeeds and before build/deploy starts, so retries after a failed deploy do not repeat setup
628628
- before asking `Customize build settings? (y/N)`, previews the detected framework and runtime so the user can see the defaults they are accepting or changing
629629
- asks `Customize build settings? (y/N)` only while binding the directory for the first time, and only asks for Framework and HTTP port when the user opts in
630+
- for Next.js, TanStack Start, and Bun/Hono deploys, reads or creates `prisma.app.json` before build and uses it for app build settings:
631+
- `Build Command` prefers `<package-manager> run build` when `package.json` has `scripts.build`
632+
- otherwise `Build Command` falls back to the framework default, such as `next build`
633+
- `Output Directory` is a literal framework output path, such as `.next/standalone`, `.output`, or `.`
634+
- does not overwrite an existing `prisma.app.json`; edit the file or delete it and rerun deploy to regenerate defaults
630635
- after setup, deploy prints `Deploying to <Project> / <Branch> / <App>`; later deploys print a compact target header such as `Deploying ./j1 to j1 / main / j1`
631636
- deploy progress uses short stage copy (`Building locally...`, `Built <size>`, `Uploading...`, `Uploaded`, `Deploying...`, `Deployed`) and never prints `Status: running` or `Deployment is running at ...`
632637
- success human output prints `Live in <duration>`, the URL on its own line, and `Logs prisma-cli app logs`
@@ -647,11 +652,12 @@ Behavior:
647652
- if schema setup fails, deploy stops before the app build/deploy starts
648653
- `--env DATABASE_URL=...`, `--env DIRECT_URL=...`, or the same keys loaded from an env file suppress automatic database prompting; combining those database env vars with `--db` is rejected
649654
- maps user-facing framework names to deploy build strategies
655+
- does not accept `--build-command` or `--output-directory`; custom build settings are edited in `prisma.app.json`, which is initially generated from `package.json` `scripts.build` and framework defaults for config-backed deploy types
650656
- uses `src/index.ts` as the Hono deploy entrypoint when the app has no `package.json#main` or `package.json#module` and that file exists
651657
- supports vanilla Bun apps with `--framework bun` using `package.json#main` or `package.json#module`, or with `--entry <path>`
652658
- treats `--entry <path>` without `--framework` as a Bun app deploy
653659
- does not print secret values
654-
- returns app, deployment id, URL, and next steps in `--json` output
660+
- returns app, deployment id, URL, deploy settings including `prisma.app.json` status/build/output metadata, and next steps in `--json` output
655661

656662
Examples:
657663

docs/product/error-conventions.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ These codes are the minimum stable set for the MVP:
169169
- `LOCAL_PROJECT_WORKSPACE_MISMATCH`
170170
- `LOCAL_STATE_STALE`
171171
- `BRANCH_NOT_DEPLOYABLE`
172+
- `APP_CONFIG_INVALID`
172173
- `FRAMEWORK_NOT_DETECTED`
173174
- `DEPLOYMENT_NOT_FOUND`
174175
- `NO_DEPLOYMENTS`
@@ -214,6 +215,7 @@ Recommended meanings:
214215
- `LOCAL_PROJECT_WORKSPACE_MISMATCH`: local Project pin points at a different workspace than the active authenticated workspace; callers should sign in to the linked workspace or relink the directory
215216
- `LOCAL_STATE_STALE`: local Project pin no longer matches platform data and continuing would be ambiguous
216217
- `BRANCH_NOT_DEPLOYABLE`: command tried to deploy to a non-deployable branch context
218+
- `APP_CONFIG_INVALID`: `prisma.app.json` is missing required build settings, has invalid JSON, or points outside the app root
217219
- `FRAMEWORK_NOT_DETECTED`: app deploy could not detect a supported Beta framework and no explicit framework/build type was provided
218220
- `DEPLOYMENT_NOT_FOUND`: requested deployment id does not exist
219221
- `NO_DEPLOYMENTS`: command resolved a branch or app but found no deployments

docs/product/output-conventions.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ Examples:
314314
- `app deploy` should state the resolved target that matters in the current slice
315315
- first local `app deploy` binding should make the Project choice explicit before work begins
316316
- subsequent `app deploy` calls should use a compact target header such as `Deploying ./j1 to j1 / main / j1`
317+
- config-backed `app deploy` builds should show whether they created or used `prisma.app.json` before build starts: `Build Command` with its source when inferred, and `Output Directory` as a literal path such as `.next/standalone` rather than an opaque framework default label
317318
- `app logs` should state the deployment it resolved
318319
- `app list-deploys` should state which app or branch is being listed
319320

docs/product/resource-model.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ Rules:
3838
- `project` is not the same thing as `app`
3939
- Public Beta does not read or write committed config files such as `prisma.config.ts` or `.prisma/settings.json` for project resolution
4040
- `.prisma/local.json` is a gitignored local pin/cache for Workspace and Project IDs; it is not a declarative repo config file
41+
- `prisma.app.json` is a committed app build-settings file only; it must not contain Workspace, Project, Branch, App, env, or secret resolution state
4142
- Project setup is explicit: users choose an existing Project or explicitly create a new one before remote work starts
4243
- `app deploy` may orchestrate Project setup, but it must not silently choose or create Project scope
4344
- everything under a project happens in a branch
@@ -103,6 +104,7 @@ Rules:
103104
- the runtime app service is scoped by branch in the platform model
104105
- the app may be selected or created as part of app deployment workflows
105106
- app selection is local CLI state when needed for the beta package
107+
- app build settings may live in `prisma.app.json` beside `package.json`; v1 fields are `buildCommand` and `outputDirectory`
106108

107109
### Deployment
108110

packages/cli/src/controllers/app.ts

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ import {
7676
executePreviewBuild,
7777
PREVIEW_BUILD_TYPES,
7878
RESOLVED_PREVIEW_BUILD_TYPES,
79+
resolveOrCreatePreviewBuildSettings,
80+
type PreviewBuildSettingsBuildType,
81+
type PreviewBuildSettingsResolution,
7982
type ResolvedPreviewBuildType,
8083
type PreviewBuildType,
8184
} from "../lib/app/preview-build";
@@ -322,6 +325,12 @@ export async function runAppDeploy(
322325
const buildType = framework.buildType;
323326
assertSupportedEntrypoint(buildType, options?.entrypoint, "deploy");
324327
const entrypoint = await resolveDeployEntrypoint(context.runtime.cwd, framework, options?.entrypoint, context.runtime.signal);
328+
const buildSettingsResolution = await resolveOrCreatePreviewBuildSettings({
329+
appPath: context.runtime.cwd,
330+
buildType,
331+
signal: context.runtime.signal,
332+
});
333+
maybeRenderDeployBuildSettings(context, buildSettingsResolution);
325334
const portMapping = parseDeployPortMapping(String(runtime.port));
326335
const branchDatabaseSetup = await maybeSetupBranchDatabase(context, provider, projectId, toBranchDatabaseDeployBranch(target.branch), {
327336
db: options?.db,
@@ -339,6 +348,7 @@ export async function runAppDeploy(
339348
region: selectedApp.region,
340349
entrypoint,
341350
buildType,
351+
buildSettings: buildSettingsResolution.settings,
342352
portMapping,
343353
envVars,
344354
interaction: undefined,
@@ -369,6 +379,18 @@ export async function runAppDeploy(
369379
},
370380
deployment: deployResult.deployment,
371381
deploySettings: {
382+
config: {
383+
path: buildSettingsResolution.relativeConfigPath,
384+
status: buildSettingsResolution.status,
385+
},
386+
buildCommand: {
387+
value: buildSettingsResolution.settings.buildCommand,
388+
source: buildSettingsResolution.settings.buildCommandSource,
389+
},
390+
outputDirectory: {
391+
value: buildSettingsResolution.settings.outputDirectory,
392+
source: buildSettingsResolution.settings.outputDirectorySource,
393+
},
372394
framework: {
373395
key: framework.key,
374396
buildType,
@@ -2598,7 +2620,7 @@ async function resolveDeployBranch(context: CommandContext, explicitBranchName:
25982620

25992621
interface ResolvedDeployFramework {
26002622
key: string;
2601-
buildType: ResolvedPreviewBuildType;
2623+
buildType: PreviewBuildSettingsBuildType;
26022624
displayName: string;
26032625
annotation: string;
26042626
}
@@ -2743,7 +2765,6 @@ async function detectNextConfig(cwd: string, signal: AbortSignal): Promise<{ exi
27432765
const candidates = [
27442766
"next.config.js",
27452767
"next.config.mjs",
2746-
"next.config.cjs",
27472768
"next.config.ts",
27482769
"next.config.mts",
27492770
];
@@ -2869,6 +2890,36 @@ async function maybeRenderDeploySetupBlock(
28692890
context.output.stderr.write(`${prefix} ${details.projectName} / ${details.branchName} / ${details.appName}\n\n`);
28702891
}
28712892

2893+
function maybeRenderDeployBuildSettings(
2894+
context: CommandContext,
2895+
resolution: PreviewBuildSettingsResolution,
2896+
): void {
2897+
if (context.flags.json || context.flags.quiet) {
2898+
return;
2899+
}
2900+
2901+
const settings = resolution.settings;
2902+
const title = resolution.status === "created"
2903+
? `Created ${resolution.relativeConfigPath}`
2904+
: `Using ${resolution.relativeConfigPath}`;
2905+
2906+
context.output.stderr.write(
2907+
`${title}\n`
2908+
+ `${renderDeployOutputRows(context.ui, [
2909+
{
2910+
label: "Build Command",
2911+
value: settings.buildCommand ?? "none",
2912+
origin: settings.buildCommandSource ?? undefined,
2913+
},
2914+
{
2915+
label: "Output Directory",
2916+
value: settings.outputDirectory,
2917+
origin: settings.outputDirectorySource ?? undefined,
2918+
},
2919+
]).join("\n")}\n\n`,
2920+
);
2921+
}
2922+
28722923
function maybeRenderProjectLinked(
28732924
context: CommandContext,
28742925
directory: string,

packages/cli/src/lib/app/bun-project.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import path from "node:path";
44
export interface BunPackageJsonLike {
55
main?: unknown;
66
module?: unknown;
7+
packageManager?: unknown;
78
scripts?: unknown;
89
dependencies?: unknown;
910
devDependencies?: unknown;

0 commit comments

Comments
 (0)