From d3743bcd83d398d17fb407dbcb54905b400bfde3 Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Fri, 16 Jan 2026 11:30:31 +0100 Subject: [PATCH 1/2] feat(cloudflare): Set the release id when CF_VERSION_METADATA is enabled --- packages/cloudflare/src/options.ts | 30 +++++++++- packages/cloudflare/test/options.test.ts | 71 ++++++++++++++++++++++++ 2 files changed, 100 insertions(+), 1 deletion(-) diff --git a/packages/cloudflare/src/options.ts b/packages/cloudflare/src/options.ts index 77a37ea51d31..2a4dc892d251 100644 --- a/packages/cloudflare/src/options.ts +++ b/packages/cloudflare/src/options.ts @@ -1,9 +1,31 @@ import type { CloudflareOptions } from './client'; +/** + * Cloudflare's version metadata binding structure. + * @see https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/ + */ +interface CfVersionMetadata { + id: string; + tag?: string; + timestamp?: string; +} + +/** + * Checks if the value is a valid CF_VERSION_METADATA binding. + */ +function isVersionMetadata(value: unknown): value is CfVersionMetadata { + return typeof value === 'object' && value !== null && 'id' in value && typeof value.id === 'string'; +} + /** * Merges the options passed in from the user with the options we read from * the Cloudflare `env` environment variable object. * + * Release is determined with the following priority (highest to lowest): + * 1. User-provided release option + * 2. SENTRY_RELEASE environment variable + * 3. CF_VERSION_METADATA.id binding (if configured in wrangler.toml) + * * @param userOptions - The options passed in from the user. * @param env - The environment variables. * @@ -14,7 +36,13 @@ export function getFinalOptions(userOptions: CloudflareOptions, env: unknown): C return userOptions; } - const release = 'SENTRY_RELEASE' in env && typeof env.SENTRY_RELEASE === 'string' ? env.SENTRY_RELEASE : undefined; + // Priority: SENTRY_RELEASE > CF_VERSION_METADATA.id + let release: string | undefined; + if ('SENTRY_RELEASE' in env && typeof env.SENTRY_RELEASE === 'string') { + release = env.SENTRY_RELEASE; + } else if ('CF_VERSION_METADATA' in env && isVersionMetadata(env.CF_VERSION_METADATA)) { + release = env.CF_VERSION_METADATA.id; + } return { release, ...userOptions }; } diff --git a/packages/cloudflare/test/options.test.ts b/packages/cloudflare/test/options.test.ts index ae8a5509b233..6efcf18688c0 100644 --- a/packages/cloudflare/test/options.test.ts +++ b/packages/cloudflare/test/options.test.ts @@ -55,4 +55,75 @@ describe('getFinalOptions', () => { expect(result).toEqual(userOptions); }); + + describe('CF_VERSION_METADATA', () => { + it('uses CF_VERSION_METADATA.id as release when no other release is set', () => { + const userOptions = { dsn: 'test-dsn' }; + const env = { CF_VERSION_METADATA: { id: 'version-123', tag: 'v1.0.0' } }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: 'version-123' }); + }); + + it('prefers SENTRY_RELEASE over CF_VERSION_METADATA.id', () => { + const userOptions = { dsn: 'test-dsn' }; + const env = { + SENTRY_RELEASE: 'env-release', + CF_VERSION_METADATA: { id: 'version-123' }, + }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: 'env-release' }); + }); + + it('prefers user release over CF_VERSION_METADATA.id', () => { + const userOptions = { dsn: 'test-dsn', release: 'user-release' }; + const env = { CF_VERSION_METADATA: { id: 'version-123' } }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: 'user-release' }); + }); + + it('prefers user release over both SENTRY_RELEASE and CF_VERSION_METADATA.id', () => { + const userOptions = { dsn: 'test-dsn', release: 'user-release' }; + const env = { + SENTRY_RELEASE: 'env-release', + CF_VERSION_METADATA: { id: 'version-123' }, + }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: 'user-release' }); + }); + + it('ignores CF_VERSION_METADATA when it is not an object', () => { + const userOptions = { dsn: 'test-dsn' }; + const env = { CF_VERSION_METADATA: 'not-an-object' }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: undefined }); + }); + + it('ignores CF_VERSION_METADATA when id is not a string', () => { + const userOptions = { dsn: 'test-dsn' }; + const env = { CF_VERSION_METADATA: { id: 123 } }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: undefined }); + }); + + it('ignores CF_VERSION_METADATA when id is missing', () => { + const userOptions = { dsn: 'test-dsn' }; + const env = { CF_VERSION_METADATA: { tag: 'v1.0.0' } }; + + const result = getFinalOptions(userOptions, env); + + expect(result).toEqual({ dsn: 'test-dsn', release: undefined }); + }); + }); }); From 4f9353a88f5e78b801bf9ecb5d237aae38c3a77d Mon Sep 17 00:00:00 2001 From: JPeer264 Date: Mon, 19 Jan 2026 09:35:45 +0100 Subject: [PATCH 2/2] fixup! feat(cloudflare): Set the release id when CF_VERSION_METADATA is enabled --- packages/cloudflare/src/options.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/packages/cloudflare/src/options.ts b/packages/cloudflare/src/options.ts index 2a4dc892d251..3c62f88f25ed 100644 --- a/packages/cloudflare/src/options.ts +++ b/packages/cloudflare/src/options.ts @@ -24,7 +24,7 @@ function isVersionMetadata(value: unknown): value is CfVersionMetadata { * Release is determined with the following priority (highest to lowest): * 1. User-provided release option * 2. SENTRY_RELEASE environment variable - * 3. CF_VERSION_METADATA.id binding (if configured in wrangler.toml) + * 3. CF_VERSION_METADATA.id binding (if configured in the wrangler config) * * @param userOptions - The options passed in from the user. * @param env - The environment variables. @@ -36,13 +36,13 @@ export function getFinalOptions(userOptions: CloudflareOptions, env: unknown): C return userOptions; } - // Priority: SENTRY_RELEASE > CF_VERSION_METADATA.id - let release: string | undefined; - if ('SENTRY_RELEASE' in env && typeof env.SENTRY_RELEASE === 'string') { - release = env.SENTRY_RELEASE; - } else if ('CF_VERSION_METADATA' in env && isVersionMetadata(env.CF_VERSION_METADATA)) { - release = env.CF_VERSION_METADATA.id; - } + // Priority: userOptions.release > SENTRY_RELEASE > CF_VERSION_METADATA.id + const release = + 'SENTRY_RELEASE' in env && typeof env.SENTRY_RELEASE === 'string' + ? env.SENTRY_RELEASE + : 'CF_VERSION_METADATA' in env && isVersionMetadata(env.CF_VERSION_METADATA) + ? env.CF_VERSION_METADATA.id + : undefined; return { release, ...userOptions }; }