Skip to content

[DNM] [TEST] fix(config-cache): Defer CLI path resolution to execution phase#1224

Draft
runningcode wants to merge 5 commits into
mainfrom
no/fix-config-cache-cli-path
Draft

[DNM] [TEST] fix(config-cache): Defer CLI path resolution to execution phase#1224
runningcode wants to merge 5 commits into
mainfrom
no/fix-config-cache-cli-path

Conversation

@runningcode
Copy link
Copy Markdown
Contributor

Summary

  • Defer sentry-cli path resolution from Gradle's configuration phase to execution phase, fixing recurring build failures when the configuration cache stores a stale CLI binary path
  • Remove SentryCliValueSource, cliExecutableProvider(), and the cliExecutable @Input property from all tasks — CLI path is now resolved fresh inside computeCommandLineArgs() at task execution time
  • Remove SentryCliInfoValueSource and SentryCliVersionValueSource which spawned sentry-cli processes during configuration phase; use BuildConfig.CliVersion and URL-based SaaS heuristics instead
  • Improve maybeExtractFromResources() to handle CLI version mismatches by extracting the current bundled version when a stale path from a previous plugin version is detected

Fixes #613
Fixes GRADLE-70

Root Cause

The CLI path was resolved during configuration via SentryCliValueSource and cached by Gradle's configuration cache. This cached path became stale in two scenarios:

  1. Version mismatch on plugin upgrade: Config cache stored sentry-cli-2.46.0.exe but the upgraded plugin ships sentry-cli-2.51.1.exe. The old recovery code in maybeExtractFromResources() only re-extracted when paths matched exactly, so sentry-cli-2.46.0.exe != sentry-cli-2.51.1.exe caused it to skip extraction.

  2. Binary deleted: The extracted CLI binary was cleaned up (OS temp cleanup, ./gradlew clean, or daemon restart) while the config cache still held the old path.

Approach

Rather than patching the config cache inputs, we eliminate the problem entirely by not caching the CLI path at all. The path is resolved fresh during each task's execution phase, which is the correct time to do filesystem I/O.

This also removes the telemetry ValueSources that executed sentry-cli info and sentry-cli --version during configuration phase (~38% overhead on large projects per #1100).

🤖 Generated with Claude Code

The sentry-cli binary path was resolved during Gradle's configuration
phase via SentryCliValueSource and cached. When the binary was deleted
(OS temp cleanup, build dir cleaned) or the plugin was upgraded
(different CLI version), the cached path became stale, causing build
failures like "Could not start sentry-cli*.exe".

Move CLI path resolution entirely to the execution phase:

- Remove SentryCliValueSource, cliExecutableProvider(), and the
  cliExecutable @input property from all tasks
- Resolve the CLI path fresh inside computeCommandLineArgs() at
  execution time via getSentryCliPath() + maybeExtractFromResources()
- Remove SentryCliInfoValueSource and SentryCliVersionValueSource
  which spawned sentry-cli processes during configuration phase;
  use BuildConfig.CliVersion and URL-based heuristics instead
- Improve maybeExtractFromResources() to handle CLI version changes
  by extracting the current bundled version when a stale path is
  detected in build/tmp/

Fixes #613

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 22, 2026

GRADLE-70

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 22, 2026

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

- Defer CLI path resolution to execution phase ([#1224](https://github.com/getsentry/sentry-android-gradle-plugin/pull/1224))

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 6a9d98f

@runningcode runningcode marked this pull request as draft May 22, 2026 12:59
@runningcode runningcode changed the title fix(config-cache): Defer CLI path resolution to execution phase [DNM] [TEST] fix(config-cache): Defer CLI path resolution to execution phase May 22, 2026
Copy link
Copy Markdown

@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.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 7f9ec0e. Configure here.

val currentExtractionPath = getCliResourcesExtractionPath(buildDir)
if (currentExtractionPath.exists()) {
return currentExtractionPath.absolutePath
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Silent fallback overrides user-specified CLI path

Low Severity

When getSentryCliPath returns a user-configured path from sentry.properties (cli.executable) that doesn't exist at execution time, maybeExtractFromResources checks currentExtractionPath.exists() before verifying the path origin. If a bundled CLI was previously extracted, this silently returns the bundled CLI path, ignoring the user's explicit configuration. The old code only attempted extraction when cliPath matched the pre-computed extraction path, so a missing user-specified path would propagate as a clear execution error.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 7f9ec0e. Configure here.

runningcode and others added 4 commits May 22, 2026 15:18
Replace private val fields that captured project.projectDir and
project.rootDir with abstract DirectoryProperty fields annotated
with @internal. Properties are wired during configuration via
asSentryCliExec() and resolved during execution, following Gradle
best practices for configuration cache compatibility.

Also removes duplicate buildDir property from
SentryUploadNativeSymbolsTask in favor of the base class property.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace fileValue(project.rootDir) with
project.rootProject.layout.projectDirectory so the property is
serialized as a project-relative reference by the config cache
instead of an absolute path.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The synchronous SentryCliInfoValueSource was removed because it ran
sentry-cli during configuration phase, which is incompatible with
Gradle's configuration cache. This restores the default organization
lookup by running sentry-cli info in a background daemon thread after
telemetry is initialized. If the process times out or fails, the scope
is left unchanged.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Build failures regarding sentry-cli7059257849644749494.exe on macOS

1 participant