diff --git a/.changeset/fuzzy-doors-know.md b/.changeset/fuzzy-doors-know.md
new file mode 100644
index 0000000000..348fa6c4eb
--- /dev/null
+++ b/.changeset/fuzzy-doors-know.md
@@ -0,0 +1,5 @@
+---
+"trigger.dev": patch
+---
+
+Fix SDK version in build manifest for out-of-sync detection
diff --git a/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts b/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts
index 7891c1191c..04b12394ef 100644
--- a/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts
+++ b/apps/webapp/app/presenters/v3/DeploymentPresenter.server.ts
@@ -108,6 +108,7 @@ export class DeploymentPresenter {
},
},
sdkVersion: true,
+ cliVersion: true,
},
},
triggeredBy: {
@@ -145,6 +146,7 @@ export class DeploymentPresenter {
},
deployedBy: deployment.triggeredBy,
sdkVersion: deployment.worker?.sdkVersion,
+ cliVersion: deployment.worker?.cliVersion,
imageReference: deployment.imageReference,
externalBuildData:
externalBuildData && externalBuildData.success ? externalBuildData.data : undefined,
diff --git a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.deployments.$deploymentParam/route.tsx b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.deployments.$deploymentParam/route.tsx
index 58efbcb5b4..7678f53633 100644
--- a/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.deployments.$deploymentParam/route.tsx
+++ b/apps/webapp/app/routes/_app.orgs.$organizationSlug.projects.v3.$projectParam.deployments.$deploymentParam/route.tsx
@@ -151,6 +151,10 @@ export default function Page() {
SDK Version
{deployment.sdkVersion ? deployment.sdkVersion : "–"}
+
+ CLI Version
+ {deployment.cliVersion ? deployment.cliVersion : "–"}
+
Started at
diff --git a/packages/cli-v3/src/build/buildWorker.ts b/packages/cli-v3/src/build/buildWorker.ts
index 0ab03f1e61..9b4678a34c 100644
--- a/packages/cli-v3/src/build/buildWorker.ts
+++ b/packages/cli-v3/src/build/buildWorker.ts
@@ -27,6 +27,7 @@ import { writeJSONFile } from "../utilities/fileSystem.js";
import { isWindows } from "std-env";
import { pathToFileURL } from "node:url";
import { logger } from "../utilities/logger.js";
+import { SdkVersionExtractor } from "./plugins.js";
export type BuildWorkerEventListener = {
onBundleStart?: () => void;
@@ -61,6 +62,8 @@ export async function buildWorker(options: BuildWorkerOptions) {
await notifyExtensionOnBuildStart(buildContext);
const pluginsFromExtensions = resolvePluginsForContext(buildContext);
+ const sdkVersionExtractor = new SdkVersionExtractor();
+
options.listener?.onBundleStart?.();
const bundleResult = await bundleWorker({
@@ -69,7 +72,7 @@ export async function buildWorker(options: BuildWorkerOptions) {
destination: options.destination,
watch: false,
resolvedConfig,
- plugins: [...pluginsFromExtensions],
+ plugins: [sdkVersionExtractor.plugin, ...pluginsFromExtensions],
jsxFactory: resolvedConfig.build.jsx.factory,
jsxFragment: resolvedConfig.build.jsx.fragment,
jsxAutomatic: resolvedConfig.build.jsx.automatic,
@@ -81,7 +84,7 @@ export async function buildWorker(options: BuildWorkerOptions) {
contentHash: bundleResult.contentHash,
runtime: resolvedConfig.runtime ?? DEFAULT_RUNTIME,
environment: options.environment,
- packageVersion: CORE_VERSION,
+ packageVersion: sdkVersionExtractor.sdkVersion ?? CORE_VERSION,
cliPackageVersion: VERSION,
target: "deploy",
files: bundleResult.files,
diff --git a/packages/cli-v3/src/build/plugins.ts b/packages/cli-v3/src/build/plugins.ts
index c478896169..81a1cecea4 100644
--- a/packages/cli-v3/src/build/plugins.ts
+++ b/packages/cli-v3/src/build/plugins.ts
@@ -4,6 +4,10 @@ import { ResolvedConfig } from "@trigger.dev/core/v3/build";
import { configPlugin } from "../config.js";
import { logger } from "../utilities/logger.js";
import { bunPlugin } from "../runtimes/bun.js";
+import { resolvePathSync as esmResolveSync } from "mlly";
+import { readPackageJSON, resolvePackageJSON } from "pkg-types";
+import { dirname } from "node:path";
+import { readJSONFile } from "../utilities/fileSystem.js";
export async function buildPlugins(
target: BuildTarget,
@@ -87,3 +91,94 @@ export function polyshedPlugin(): esbuild.Plugin {
},
};
}
+
+export class SdkVersionExtractor {
+ private _sdkVersion: string | undefined;
+ private _ranOnce = false;
+
+ get sdkVersion() {
+ return this._sdkVersion;
+ }
+
+ get plugin(): esbuild.Plugin {
+ return {
+ name: "sdk-version",
+ setup: (build) => {
+ build.onResolve({ filter: /^@trigger\.dev\/sdk\// }, async (args) => {
+ if (this._ranOnce) {
+ return undefined;
+ } else {
+ this._ranOnce = true;
+ }
+
+ logger.debug("[SdkVersionExtractor] Extracting SDK version", { args });
+
+ try {
+ const resolvedPath = esmResolveSync(args.path, {
+ url: args.resolveDir,
+ });
+
+ logger.debug("[SdkVersionExtractor] Resolved SDK module path", { resolvedPath });
+
+ const packageJsonPath = await resolvePackageJSON(dirname(resolvedPath), {
+ test: async (filePath) => {
+ try {
+ const candidate = await readJSONFile(filePath);
+
+ // Exclude esm type markers
+ return Object.keys(candidate).length > 1 || !candidate.type;
+ } catch (error) {
+ logger.debug("[SdkVersionExtractor] Error during package.json test", {
+ error: error instanceof Error ? error.message : error,
+ });
+
+ return false;
+ }
+ },
+ });
+
+ if (!packageJsonPath) {
+ return undefined;
+ }
+
+ logger.debug("[SdkVersionExtractor] Found package.json", { packageJsonPath });
+
+ const packageJson = await readPackageJSON(packageJsonPath);
+
+ if (!packageJson.name || packageJson.name !== "@trigger.dev/sdk") {
+ logger.debug("[SdkVersionExtractor] No match for SDK package name", {
+ packageJsonPath,
+ packageJson,
+ });
+
+ return undefined;
+ }
+
+ if (!packageJson.version) {
+ logger.debug("[SdkVersionExtractor] No version found in package.json", {
+ packageJsonPath,
+ packageJson,
+ });
+
+ return undefined;
+ }
+
+ this._sdkVersion = packageJson.version;
+
+ logger.debug("[SdkVersionExtractor] Found SDK version", {
+ args,
+ packageJsonPath,
+ sdkVersion: this._sdkVersion,
+ });
+
+ return undefined;
+ } catch (error) {
+ logger.debug("[SdkVersionExtractor] Failed to extract SDK version", { error });
+ }
+
+ return undefined;
+ });
+ },
+ };
+ }
+}