Improve the update CLI command and fix missing tsconfig.json error (#1315)
* Fixes for CLI update command, and make the hide the "whoami" command output when running in dev * Fix an issue where a missing tsconfig.json file would throw an error on dev/deploy * Don’t show latest CLI warning when using a prerelease * Only print CLI update required message when update is embedded * Strip out TRIGGER\_ keys when using syncEnvVars, to prevent deploy errors
This commit is contained in:
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
"trigger.dev": patch
|
||||||
|
"@trigger.dev/core": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix an issue where a missing tsconfig.json file would throw an error on dev/deploy
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"trigger.dev": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixes for CLI update command, and make the hide the "whoami" command output when running in dev.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@trigger.dev/build": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Strip out TRIGGER\_ keys when using syncEnvVars, to prevent deploy errors
|
||||||
@@ -63,6 +63,8 @@ const UNSYNCABLE_ENV_VARS = [
|
|||||||
"_",
|
"_",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
const UNSYNCABLE_ENV_VARS_PREFIXES = ["TRIGGER_"];
|
||||||
|
|
||||||
export type SyncEnvVarsFunction = (params: SyncEnvVarsParams) => SyncEnvVarsResult;
|
export type SyncEnvVarsFunction = (params: SyncEnvVarsParams) => SyncEnvVarsResult;
|
||||||
|
|
||||||
export type SyncEnvVarsOptions = {
|
export type SyncEnvVarsOptions = {
|
||||||
@@ -98,6 +100,11 @@ export function syncEnvVars(fn: SyncEnvVarsFunction, options?: SyncEnvVarsOption
|
|||||||
return acc;
|
return acc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Strip out any TRIGGER_ prefix env vars
|
||||||
|
if (UNSYNCABLE_ENV_VARS_PREFIXES.some((prefix) => key.startsWith(prefix))) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
acc[key] = value;
|
acc[key] = value;
|
||||||
return acc;
|
return acc;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ export async function devCommand(options: DevCommandOptions) {
|
|||||||
|
|
||||||
const authorization = await login({
|
const authorization = await login({
|
||||||
embedded: true,
|
embedded: true,
|
||||||
|
silent: true,
|
||||||
defaultApiUrl: options.apiUrl,
|
defaultApiUrl: options.apiUrl,
|
||||||
profile: options.profile,
|
profile: options.profile,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -59,12 +59,18 @@ export type LoginOptions = {
|
|||||||
defaultApiUrl?: string;
|
defaultApiUrl?: string;
|
||||||
embedded?: boolean;
|
embedded?: boolean;
|
||||||
profile?: string;
|
profile?: string;
|
||||||
|
silent?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export async function login(options?: LoginOptions): Promise<LoginResult> {
|
export async function login(options?: LoginOptions): Promise<LoginResult> {
|
||||||
return await tracer.startActiveSpan("login", async (span) => {
|
return await tracer.startActiveSpan("login", async (span) => {
|
||||||
try {
|
try {
|
||||||
const opts = { defaultApiUrl: "https://api.trigger.dev", embedded: false, ...options };
|
const opts = {
|
||||||
|
defaultApiUrl: "https://api.trigger.dev",
|
||||||
|
embedded: false,
|
||||||
|
silent: false,
|
||||||
|
...options,
|
||||||
|
};
|
||||||
|
|
||||||
span.setAttributes({
|
span.setAttributes({
|
||||||
"cli.config.apiUrl": opts.defaultApiUrl,
|
"cli.config.apiUrl": opts.defaultApiUrl,
|
||||||
@@ -111,7 +117,8 @@ export async function login(options?: LoginOptions): Promise<LoginResult> {
|
|||||||
skipTelemetry: !span.isRecording(),
|
skipTelemetry: !span.isRecording(),
|
||||||
logLevel: logger.loggerLevel,
|
logLevel: logger.loggerLevel,
|
||||||
},
|
},
|
||||||
true
|
true,
|
||||||
|
opts.silent
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!whoAmIResult.success) {
|
if (!whoAmIResult.success) {
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ export function configureUpdateCommand(program: Command) {
|
|||||||
const triggerPackageFilter = /^@trigger\.dev/;
|
const triggerPackageFilter = /^@trigger\.dev/;
|
||||||
|
|
||||||
export async function updateCommand(dir: string, options: UpdateCommandOptions) {
|
export async function updateCommand(dir: string, options: UpdateCommandOptions) {
|
||||||
await updateTriggerPackages(dir, options);
|
await updateTriggerPackages(dir, options, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateTriggerPackages(
|
export async function updateTriggerPackages(
|
||||||
@@ -74,7 +74,7 @@ export async function updateTriggerPackages(
|
|||||||
|
|
||||||
const newCliVersion = await updateCheck();
|
const newCliVersion = await updateCheck();
|
||||||
|
|
||||||
if (newCliVersion) {
|
if (newCliVersion && !cliVersion.startsWith("0.0.0")) {
|
||||||
prettyWarning(
|
prettyWarning(
|
||||||
"You're not running the latest CLI version, please consider updating ASAP",
|
"You're not running the latest CLI version, please consider updating ASAP",
|
||||||
`Current: ${cliVersion}\nLatest: ${newCliVersion}`,
|
`Current: ${cliVersion}\nLatest: ${newCliVersion}`,
|
||||||
@@ -127,24 +127,30 @@ export async function updateTriggerPackages(
|
|||||||
|
|
||||||
if (mismatches.length === 0) {
|
if (mismatches.length === 0) {
|
||||||
if (!embedded) {
|
if (!embedded) {
|
||||||
outro(`Nothing to do${newCliVersion ? " ..but you should really update your CLI!" : ""}`);
|
outro(`Nothing to update${newCliVersion ? " ..but you should really update your CLI!" : ""}`);
|
||||||
return hasOutput;
|
return hasOutput;
|
||||||
}
|
}
|
||||||
return hasOutput;
|
return hasOutput;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isDowngrade) {
|
if (embedded) {
|
||||||
prettyError("Some of the installed @trigger.dev packages are newer than your CLI version");
|
if (isDowngrade) {
|
||||||
} else {
|
prettyError("Some of the installed @trigger.dev packages are newer than your CLI version");
|
||||||
prettyWarning(
|
} else {
|
||||||
"Mismatch between your CLI version and installed packages",
|
if (embedded) {
|
||||||
"We recommend pinned versions for guaranteed compatibility"
|
prettyWarning(
|
||||||
);
|
"Mismatch between your CLI version and installed packages",
|
||||||
|
"We recommend pinned versions for guaranteed compatibility"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasTTY) {
|
if (!hasTTY) {
|
||||||
// Running in CI with version mismatch detected
|
// Running in CI with version mismatch detected
|
||||||
outro("Deploy failed");
|
if (embedded) {
|
||||||
|
outro("Deploy failed");
|
||||||
|
}
|
||||||
|
|
||||||
console.log(
|
console.log(
|
||||||
`ERROR: Version mismatch detected while running in CI. This won't end well. Aborting.
|
`ERROR: Version mismatch detected while running in CI. This won't end well. Aborting.
|
||||||
@@ -162,8 +168,7 @@ export async function updateTriggerPackages(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// WARNING: We can only start accepting user input once we know this is a TTY, otherwise, the process will exit with an error in CI
|
// WARNING: We can only start accepting user input once we know this is a TTY, otherwise, the process will exit with an error in CI
|
||||||
|
if (isDowngrade && embedded) {
|
||||||
if (isDowngrade) {
|
|
||||||
printUpdateTable("Versions", mismatches, cliVersion, "installed", "CLI");
|
printUpdateTable("Versions", mismatches, cliVersion, "installed", "CLI");
|
||||||
|
|
||||||
outro("CLI update required!");
|
outro("CLI update required!");
|
||||||
@@ -187,14 +192,20 @@ export async function updateTriggerPackages(
|
|||||||
|
|
||||||
if (!userWantsToUpdate) {
|
if (!userWantsToUpdate) {
|
||||||
if (requireUpdate) {
|
if (requireUpdate) {
|
||||||
outro("You shall not pass!");
|
if (embedded) {
|
||||||
|
outro("You shall not pass!");
|
||||||
|
|
||||||
logger.log(
|
logger.log(
|
||||||
`${chalkError(
|
`${chalkError(
|
||||||
"X Error:"
|
"X Error:"
|
||||||
)} Update required: Version mismatches are a common source of bugs and errors. Please update or use \`--skip-update-check\` at your own risk.\n`
|
)} Update required: Version mismatches are a common source of bugs and errors. Please update or use \`--skip-update-check\` at your own risk.\n`
|
||||||
);
|
);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
|
} else {
|
||||||
|
outro("No updates applied");
|
||||||
|
|
||||||
|
process.exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!embedded) {
|
if (!embedded) {
|
||||||
@@ -205,7 +216,7 @@ export async function updateTriggerPackages(
|
|||||||
}
|
}
|
||||||
|
|
||||||
const installSpinner = spinner();
|
const installSpinner = spinner();
|
||||||
installSpinner.start("Writing new package.json file");
|
installSpinner.start("Updating dependencies in package.json");
|
||||||
|
|
||||||
// Backup package.json
|
// Backup package.json
|
||||||
const packageJsonBackupPath = `${packageJsonPath}.bak`;
|
const packageJsonBackupPath = `${packageJsonPath}.bak`;
|
||||||
@@ -235,12 +246,16 @@ export async function updateTriggerPackages(
|
|||||||
const packageManager = await detectPackageManager(projectPath);
|
const packageManager = await detectPackageManager(projectPath);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
installSpinner.message(`Installing new package versions with ${packageManager}`);
|
installSpinner.message(
|
||||||
|
`Installing new package versions${packageManager ? ` with ${packageManager.name}` : ""}`
|
||||||
|
);
|
||||||
|
|
||||||
await installDependencies({ cwd: projectPath });
|
await installDependencies({ cwd: projectPath, silent: true });
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
installSpinner.stop(
|
installSpinner.stop(
|
||||||
`Failed to install new package versions${packageManager ? ` with ${packageManager}` : ""}`
|
`Failed to install new package versions${
|
||||||
|
packageManager ? ` with ${packageManager.name}` : ""
|
||||||
|
}`
|
||||||
);
|
);
|
||||||
|
|
||||||
// Remove exit handler in case of failure
|
// Remove exit handler in case of failure
|
||||||
|
|||||||
@@ -51,27 +51,32 @@ export async function whoAmICommand(options: unknown) {
|
|||||||
|
|
||||||
export async function whoAmI(
|
export async function whoAmI(
|
||||||
options?: WhoamiCommandOptions,
|
options?: WhoamiCommandOptions,
|
||||||
embedded: boolean = false
|
embedded: boolean = false,
|
||||||
|
silent: boolean = false
|
||||||
): Promise<WhoAmIResult> {
|
): Promise<WhoAmIResult> {
|
||||||
if (!embedded) {
|
if (!embedded) {
|
||||||
intro(`Displaying your account details [${options?.profile ?? "default"}]`);
|
intro(`Displaying your account details [${options?.profile ?? "default"}]`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadingSpinner = spinner();
|
const loadingSpinner = spinner();
|
||||||
loadingSpinner.start("Checking your account details");
|
|
||||||
|
if (!silent) {
|
||||||
|
loadingSpinner.start("Checking your account details");
|
||||||
|
}
|
||||||
|
|
||||||
const authentication = await isLoggedIn(options?.profile);
|
const authentication = await isLoggedIn(options?.profile);
|
||||||
|
|
||||||
if (!authentication.ok) {
|
if (!authentication.ok) {
|
||||||
if (authentication.error === "fetch failed") {
|
if (authentication.error === "fetch failed") {
|
||||||
loadingSpinner.stop("Fetch failed. Platform down?");
|
!silent && loadingSpinner.stop("Fetch failed. Platform down?");
|
||||||
} else {
|
} else {
|
||||||
if (embedded) {
|
if (embedded) {
|
||||||
loadingSpinner.stop(
|
!silent &&
|
||||||
`Failed to check account details. You may want to run \`trigger.dev logout --profile ${
|
loadingSpinner.stop(
|
||||||
options?.profile ?? "default"
|
`Failed to check account details. You may want to run \`trigger.dev logout --profile ${
|
||||||
}\` and try again.`
|
options?.profile ?? "default"
|
||||||
);
|
}\` and try again.`
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
loadingSpinner.stop(
|
loadingSpinner.stop(
|
||||||
`You must login first. Use \`trigger.dev login --profile ${
|
`You must login first. Use \`trigger.dev login --profile ${
|
||||||
@@ -110,7 +115,7 @@ URL: ${chalkLink(authentication.auth.apiUrl)}
|
|||||||
`Account details [${authentication.profile}]`
|
`Account details [${authentication.profile}]`
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
loadingSpinner.stop(`Retrieved your account details for ${userData.data.email}`);
|
!silent && loadingSpinner.stop(`Retrieved your account details for ${userData.data.email}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return userData;
|
return userData;
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ async function resolveConfig(
|
|||||||
warn = true
|
warn = true
|
||||||
): Promise<ResolvedConfig> {
|
): Promise<ResolvedConfig> {
|
||||||
const packageJsonPath = await resolvePackageJSON(cwd);
|
const packageJsonPath = await resolvePackageJSON(cwd);
|
||||||
const tsconfigPath = await resolveTSConfig(cwd);
|
const tsconfigPath = await safeResolveTsConfig(cwd);
|
||||||
const lockfilePath = await resolveLockfile(cwd);
|
const lockfilePath = await resolveLockfile(cwd);
|
||||||
const workspaceDir = await findWorkspaceDir(cwd);
|
const workspaceDir = await findWorkspaceDir(cwd);
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ async function resolveConfig(
|
|||||||
conditions: [],
|
conditions: [],
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
) as ResolvedConfig; // TODO: For some reason, without this, there is a weird type error complaining about tsconfigPath being string | nullish, which can't be assigned to string | undefined
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...mergedConfig,
|
...mergedConfig,
|
||||||
@@ -188,6 +188,14 @@ async function resolveConfig(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function safeResolveTsConfig(cwd: string) {
|
||||||
|
try {
|
||||||
|
return await resolveTSConfig(cwd);
|
||||||
|
} catch {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const IGNORED_DIRS = ["node_modules", ".git", "dist", "out", "build"];
|
const IGNORED_DIRS = ["node_modules", ".git", "dist", "out", "build"];
|
||||||
|
|
||||||
async function autoDetectDirs(workingDir: string): Promise<string[]> {
|
async function autoDetectDirs(workingDir: string): Promise<string[]> {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export async function resolveFileSources(
|
|||||||
}
|
}
|
||||||
|
|
||||||
await resolveConfigSource(sources, resolvedConfig.workingDir, resolvedConfig.configFile);
|
await resolveConfigSource(sources, resolvedConfig.workingDir, resolvedConfig.configFile);
|
||||||
await resolveConfigSource(sources, resolvedConfig.workingDir, resolvedConfig.tsconfig);
|
await resolveConfigSource(sources, resolvedConfig.workingDir, resolvedConfig.tsconfigPath);
|
||||||
await resolveConfigSource(sources, resolvedConfig.workingDir, resolvedConfig.packageJsonPath);
|
await resolveConfigSource(sources, resolvedConfig.workingDir, resolvedConfig.packageJsonPath);
|
||||||
|
|
||||||
return sources;
|
return sources;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ export type ResolvedConfig = Prettify<
|
|||||||
packageJsonPath: string;
|
packageJsonPath: string;
|
||||||
lockfilePath: string;
|
lockfilePath: string;
|
||||||
configFile?: string;
|
configFile?: string;
|
||||||
|
tsconfigPath?: string;
|
||||||
resolveEnvVars?: ResolveEnvironmentVariablesFunction;
|
resolveEnvVars?: ResolveEnvironmentVariablesFunction;
|
||||||
instrumentedPackageNames?: string[];
|
instrumentedPackageNames?: string[];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user