Skip to content

Commit c44fa03

Browse files
runningcodeclaude
andcommitted
build(samples): Move the Android sample to its own build
The Android sample is now a standalone Gradle build that includes the SDK build. It depends on io.sentry:* coordinates, which Gradle substitutes with the SDK's projects, so there is nothing to publish first. The SDK build doesn't include it back, so the sample's plugins (KSP, SQLDelight, Room, CameraX) no longer load in the SDK build. The macrobenchmark moves into the sample's build, because AGP requires a benchmark and the app it targets to be in the same build. Root check and spotlessApply no longer reach the sample, so preMerge runs the sample build's check, and the format workflow runs its spotlessApply. That check covers what the root check ran for it: lint, unit tests, SQLDelight migrations and spotless. Run it with ./gradlew -p sentry-samples/sentry-samples-android <task>. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 1bd946c commit c44fa03

15 files changed

Lines changed: 154 additions & 36 deletions

File tree

‎.github/workflows/format-code.yml‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ jobs:
2424
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}
2525

2626
- name: Format with spotlessApply
27-
run: ./gradlew spotlessApply
27+
run: |
28+
./gradlew spotlessApply
29+
./gradlew -p sentry-samples/sentry-samples-android spotlessApply
2830
2931
# actions/checkout fetches only a single commit in a detached HEAD state. Therefore
3032
# we need to pass the current branch, otherwise we can't commit the changes.

‎.github/workflows/integration-tests-macrobenchmark.yml‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: 'Integration Tests - Macrobenchmark'
2-
# Runs the sentry-uitest-android-macrobenchmark cold-start benchmark on a Sauce Labs real
2+
# Runs the sentry-samples-android macrobenchmark cold-start benchmark on a Sauce Labs real
33
# device and recovers timeToInitialDisplay from the device log.
44
#
55
on:
@@ -33,7 +33,7 @@ jobs:
3333

3434
- name: Assemble target app and Macrobenchmark apk
3535
if: env.SAUCE_USERNAME != null
36-
run: ./gradlew :sentry-samples:sentry-samples-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android-macrobenchmark:assembleBenchmark
36+
run: ./gradlew -p sentry-samples/sentry-samples-android :assembleRelease :macrobenchmark:assembleBenchmark
3737

3838
- name: Run Macrobenchmark in SauceLab
3939
uses: saucelabs/saucectl-run-action@283660aa934c02723c497efa151d582a3acc5801 # pin@v3

‎.sauce/sentry-uitest-android-macrobenchmark.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ defaults:
1515

1616
espresso:
1717
app: ./sentry-samples/sentry-samples-android/build/outputs/apk/release/sentry-samples-android-release.apk
18-
testApp: ./sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build/outputs/apk/benchmark/sentry-uitest-android-macrobenchmark-benchmark.apk
18+
testApp: ./sentry-samples/sentry-samples-android/macrobenchmark/build/outputs/apk/benchmark/macrobenchmark-benchmark.apk
1919

2020
suites:
2121

‎AGENTS.md‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ resolves the per-module test task, including integration test suites, for you.
6464

6565
# Run critical UI tests
6666
./scripts/test-ui-critical.sh
67+
68+
# Build the Android sample, a separate Gradle build that includes this one
69+
./gradlew -p sentry-samples/sentry-samples-android assembleDebug
6770
```
6871

6972
## Development Workflow Rules
@@ -110,7 +113,7 @@ The repository is organized into multiple modules:
110113

111114
### Utility Modules
112115
- **`sentry-test-support`** - Shared test utilities, including `MockSentryServer` and envelope matchers
113-
- **`sentry-samples`** - Example applications
116+
- **`sentry-samples`** - Example applications. `sentry-samples-android` is a separate Gradle build that includes this one, so root tasks such as `check` and `spotlessApply` don't reach it
114117
- **`sentry-bom`** - Bill of Materials for dependency management
115118

116119
### Key Architectural Patterns

‎Makefile‎

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
.PHONY: all clean compile javadocs dryRelease update checkFormat api assembleUiTestRelease assembleUiTestCriticalRelease runUiTestCritical check preMerge publish
1+
.PHONY: all clean compile javadocs dryRelease update checkFormat api assembleUiTestRelease assembleUiTestCriticalRelease runUiTestCritical check checkSampleAndroid preMerge publish
22

33
all: stop clean javadocs compile
44
assembleUiTests: assembleUiTestRelease
5-
preMerge: check
5+
preMerge: check checkSampleAndroid
66
publish: clean dryRelease
77

88
# deep clean
@@ -29,6 +29,7 @@ update:
2929
# Spotless check's code
3030
checkFormat:
3131
./gradlew spotlessJavaCheck spotlessKotlinCheck
32+
./gradlew -p sentry-samples/sentry-samples-android spotlessJavaCheck spotlessKotlinCheck
3233

3334
# Binary compatibility validator
3435
api:
@@ -49,3 +50,7 @@ runUiTestCritical:
4950
# Run tests and lint
5051
check:
5152
./gradlew check
53+
54+
# The Android sample is a separate build, so the root `check` doesn't reach it
55+
checkSampleAndroid:
56+
./gradlew -p sentry-samples/sentry-samples-android check

‎build.gradle.kts‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,6 @@ apiValidation {
5050
)
5151
ignoredProjects.addAll(
5252
listOf(
53-
"sentry-samples-android",
5453
"sentry-samples-console",
5554
"sentry-samples-console-opentelemetry-noagent",
5655
"sentry-samples-jul",

‎sentry-samples/sentry-samples-android/README.md‎

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,21 @@ profiling) and integrations (Compose, OkHttp, SQLite, etc.).
88
Install the app on your device or emulator:
99

1010
```
11-
./gradlew :sentry-samples:sentry-samples-android:installDebug
11+
./gradlew -p sentry-samples/sentry-samples-android installDebug
1212
```
1313

14-
or simply open the project in Android Studio and run the `sentry-samples-android` configuration.
14+
or open the `sentry-samples/sentry-samples-android` directory in Android Studio and run the `sentry-samples-android` configuration.
15+
16+
The sample is a separate Gradle build that includes the SDK build, so changes to the SDK show up in the next build of the sample, with nothing to publish first.
17+
The SDK build doesn't include the sample, so `./gradlew` from the repository root doesn't build, lint or format it.
1518

1619
You can also apply the [Sentry Android Gradle Plugin](https://github.com/getsentry/sentry-android-gradle-plugin) (SAGP) when building (not applied by default):
1720

1821
```
19-
./gradlew :sentry-samples:sentry-samples-android:installDebug -PuseSagp
22+
./gradlew -p sentry-samples/sentry-samples-android installDebug -PuseSagp
2023
```
2124

22-
In Android Studio, add `useSagp=` (empty value) to `gradle.properties`, or pass `-PuseSagp` as a Gradle project property.
25+
In Android Studio, add `useSagp=` (empty value) to the sample's `gradle.properties`, or pass `-PuseSagp` as a Gradle project property.
2326

2427
For LLM-driven verification, use `adb` to inspect and interact with the running emulator. Compose-based screens often expose stable
2528
`Modifier.testTag()` values, which can be used with the UI hierarchy dump to locate controls reliably.
@@ -55,7 +58,7 @@ Re-run `publishToMavenLocal` after each SAGP change.
5558
Then build from sentry-java:
5659

5760
```
58-
./gradlew :sentry-samples:sentry-samples-android:installDebug -PuseSagp
61+
./gradlew -p sentry-samples/sentry-samples-android installDebug -PuseSagp
5962
```
6063

6164
## Viewing SDK output

‎sentry-samples/sentry-samples-android/build.gradle.kts‎

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,18 @@ import org.gradle.internal.extensions.stdlib.capitalized
88
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
99

1010
plugins {
11-
id("com.android.application")
11+
alias(libs.plugins.android.application)
12+
id("io.sentry.spotless")
13+
id("io.sentry.jdk-target")
1214
alias(libs.plugins.kotlin.android)
1315
alias(libs.plugins.kotlin.compose)
1416
alias(libs.plugins.ksp)
1517
alias(libs.plugins.sentry) apply false
1618
alias(libs.plugins.sqldelight)
1719
}
1820

21+
val sentryVersion = libs.versions.sentry.get()
22+
1923
if (providers.gradleProperty("useSagp").isPresent) {
2024
apply(plugin = "io.sentry.android.gradle")
2125
}
@@ -53,7 +57,7 @@ android {
5357
minSdk = 23
5458
targetSdk = libs.versions.targetSdk.get().toInt()
5559
versionCode = 2
56-
versionName = project.version.toString()
60+
versionName = sentryVersion
5761

5862
externalNativeBuild {
5963
cmake {
@@ -104,7 +108,7 @@ android {
104108

105109
signingConfigs {
106110
getByName("debug") {
107-
storeFile = rootProject.file("debug.keystore")
111+
storeFile = file("../../debug.keystore")
108112
storePassword = "android"
109113
keyAlias = "androiddebugkey"
110114
keyPassword = "android"
@@ -146,7 +150,7 @@ android {
146150
val toggleNativeLoggingTask =
147151
project.tasks.register<ToggleNativeLoggingTask>(taskName) {
148152
mergedManifest.set(variant.artifacts.get(SingleArtifact.MERGED_MANIFEST))
149-
rootDir.set(project.rootDir.absolutePath)
153+
repoDir.set(layout.projectDirectory.dir("../..").asFile.canonicalPath)
150154
}
151155
project.afterEvaluate {
152156
(variant as? VariantImpl<*>)?.taskContainer?.assembleTask?.configure {
@@ -175,19 +179,19 @@ sqldelight {
175179
dependencies {
176180
implementation(kotlin("stdlib-jdk8", getKotlinPluginVersion()))
177181

178-
implementation(projects.sentryAndroid)
179-
implementation(projects.sentryAndroidFragment)
180-
implementation(projects.sentryAndroidNavigation)
181-
implementation(projects.sentryAndroidNavigation3)
182-
implementation(projects.sentryAndroidSqlite)
183-
implementation(projects.sentryAndroidTimber)
184-
implementation(projects.sentryCompose)
185-
implementation(projects.sentryKotlinExtensions)
186-
implementation(projects.sentryOkhttp)
187-
implementation(projects.sentrySpotlight)
182+
implementation("io.sentry:sentry-android:$sentryVersion")
183+
implementation("io.sentry:sentry-android-fragment:$sentryVersion")
184+
implementation("io.sentry:sentry-android-navigation:$sentryVersion")
185+
implementation("io.sentry:sentry-android-navigation3:$sentryVersion")
186+
implementation("io.sentry:sentry-android-sqlite:$sentryVersion")
187+
implementation("io.sentry:sentry-android-timber:$sentryVersion")
188+
implementation("io.sentry:sentry-compose:$sentryVersion")
189+
implementation("io.sentry:sentry-kotlin-extensions:$sentryVersion")
190+
implementation("io.sentry:sentry-okhttp:$sentryVersion")
191+
implementation("io.sentry:sentry-spotlight:$sentryVersion")
188192

189193
// how to exclude androidx if release health feature is disabled
190-
// implementation(projects.sentryAndroid) {
194+
// implementation("io.sentry:sentry-android:$sentryVersion") {
191195
// exclude(group = "androidx.lifecycle", module = "lifecycle-process")
192196
// exclude(group = "androidx.lifecycle", module = "lifecycle-common-java8")
193197
// exclude(group = "androidx.core", module = "core")
@@ -228,15 +232,15 @@ dependencies {
228232
ksp(libs.androidx.room.compiler)
229233
ksp(libs.androidx.room3.compiler)
230234

231-
debugImplementation(projects.sentryAndroidDistribution)
235+
debugImplementation("io.sentry:sentry-android-distribution:$sentryVersion")
232236
debugImplementation(libs.leakcanary)
233237

234238
testImplementation(libs.google.truth)
235239
testImplementation(libs.kotlin.test.junit)
236240
}
237241

238242
abstract class ToggleNativeLoggingTask : Exec() {
239-
@get:Input abstract val rootDir: Property<String>
243+
@get:Input abstract val repoDir: Property<String>
240244

241245
@get:InputFile abstract val mergedManifest: RegularFileProperty
242246

@@ -254,7 +258,7 @@ abstract class ToggleNativeLoggingTask : Exec() {
254258
args.add(0, "cmd")
255259
args.add(1, "/c")
256260
}
257-
args.add("${rootDir.get()}/scripts/toggle-codec-logs.sh")
261+
args.add("${repoDir.get()}/scripts/toggle-codec-logs.sh")
258262
args.add(if (value) "enable" else "disable")
259263
commandLine(args)
260264
super.exec()
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Gradle properties are per build, so this repeats what the sample needs from the SDK build's
2+
# gradle.properties. settings.gradle.kts reads the SDK version from that file.
3+
4+
org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=2g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
5+
org.gradle.caching=true
6+
org.gradle.parallel=true
7+
org.gradle.configureondemand=true
8+
org.gradle.configuration-cache=true
9+
org.gradle.configuration-cache.parallel=true
10+
11+
android.useAndroidX=true
12+
# AGP 9+ migration opt-outs until we remove kotlin-android plugin and adopt built-in Kotlin.
13+
android.builtInKotlin=false
14+
android.newDsl=false
15+
16+
android.defaults.buildfeatures.renderscript=false
17+
android.defaults.buildfeatures.shaders=false
18+
android.defaults.buildfeatures.aidl=false
19+
android.defaults.buildfeatures.resvalues=false
20+
android.nonTransitiveRClass=true
21+
22+
kotlin.stdlib.default.dependency=false
23+
24+
systemProp.org.gradle.internal.http.socketTimeout=120000

sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/README.md renamed to sentry-samples/sentry-samples-android/macrobenchmark/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# sentry-uitest-android-macrobenchmark
1+
# macrobenchmark
22

33
Jetpack Macrobenchmark for cold-start of `sentry-samples-android`, used to evaluate SDK-init
44
performance changes on a real device in a **stable, reproducible** way. Not run in CI.
@@ -28,7 +28,7 @@ unlocked-clock device after ~14 iterations, inflating the tail of longer runs.
2828
Connect a device, then:
2929

3030
```bash
31-
./gradlew :sentry-android-integration-tests:sentry-uitest-android-macrobenchmark:connectedBenchmarkAndroidTest
31+
./gradlew -p sentry-samples/sentry-samples-android :macrobenchmark:connectedBenchmarkAndroidTest
3232
```
3333

3434
Results print to the console and are written to

0 commit comments

Comments
 (0)