ref(snapshots): Register snapshot upload tasks per variant#1105
ref(snapshots): Register snapshot upload tasks per variant#1105runningcode merged 2 commits intomainfrom
Conversation
Move SentryUploadSnapshotsTask registration from SentryPlugin (global) into AndroidComponentsConfig (per-variant), matching the pattern used by proguard mappings, source bundles, and native symbols. This wires applicationId directly from ApplicationVariant, eliminating the need for the SnapshotsExtension and manual appId configuration. Also wires sentry telemetry into the task. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
abfbe2b to
9d95db7
Compare
Semver Impact of This PR🟢 Patch (bug fixes) 📋 Changelog PreviewThis is how your changes will appear in the changelog. This PR will not 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.
| task.vcsBaseRef.set(extension.vcsInfo.baseRef) | ||
| task.vcsPrNumber.set(extension.vcsInfo.prNumber) | ||
| sentryTelemetryProvider?.let { task.sentryTelemetryService.set(it) } | ||
| task.withSentryTelemetry(extension, sentryTelemetryProvider) |
There was a problem hiding this comment.
Reversed ordering of asSentryCliExec and withSentryTelemetry
Low Severity
The call order of task.withSentryTelemetry() and task.asSentryCliExec() is reversed compared to every other task registration in the codebase (SentryUploadAppArtifactTask, SentryUploadNativeSymbolsTask, BundleSourcesTask, UploadSourceBundleTask). All other tasks call asSentryCliExec() first, then withSentryTelemetry(). Since both methods register doFirst/doLast actions, and Gradle executes doFirst in LIFO and doLast in FIFO order, this swap changes the runtime execution order of telemetry span tracking relative to CLI error handling.
There was a problem hiding this comment.
probably this is good to align with other tasks, since SentryTelemetryService does some things (e.g. error handling) based on the output of SentryCliException (which is handled in asSentryCliExec), so should probably be reordered
| sentryProject, | ||
| ) | ||
|
|
||
| variant.configureSnapshotsTasks( |
There was a problem hiding this comment.
So, this is done inside the isVariantAllowed which means that if you disable sentry for the debug variants then you will need to upload your snapshots with the release variant.
This doesn't pose any problems other than it might be confusing for users.
They will have to do something like this:
afterEvaluate {
tasks.named<SentryUploadSnapshotsTask>("sentryUploadSnapshotsRelease") {
dependsOn(tasks.named("recordRoborazziDebug"))
snapshotsPath.set(file("snapshotsDir"))
}
}
Alternatively, we can move it outside the isVariantAllowed but then we would either not have telemetry or move the telemetry outside the isVariantAllowed.
I think we should do it like this since it is the safest option, we can always move it outside isVariantAllowed if customers complain.
There was a problem hiding this comment.
this sounds good -- named should throw if a task with that name does not exist right? So even if they ignored a variant, gradle won't let them wire a non-existing task and would surface this quickly, so hopefully this would resolve the confusion
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
| @get:PathSensitive(PathSensitivity.RELATIVE) | ||
| abstract val snapshotsPath: DirectoryProperty | ||
|
|
||
| @Option(option = "snapshots-path", description = "Path to the snapshots directory to upload") |
There was a problem hiding this comment.
Bug: The SentryUploadSnapshotsTask will cause a Gradle validation error if the required snapshotsPath property is not explicitly configured by the user, as it's no longer set by default.
Severity: MEDIUM
Suggested Fix
Add the @get:Optional annotation to the snapshotsPath property. In the task's execution logic, check if the property has a value. If it doesn't, either skip the task's execution or log a clear warning message instructing the user on how to configure the snapshotsPath property.
Prompt for AI Agent
Review the code at the location below. A potential bug has been identified by an AI
agent.
Verify if this is a real issue. If it is, propose a fix; if not, explain why it's not
valid.
Location:
plugin-build/src/main/kotlin/io/sentry/android/gradle/tasks/SentryUploadSnapshotsTask.kt#L32-L35
Potential issue: The `snapshotsPath` property in `SentryUploadSnapshotsTask` is declared
as a required `@InputDirectory` but is no longer configured by default from the Sentry
extension. If a user runs a `sentryUploadSnapshots...` task without manually configuring
the `snapshotsPath` for that specific task, the build will fail with a generic Gradle
validation error. This happens because the property is used via `snapshotsPath.get()`
without a prior check, and the missing `@Optional` annotation causes Gradle to enforce
its presence before task execution. The error message from Gradle is not specific to the
Sentry plugin, making it difficult for users to understand that they need to set this
property.
Did we get this right? 👍 / 👎 to inform future reviews.
There was a problem hiding this comment.
This is how we expect it to be configured. The task needs to be manually wired now.
romtsn
left a comment
There was a problem hiding this comment.
the approach looks good to me -- given there's no auto-wiring for this task anyway, i think it's fine to configure it directly 👍
|
Thanks! |


Motivation
In practice, users will want to wire
snapshotsPathto the output of another task that generates the snapshots. Configuring this through an extension block is clunky because extensions aren't designed for task-to-task wiring — directly configuring the task makes this straightforward.Before
A single global task configured via the
sentry.snapshotsextension block. Users had to manually setappId:sentry { snapshots { appId = "com.example.app" path = file("path/to/snapshots") } }In practice, however, the task will need to be configured with the output of the task that generates the snapshot. So the
appIdis set in the extension and the path in the task.After
Per-variant tasks with
appIdauto-wired from the variant'sapplicationId. Users only need to setsnapshotsPathon the task directly and wiring the output of a snapshot-generating task is also straightforward.Fixes EME-920
#skip-changelog
🤖 Generated with Claude Code