Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
8f1c695
build(samples): Move the Android sample to its own build
runningcode Oct 27, 2026
4c6e2cd
ci(samples): Run the Android sample's check in its own workflow
runningcode Nov 2, 2026
931259c
ci(samples): Drop the Gradle encryption key and buildSrc cache from t…
runningcode Nov 2, 2026
21551f0
ci(samples): Check out the default ref without submodules in the Samp…
runningcode Nov 2, 2026
7f922ae
build(samples): Link the Android sample's Gradle files to the SDK bui…
runningcode Nov 5, 2026
d5f25ea
ci(samples): Drop the JUnit report step from the Samples workflow
runningcode Nov 5, 2026
6d06ad6
build(samples): Bring back make format for every build
runningcode Nov 5, 2026
175e10b
build(samples): Read the sample's SDK version through the catalog
runningcode Nov 5, 2026
645b4cf
ci(samples): Use the setup-gradle version of the other workflows
runningcode Nov 5, 2026
306b092
build(samples): Drop the comment on the macrobenchmark's target project
runningcode Nov 5, 2026
84290c7
build(samples): Drop the header comment from the Android sample's set…
runningcode Nov 5, 2026
c835065
build(samples): Move the Android integration tests to their own build
runningcode Oct 27, 2026
ce6fb57
ci(samples): Run the Android integration tests' check in the Samples …
runningcode Nov 2, 2026
d6eff98
build: Drop the root's SAGP declaration and local SAGP repository
runningcode Nov 5, 2026
96f4e02
build(samples): Link the integration tests' Gradle files to the SDK b…
runningcode Nov 5, 2026
9b47410
build(samples): Include each integration test project on its own line
runningcode Nov 5, 2026
8dd0deb
build(samples): Keep the integration tests' Develocity and dependency…
runningcode Nov 5, 2026
2565610
build(samples): Drop the comment on the integration tests' root plugins
runningcode Nov 5, 2026
27ec18e
build(samples): Drop the header comment from the integration tests' s…
runningcode Nov 5, 2026
f9a4d8d
Merge pull request #6393 from getsentry/no/android-integration-tests-…
runningcode Nov 6, 2026
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: 2 additions & 2 deletions .claude/skills/create-java-pr/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ Derive the branch name from the changes being made. Use `feat/`, `fix/`, `ref/`,
## Step 2: Format Code and Regenerate API Files

```bash
./gradlew spotlessApply updateKotlinAbi
make format api
```

This is **required** before every PR in this repo. It formats all Java/Kotlin code via Spotless and regenerates the `.api` binary compatibility files.
This is **required** before every PR in this repo. It formats all Java/Kotlin code via Spotless, including the separate builds the root `spotlessApply` doesn't reach, and regenerates the `.api` binary compatibility files.

If the command fails, diagnose and fix the issue before continuing.

Expand Down
6 changes: 5 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ registries:
password: dummy # Required by dependabot
updates:
- package-ecosystem: "gradle"
directory: "/"
# The root build doesn't include the separate sample and test builds.
directories:
- "/"
- "/sentry-samples/sentry-samples-android"
- "/sentry-android-integration-tests"
registries:
- gradle-plugin-portal
schedule:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/agp-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ jobs:
disable-spellchecker: true
emulator-options: -no-snapshot-save -no-window -gpu swiftshader_indirect -noaudio -no-boot-anim -camera-back none
disk-size: 4096M
script: ./gradlew sentry-android-integration-tests:sentry-uitest-android:connectedReleaseAndroidTest -Denvironment=github --daemon
script: ./gradlew -p sentry-android-integration-tests :sentry-uitest-android:connectedReleaseAndroidTest -Denvironment=github --daemon

- name: Upload test results
if: always()
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/format-code.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ jobs:
uses: gradle/actions/setup-gradle@8da46b539cd8fe6ab27ca75128919a18d757604c # v6.4.1

- name: Format with spotlessApply
run: ./gradlew spotlessApply
run: make format

# 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
2 changes: 1 addition & 1 deletion .github/workflows/integration-tests-size.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,6 @@ jobs:
uses: gradle/actions/setup-gradle@8da46b539cd8fe6ab27ca75128919a18d757604c # v6.4.1

- name: Size Analysis
run: ./gradlew :sentry-android-integration-tests:test-app-size:bundleRelease
run: ./gradlew -p sentry-android-integration-tests :test-app-size:bundleRelease
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
50 changes: 50 additions & 0 deletions .github/workflows/samples.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
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
- name: sentry-android-integration-tests
path: sentry-android-integration-tests

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@8da46b539cd8fe6ab27ca75128919a18d757604c # v6.4.1

- 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/*
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
15 changes: 9 additions & 6 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ The project uses **Gradle** with Kotlin DSL. Key build files:
## Essential Commands

```bash
# Format code and regenerate .api files (REQUIRED before committing)
./gradlew spotlessApply updateKotlinAbi
# Format code in every build and regenerate .api files (REQUIRED before committing)
make format api

# Run all tests and linter
./gradlew check
Expand All @@ -59,11 +59,14 @@ resolves the per-module test task, including integration test suites, for you.

### Android-Specific Commands
```bash
# Assemble Android test APKs
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest
# Assemble Android test APKs, in a separate Gradle build that includes this one
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:assembleRelease :sentry-uitest-android:assembleAndroidTest

# 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 All @@ -74,7 +77,7 @@ resolves the per-module test task, including integration test suites, for you.
3. **Use todo tracking**: Work through todo items, marking them as complete as you go
4. **High-level communication**: Give high-level explanations of changes made, not step-by-step descriptions
5. **Simplicity first**: Make every task and code change as simple as possible. Avoid massive or complex changes. Impact as little code as possible.
6. **Format and regenerate**: Once done, format code and regenerate .api files: `./gradlew spotlessApply updateKotlinAbi`
6. **Format and regenerate**: Once done, format code and regenerate .api files: `make format api`
7. **Propose commit**: As final step, git stage relevant files and propose (but not execute) a single git commit command. This applies to implementation work; when the task is to open a PR, the `create-java-pr` skill takes over from here and does commit, push, and open it.

## Repository Skills
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
6 changes: 1 addition & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,7 @@ To format the changed code and make CI happy you can run:
make format
```

or

```shell
./gradlew spotlessApply
```
`./gradlew spotlessApply` alone formats only the SDK build, not the separate builds it doesn't include, such as the Android sample.

# Binary compatibility validation

Expand Down
14 changes: 11 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
.PHONY: all clean compile javadocs dryRelease update checkFormat api assembleUiTestRelease assembleUiTestCriticalRelease runUiTestCritical check preMerge publish
.PHONY: all clean compile javadocs dryRelease update format checkFormat api assembleUiTestRelease assembleUiTestCriticalRelease runUiTestCritical check preMerge publish

all: stop clean javadocs compile
assembleUiTests: assembleUiTestRelease
Expand All @@ -25,21 +25,29 @@ dryRelease:
update:
./gradlew dependencyUpdates -Drevision=release

# Spotless formats the code. The root spotlessApply doesn't reach the separate builds.
format:
./gradlew spotlessApply
./gradlew -p sentry-samples/sentry-samples-android spotlessApply
./gradlew -p sentry-android-integration-tests spotlessApply

# Spotless check's code
checkFormat:
./gradlew spotlessJavaCheck spotlessKotlinCheck
./gradlew -p sentry-samples/sentry-samples-android spotlessJavaCheck spotlessKotlinCheck
./gradlew -p sentry-android-integration-tests spotlessJavaCheck spotlessKotlinCheck

# Binary compatibility validator
api:
./gradlew updateKotlinAbi

# Assemble release and Android test apk of the uitest-android module
assembleUiTestRelease:
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:assembleRelease :sentry-uitest-android:assembleAndroidTest

# Assemble release of the uitest-android-critical module
assembleUiTestCriticalRelease:
./gradlew :sentry-android-integration-tests:sentry-uitest-android-critical:assembleRelease
./gradlew -p sentry-android-integration-tests :sentry-uitest-android-critical:assembleRelease

# Run Maestro tests for the uitest-android-critical module
runUiTestCritical:
Expand Down
4 changes: 0 additions & 4 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ plugins {
alias(libs.plugins.gradle.versions) apply false
alias(libs.plugins.spring.dependency.management) apply false
id("io.sentry.javadoc.aggregate")
alias(libs.plugins.sentry) apply false
alias(libs.plugins.android.application) apply false
}

Expand All @@ -34,9 +33,6 @@ buildscript {
google()
}
dependencies {
// add classpath of sentry android gradle plugin
// classpath("io.sentry:sentry-android-gradle-plugin:{version}")

classpath(libs.commons.compress)
}
}
Expand Down
1 change: 0 additions & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ 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.experimental.lint.version=9.4.0

android.disableAgpUpgradePrompt=true

Expand Down
6 changes: 6 additions & 0 deletions sentry-android-integration-tests/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
# Android performance-impact and integration tests

This directory is a separate Gradle build that includes the SDK build, so run its tasks with
`./gradlew -p sentry-android-integration-tests <task>`. The SDK build doesn't include it, so
`./gradlew` from the repository root doesn't build, lint or format these apps.
`gradle.properties`, `gradlew`, `gradle/wrapper` and `gradle/gradle-daemon-jvm.properties` are
symlinks to the SDK build's, so both builds use the same Gradle, JDK and settings.

* [Espresso-based UI tests](./sentry-uitest-android) - run within SauceLabs (see /.sauce/*.yml)
* Also used for compatibility test matrix against new AGP versions
9 changes: 9 additions & 0 deletions sentry-android-integration-tests/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugins {
alias(libs.plugins.android.application) apply false
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.errorprone) apply false
alias(libs.plugins.detekt) apply false
alias(libs.plugins.gradle.versions) apply false
alias(libs.plugins.sentry) apply false
}
1 change: 1 addition & 0 deletions sentry-android-integration-tests/gradle.properties
1 change: 1 addition & 0 deletions sentry-android-integration-tests/gradle/wrapper
1 change: 1 addition & 0 deletions sentry-android-integration-tests/gradlew

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ plugins {
id("com.android.application")
alias(libs.plugins.kotlin.android)
alias(libs.plugins.kotlin.compose)
id("io.sentry.spotless")
id("io.sentry.jdk-target")
}

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

android {
compileSdk = libs.versions.compileSdk.get().toInt()
compileSdkMinor = libs.versions.compileSdkMinor.get().toInt()
Expand Down Expand Up @@ -47,7 +51,7 @@ dependencies {
implementation(libs.androidx.compose.material3)
implementation(libs.androidx.constraintlayout)
implementation(libs.androidx.core)
implementation(projects.sentryAndroidCore)
implementation("io.sentry:sentry-android-core:$sentryVersion")
}

tasks.withType<Detekt>().configureEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ By default the envelopes sent to relay are caught by a mock server which allows

# How to use

Simply run `./gradlew connectedCheck` to run all ui tests of all modules (requires a connected device, either physical or an emulator).
Simply run `./gradlew -p sentry-android-integration-tests connectedCheck` to run all ui tests of all modules (requires a connected device, either physical or an emulator).

# SauceLabs
To run on saucelabs execute following commands (need also `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` environment variables):
For End 2 End:
```
./gradlew :sentry-android-integration-tests:sentry-uitest-android:assembleRelease :sentry-android-integration-tests:sentry-uitest-android:assembleAndroidTest
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:assembleRelease :sentry-uitest-android:assembleAndroidTest
saucectl run -c .sauce/sentry-uitest-android-end2end.yml
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ plugins {
alias(libs.plugins.errorprone)
alias(libs.plugins.gradle.versions)
alias(libs.plugins.detekt)
id("io.sentry.spotless")
id("io.sentry.jdk-target")
}

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

android {
compileSdk = libs.versions.compileSdk.get().toInt()
compileSdkMinor = libs.versions.compileSdkMinor.get().toInt()
Expand Down Expand Up @@ -46,7 +50,7 @@ android {

signingConfigs {
getByName("debug") {
storeFile = rootProject.file("debug.keystore")
storeFile = file("../../debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
Expand Down Expand Up @@ -90,10 +94,10 @@ dependencies {
implementation(kotlin("stdlib-jdk8", getKotlinPluginVersion()))

if (applySentryIntegrations) {
implementation(projects.sentryAndroid)
implementation(projects.sentryCompose)
implementation("io.sentry:sentry-android:$sentryVersion")
implementation("io.sentry:sentry-compose:$sentryVersion")
} else {
implementation(projects.sentryAndroidCore)
implementation("io.sentry:sentry-android-core:$sentryVersion")
}
implementation(libs.androidx.appcompat)
implementation(libs.androidx.activity.compose)
Expand All @@ -112,7 +116,7 @@ dependencies {
errorprone(libs.nullaway)

androidTestUtil(libs.androidx.test.orchestrator)
androidTestImplementation(projects.sentryTestSupport)
androidTestImplementation("io.sentry:sentry-test-support:$sentryVersion")
androidTestImplementation(libs.androidx.test.core.ktx)
androidTestImplementation(libs.androidx.test.espresso.core)
androidTestImplementation(libs.androidx.test.ext.junit)
Expand All @@ -132,6 +136,12 @@ tasks.withType<JavaCompile>().configureEach {
}
}

detekt {
buildUponDefaultConfig = true
allRules = true
config.setFrom(file("../../detekt.yml"))
}

tasks.withType<Detekt>().configureEach {
// Target version of the generated JVM bytecode. It is used for type resolution.
jvmTarget = JavaVersion.VERSION_1_8.toString()
Expand Down
Loading
Loading