fix(android): make Sentry Gradle tasks Configuration Cache compatible#6469
Conversation
Semver Impact of This PR⚪ None (no version bump detected) 📋 Changelog PreviewThis is how your changes will appear in the changelog.
🤖 This preview updates automatically when you update the PR. |
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.
Reviewed by Cursor Bugbot for commit 7d293fd. Configure here.
|
Update — I ran a full The upload task's After that fix, a fresh configuration-cache store shows So the change now covers both |
| "require.resolve('@sentry/cli/package.json', { paths: [require.resolve('@sentry/react-native/package.json')] })", | ||
| ), | ||
| ).directory(rootDir) | ||
| ).directory(reactRoot) |
There was a problem hiding this comment.
This has been changed to .directory(reactRoot) but several lines (at line 181) .directory(rootDir) is still being used. Could you change it for consistency?
There was a problem hiding this comment.
Done in c2fb76f — reverted to .directory(rootDir) to match resolveSentryReactNativeSDKPath. Both helpers run at configuration time now, so rootDir is Configuration Cache safe in both.
|
|
||
| ### Fixes | ||
|
|
||
| - Make `copySentryJsonConfiguration` and the `*_SentryUpload` Gradle tasks compatible with the Gradle Configuration Cache ([#6466](https://github.com/getsentry/sentry-react-native/issues/6466)) |
There was a problem hiding this comment.
This should point to the PR and not to the issue.
| // `copyOptionsFileEnabled` is a Property populated in `afterEvaluate` (below) rather than at | ||
| // apply-time, so a `project.ext.shouldCopySentryOptionsFile` override placed after `apply from` | ||
| // is still honored. Referencing the Property in `onlyIf` keeps the tasks Config Cache compatible. | ||
| val copyOptionsFileEnabled = objects.property(Boolean::class.java) |
There was a problem hiding this comment.
This has no default. If afterEvaluateat line 117 doesn't run (due to let's say a configuration error), .get() inside onlyIf will throw an IllegalStateException
There was a problem hiding this comment.
Good point — fixed in c2fb76f by adding .convention(true), which preserves the documented default (copy enabled, i.e. SENTRY_COPY_OPTIONS_FILE != "false") so .get() returns the default instead of throwing if afterEvaluate never runs.
…changelog
- `copyOptionsFileEnabled` now has `.convention(true)`, preserving the
documented default (copy enabled) so `onlyIf { .get() }` can't throw
IllegalStateException if `afterEvaluate` never runs.
- `resolveSentryCliPackagePath` reverted to `.directory(rootDir)` to match
`resolveSentryReactNativeSDKPath`; both run at configuration time now, so
`rootDir` is Configuration Cache safe and consistent.
- CHANGELOG entry links the PR (getsentry#6469) instead of the issue.
Re-verified on a fresh configuration-cache store (RN 0.83.9, Gradle 9.0.0):
copySentryJsonConfiguration, _SentryUpload, and _SentryCollectModules all
execute with no sentry.gradle failure.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Code <noreply@anthropic.com>
`copySentryJsonConfiguration` and the `*_SentryUpload` tasks no longer read `project` state at execution time — `onlyIf` predicates resolving closures from `project.extra`, plus `project.rootDir`, `project.copy`, `project.logger`, and `Project.file` inside task actions. Environment reads are captured at configuration time, file copies use an injected `FileSystemOperations`, and task actions use the task's own `logger`. No behaviour change. This fixes the hard `Could not evaluate onlyIf predicate` failure when `org.gradle.configuration-cache=true` (Gradle 9 recommends it by default). Verified end-to-end on a React Native 0.83.9 app with Gradle 9.0.0: the equivalent Groovy `sentry.gradle` (shipped in 8.10.0) went from BUILD FAILED (`Could not evaluate onlyIf predicate for task ':app:copySentryJsonConfiguration'`) to BUILD SUCCESSFUL with config cache enabled after this change. See getsentry#6466. Interim step ahead of the SAGP migration (getsentry/sentry-android-gradle-plugin#796). Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Code <noreply@anthropic.com>
Addresses review feedback: capturing `SENTRY_DISABLE_AUTO_UPLOAD` via
`System.getenv` at apply-time ignored a `project.ext.shouldSentryAutoUploadGeneral`
override set right after `apply from` (e.g. the Expo `disableAutoUpload` config
plugin, which injects `project.ext.shouldSentryAutoUploadGeneral = { -> return false }`).
Uploads would then run even when the user disabled them.
Now capture `shouldSentryAutoUploadGeneral()` inside the `onVariants` callback,
which runs after the app `build.gradle` has evaluated, so the override is in
effect. Likewise capture `shouldCopySentryOptionsFile()` via the closure rather
than re-reading the env var, so `project.ext` overrides of it keep working.
Both `onlyIf` specs still reference a captured boolean, so the tasks remain
Configuration Cache compatible, and the original override behavior is restored.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Code <noreply@anthropic.com>
…(CC)
Addresses two more review findings plus a failure surfaced by a full
bundle run under the configuration cache:
1. `copyOptionsFileEnabled` is now a `Property` set in `afterEvaluate` (after
the app build.gradle evaluates), so a `project.ext.shouldCopySentryOptionsFile`
override placed after `apply from` is honored — mirroring the deferral
already applied for `shouldSentryAutoUploadGeneral`.
2. `resolveSentryCliPackagePath(reactRoot)` is now resolved at configuration
time and captured, instead of being called inside the `*_SentryUpload`
`doLast` exec closure. A `:app:createBundle...JsAndAssets` run with
`configuration-cache=true` showed the previous revision still failed at
execution ("Could not find method resolveSentryCliPackagePath() ... on
DefaultExecAction_Decorated"): a serialized task action cannot resolve
top-level script methods.
Verified on a fresh configuration-cache store (React Native 0.83.9,
Gradle 9.0.0): copySentryJsonConfiguration, _SentryUpload, and
_SentryCollectModules execute with no sentry.gradle hard failure. Only the
pre-existing warn-level config-time `require.resolve` external processes
(resolveSentryReactNativeSDKPath / resolveSentryCliPackagePath) remain, which
are out of scope for this PR.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Code <noreply@anthropic.com>
…changelog
- `copyOptionsFileEnabled` now has `.convention(true)`, preserving the
documented default (copy enabled) so `onlyIf { .get() }` can't throw
IllegalStateException if `afterEvaluate` never runs.
- `resolveSentryCliPackagePath` reverted to `.directory(rootDir)` to match
`resolveSentryReactNativeSDKPath`; both run at configuration time now, so
`rootDir` is Configuration Cache safe and consistent.
- CHANGELOG entry links the PR (getsentry#6469) instead of the issue.
Re-verified on a fresh configuration-cache store (RN 0.83.9, Gradle 9.0.0):
copySentryJsonConfiguration, _SentryUpload, and _SentryCollectModules all
execute with no sentry.gradle failure.
Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Code <noreply@anthropic.com>
c2fb76f to
9c4bfe2
Compare

📜 Description
Makes the two Sentry Gradle tasks compatible with the Gradle Configuration Cache by removing
project-state access at execution time.Fixes the hard failure reported in #6466 (and the earlier #4252):
...which also occurs for
:app:copySentryJsonConfiguration. These are hard, non-warnable exceptions —org.gradle.configuration-cache.problems=warndoes not rescue them.What changed in
packages/core/sentry.gradle.ktsThe exec-time
projectaccesses were:onlyIf { shouldCopySentryOptionsFile() }/onlyIf { shouldSentryAutoUploadGeneral() }— these resolve closures stored inproject.extra, so evaluating theonlyIf(at execution time) dereferencesproject.copySentryJsonConfiguration'sdoLast:project.rootDirandcopy { … }(i.e.project.copy).*_SentryUploadtask actions:project.loggerandProject.file(...).resolveSentryCliPackagePath(...)(called from the uploaddoLast) used.directory(rootDir).Fixes, all behaviour-preserving and using patterns already present in this file (the CLI itself already runs via an injected
ExecOperations):vals referenced by theonlyIfspecs.project.rootDircaptured at configuration time.copy { }→ an injectedFileSystemOperations(InjectedFsOps), mirroringInjectedExecOps.project.logger→ the task's ownlogger.Project.file("$reactRoot/…")→File("$reactRoot/…")(path is already absolute).resolveSentryCliPackagePathresolves fromreactRootinstead ofrootDir.This is an interim step ahead of the full SAGP migration tracked in getsentry/sentry-android-gradle-plugin#796.
Out of scope (called out for transparency)
resolveSentryReactNativeSDKPathstill runsnode --print require.resolve(...)as an external process at configuration time. That is a separate, warn-level Configuration Cache problem shared with several other React Native libraries (netinfo, keychain, keyboard-controller, …) and does not fail the build the way theonlyIfdid. Left for a follow-up so this PR stays focused on the hard failures.💡 Motivation and Context
Gradle 9 recommends the Configuration Cache by default and nags on every build; the configuration phase is a meaningful share of Android build time on large RN apps. Today
sentry.gradle(.kts)makes the build error out entirely when it's enabled. See #6466 for the full analysis.💚 How did you test it?
Verified end-to-end on a React Native 0.83.9 app with Gradle 9.0.0 (
org.gradle.configuration-cache=true,problems=warn).Because the released
8.xline still ships the Groovysentry.gradle(the.ktsis a8.14.0+rewrite of the same logic), the fix was proven against the equivalent Groovy script installed via 8.10.0, then ported here 1:1 to Kotlin:sentry.gradleCould not evaluate onlyIf predicate for task ':app:copySentryJsonConfiguration'→ BUILD FAILED> Task :app:copySentryJsonConfigurationruns → BUILD SUCCESSFULAfter the fix, the remaining Configuration Cache problems are only the warn-level config-time external-process ones noted above (no
sentry.gradlehard failure).The
*_SentryUploadtask action changes (logger,file(),resolveSentryCliPackagePath) are the same violation classes; they were applied by static analysis (a real upload run needs live credentials), withcopySentryJsonConfigurationas the empirical anchor for the sharedonlyIf/project-access mechanism.📝 Checklist
CHANGELOG.mdentry (Unreleased → Fixes).Closes #6466
Generated with Claude Code