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
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,9 @@
},
"dependencies": {
"@clack/prompts": "^1.5.0",
"@prisma/compute-sdk": "^0.20.0",
"@prisma/compute-sdk": "^0.21.0",
"@prisma/credentials-store": "^7.8.0",
"@prisma/management-api-sdk": "^1.35.0",
"@prisma/management-api-sdk": "^1.37.0",
"c12": "4.0.0-beta.5",
"colorette": "^2.0.20",
"commander": "^14.0.3",
Expand Down
5 changes: 2 additions & 3 deletions packages/cli/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { getCliName, getCliVersion } from "./lib/version";
import { attachCommandDescriptor } from "./shell/command-meta";
import { CliError } from "./shell/errors";
import { addCompactGlobalFlags } from "./shell/global-flags";
import { writeHumanError, writeJsonError, writeJsonSuccess } from "./shell/output";
import { formatUnexpectedError, writeHumanError, writeJsonError, writeJsonSuccess } from "./shell/output";
import { disposePromptState } from "./shell/prompt";
import { configureRuntimeCommand, createCommandContext, type CliRuntime } from "./shell/runtime";
import { createShellUi } from "./shell/ui";
Expand Down Expand Up @@ -49,8 +49,7 @@ export async function runCli(options: RunCliOptions = {}): Promise<number> {
return error.code === "commander.helpDisplayed" ? 0 : 2;
}

const message = error instanceof Error ? error.stack ?? error.message : String(error);
runtime.stderr.write(`${message}\n`);
runtime.stderr.write(formatUnexpectedError(error, runtime.argv.includes("--trace")));
return 1;
} finally {
disposePromptState(runtime.stdin);
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/src/controllers/app-env-file.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { CommandSuccess } from "../shell/output";
import type { CommandContext } from "../shell/runtime";
import type {
EnvAddResult,
EnvResolvedContext,
EnvUpdateResult,
EnvVariableMetadata,
} from "../types/app-env";
Expand All @@ -29,6 +30,7 @@ export async function runEnvAddFile(
resolved: ResolvedEnvFileScope,
filePath: string,
assignments: EnvFileAssignment[],
verboseContext: EnvResolvedContext,
): Promise<CommandSuccess<EnvAddResult>> {
const existing = await findVariablesByNaturalKey(
client,
Expand Down Expand Up @@ -96,6 +98,7 @@ export async function runEnvAddFile(
command: "project.env.add",
result: {
projectId,
verboseContext,
scope: resolved.descriptor,
variables,
file: {
Expand All @@ -115,6 +118,7 @@ export async function runEnvUpdateFile(
resolved: ResolvedEnvFileScope,
filePath: string,
assignments: EnvFileAssignment[],
verboseContext: EnvResolvedContext,
): Promise<CommandSuccess<EnvUpdateResult>> {
const existing = await findVariablesByNaturalKey(
client,
Expand Down Expand Up @@ -172,6 +176,7 @@ export async function runEnvUpdateFile(
command: "project.env.update",
result: {
projectId,
verboseContext,
scope: resolved.descriptor,
variables,
file: {
Expand Down
32 changes: 22 additions & 10 deletions packages/cli/src/controllers/app-env.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import type {
EnvListTarget,
EnvListResult,
EnvRmResult,
EnvResolvedContext,
EnvScopeDescriptor,
EnvUpdateResult,
} from "../types/app-env";
Expand Down Expand Up @@ -92,14 +93,14 @@ export async function runEnvAdd(
}

const input = await resolveEnvWriteInput(context, source, "add");
const { client, projectId } = await requireClientAndProject(context, flags.projectRef, "project env add");
const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env add");
const resolved = await resolveScopeToApi(client, projectId, scope, {
createBranchIfMissing: true,
signal: context.runtime.signal,
});

if (input.kind === "file") {
return runEnvAddFile(context, client, projectId, resolved, input.filePath, input.assignments);
return runEnvAddFile(context, client, projectId, resolved, input.filePath, input.assignments, verboseContext);
}

const existing = await findVariableByNaturalKey(client, projectId, input.key, resolved, context.runtime.signal);
Expand All @@ -121,7 +122,6 @@ export async function runEnvAdd(
const warnings =
scope.kind === "branch" &&
!(await findVariableByNaturalKey(client, projectId, input.key, {
scope: { kind: "role", role: "preview" },
descriptor: { kind: "role", role: "preview" },
apiTarget: { class: "preview", branchId: null },
}, context.runtime.signal))
Expand Down Expand Up @@ -153,6 +153,7 @@ export async function runEnvAdd(
command: "project.env.add",
result: {
projectId,
verboseContext,
scope: resolved.descriptor,
variable: toMetadata(data.data as RawEnvironmentVariable, resolved.descriptor),
},
Expand All @@ -179,14 +180,14 @@ export async function runEnvUpdate(
}

const input = await resolveEnvWriteInput(context, source, "update");
const { client, projectId } = await requireClientAndProject(context, flags.projectRef, "project env update");
const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env update");
const resolved = await resolveScopeToApi(client, projectId, scope, {
createBranchIfMissing: false,
signal: context.runtime.signal,
});

if (input.kind === "file") {
return runEnvUpdateFile(context, client, projectId, resolved, input.filePath, input.assignments);
return runEnvUpdateFile(context, client, projectId, resolved, input.filePath, input.assignments, verboseContext);
}

const existing = await findVariableByNaturalKey(client, projectId, input.key, resolved, context.runtime.signal);
Expand Down Expand Up @@ -221,6 +222,7 @@ export async function runEnvUpdate(
command: "project.env.update",
result: {
projectId,
verboseContext,
scope: resolved.descriptor,
variable: toMetadata(data.data as RawEnvironmentVariable, resolved.descriptor),
},
Expand Down Expand Up @@ -301,8 +303,8 @@ export async function runEnvList(
): Promise<CommandSuccess<EnvListResult>> {
const explicit = resolveEnvScope(flags, { requireExplicit: false, command: "list" });

const { client, projectId } = await requireClientAndProject(context, flags.projectRef, "project env list");
const resolved = await resolveListScopeToApi(client, projectId, explicit, {
const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env list");
const resolved = await resolveListScopeToApi(client, projectId, explicit ?? undefined, {
cwd: context.runtime.cwd,
signal: context.runtime.signal,
});
Expand All @@ -318,6 +320,7 @@ export async function runEnvList(
command: "project.env.list",
result: {
projectId,
verboseContext,
scope: resolved.descriptor,
target: resolved.target,
variables: variables.map((row) => toMetadata(row, resolved.descriptor)),
Expand Down Expand Up @@ -355,7 +358,7 @@ export async function runEnvRemove(
);
}

const { client, projectId } = await requireClientAndProject(context, flags.projectRef, "project env remove");
const { client, projectId, verboseContext } = await requireClientAndProject(context, flags.projectRef, "project env remove");
const resolved = await resolveScopeToApi(client, projectId, scope, {
createBranchIfMissing: false,
signal: context.runtime.signal,
Expand Down Expand Up @@ -390,6 +393,7 @@ export async function runEnvRemove(
command: "project.env.remove",
result: {
projectId,
verboseContext,
scope: resolved.descriptor,
key,
},
Expand All @@ -402,7 +406,7 @@ async function requireClientAndProject(
context: CommandContext,
explicitProject: string | undefined,
commandName: string,
): Promise<{ client: ManagementApiClient; projectId: string }> {
): Promise<{ client: ManagementApiClient; projectId: string; verboseContext: EnvResolvedContext }> {
const authState = await requireAuthenticatedAuthState(context);
const client = await requireComputeAuth(context.runtime.env, context.runtime.signal);
if (!client) {
Expand All @@ -420,7 +424,15 @@ async function requireClientAndProject(
commandName,
});

return { client, projectId: target.project.id };
return {
client,
projectId: target.project.id,
verboseContext: {
workspace: authState.workspace,
project: target.project,
resolution: target.resolution,
},
};
}

async function resolveScopeToApi(
Expand Down
33 changes: 32 additions & 1 deletion packages/cli/src/controllers/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
AppOpenResult,
AppPromoteResult,
AppRemoveResult,
AppResolvedContext,
AppRollbackResult,
AppShowResult,
AppRunResult,
Expand All @@ -38,7 +39,7 @@ import type { ProjectResolution, ProjectSummary } from "../types/project";
import { requireComputeAuth } from "../lib/auth/guard";
import { readAuthState } from "../lib/auth/auth-ops";
import { getApiBaseUrl, SERVICE_TOKEN_ENV_VAR } from "../lib/auth/client";
import { parseEnvAssignments } from "../lib/app/env-vars";
import { envVarNames, parseEnvAssignments } from "../lib/app/env-vars";
import { renderDeployOutputRows, renderDeploySettingsPreview } from "../lib/app/deploy-output";
import {
DEFAULT_LOCAL_DEV_PORT,
Expand Down Expand Up @@ -367,6 +368,18 @@ export async function runAppDeploy(
name: deployResult.app.name,
},
deployment: deployResult.deployment,
deploySettings: {
framework: {
key: framework.key,
buildType,
name: framework.displayName,
source: framework.annotation,
},
entrypoint: entrypoint ?? null,
httpPort: runtime.port,
region: selectedApp.region ?? null,
envVars: envVarNames(envVars),
},
durationMs: deployDurationMs,
localPin: localPinResult,
},
Expand All @@ -393,6 +406,7 @@ export async function runAppListDeploys(
command: "app.list-deploys",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: null,
deployments: [],
},
Expand Down Expand Up @@ -423,6 +437,7 @@ export async function runAppListDeploys(
command: "app.list-deploys",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: {
id: deploymentsResult.app.id,
name: deploymentsResult.app.name,
Expand Down Expand Up @@ -454,6 +469,7 @@ export async function runAppShow(
command: "app.show",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: null,
liveDeployment: null,
liveUrl: null,
Expand Down Expand Up @@ -489,6 +505,7 @@ export async function runAppShow(
command: "app.show",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: {
id: deploymentsResult.app.id,
name: deploymentsResult.app.name,
Expand Down Expand Up @@ -625,6 +642,7 @@ export async function runAppOpen(
command: "app.open",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: {
id: deploymentsResult.app.id,
name: deploymentsResult.app.name,
Expand Down Expand Up @@ -1094,6 +1112,7 @@ export async function runAppPromote(
command: "app.promote",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: {
id: deploymentsResult.app.id,
name: deploymentsResult.app.name,
Expand Down Expand Up @@ -1164,6 +1183,7 @@ export async function runAppRollback(
command: "app.rollback",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: {
id: deploymentsResult.app.id,
name: deploymentsResult.app.name,
Expand Down Expand Up @@ -1205,6 +1225,7 @@ export async function runAppRemove(
command: "app.remove",
result: {
projectId,
verboseContext: toAppVerboseContext(target),
app: {
id: removedApp.id,
name: removedApp.name,
Expand Down Expand Up @@ -2493,11 +2514,21 @@ function toBranchKind(name: string): BranchKind {

function toResultBranch(branch: ResolvedAppProjectContext["branch"]): AppDeployResult["branch"] {
return {
id: branch.id,
name: branch.name,
kind: branch.kind,
};
}

function toAppVerboseContext(target: ResolvedAppProjectContext): AppResolvedContext {
return {
workspace: target.workspace,
project: target.project,
branch: target.branch,
resolution: target.resolution,
};
}

function toBranchDatabaseDeployBranch(branch: ResolvedAppProjectContext["branch"]): BranchDatabaseDeployBranch {
if (!branch.id) {
throw new Error(`Deploy branch "${branch.name}" was not resolved remotely.`);
Expand Down
5 changes: 5 additions & 0 deletions packages/cli/src/controllers/branch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ async function listRealBranches(context: CommandContext): Promise<BranchListResu
return {
projectId: target.project.id,
projectName: target.project.name,
verboseContext: {
workspace,
project: target.project,
resolution: target.resolution,
},
branches: sortBranches(branches.map(toBranchSummary)),
};
}
Expand Down
18 changes: 18 additions & 0 deletions packages/cli/src/lib/diagnostics.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { resolveLocalStateFilePath } from "../adapters/local-state";
import { resolveStateDir, type CommandContext } from "../shell/runtime";
import type { CommandDiagnostics } from "../types/diagnostics";
import { readLocalGitState } from "./git/local-status";

export async function collectCommandDiagnostics(
context: CommandContext,
options: { durationMs?: number } = {},
): Promise<CommandDiagnostics> {
const stateDir = resolveStateDir(context.runtime);

return {
cwd: context.runtime.cwd,
stateFilePath: resolveLocalStateFilePath(stateDir),
git: await readLocalGitState(context.runtime.cwd, context.runtime.signal),
durationMs: options.durationMs,
};
}
Loading
Loading