Skip to content

Commit 75b183d

Browse files
authored
feat(cloudflare): Automatically set the release id when CF_VERSION_METADATA is enabled (#18855)
The `CF_VERSION_METADATA` only has one reason - to add the release id. Since we already set the release when `SENTRY_RELEASE` is enabled automatically, we can do the same for `CF_VERSION_METADATA`. The docs will then also be updated to state how the release id can be set in different ways: getsentry/sentry-docs#16006 Closes #18856 (added automatically) Closes [JS-1489](https://linear.app/getsentry/issue/JS-1489/featcloudflare-automatically-set-the-release-id-when-cf-version)
1 parent df0bff8 commit 75b183d

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

packages/cloudflare/src/options.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,31 @@
11
import type { CloudflareOptions } from './client';
22

3+
/**
4+
* Cloudflare's version metadata binding structure.
5+
* @see https://developers.cloudflare.com/workers/runtime-apis/bindings/version-metadata/
6+
*/
7+
interface CfVersionMetadata {
8+
id: string;
9+
tag?: string;
10+
timestamp?: string;
11+
}
12+
13+
/**
14+
* Checks if the value is a valid CF_VERSION_METADATA binding.
15+
*/
16+
function isVersionMetadata(value: unknown): value is CfVersionMetadata {
17+
return typeof value === 'object' && value !== null && 'id' in value && typeof value.id === 'string';
18+
}
19+
320
/**
421
* Merges the options passed in from the user with the options we read from
522
* the Cloudflare `env` environment variable object.
623
*
24+
* Release is determined with the following priority (highest to lowest):
25+
* 1. User-provided release option
26+
* 2. SENTRY_RELEASE environment variable
27+
* 3. CF_VERSION_METADATA.id binding (if configured in the wrangler config)
28+
*
729
* @param userOptions - The options passed in from the user.
830
* @param env - The environment variables.
931
*
@@ -14,7 +36,13 @@ export function getFinalOptions(userOptions: CloudflareOptions, env: unknown): C
1436
return userOptions;
1537
}
1638

17-
const release = 'SENTRY_RELEASE' in env && typeof env.SENTRY_RELEASE === 'string' ? env.SENTRY_RELEASE : undefined;
39+
// Priority: userOptions.release > SENTRY_RELEASE > CF_VERSION_METADATA.id
40+
const release =
41+
'SENTRY_RELEASE' in env && typeof env.SENTRY_RELEASE === 'string'
42+
? env.SENTRY_RELEASE
43+
: 'CF_VERSION_METADATA' in env && isVersionMetadata(env.CF_VERSION_METADATA)
44+
? env.CF_VERSION_METADATA.id
45+
: undefined;
1846

1947
return { release, ...userOptions };
2048
}

packages/cloudflare/test/options.test.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,4 +55,75 @@ describe('getFinalOptions', () => {
5555

5656
expect(result).toEqual(userOptions);
5757
});
58+
59+
describe('CF_VERSION_METADATA', () => {
60+
it('uses CF_VERSION_METADATA.id as release when no other release is set', () => {
61+
const userOptions = { dsn: 'test-dsn' };
62+
const env = { CF_VERSION_METADATA: { id: 'version-123', tag: 'v1.0.0' } };
63+
64+
const result = getFinalOptions(userOptions, env);
65+
66+
expect(result).toEqual({ dsn: 'test-dsn', release: 'version-123' });
67+
});
68+
69+
it('prefers SENTRY_RELEASE over CF_VERSION_METADATA.id', () => {
70+
const userOptions = { dsn: 'test-dsn' };
71+
const env = {
72+
SENTRY_RELEASE: 'env-release',
73+
CF_VERSION_METADATA: { id: 'version-123' },
74+
};
75+
76+
const result = getFinalOptions(userOptions, env);
77+
78+
expect(result).toEqual({ dsn: 'test-dsn', release: 'env-release' });
79+
});
80+
81+
it('prefers user release over CF_VERSION_METADATA.id', () => {
82+
const userOptions = { dsn: 'test-dsn', release: 'user-release' };
83+
const env = { CF_VERSION_METADATA: { id: 'version-123' } };
84+
85+
const result = getFinalOptions(userOptions, env);
86+
87+
expect(result).toEqual({ dsn: 'test-dsn', release: 'user-release' });
88+
});
89+
90+
it('prefers user release over both SENTRY_RELEASE and CF_VERSION_METADATA.id', () => {
91+
const userOptions = { dsn: 'test-dsn', release: 'user-release' };
92+
const env = {
93+
SENTRY_RELEASE: 'env-release',
94+
CF_VERSION_METADATA: { id: 'version-123' },
95+
};
96+
97+
const result = getFinalOptions(userOptions, env);
98+
99+
expect(result).toEqual({ dsn: 'test-dsn', release: 'user-release' });
100+
});
101+
102+
it('ignores CF_VERSION_METADATA when it is not an object', () => {
103+
const userOptions = { dsn: 'test-dsn' };
104+
const env = { CF_VERSION_METADATA: 'not-an-object' };
105+
106+
const result = getFinalOptions(userOptions, env);
107+
108+
expect(result).toEqual({ dsn: 'test-dsn', release: undefined });
109+
});
110+
111+
it('ignores CF_VERSION_METADATA when id is not a string', () => {
112+
const userOptions = { dsn: 'test-dsn' };
113+
const env = { CF_VERSION_METADATA: { id: 123 } };
114+
115+
const result = getFinalOptions(userOptions, env);
116+
117+
expect(result).toEqual({ dsn: 'test-dsn', release: undefined });
118+
});
119+
120+
it('ignores CF_VERSION_METADATA when id is missing', () => {
121+
const userOptions = { dsn: 'test-dsn' };
122+
const env = { CF_VERSION_METADATA: { tag: 'v1.0.0' } };
123+
124+
const result = getFinalOptions(userOptions, env);
125+
126+
expect(result).toEqual({ dsn: 'test-dsn', release: undefined });
127+
});
128+
});
58129
});

0 commit comments

Comments
 (0)