Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .github/workflows/format-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@ jobs:
cache-encryption-key: ${{ secrets.GRADLE_ENCRYPTION_KEY }}

- name: Format with spotlessApply
run: ./gradlew spotlessApply
run: |
./gradlew spotlessApply
./gradlew -p sentry-samples/sentry-samples-android spotlessApply

# actions/checkout fetches only a single commit in a detached HEAD state. Therefore
# we need to pass the current branch, otherwise we can't commit the changes.
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/integration-tests-macrobenchmark.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: 'Integration Tests - Macrobenchmark'
# Runs the sentry-uitest-android-macrobenchmark cold-start benchmark on a Sauce Labs real
# Runs the sentry-samples-android macrobenchmark cold-start benchmark on a Sauce Labs real
# device and recovers timeToInitialDisplay from the device log.
#
on:
Expand Down Expand Up @@ -33,7 +33,7 @@ jobs:

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

- name: Run Macrobenchmark in SauceLab
uses: saucelabs/saucectl-run-action@283660aa934c02723c497efa151d582a3acc5801 # pin@v3
Expand Down
61 changes: 61 additions & 0 deletions .github/workflows/samples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
name: 'Samples'
# Runs `check` in each build the SDK build doesn't include, so a broken sample or
# integration test fails its own job instead of the SDK's Build job.
on:
push:
branches:
- main
pull_request:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
check:
name: Check ${{ matrix.name }}
runs-on: ubuntu-latest

strategy:
fail-fast: false
matrix:
include:
- name: sentry-samples-android
path: sentry-samples/sentry-samples-android

steps:
- name: Checkout Repo
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1

- name: Setup Java Version
uses: actions/setup-java@b843ebf9b913146b38da2eaa7aeddf76074ae1ad # v6.1.0
with:
distribution: 'temurin'
java-version: '21'

- name: Setup Gradle
uses: gradle/actions/setup-gradle@3f5f9adaf7d9fecd50b5935e54106014257a94e6 # v6.4.0

- name: Run Tests and Lint
run: ./gradlew -p ${{ matrix.path }} check

- name: Upload test results
if: always()
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7
with:
name: test-results-${{ matrix.name }}
path: |
**/build/reports/*

- name: Test Report
uses: phoenix-actions/test-reporting@7317eea6e13c47348dd0bb318669485157c518d6 # pin@v16
if: always()
with:
name: JUnit ${{ matrix.name }}
list-suites: 'failed'
list-tests: 'failed'
path: |
**/build/test-results/**/*.xml
reporter: java-junit
output-to: step-summary
fail-on-error: false
2 changes: 1 addition & 1 deletion .sauce/sentry-uitest-android-macrobenchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ defaults:

espresso:
app: ./sentry-samples/sentry-samples-android/build/outputs/apk/release/sentry-samples-android-release.apk
testApp: ./sentry-android-integration-tests/sentry-uitest-android-macrobenchmark/build/outputs/apk/benchmark/sentry-uitest-android-macrobenchmark-benchmark.apk
testApp: ./sentry-samples/sentry-samples-android/macrobenchmark/build/outputs/apk/benchmark/macrobenchmark-benchmark.apk

suites:

Expand Down
5 changes: 4 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ resolves the per-module test task, including integration test suites, for you.

# Run critical UI tests
./scripts/test-ui-critical.sh

# Build the Android sample, a separate Gradle build that includes this one
./gradlew -p sentry-samples/sentry-samples-android assembleDebug
```

## Development Workflow Rules
Expand Down Expand Up @@ -110,7 +113,7 @@ The repository is organized into multiple modules:

### Utility Modules
- **`sentry-test-support`** - Shared test utilities, including `MockSentryServer` and envelope matchers
- **`sentry-samples`** - Example applications
- **`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
- **`sentry-bom`** - Bill of Materials for dependency management

### Key Architectural Patterns
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ update:
# Spotless check's code
checkFormat:
./gradlew spotlessJavaCheck spotlessKotlinCheck
./gradlew -p sentry-samples/sentry-samples-android spotlessJavaCheck spotlessKotlinCheck

# Binary compatibility validator
api:
Expand Down
13 changes: 8 additions & 5 deletions sentry-samples/sentry-samples-android/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,21 @@ profiling) and integrations (Compose, OkHttp, SQLite, etc.).
Install the app on your device or emulator:

```
./gradlew :sentry-samples:sentry-samples-android:installDebug
./gradlew -p sentry-samples/sentry-samples-android installDebug
```

or simply open the project in Android Studio and run the `sentry-samples-android` configuration.
or open the `sentry-samples/sentry-samples-android` directory in Android Studio and run the `sentry-samples-android` configuration.

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.
The SDK build doesn't include the sample, so `./gradlew` from the repository root doesn't build, lint or format it.

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

```
./gradlew :sentry-samples:sentry-samples-android:installDebug -PuseSagp
./gradlew -p sentry-samples/sentry-samples-android installDebug -PuseSagp
```

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

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

```
./gradlew :sentry-samples:sentry-samples-android:installDebug -PuseSagp
./gradlew -p sentry-samples/sentry-samples-android installDebug -PuseSagp
```

## Viewing SDK output
Expand Down
40 changes: 22 additions & 18 deletions sentry-samples/sentry-samples-android/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@ import org.gradle.internal.extensions.stdlib.capitalized
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion

plugins {
id("com.android.application")
alias(libs.plugins.android.application)
id("io.sentry.spotless")
id("io.sentry.jdk-target")
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
alias(libs.plugins.ksp)
alias(libs.plugins.sentry) apply false
alias(libs.plugins.sqldelight)
}

val sentryVersion = libs.versions.sentry.get()

if (providers.gradleProperty("useSagp").isPresent) {
apply(plugin = "io.sentry.android.gradle")
}
Expand Down Expand Up @@ -53,7 +57,7 @@ android {
minSdk = 23
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 2
versionName = project.version.toString()
versionName = sentryVersion

externalNativeBuild {
cmake {
Expand Down Expand Up @@ -104,7 +108,7 @@ android {

signingConfigs {
getByName("debug") {
storeFile = rootProject.file("debug.keystore")
storeFile = file("../../debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
Expand Down Expand Up @@ -146,7 +150,7 @@ android {
val toggleNativeLoggingTask =
project.tasks.register<ToggleNativeLoggingTask>(taskName) {
mergedManifest.set(variant.artifacts.get(SingleArtifact.MERGED_MANIFEST))
rootDir.set(project.rootDir.absolutePath)
repoDir.set(layout.projectDirectory.dir("../..").asFile.canonicalPath)
}
project.afterEvaluate {
(variant as? VariantImpl<*>)?.taskContainer?.assembleTask?.configure {
Expand Down Expand Up @@ -175,19 +179,19 @@ sqldelight {
dependencies {
implementation(kotlin("stdlib-jdk8", getKotlinPluginVersion()))

implementation(projects.sentryAndroid)
implementation(projects.sentryAndroidFragment)
implementation(projects.sentryAndroidNavigation)
implementation(projects.sentryAndroidNavigation3)
implementation(projects.sentryAndroidSqlite)
implementation(projects.sentryAndroidTimber)
implementation(projects.sentryCompose)
implementation(projects.sentryKotlinExtensions)
implementation(projects.sentryOkhttp)
implementation(projects.sentrySpotlight)
implementation("io.sentry:sentry-android:$sentryVersion")
implementation("io.sentry:sentry-android-fragment:$sentryVersion")
implementation("io.sentry:sentry-android-navigation:$sentryVersion")
implementation("io.sentry:sentry-android-navigation3:$sentryVersion")
implementation("io.sentry:sentry-android-sqlite:$sentryVersion")
implementation("io.sentry:sentry-android-timber:$sentryVersion")
implementation("io.sentry:sentry-compose:$sentryVersion")
implementation("io.sentry:sentry-kotlin-extensions:$sentryVersion")
implementation("io.sentry:sentry-okhttp:$sentryVersion")
implementation("io.sentry:sentry-spotlight:$sentryVersion")

// how to exclude androidx if release health feature is disabled
// implementation(projects.sentryAndroid) {
// implementation("io.sentry:sentry-android:$sentryVersion") {
// exclude(group = "androidx.lifecycle", module = "lifecycle-process")
// exclude(group = "androidx.lifecycle", module = "lifecycle-common-java8")
// exclude(group = "androidx.core", module = "core")
Expand Down Expand Up @@ -228,15 +232,15 @@ dependencies {
ksp(libs.androidx.room.compiler)
ksp(libs.androidx.room3.compiler)

debugImplementation(projects.sentryAndroidDistribution)
debugImplementation("io.sentry:sentry-android-distribution:$sentryVersion")
debugImplementation(libs.leakcanary)

testImplementation(libs.google.truth)
testImplementation(libs.kotlin.test.junit)
}

abstract class ToggleNativeLoggingTask : Exec() {
@get:Input abstract val rootDir: Property<String>
@get:Input abstract val repoDir: Property<String>

@get:InputFile abstract val mergedManifest: RegularFileProperty

Expand All @@ -254,7 +258,7 @@ abstract class ToggleNativeLoggingTask : Exec() {
args.add(0, "cmd")
args.add(1, "/c")
}
args.add("${rootDir.get()}/scripts/toggle-codec-logs.sh")
args.add("${repoDir.get()}/scripts/toggle-codec-logs.sh")
args.add(if (value) "enable" else "disable")
commandLine(args)
super.exec()
Expand Down
24 changes: 24 additions & 0 deletions sentry-samples/sentry-samples-android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Gradle properties are per build, so this repeats what the sample needs from the SDK build's
# gradle.properties. settings.gradle.kts reads the SDK version from that file.

org.gradle.jvmargs=-Xmx6g -XX:MaxMetaspaceSize=2g -XX:+CrashOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC
org.gradle.caching=true
org.gradle.parallel=true
org.gradle.configureondemand=true
org.gradle.configuration-cache=true
org.gradle.configuration-cache.parallel=true

android.useAndroidX=true
# AGP 9+ migration opt-outs until we remove kotlin-android plugin and adopt built-in Kotlin.
android.builtInKotlin=false
android.newDsl=false

android.defaults.buildfeatures.renderscript=false
android.defaults.buildfeatures.shaders=false
android.defaults.buildfeatures.aidl=false
android.defaults.buildfeatures.resvalues=false
android.nonTransitiveRClass=true

kotlin.stdlib.default.dependency=false

systemProp.org.gradle.internal.http.socketTimeout=120000
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# sentry-uitest-android-macrobenchmark
# macrobenchmark

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

```bash
./gradlew :sentry-android-integration-tests:sentry-uitest-android-macrobenchmark:connectedBenchmarkAndroidTest
./gradlew -p sentry-samples/sentry-samples-android :macrobenchmark:connectedBenchmarkAndroidTest
```

Results print to the console and are written to
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
plugins {
id("com.android.test")
id("io.sentry.spotless")
id("io.sentry.jdk-target")
alias(libs.plugins.kotlin.android)
}

Expand All @@ -26,7 +28,8 @@ android {
}
}

targetProjectPath = ":sentry-samples:sentry-samples-android"
// The sample app is the root project of this build.
targetProjectPath = ":"
// Run the test in its own process so it measures the target app cold, not itself.
experimentalProperties["android.experimental.self-instrumenting"] = true
}
Expand Down
Loading
Loading