Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
Plus 9 more 🤖 This preview updates automatically when you update the PR. |
| release: env.EAS_BUILD_APP_VERSION, | ||
| tags: { ...createEASBuildTags(env), ...customTags }, | ||
| contexts: { eas_build: createEASBuildContext(env), runtime: { name: 'node', version: process.version } }, | ||
| sdk: { name: 'sentry.javascript.react-native.eas-build-hooks', version: '1.0.0' }, |
There was a problem hiding this comment.
Hardcoded SDK version diverges from actual package version
Medium Severity
The sdk.version in createBaseEvent is hardcoded as '1.0.0' while the actual package version is '8.1.0'. The SDK_VERSION constant is already available in ../version and used elsewhere (e.g., sdkinfo.ts). This means every EAS build hook event sent to Sentry will report an incorrect SDK version, and it will never auto-update with future releases.
There was a problem hiding this comment.
This feedback looks valid 👍
There was a problem hiding this comment.
@alwx I think we should use a dynamic version here like:
| sdk: { name: 'sentry.javascript.react-native.eas-build-hooks', version: '1.0.0' }, | |
| sdk: { name: 'sentry.javascript.react-native.eas-build-hooks', version: SDK_VERSION }, |
after importing above
Android (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 86584b7+dirty | 463.83 ms | 500.31 ms | 36.48 ms |
| 9a81842+dirty | 412.23 ms | 416.56 ms | 4.33 ms |
| c637fc7+dirty | 433.70 ms | 467.76 ms | 34.06 ms |
| d73150f+dirty | 411.21 ms | 465.86 ms | 54.65 ms |
| fa7bb7e+dirty | 350.37 ms | 377.02 ms | 26.65 ms |
| 3bd3f0d+dirty | 447.21 ms | 472.31 ms | 25.10 ms |
| 88890fe+dirty | 350.94 ms | 365.74 ms | 14.80 ms |
| 95aaf8a | 437.89 ms | 419.45 ms | -18.44 ms |
| c0842e7+dirty | 527.76 ms | 566.69 ms | 38.93 ms |
| 1e7a472+dirty | 348.80 ms | 362.55 ms | 13.75 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 86584b7+dirty | 43.75 MiB | 48.08 MiB | 4.33 MiB |
| 9a81842+dirty | 43.75 MiB | 48.08 MiB | 4.33 MiB |
| c637fc7+dirty | 43.75 MiB | 48.40 MiB | 4.64 MiB |
| d73150f+dirty | 43.75 MiB | 48.55 MiB | 4.80 MiB |
| fa7bb7e+dirty | 17.75 MiB | 19.75 MiB | 2.00 MiB |
| 3bd3f0d+dirty | 17.75 MiB | 19.70 MiB | 1.95 MiB |
| 88890fe+dirty | 17.75 MiB | 19.71 MiB | 1.96 MiB |
| 95aaf8a | 17.75 MiB | 19.68 MiB | 1.93 MiB |
| c0842e7+dirty | 43.75 MiB | 48.41 MiB | 4.66 MiB |
| 1e7a472+dirty | 17.75 MiB | 19.70 MiB | 1.96 MiB |
iOS (legacy) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ea3e26e+dirty | 1229.13 ms | 1228.46 ms | -0.67 ms |
| 80e4616+dirty | 1221.32 ms | 1225.64 ms | 4.32 ms |
| 818a608+dirty | 1205.76 ms | 1208.00 ms | 2.24 ms |
| 77061ed+dirty | 1233.16 ms | 1234.88 ms | 1.71 ms |
| bef3709+dirty | 1222.07 ms | 1220.24 ms | -1.83 ms |
| a206511+dirty | 1185.00 ms | 1186.35 ms | 1.35 ms |
| 74979ac+dirty | 1210.49 ms | 1213.31 ms | 2.82 ms |
| a2bb688+dirty | 1223.53 ms | 1232.90 ms | 9.37 ms |
| 8a868fe+dirty | 1221.50 ms | 1230.78 ms | 9.28 ms |
| d590428+dirty | 1211.77 ms | 1220.51 ms | 8.75 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ea3e26e+dirty | 3.41 MiB | 4.58 MiB | 1.17 MiB |
| 80e4616+dirty | 3.38 MiB | 4.60 MiB | 1.22 MiB |
| 818a608+dirty | 2.63 MiB | 3.91 MiB | 1.28 MiB |
| 77061ed+dirty | 2.63 MiB | 3.98 MiB | 1.34 MiB |
| bef3709+dirty | 3.38 MiB | 4.78 MiB | 1.40 MiB |
| a206511+dirty | 3.41 MiB | 4.67 MiB | 1.25 MiB |
| 74979ac+dirty | 3.38 MiB | 4.60 MiB | 1.22 MiB |
| a2bb688+dirty | 2.63 MiB | 3.99 MiB | 1.36 MiB |
| 8a868fe+dirty | 3.38 MiB | 4.60 MiB | 1.22 MiB |
| d590428+dirty | 3.38 MiB | 4.78 MiB | 1.39 MiB |
Android (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 7480abe+dirty | 363.80 ms | 431.34 ms | 67.54 ms |
| 2b89ce9+dirty | 372.22 ms | 417.06 ms | 44.84 ms |
| 170d5ea+dirty | 348.79 ms | 406.94 ms | 58.15 ms |
| b1579bc+dirty | 391.87 ms | 456.26 ms | 64.39 ms |
| 73f2455+dirty | 369.33 ms | 398.90 ms | 29.57 ms |
| 0b64753+dirty | 358.55 ms | 429.16 ms | 70.61 ms |
| 6a70a7e+dirty | 382.45 ms | 424.54 ms | 42.09 ms |
| 2adbd1e+dirty | 366.13 ms | 419.49 ms | 53.36 ms |
| f8d19f8+dirty | 374.17 ms | 383.40 ms | 9.23 ms |
| 7be1f99+dirty | 369.02 ms | 399.60 ms | 30.58 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| 7480abe+dirty | 7.15 MiB | 8.41 MiB | 1.26 MiB |
| 2b89ce9+dirty | 7.15 MiB | 8.41 MiB | 1.26 MiB |
| 170d5ea+dirty | 7.15 MiB | 8.42 MiB | 1.27 MiB |
| b1579bc+dirty | 43.94 MiB | 49.27 MiB | 5.33 MiB |
| 73f2455+dirty | 43.94 MiB | 48.82 MiB | 4.88 MiB |
| 0b64753+dirty | 7.15 MiB | 8.42 MiB | 1.27 MiB |
| 6a70a7e+dirty | 7.15 MiB | 8.42 MiB | 1.26 MiB |
| 2adbd1e+dirty | 7.15 MiB | 8.43 MiB | 1.28 MiB |
| f8d19f8+dirty | 43.94 MiB | 48.91 MiB | 4.97 MiB |
| 7be1f99+dirty | 7.15 MiB | 8.42 MiB | 1.27 MiB |
iOS (new) Performance metrics 🚀
|
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ea3e26e+dirty | 1216.61 ms | 1214.15 ms | -2.47 ms |
| 80e4616+dirty | 1206.90 ms | 1205.94 ms | -0.96 ms |
| 818a608+dirty | 1218.84 ms | 1223.18 ms | 4.34 ms |
| 77061ed+dirty | 1210.77 ms | 1218.45 ms | 7.68 ms |
| bef3709+dirty | 1217.79 ms | 1225.33 ms | 7.54 ms |
| a206511+dirty | 1225.02 ms | 1223.74 ms | -1.28 ms |
| 74979ac+dirty | 1212.33 ms | 1212.54 ms | 0.21 ms |
| a2bb688+dirty | 1244.82 ms | 1238.60 ms | -6.22 ms |
| 8a868fe+dirty | 1206.85 ms | 1215.04 ms | 8.19 ms |
| d590428+dirty | 1221.23 ms | 1225.27 ms | 4.03 ms |
App size
| Revision | Plain | With Sentry | Diff |
|---|---|---|---|
| ea3e26e+dirty | 3.41 MiB | 4.58 MiB | 1.17 MiB |
| 80e4616+dirty | 3.38 MiB | 4.60 MiB | 1.22 MiB |
| 818a608+dirty | 3.19 MiB | 4.48 MiB | 1.29 MiB |
| 77061ed+dirty | 3.19 MiB | 4.54 MiB | 1.36 MiB |
| bef3709+dirty | 3.38 MiB | 4.78 MiB | 1.40 MiB |
| a206511+dirty | 3.41 MiB | 4.67 MiB | 1.25 MiB |
| 74979ac+dirty | 3.38 MiB | 4.60 MiB | 1.22 MiB |
| a2bb688+dirty | 3.19 MiB | 4.56 MiB | 1.37 MiB |
| 8a868fe+dirty | 3.38 MiB | 4.60 MiB | 1.22 MiB |
| d590428+dirty | 3.38 MiB | 4.78 MiB | 1.39 MiB |
Yeah, adding a feature changelog would be nice. |
| * | ||
| * Add it to your package.json scripts: | ||
| * | ||
| * "eas-build-on-complete": "sentry-eas-build-on-complete" |
There was a problem hiding this comment.
It would be nice to have docs for these features and add a small mention on how to use them on changelog.
|
I did another code review and so far it's good! I have one small suggestion before we can merge this PR |
2d9e8b0 to
2d1bd0b
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Autofix Details
Bugbot Autofix prepared a fix for the issue found in the latest run.
- ✅ Fixed: Three hook scripts duplicate identical boilerplate code
- I extracted a shared
runEASHookScripthelper inscripts/eas/utils.jsand updated all three hook entry scripts to use it with only hook-specific options and handler differences.
- I extracted a shared
Or push these changes by commenting:
@cursor push 1a16906a55
Preview (1a16906a55)
diff --git a/packages/core/scripts/eas/build-on-complete.js b/packages/core/scripts/eas/build-on-complete.js
--- a/packages/core/scripts/eas/build-on-complete.js
+++ b/packages/core/scripts/eas/build-on-complete.js
@@ -30,24 +30,14 @@
*
*/
-const { loadEnv, loadHooksModule, parseBaseOptions, runHook } = require('./utils');
+const { runEASHookScript } = require('./utils');
-async function main() {
- loadEnv();
-
- const hooks = loadHooksModule();
- const options = {
- ...parseBaseOptions(),
+runEASHookScript({
+ hookName: 'on-complete',
+ hookFn: (hooks, options) => hooks.captureEASBuildComplete(options),
+ getOptions: () => ({
errorMessage: process.env.SENTRY_EAS_BUILD_ERROR_MESSAGE,
successMessage: process.env.SENTRY_EAS_BUILD_SUCCESS_MESSAGE,
captureSuccessfulBuilds: process.env.SENTRY_EAS_BUILD_CAPTURE_SUCCESS === 'true',
- };
-
- await runHook('on-complete', () => hooks.captureEASBuildComplete(options));
-}
-
-main().catch(error => {
- // eslint-disable-next-line no-console
- console.error('[Sentry] Unexpected error in eas-build-on-complete hook:', error);
- process.exit(1);
+ }),
});
diff --git a/packages/core/scripts/eas/build-on-error.js b/packages/core/scripts/eas/build-on-error.js
--- a/packages/core/scripts/eas/build-on-error.js
+++ b/packages/core/scripts/eas/build-on-error.js
@@ -21,22 +21,12 @@
* @see https://docs.sentry.io/platforms/react-native/
*/
-const { loadEnv, loadHooksModule, parseBaseOptions, runHook } = require('./utils');
+const { runEASHookScript } = require('./utils');
-async function main() {
- loadEnv();
-
- const hooks = loadHooksModule();
- const options = {
- ...parseBaseOptions(),
+runEASHookScript({
+ hookName: 'on-error',
+ hookFn: (hooks, options) => hooks.captureEASBuildError(options),
+ getOptions: () => ({
errorMessage: process.env.SENTRY_EAS_BUILD_ERROR_MESSAGE,
- };
-
- await runHook('on-error', () => hooks.captureEASBuildError(options));
-}
-
-main().catch(error => {
- // eslint-disable-next-line no-console
- console.error('[Sentry] Unexpected error in eas-build-on-error hook:', error);
- process.exit(1);
+ }),
});
diff --git a/packages/core/scripts/eas/build-on-success.js b/packages/core/scripts/eas/build-on-success.js
--- a/packages/core/scripts/eas/build-on-success.js
+++ b/packages/core/scripts/eas/build-on-success.js
@@ -22,23 +22,13 @@
* @see https://docs.sentry.io/platforms/react-native/
*/
-const { loadEnv, loadHooksModule, parseBaseOptions, runHook } = require('./utils');
+const { runEASHookScript } = require('./utils');
-async function main() {
- loadEnv();
-
- const hooks = loadHooksModule();
- const options = {
- ...parseBaseOptions(),
+runEASHookScript({
+ hookName: 'on-success',
+ hookFn: (hooks, options) => hooks.captureEASBuildSuccess(options),
+ getOptions: () => ({
successMessage: process.env.SENTRY_EAS_BUILD_SUCCESS_MESSAGE,
captureSuccessfulBuilds: process.env.SENTRY_EAS_BUILD_CAPTURE_SUCCESS === 'true',
- };
-
- await runHook('on-success', () => hooks.captureEASBuildSuccess(options));
-}
-
-main().catch(error => {
- // eslint-disable-next-line no-console
- console.error('[Sentry] Unexpected error in eas-build-on-success hook:', error);
- process.exit(1);
+ }),
});
diff --git a/packages/core/scripts/eas/utils.js b/packages/core/scripts/eas/utils.js
--- a/packages/core/scripts/eas/utils.js
+++ b/packages/core/scripts/eas/utils.js
@@ -116,9 +116,36 @@
}
}
+/**
+ * Runs a specific EAS build hook script with shared setup and fatal error handling.
+ * @param {object} params - Hook script configuration
+ * @param {string} params.hookName - Name of the hook for logging
+ * @param {(hooks: object, options: object) => Promise<void>} params.hookFn - Hook invocation function
+ * @param {() => object} [params.getOptions] - Returns hook-specific options from env vars
+ */
+function runEASHookScript({ hookName, hookFn, getOptions }) {
+ async function main() {
+ loadEnv();
+
+ const hooks = loadHooksModule();
+ const options = {
+ ...parseBaseOptions(),
+ ...(getOptions ? getOptions() : {}),
+ };
+
+ await runHook(hookName, () => hookFn(hooks, options));
+ }
+
+ main().catch(error => {
+ console.error(`[Sentry] Unexpected error in eas-build-${hookName} hook:`, error);
+ process.exit(1);
+ });
+}
+
module.exports = {
loadEnv,
loadHooksModule,
parseBaseOptions,
runHook,
+ runEASHookScript,
};| } | ||
| } | ||
| ``` | ||
| Set `SENTRY_DSN` in your EAS secrets, and optionally `SENTRY_EAS_BUILD_CAPTURE_SUCCESS=true` to also capture successful builds. |
There was a problem hiding this comment.
That all would require documentation changes; will make sure to handle them next.
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
| if (!options.captureSuccessfulBuilds) { | ||
| console.log('[Sentry] Skipping successful build capture (captureSuccessfulBuilds is false).'); | ||
| return; | ||
| } |
There was a problem hiding this comment.
on-success hook silently skips capture without extra env var
Medium Severity
When the on-success hook is invoked directly via the sentry-eas-build-on-success bin command, captureEASBuildSuccess always checks if (!options.captureSuccessfulBuilds) and returns early. In eas-build-hook.js, captureSuccessfulBuilds defaults to false (since undefined === 'true' is false) when SENTRY_EAS_BUILD_CAPTURE_SUCCESS is unset. A user who explicitly configures "eas-build-on-success": "sentry-eas-build-on-success" in their npm scripts clearly intends to capture successful builds, yet the hook silently does nothing without the additional env var. The captureSuccessfulBuilds guard is appropriate for the on-complete path but counterintuitive for the dedicated on-success hook.
Additional Locations (1)
| /* eslint-disable no-console */ | ||
|
|
||
| import type { DsnComponents } from '@sentry/core'; | ||
| import { dsnToString, makeDsn, uuid4 } from '@sentry/core'; |
There was a problem hiding this comment.
| import { dsnToString, makeDsn, uuid4 } from '@sentry/core'; | |
| import { dsnToString, makeDsn, uuid4 } from '@sentry/core'; | |
| import { SDK_VERSION } from '../version'; |



📢 Type of change
📜 Description
Introduces build hooks for EAS and fixes #5428
📝 Checklist
sendDefaultPIIis enabled