feat(core,webapp): support isSecret on environment variable imports (#3809)

## Summary

The environment variables import API now accepts an optional `isSecret`
flag, so imported variables can be created as secret (redacted)
environment variables instead of plaintext. When the flag is omitted,
variables default to non-secret, preserving existing behavior for CLI
deploys and dashboard imports.

This is useful for tools that push secrets into Trigger.dev (for
example, syncing from a secrets manager) and want them stored as secrets
rather than plain environment variables.

It's available through `envvars.import` in the SDK and the `POST
/api/v1/projects/{projectRef}/envvars/{slug}/import` endpoint, and is
honored for both regular and preview-branch environments.

```ts
await envvars.import("proj_1234", "prod", {
  variables: { STRIPE_SECRET_KEY: "sk_live_..." },
  isSecret: true,
});
```
This commit is contained in:
Eric Allam
2026-06-02 15:57:06 +01:00
committed by GitHub
parent 005d7e0a3f
commit 4b78d7e84e
4 changed files with 20 additions and 0 deletions
+12
View File
@@ -0,0 +1,12 @@
---
"@trigger.dev/core": patch
---
`envvars.upload` now accepts an optional `isSecret` flag, letting you create the imported variables as secret (redacted) environment variables. When omitted, variables default to non-secret.
```ts
await envvars.upload("proj_1234", "prod", {
variables: { STRIPE_SECRET_KEY: "sk_live_..." },
isSecret: true,
});
```
@@ -40,6 +40,7 @@ export async function action({ params, request }: ActionFunctionArgs) {
const result = await repository.create(environment.project.id, {
override: typeof body.override === "boolean" ? body.override : false,
isSecret: body.isSecret,
environmentIds: [environment.id],
// Pass parent environment ID so new variables can inherit isSecret from parent
parentEnvironmentId: environment.parentEnvironmentId ?? undefined,
@@ -54,6 +55,7 @@ export async function action({ params, request }: ActionFunctionArgs) {
if (environment.parentEnvironmentId && body.parentVariables) {
const parentResult = await repository.create(environment.project.id, {
override: typeof body.override === "boolean" ? body.override : false,
isSecret: body.isSecret,
environmentIds: [environment.parentEnvironmentId],
variables: Object.entries(body.parentVariables).map(([key, value]) => ({
key,
+4
View File
@@ -14,6 +14,10 @@ export interface ImportEnvironmentVariablesParams {
*/
variables: Record<string, string>;
override?: boolean;
/**
* When `true`, the imported variables are created as secret (redacted) environment variables. Defaults to `false`.
*/
isSecret?: boolean;
}
export interface CreateEnvironmentVariableParams {
+2
View File
@@ -1215,6 +1215,8 @@ export const ImportEnvironmentVariablesRequestBody = z.object({
variables: z.record(z.string()),
parentVariables: z.record(z.string()).optional(),
override: z.boolean().optional(),
// When omitted, variables default to non-secret (the DB default is false).
isSecret: z.boolean().optional(),
source: z
.discriminatedUnion("type", [
z.object({ type: z.literal("user"), userId: z.string() }),