Skip to content

EAS Build Hooks#5666

Merged
alwx merged 11 commits intomainfrom
alwx/experiment/eas-build
Mar 5, 2026
Merged

EAS Build Hooks#5666
alwx merged 11 commits intomainfrom
alwx/experiment/eas-build

Conversation

@alwx
Copy link
Contributor

@alwx alwx commented Feb 13, 2026

📢 Type of change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring

📜 Description

Introduces build hooks for EAS and fixes #5428

📝 Checklist

  • I added tests to verify changes
  • No new PII added or SDK only sends newly added PII if sendDefaultPII is enabled
  • I updated the docs if needed.
  • I updated the wizard if needed.
  • All tests passing
  • No breaking changes

@github-actions
Copy link
Contributor

github-actions bot commented Feb 13, 2026

Semver Impact of This PR

None (no version bump detected)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


  • EAS Build Hooks by alwx in #5666
  • chore(deps): update CLI to v3.3.0 by github-actions in #5762
  • chore(deps): update Cocoa SDK to v9.6.0 by github-actions in #5759
  • [iOS + Android] Add the ability to intercept errors from native side and forward them to JS console by alwx in #5622
  • Feat(Expo): Add expo constants on event context. by lucas-zimerman in #5748
  • chore(deps): update JavaScript SDK to v10.42.0 by github-actions in #5753
  • feat(core): Capture dynamic route params as span attributes by antonis in #5750
  • chore(deps): bump brace-expansion from 1.1.11 to 1.1.12 by dependabot in #5751
  • chore(deps): bump minimatch to fix ReDoS vulnerabilities and tmp to ^0.2.4 by antonis in #5749
  • chore(deps): bump getsentry/craft/.github/workflows/changelog-preview.yml from 2.21.7 to 2.23.1 by dependabot in #5738
  • chore(deps): update Wizard to v6.12.0 by github-actions in #5747
  • chore(deps): update JavaScript SDK to v10.41.0 by github-actions in #5744
  • chore(deps): bump tar to ^7.5.8 by antonis in #5703
  • chore(deps): bump js-yaml to fix prototype pollution in merge by antonis in #5709
  • chore(deps): bump ajv to fix ReDoS in $data option by antonis in #5710
  • chore(deps): update CLI to v3.2.3 by github-actions in #5743
  • Fixes the issue with unit mismatch in adjustTransactionDuration by alwx in #5740
  • Handle inactive state for spans by alwx in #5742
  • chore(deps): bump actions/github-script from 7 to 8 by dependabot in #5737
  • chore(deps): bump actions/upload-artifact from 6 to 7 by dependabot in #5739
  • chore(deps): bump futureware-tech/simulator-action from 4 to 5 by dependabot in #5735
  • chore(deps): bump actions/download-artifact from 7 to 8 by dependabot in #5736
  • chore(deps): bump path-to-regexp to 0.1.12 by antonis in #5706
  • fix(ios): resolve relative SOURCEMAP_FILE against project root in Xcode build script by antonis in #5730

Plus 9 more


🤖 This preview updates automatically when you update the PR.

@alwx alwx self-assigned this Feb 16, 2026
@alwx alwx changed the title WIP: EAS Build Hooks EAS Build Hooks Feb 23, 2026
@alwx alwx marked this pull request as ready for review February 23, 2026 12:08
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' },
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Fix in Cursor Fix in Web

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feedback looks valid 👍

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@alwx I think we should use a dynamic version here like:

Suggested change
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

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@antonis 👍

@alwx alwx added the ready-to-merge Triggers the full CI test suite label Feb 23, 2026
@alwx alwx enabled auto-merge (squash) February 23, 2026 12:39
@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

Android (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 429.53 ms 491.94 ms 62.41 ms
Size 43.75 MiB 48.50 MiB 4.75 MiB

Baseline results on branch: main

Startup times

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

Previous results on branch: alwx/experiment/eas-build

Startup times

Revision Plain With Sentry Diff
e51ef4e+dirty 411.16 ms 444.28 ms 33.12 ms

App size

Revision Plain With Sentry Diff
e51ef4e+dirty 43.75 MiB 48.46 MiB 4.71 MiB

@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

iOS (legacy) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1218.74 ms 1217.94 ms -0.80 ms
Size 3.38 MiB 4.81 MiB 1.42 MiB

Baseline results on branch: main

Startup times

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

Previous results on branch: alwx/experiment/eas-build

Startup times

Revision Plain With Sentry Diff
e51ef4e+dirty 1222.04 ms 1226.24 ms 4.20 ms

App size

Revision Plain With Sentry Diff
e51ef4e+dirty 3.38 MiB 4.78 MiB 1.40 MiB

@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

Android (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 393.58 ms 427.72 ms 34.14 ms
Size 43.94 MiB 49.34 MiB 5.40 MiB

Baseline results on branch: main

Startup times

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

Previous results on branch: alwx/experiment/eas-build

Startup times

Revision Plain With Sentry Diff
e51ef4e+dirty 359.31 ms 385.06 ms 25.76 ms

App size

Revision Plain With Sentry Diff
e51ef4e+dirty 43.94 MiB 49.33 MiB 5.39 MiB

@github-actions
Copy link
Contributor

github-actions bot commented Feb 23, 2026

iOS (new) Performance metrics 🚀

  Plain With Sentry Diff
Startup time 1209.64 ms 1215.04 ms 5.40 ms
Size 3.38 MiB 4.81 MiB 1.42 MiB

Baseline results on branch: main

Startup times

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

Previous results on branch: alwx/experiment/eas-build

Startup times

Revision Plain With Sentry Diff
e51ef4e+dirty 1219.77 ms 1224.57 ms 4.80 ms

App size

Revision Plain With Sentry Diff
e51ef4e+dirty 3.38 MiB 4.78 MiB 1.40 MiB

@lucas-zimerman
Copy link
Collaborator

Fails
🚫 Please consider adding a changelog entry for the next release.

Instructions and example for changelog

Please add an entry to CHANGELOG.md to the "Unreleased" section. Make sure the entry includes this PR's number.

Example:

## Unreleased

### Features

- EAS Build Hooks ([#5666](https://github.com/getsentry/sentry-react-native/pull/5666))

If none of the above apply, you can opt out of this check by adding #skip-changelog to the PR description or adding a skip-changelog label.

Generated by 🚫 dangerJS against 9b0d8e7

Yeah, adding a feature changelog would be nice.

*
* Add it to your package.json scripts:
*
* "eas-build-on-complete": "sentry-eas-build-on-complete"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have docs for these features and add a small mention on how to use them on changelog.

@lucas-zimerman
Copy link
Collaborator

I did another code review and so far it's good! I have one small suggestion before we can merge this PR

@alwx alwx force-pushed the alwx/experiment/eas-build branch from 2d9e8b0 to 2d1bd0b Compare March 5, 2026 10:03
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 runEASHookScript helper in scripts/eas/utils.js and updated all three hook entry scripts to use it with only hook-specific options and handler differences.

Create PR

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,
 };
This Bugbot Autofix run was free. To enable autofix for future PRs, go to the Cursor dashboard.

}
}
```
Set `SENTRY_DSN` in your EAS secrets, and optionally `SENTRY_EAS_BUILD_CAPTURE_SUCCESS=true` to also capture successful builds.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That all would require documentation changes; will make sure to handle them next.

@alwx alwx requested review from antonis and lucas-zimerman March 5, 2026 10:32
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)

Fix in Cursor Fix in Web

/* eslint-disable no-console */

import type { DsnComponents } from '@sentry/core';
import { dsnToString, makeDsn, uuid4 } from '@sentry/core';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import { dsnToString, makeDsn, uuid4 } from '@sentry/core';
import { dsnToString, makeDsn, uuid4 } from '@sentry/core';
import { SDK_VERSION } from '../version';

Copy link
Collaborator

@lucas-zimerman lucas-zimerman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@alwx alwx merged commit 9ee3737 into main Mar 5, 2026
68 of 78 checks passed
@alwx alwx deleted the alwx/experiment/eas-build branch March 5, 2026 11:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-to-merge Triggers the full CI test suite

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Expo] EAS build hooks

3 participants