improve the syncEnvVars output and adapt resolveEnvVars
This commit is contained in:
@@ -9,6 +9,7 @@ import { BuildManifest, BuildTarget } from "@trigger.dev/core/v3/schemas";
|
||||
import * as esbuild from "esbuild";
|
||||
import { logger } from "../utilities/logger.js";
|
||||
import { resolveModule } from "./resolveModule.js";
|
||||
import { log, spinner } from "@clack/prompts";
|
||||
|
||||
export interface InternalBuildContext extends BuildContext {
|
||||
getLayers(): BuildLayer[];
|
||||
@@ -98,6 +99,12 @@ export function createBuildContext(
|
||||
debug: (...args) => logger.debug(...args),
|
||||
log: (...args) => logger.log(...args),
|
||||
warn: (...args) => logger.warn(...args),
|
||||
progress: (message) => log.message(message),
|
||||
spinner: (message) => {
|
||||
const $spinner = spinner();
|
||||
$spinner.start(message);
|
||||
return $spinner;
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
@@ -130,6 +137,8 @@ function applyLayerToManifest(layer: BuildLayer, manifest: BuildManifest): Build
|
||||
|
||||
if (layer.deploy?.env) {
|
||||
manifest.deploy.env ??= {};
|
||||
manifest.deploy.sync ??= {};
|
||||
manifest.deploy.sync.env ??= {};
|
||||
|
||||
for (const [key, value] of Object.entries(layer.deploy.env)) {
|
||||
if (!value) {
|
||||
@@ -137,15 +146,11 @@ function applyLayerToManifest(layer: BuildLayer, manifest: BuildManifest): Build
|
||||
}
|
||||
|
||||
if (layer.deploy.override || manifest.deploy.env[key] === undefined) {
|
||||
let needsSyncing = manifest.deploy.needsSyncing;
|
||||
const existingValue = manifest.deploy.env[key];
|
||||
|
||||
if (existingValue !== value) {
|
||||
needsSyncing = true;
|
||||
manifest.deploy.sync.env[key] = value;
|
||||
}
|
||||
|
||||
manifest.deploy.env[key] = value;
|
||||
manifest.deploy.needsSyncing = needsSyncing;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
import { intro, log, outro } from "@clack/prompts";
|
||||
import { DEFAULT_RUNTIME, ResolvedConfig } from "@trigger.dev/core/v3/build";
|
||||
import {
|
||||
BuildManifest,
|
||||
InitializeDeploymentResponseBody,
|
||||
TaskFile,
|
||||
} from "@trigger.dev/core/v3/schemas";
|
||||
import { intro, outro } from "@clack/prompts";
|
||||
import { CORE_VERSION } from "@trigger.dev/core/v3";
|
||||
import { DEFAULT_RUNTIME, ResolvedConfig } from "@trigger.dev/core/v3/build";
|
||||
import { BuildManifest, InitializeDeploymentResponseBody } from "@trigger.dev/core/v3/schemas";
|
||||
import { Command, Option as CommandOption } from "commander";
|
||||
import { writeFile } from "node:fs/promises";
|
||||
import { join, relative, resolve } from "node:path";
|
||||
import { readPackageJSON, writePackageJSON } from "pkg-types";
|
||||
import { z } from "zod";
|
||||
import { CliApiClient } from "../apiClient.js";
|
||||
import { bundleWorker } from "../build/bundle.js";
|
||||
import {
|
||||
createBuildContext,
|
||||
@@ -31,22 +29,7 @@ import {
|
||||
wrapCommandAction,
|
||||
} from "../cli/common.js";
|
||||
import { loadConfig } from "../config.js";
|
||||
import { createTempDir, writeJSONFile } from "../utilities/fileSystem.js";
|
||||
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
|
||||
import { logger } from "../utilities/logger.js";
|
||||
import { getProjectClient } from "../utilities/session.js";
|
||||
import { getTmpDir } from "../utilities/tempDirectories.js";
|
||||
import { login } from "./login.js";
|
||||
import { updateTriggerPackages } from "./update.js";
|
||||
import { spinner } from "../utilities/windows.js";
|
||||
import { readFile, writeFile } from "node:fs/promises";
|
||||
import { VERSION } from "../version.js";
|
||||
import { resolveFileSources } from "../utilities/sourceFiles.js";
|
||||
import { buildImage, generateContainerfile } from "../deploy/buildImage.js";
|
||||
import { buildManifestToJSON } from "../utilities/buildManifest.js";
|
||||
import { CliApiClient } from "../apiClient.js";
|
||||
import { chalkError, chalkWarning, cliLink } from "../utilities/cliOutput.js";
|
||||
import { docs, getInTouch } from "../utilities/links.js";
|
||||
import {
|
||||
checkLogsForErrors,
|
||||
checkLogsForWarnings,
|
||||
@@ -54,6 +37,19 @@ import {
|
||||
printWarnings,
|
||||
saveLogs,
|
||||
} from "../deploy/logs.js";
|
||||
import { buildManifestToJSON } from "../utilities/buildManifest.js";
|
||||
import { chalkError, cliLink } from "../utilities/cliOutput.js";
|
||||
import { writeJSONFile } from "../utilities/fileSystem.js";
|
||||
import { printStandloneInitialBanner } from "../utilities/initialBanner.js";
|
||||
import { logger } from "../utilities/logger.js";
|
||||
import { getProjectClient } from "../utilities/session.js";
|
||||
import { resolveFileSources } from "../utilities/sourceFiles.js";
|
||||
import { getTmpDir } from "../utilities/tempDirectories.js";
|
||||
import { spinner } from "../utilities/windows.js";
|
||||
import { VERSION } from "../version.js";
|
||||
import { login } from "./login.js";
|
||||
import { updateTriggerPackages } from "./update.js";
|
||||
import { loadDotEnvVars, resolveDotEnvVars } from "../utilities/dotEnv.js";
|
||||
|
||||
const DeployCommandOptions = CommonCommandOptions.extend({
|
||||
dryRun: z.boolean().default(false),
|
||||
@@ -210,6 +206,7 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
}
|
||||
|
||||
const serverEnvVars = await projectClient.client.getEnvironmentVariables(resolvedConfig.project);
|
||||
loadDotEnvVars(resolvedConfig.workingDir);
|
||||
|
||||
const destination = getTmpDir(resolvedConfig.workingDir, "build", options.dryRun);
|
||||
const externalsExtension = createExternalsBuildExtension("deploy", resolvedConfig);
|
||||
@@ -293,18 +290,21 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
}
|
||||
|
||||
if (
|
||||
buildManifest.deploy.env &&
|
||||
Object.keys(buildManifest.deploy.env).length > 0 &&
|
||||
buildManifest.deploy.needsSyncing
|
||||
buildManifest.deploy.sync &&
|
||||
buildManifest.deploy.sync.env &&
|
||||
Object.keys(buildManifest.deploy.sync.env).length > 0
|
||||
) {
|
||||
const numberOfEnvVars = Object.keys(buildManifest.deploy.sync.env).length;
|
||||
const vars = numberOfEnvVars === 1 ? "var" : "vars";
|
||||
|
||||
if (!options.skipSyncEnvVars) {
|
||||
const $spinner = spinner();
|
||||
$spinner.start("Syncing environment variables with the server");
|
||||
$spinner.start(`Syncing ${numberOfEnvVars} env ${vars} with the server`);
|
||||
const success = await syncEnvVarsWithServer(
|
||||
projectClient.client,
|
||||
resolvedConfig.project,
|
||||
options.env,
|
||||
buildManifest.deploy.env
|
||||
buildManifest.deploy.sync.env
|
||||
);
|
||||
|
||||
if (!success) {
|
||||
@@ -313,19 +313,19 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) {
|
||||
deployment,
|
||||
{
|
||||
name: "SyncEnvVarsError",
|
||||
message: "Failed to sync environment variables with the server",
|
||||
message: `Failed to sync ${numberOfEnvVars} env ${vars} with the server`,
|
||||
},
|
||||
"",
|
||||
$spinner
|
||||
);
|
||||
} else {
|
||||
$spinner.stop("Successfully synced environment variables with the server");
|
||||
$spinner.stop(`Successfully synced ${numberOfEnvVars} env ${vars} with the server`);
|
||||
}
|
||||
} else {
|
||||
logger.log(
|
||||
"Skipping syncing env vars. The environment variables in your project have changed, but the --skip-sync-env-vars flag was provided."
|
||||
);
|
||||
}
|
||||
|
||||
logger.log(
|
||||
"Skipping syncing environment variables. The environment variables in your project have changed, but the --skip-sync-env-vars flag was provided."
|
||||
);
|
||||
}
|
||||
|
||||
const version = deployment.version;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { TriggerConfig } from "@trigger.dev/core/v3";
|
||||
import { ResolveEnvironmentVariablesFunction, TriggerConfig } from "@trigger.dev/core/v3";
|
||||
import { DEFAULT_RUNTIME, ResolvedConfig } from "@trigger.dev/core/v3/build";
|
||||
import * as c12 from "c12";
|
||||
import { defu } from "defu";
|
||||
@@ -8,7 +8,7 @@ import { basename, dirname, isAbsolute, join, relative } from "node:path";
|
||||
import { findWorkspaceDir, resolveLockfile, resolvePackageJSON, resolveTSConfig } from "pkg-types";
|
||||
import { generateCode, loadFile } from "./imports/magicast.js";
|
||||
import { logger } from "./utilities/logger.js";
|
||||
import { additionalFiles, additionalPackages } from "@trigger.dev/core/v3/extensions";
|
||||
import { additionalFiles, additionalPackages, syncEnvVars } from "@trigger.dev/core/v3/extensions";
|
||||
|
||||
export type ResolveConfigOptions = {
|
||||
cwd?: string;
|
||||
@@ -99,6 +99,9 @@ export function configPlugin(resolvedConfig: ResolvedConfig): esbuild.Plugin | u
|
||||
|
||||
options.build = {};
|
||||
|
||||
// Remove export resolveEnvVars function as well
|
||||
delete $mod.exports.resolveEnvVars;
|
||||
|
||||
const contents = generateCode($mod);
|
||||
|
||||
logger.debug("trigger-config-strip.onLoad.contents", contents);
|
||||
@@ -247,7 +250,11 @@ function validateConfig(config: TriggerConfig, warn = true) {
|
||||
`The "resolveEnvVars" option is deprecated and will be removed. Use the "syncEnvVars" build extension instead. See https://trigger.dev/docs/trigger-config#syncEnvVars for more information.`
|
||||
);
|
||||
|
||||
//
|
||||
const resolveEnvVarsFn = config.resolveEnvVars as ResolveEnvironmentVariablesFunction;
|
||||
|
||||
config.build ??= {};
|
||||
config.build.extensions ??= [];
|
||||
config.build.extensions.push(adaptResolveEnvVarsToSyncEnvVarsExtension(resolveEnvVarsFn));
|
||||
}
|
||||
|
||||
if (config.runtime && config.runtime === "bun") {
|
||||
@@ -255,3 +262,20 @@ function validateConfig(config: TriggerConfig, warn = true) {
|
||||
logger.warn(`The "bun" runtime is currently experimental and may not work as expected.`);
|
||||
}
|
||||
}
|
||||
|
||||
function adaptResolveEnvVarsToSyncEnvVarsExtension(
|
||||
resolveEnvVarsFn: ResolveEnvironmentVariablesFunction
|
||||
) {
|
||||
return syncEnvVars(
|
||||
async (ctx) => {
|
||||
const resolveEnvVarsResult = await resolveEnvVarsFn(ctx);
|
||||
|
||||
if (!resolveEnvVarsResult) {
|
||||
return;
|
||||
}
|
||||
|
||||
return resolveEnvVarsResult.variables;
|
||||
},
|
||||
{ override: true }
|
||||
);
|
||||
}
|
||||
|
||||
@@ -19,3 +19,11 @@ export function resolveDotEnvVars(cwd?: string) {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
export function loadDotEnvVars(cwd?: string) {
|
||||
dotenv.config({
|
||||
path: [".env", ".env.local", ".env.development.local"].map((p) =>
|
||||
resolve(cwd ?? process.cwd(), p)
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -24,10 +24,17 @@ export interface BuildExtension {
|
||||
) => Promise<undefined | void> | undefined | void;
|
||||
}
|
||||
|
||||
export interface BuildSpinner {
|
||||
stop: (message: string, code?: number) => void;
|
||||
message: (message: string) => void;
|
||||
}
|
||||
|
||||
export interface BuildLogger {
|
||||
debug: (...args: unknown[]) => void;
|
||||
log: (...args: unknown[]) => void;
|
||||
warn: (...args: unknown[]) => void;
|
||||
progress: (message: string) => void;
|
||||
spinner: (message: string) => BuildSpinner;
|
||||
}
|
||||
|
||||
export interface BuildContext {
|
||||
|
||||
@@ -2,3 +2,4 @@ export * from "./emitDecoratorMetadata.js";
|
||||
export * from "./additionalFiles.js";
|
||||
export * from "./additionalPackages.js";
|
||||
export * from "./prisma.js";
|
||||
export * from "./syncEnvVars.js";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { BuildExtension } from "../build/extensions.js";
|
||||
import { BuildContext, BuildExtension } from "../build/extensions.js";
|
||||
|
||||
export type SyncEnvVarsBody = Record<string, string> | Array<{ name: string; value: string }>;
|
||||
|
||||
@@ -77,14 +77,18 @@ export function syncEnvVars(fn: SyncEnvVarsFunction, options?: SyncEnvVarsOption
|
||||
return;
|
||||
}
|
||||
|
||||
const $spinner = context.logger.spinner("Invoking syncEnvVars callback");
|
||||
|
||||
const result = await callSyncEnvVarsFn(
|
||||
fn,
|
||||
manifest.deploy.env ?? {},
|
||||
manifest.environment,
|
||||
context.config.project
|
||||
context
|
||||
);
|
||||
|
||||
if (!result) {
|
||||
$spinner.stop("No env vars detected");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -100,6 +104,18 @@ export function syncEnvVars(fn: SyncEnvVarsFunction, options?: SyncEnvVarsOption
|
||||
{} as Record<string, string>
|
||||
);
|
||||
|
||||
const numberOfEnvVars = Object.keys(env).length;
|
||||
|
||||
if (numberOfEnvVars === 0) {
|
||||
$spinner.stop("No env vars detected");
|
||||
|
||||
return;
|
||||
} else if (numberOfEnvVars === 1) {
|
||||
$spinner.stop(`Found 1 env var`);
|
||||
} else {
|
||||
$spinner.stop(`Found ${numberOfEnvVars} env vars to sync`);
|
||||
}
|
||||
|
||||
context.addLayer({
|
||||
id: "sync-env-vars",
|
||||
deploy: {
|
||||
@@ -115,23 +131,26 @@ async function callSyncEnvVarsFn(
|
||||
syncEnvVarsFn: SyncEnvVarsFunction | undefined,
|
||||
env: Record<string, string>,
|
||||
environment: string,
|
||||
projectRef: string
|
||||
context: BuildContext
|
||||
): Promise<Record<string, string> | undefined> {
|
||||
if (syncEnvVarsFn && typeof syncEnvVarsFn === "function") {
|
||||
let resolvedEnvVars: Record<string, string> = {};
|
||||
let result;
|
||||
|
||||
let result = syncEnvVarsFn({
|
||||
projectRef,
|
||||
environment,
|
||||
env,
|
||||
});
|
||||
try {
|
||||
result = await syncEnvVarsFn({
|
||||
projectRef: context.config.project,
|
||||
environment,
|
||||
env,
|
||||
});
|
||||
} catch (error) {
|
||||
context.logger.warn("Error calling syncEnvVars function", error);
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
result = await result;
|
||||
|
||||
if (Array.isArray(result)) {
|
||||
for (const item of result) {
|
||||
if (
|
||||
|
||||
@@ -44,7 +44,11 @@ export const BuildManifest = z.object({
|
||||
}),
|
||||
deploy: z.object({
|
||||
env: z.record(z.string()).optional(),
|
||||
needsSyncing: z.boolean().optional(),
|
||||
sync: z
|
||||
.object({
|
||||
env: z.record(z.string()).optional(),
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -1,12 +1,34 @@
|
||||
import { OpenAIInstrumentation } from "@traceloop/instrumentation-openai";
|
||||
import { defineConfig, ResolveEnvironmentVariablesFunction } from "@trigger.dev/sdk/v3";
|
||||
import { emitDecoratorMetadata } from "@trigger.dev/sdk/v3/extensions";
|
||||
import { InfisicalClient } from "@infisical/sdk";
|
||||
|
||||
export const resolveEnvVars: ResolveEnvironmentVariablesFunction = async ({
|
||||
projectRef,
|
||||
env,
|
||||
environment,
|
||||
}) => {};
|
||||
export const resolveEnvVars: ResolveEnvironmentVariablesFunction = async (ctx) => {
|
||||
if (
|
||||
process.env.INFISICAL_CLIENT_ID === undefined ||
|
||||
process.env.INFISICAL_CLIENT_SECRET === undefined ||
|
||||
process.env.INFISICAL_PROJECT_ID === undefined
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const client = new InfisicalClient({
|
||||
clientId: process.env.INFISICAL_CLIENT_ID,
|
||||
clientSecret: process.env.INFISICAL_CLIENT_SECRET,
|
||||
});
|
||||
|
||||
const secrets = await client.listSecrets({
|
||||
environment: ctx.environment,
|
||||
projectId: process.env.INFISICAL_PROJECT_ID,
|
||||
});
|
||||
|
||||
return {
|
||||
variables: secrets.map((secret) => ({
|
||||
name: secret.secretKey,
|
||||
value: secret.secretValue,
|
||||
})),
|
||||
};
|
||||
};
|
||||
|
||||
export default defineConfig({
|
||||
project: "yubjwjsfkxnylobaqvqz",
|
||||
|
||||
Reference in New Issue
Block a user