Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ describe('runPreflight — secret manifest verification (ADR-0029)', () => {
expect(message).toContain('STRIPE_SECRET_KEY');
expect(message).toContain('service "ingest"');
expect(message).toContain('production');
expect(message).toContain(
'prisma project env add STRIPE_SECRET_KEY="<value>" --project proj --role production',
);
expect(state.posts).toEqual([]);
});

Expand Down
32 changes: 23 additions & 9 deletions packages/1-prisma-cloud/1-extensions/target/src/preflight.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,20 +207,34 @@ const fillFailedError = (key: string, error: unknown): Error =>

function missingError(
missing: readonly MissingBinding[],
projectId: string,
branchId: string | undefined,
stage: string | undefined,
): Error {
const scope =
const lines = missing.map((m) => ` - ${m.name} (used by service "${m.serviceAddress}")`);
const countPhrase =
missing.length === 1 ? '1 required setting has' : `${missing.length} required settings have`;
const scopeFlag =
branchId === undefined ? '--role production' : `--branch "${stage ?? branchId}"`;
// `project env add` takes a single KEY=VALUE per call; the placeholder is
// quoted so a pasted command is not read as a shell redirection.
const commands = missing.map(
(m) => `prisma project env add ${m.name}="<value>" --project ${projectId} ${scopeFlag}`,
);
const runStep =
commands.length === 1
? `Run: ${commands[0]}`
: `Run, once per setting:\n${commands.map((cmd) => ` ${cmd}`).join('\n')}`;
const consoleStep =
branchId === undefined
? 'the production class (project-level template)'
: `the preview class of stage "${stage ?? branchId}" (branch override or template)`;
const lines = missing.map((m) => ` - ${m.name} (required by service "${m.serviceAddress}")`);
? 'add each one under Production. Those values apply when the default branch deploys to production.'
: `add each one under Preview. Preview values apply to every branch deploy, including "${stage ?? branchId}".`;
return new Error(
`Deploy preflight failed — ${missing.length} env var(s) (secret or env-sourced param) are not ` +
`provisioned on Prisma Cloud for ${scope}, and are absent from the deploy shell:\n` +
`Deploy failed. ${countPhrase} no value:\n` +
`${lines.join('\n')}\n\n` +
'Set each in the deploy shell environment (the CLI will provision it on deploy), or create ' +
`it on the platform (Prisma Console or the Management API) in ${scope}.`,
'Set the value in one of these two places, then deploy again:\n' +
` - ${runStep}\n` +
` - Or in the Prisma Console: open the project, go to Environment variables, and ${consoleStep}`,
);
}

Expand Down Expand Up @@ -280,7 +294,7 @@ export async function runPreflight(
}
missing.push(meta);
}
if (missing.length > 0) throw missingError(missing, branchId, input.stage);
if (missing.length > 0) throw missingError(missing, projectId, branchId, input.stage);
return updatedAt;
}

Expand Down
Loading