Adding some additional telemetry during deploy to help debug issues
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"trigger.dev": patch
|
||||
---
|
||||
|
||||
Adding some additional telemetry during deploy to help debug issues
|
||||
@@ -1286,7 +1286,7 @@ async function compileProject(
|
||||
|
||||
const javascriptProject = new JavascriptProject(config.projectDir);
|
||||
|
||||
const dependencies = await gatherRequiredDependencies(allImports, config, javascriptProject);
|
||||
const dependencies = await resolveRequiredDependencies(allImports, config, javascriptProject);
|
||||
|
||||
logger.debug("gatherRequiredDependencies()", { dependencies });
|
||||
|
||||
@@ -1300,6 +1300,10 @@ async function compileProject(
|
||||
},
|
||||
};
|
||||
|
||||
span.setAttributes({
|
||||
...flattenAttributes(packageJsonContents, "packageJson.contents"),
|
||||
});
|
||||
|
||||
await writeJSONFile(join(tempDir, "package.json"), packageJsonContents);
|
||||
|
||||
const copyResult = await copyAdditionalFiles(config, tempDir);
|
||||
@@ -1548,81 +1552,103 @@ async function typecheckProject(config: ResolvedConfig, options: DeployCommandOp
|
||||
|
||||
// Returns the dependencies that are required by the output that are found in output and the CLI package dependencies
|
||||
// Returns the dependency names and the version to use (taken from the CLI deps package.json)
|
||||
async function gatherRequiredDependencies(
|
||||
async function resolveRequiredDependencies(
|
||||
imports: Metafile["outputs"][string]["imports"],
|
||||
config: ResolvedConfig,
|
||||
project: JavascriptProject
|
||||
) {
|
||||
const dependencies: Record<string, string> = {};
|
||||
const resolvablePackageNames = new Set<string>();
|
||||
return await tracer.startActiveSpan("resolveRequiredDependencies", async (span) => {
|
||||
const resolvablePackageNames = new Set<string>();
|
||||
|
||||
for (const file of imports) {
|
||||
if ((file.kind !== "require-call" && file.kind !== "dynamic-import") || !file.external) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const packageName = detectPackageNameFromImportPath(file.path);
|
||||
|
||||
if (!packageName) {
|
||||
continue;
|
||||
}
|
||||
|
||||
resolvablePackageNames.add(packageName);
|
||||
}
|
||||
|
||||
const resolvedPackageVersions = await project.resolveAll(Array.from(resolvablePackageNames));
|
||||
const missingPackages = Array.from(resolvablePackageNames).filter(
|
||||
(packageName) => !resolvedPackageVersions[packageName]
|
||||
);
|
||||
|
||||
for (const missingPackage of missingPackages) {
|
||||
const internalDependencyVersion =
|
||||
(packageJson.dependencies as Record<string, string>)[missingPackage] ??
|
||||
detectDependencyVersion(missingPackage);
|
||||
|
||||
if (internalDependencyVersion) {
|
||||
dependencies[missingPackage] = stripWorkspaceFromVersion(internalDependencyVersion);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [packageName, version] of Object.entries(resolvedPackageVersions)) {
|
||||
dependencies[packageName] = version;
|
||||
}
|
||||
|
||||
if (config.additionalPackages) {
|
||||
for (const packageName of config.additionalPackages) {
|
||||
if (dependencies[packageName]) {
|
||||
for (const file of imports) {
|
||||
if ((file.kind !== "require-call" && file.kind !== "dynamic-import") || !file.external) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const packageParts = parsePackageName(packageName);
|
||||
const packageName = detectPackageNameFromImportPath(file.path);
|
||||
|
||||
if (packageParts.version) {
|
||||
dependencies[packageParts.name] = packageParts.version;
|
||||
if (!packageName) {
|
||||
continue;
|
||||
} else {
|
||||
const externalDependencyVersion = await project.resolve(packageParts.name, {
|
||||
allowDev: true,
|
||||
});
|
||||
}
|
||||
|
||||
if (externalDependencyVersion) {
|
||||
dependencies[packageParts.name] = externalDependencyVersion;
|
||||
resolvablePackageNames.add(packageName);
|
||||
}
|
||||
|
||||
span.setAttribute("resolvablePackageNames", Array.from(resolvablePackageNames));
|
||||
|
||||
const resolvedPackageVersions = await project.resolveAll(Array.from(resolvablePackageNames));
|
||||
const missingPackages = Array.from(resolvablePackageNames).filter(
|
||||
(packageName) => !resolvedPackageVersions[packageName]
|
||||
);
|
||||
|
||||
span.setAttributes({
|
||||
...flattenAttributes(resolvedPackageVersions, "resolvedPackageVersions"),
|
||||
});
|
||||
span.setAttribute("missingPackages", missingPackages);
|
||||
|
||||
const dependencies: Record<string, string> = {};
|
||||
|
||||
for (const missingPackage of missingPackages) {
|
||||
const internalDependencyVersion =
|
||||
(packageJson.dependencies as Record<string, string>)[missingPackage] ??
|
||||
detectDependencyVersion(missingPackage);
|
||||
|
||||
if (internalDependencyVersion) {
|
||||
dependencies[missingPackage] = stripWorkspaceFromVersion(internalDependencyVersion);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [packageName, version] of Object.entries(resolvedPackageVersions)) {
|
||||
dependencies[packageName] = version;
|
||||
}
|
||||
|
||||
if (config.additionalPackages) {
|
||||
span.setAttribute("additionalPackages", config.additionalPackages);
|
||||
|
||||
for (const packageName of config.additionalPackages) {
|
||||
if (dependencies[packageName]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const packageParts = parsePackageName(packageName);
|
||||
|
||||
if (packageParts.version) {
|
||||
dependencies[packageParts.name] = packageParts.version;
|
||||
continue;
|
||||
} else {
|
||||
logger.log(
|
||||
`${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
|
||||
packageName
|
||||
)}, add a version specifier to the package name (e.g. ${
|
||||
packageParts.name
|
||||
}@latest) or add it to your project's package.json`
|
||||
);
|
||||
const externalDependencyVersion = await project.resolve(packageParts.name, {
|
||||
allowDev: true,
|
||||
});
|
||||
|
||||
if (externalDependencyVersion) {
|
||||
dependencies[packageParts.name] = externalDependencyVersion;
|
||||
continue;
|
||||
} else {
|
||||
logger.log(
|
||||
`${chalkWarning("X Warning:")} Could not find version for package ${chalkPurple(
|
||||
packageName
|
||||
)}, add a version specifier to the package name (e.g. ${
|
||||
packageParts.name
|
||||
}@latest) or add it to your project's package.json`
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure we sort the dependencies by key to ensure consistent hashing
|
||||
return Object.fromEntries(Object.entries(dependencies).sort(([a], [b]) => a.localeCompare(b)));
|
||||
// Make sure we sort the dependencies by key to ensure consistent hashing
|
||||
const result = Object.fromEntries(
|
||||
Object.entries(dependencies).sort(([a], [b]) => a.localeCompare(b))
|
||||
);
|
||||
|
||||
span.setAttributes({
|
||||
...flattenAttributes(result, "dependencies"),
|
||||
});
|
||||
|
||||
span.end();
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
type AdditionalFilesReturn =
|
||||
|
||||
@@ -149,7 +149,7 @@ export function bundleDependenciesPlugin(
|
||||
}
|
||||
}
|
||||
|
||||
logger.ignore(`[${buildIdentifier}] Externalizing ${args.path}`, {
|
||||
logger.debug(`[${buildIdentifier}] Externalizing ${args.path}`, {
|
||||
...args,
|
||||
});
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ import { PackageManager, getUserPackageManager } from "./getUserPackageManager";
|
||||
import { PackageJson } from "type-fest";
|
||||
import { assertExhaustive } from "./assertExhaustive";
|
||||
import { builtinModules } from "node:module";
|
||||
import { tracer } from "../cli/common";
|
||||
import { recordSpanException } from "@trigger.dev/core/v3/otel";
|
||||
import { flattenAttributes } from "@trigger.dev/core/v3";
|
||||
|
||||
export type ResolveOptions = { allowDev: boolean };
|
||||
|
||||
@@ -47,60 +50,81 @@ export class JavascriptProject {
|
||||
packageNames: string[],
|
||||
options?: ResolveOptions
|
||||
): Promise<Record<string, string>> {
|
||||
const externalPackages = packageNames.filter((packageName) => !isBuiltInModule(packageName));
|
||||
return tracer.startActiveSpan("JavascriptProject.resolveAll", async (span) => {
|
||||
const externalPackages = packageNames.filter((packageName) => !isBuiltInModule(packageName));
|
||||
|
||||
const opts = { allowDev: false, ...options };
|
||||
const opts = { allowDev: false, ...options };
|
||||
|
||||
const command = await this.#getCommand();
|
||||
const command = await this.#getCommand();
|
||||
|
||||
try {
|
||||
const versions = await command.resolveDependencyVersions(externalPackages, {
|
||||
cwd: this.projectPath,
|
||||
span.setAttributes({
|
||||
externalPackages,
|
||||
packageManager: command.name,
|
||||
});
|
||||
|
||||
if (versions) {
|
||||
logger.debug(`Resolved [${externalPackages.join(", ")}] version using ${command.name}`, {
|
||||
versions,
|
||||
try {
|
||||
const versions = await command.resolveDependencyVersions(externalPackages, {
|
||||
cwd: this.projectPath,
|
||||
});
|
||||
}
|
||||
|
||||
// Merge the resolved versions with the package.json dependencies
|
||||
const missingPackages = externalPackages.filter((packageName) => !versions[packageName]);
|
||||
const missingPackageVersions: Record<string, string> = {};
|
||||
|
||||
for (const packageName of missingPackages) {
|
||||
const packageJsonVersion = this.packageJson.dependencies?.[packageName];
|
||||
|
||||
if (typeof packageJsonVersion === "string") {
|
||||
logger.debug(`Resolved ${packageName} version using package.json`, {
|
||||
packageJsonVersion,
|
||||
if (versions) {
|
||||
logger.debug(`Resolved [${externalPackages.join(", ")}] version using ${command.name}`, {
|
||||
versions,
|
||||
});
|
||||
|
||||
missingPackageVersions[packageName] = packageJsonVersion;
|
||||
span.setAttributes({
|
||||
...flattenAttributes(versions, "versions"),
|
||||
});
|
||||
}
|
||||
|
||||
if (opts.allowDev) {
|
||||
const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
|
||||
// Merge the resolved versions with the package.json dependencies
|
||||
const missingPackages = externalPackages.filter((packageName) => !versions[packageName]);
|
||||
const missingPackageVersions: Record<string, string> = {};
|
||||
|
||||
if (typeof devPackageJsonVersion === "string") {
|
||||
logger.debug(`Resolved ${packageName} version using devDependencies`, {
|
||||
devPackageJsonVersion,
|
||||
for (const packageName of missingPackages) {
|
||||
const packageJsonVersion = this.packageJson.dependencies?.[packageName];
|
||||
|
||||
if (typeof packageJsonVersion === "string") {
|
||||
logger.debug(`Resolved ${packageName} version using package.json`, {
|
||||
packageJsonVersion,
|
||||
});
|
||||
|
||||
missingPackageVersions[packageName] = devPackageJsonVersion;
|
||||
missingPackageVersions[packageName] = packageJsonVersion;
|
||||
}
|
||||
|
||||
if (opts.allowDev) {
|
||||
const devPackageJsonVersion = this.packageJson.devDependencies?.[packageName];
|
||||
|
||||
if (typeof devPackageJsonVersion === "string") {
|
||||
logger.debug(`Resolved ${packageName} version using devDependencies`, {
|
||||
devPackageJsonVersion,
|
||||
});
|
||||
|
||||
missingPackageVersions[packageName] = devPackageJsonVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span.setAttributes({
|
||||
...flattenAttributes(missingPackageVersions, "missingPackageVersions"),
|
||||
missingPackages,
|
||||
});
|
||||
|
||||
span.end();
|
||||
|
||||
return { ...versions, ...missingPackageVersions };
|
||||
} catch (error) {
|
||||
recordSpanException(span, error);
|
||||
span.end();
|
||||
|
||||
logger.debug(`Failed to resolve dependency versions using ${command.name}`, {
|
||||
packageNames,
|
||||
error,
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
return { ...versions, ...missingPackageVersions };
|
||||
} catch (error) {
|
||||
logger.debug(`Failed to resolve dependency versions using ${command.name}`, {
|
||||
packageNames,
|
||||
error,
|
||||
});
|
||||
|
||||
return {};
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async resolve(packageName: string, options?: ResolveOptions): Promise<string | undefined> {
|
||||
|
||||
Reference in New Issue
Block a user