Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
89a16e4
build(samples): Prepare the samples to build outside the SDK build
runningcode Oct 27, 2026
a9e0668
Apply suggestion from @romtsn
romtsn Oct 29, 2026
59b6acb
build(samples): Move the Android sample to its own build
runningcode Oct 27, 2026
12236dd
ci(samples): Run the Android sample's check in its own workflow
runningcode Nov 2, 2026
6feed07
ci(samples): Drop the Gradle encryption key and buildSrc cache from t…
runningcode Nov 2, 2026
25b7d71
ci(samples): Check out the default ref without submodules in the Samp…
runningcode Nov 2, 2026
8a10160
build(samples): Link the Android sample's Gradle files to the SDK bui…
runningcode Nov 5, 2026
2387556
ci(samples): Drop the JUnit report step from the Samples workflow
runningcode Nov 5, 2026
c30bc10
build(samples): Bring back make format for every build
runningcode Nov 5, 2026
f37c574
build(samples): Read the sample's SDK version through the catalog
runningcode Nov 5, 2026
07cd03b
ci(samples): Use the setup-gradle version of the other workflows
runningcode Nov 5, 2026
0eb159e
build(samples): Drop the comment on the macrobenchmark's target project
runningcode Nov 5, 2026
6a678c6
build(samples): Drop the header comment from the Android sample's set…
runningcode Nov 5, 2026
070f5c9
build(samples): Move the Android integration tests to their own build
runningcode Oct 27, 2026
da5cf06
ci(samples): Run the Android integration tests' check in the Samples …
runningcode Nov 2, 2026
c42a2e7
build: Drop the root's SAGP declaration and local SAGP repository
runningcode Nov 5, 2026
2d4595f
build(samples): Link the integration tests' Gradle files to the SDK b…
runningcode Nov 5, 2026
0868820
build(samples): Include each integration test project on its own line
runningcode Nov 5, 2026
800282d
build(samples): Keep the integration tests' Develocity and dependency…
runningcode Nov 5, 2026
03cda83
build(samples): Drop the comment on the integration tests' root plugins
runningcode Nov 5, 2026
0825f70
build(samples): Drop the header comment from the integration tests' s…
runningcode Nov 5, 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/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
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,23 @@ private val PUBLISHED_JAVA_VERSION = JavaVersion.VERSION_1_8
* archives are checked for it
* - published Android modules main code targets Java 1.8
* - minSdk is set for Android libraries
* - javac warnings fail the build
*/
class JdkTargetConvention : Plugin<Project> {
override fun apply(project: Project) {
project.tasks.withType(JavaCompile::class.java).configureEach {
options.compilerArgs.addAll(
listOf(
"-Xlint:all",
"-Werror",
"-Xlint:-classfile",
"-Xlint:-processing",
"-Xlint:-try",
"-Xlint:-options",
)
)
}

project.plugins.withType(JavaBasePlugin::class.java) {
project.extensions.getByType(JavaPluginExtension::class.java).toolchain {
languageVersion.set(BUILD_JDK)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
package io.sentry.gradle

import java.net.URI
import java.nio.file.FileSystems
import java.nio.file.Files
Expand Down
10 changes: 1 addition & 9 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,14 @@ 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
}

buildscript {
repositories {
google()
}
dependencies {
classpath(Config.BuildPlugins.androidGradle)

// add classpath of sentry android gradle plugin
// classpath("io.sentry:sentry-android-gradle-plugin:{version}")

classpath(libs.commons.compress)
}
}
Expand All @@ -50,9 +45,6 @@ allprojects {
TestLogEvent.FAILED
)
}
withType<JavaCompile>().configureEach {
options.compilerArgs.addAll(arrayOf("-Xlint:all", "-Werror", "-Xlint:-classfile", "-Xlint:-processing", "-Xlint:-try", "-Xlint:-options"))
}
}
}

Expand Down
5 changes: 0 additions & 5 deletions buildSrc/src/main/java/Config.kt
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@

object Config {
val AGP = System.getenv("VERSION_AGP") ?: "9.4.0"
val kotlinStdLib = "stdlib-jdk8"
val kotlinStdLibVersionAndroid = "1.9.24"
val kotlinTestJunit = "test-junit"

object BuildPlugins {
val androidGradle = "com.android.tools.build:gradle:$AGP"
}

object Android {
val abiFilters = listOf("x86", "armeabi-v7a", "x86_64", "arm64-v8a")

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
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ retrofit = "2.9.0"
room2 = "2.8.4"
room3 = "3.0.0-rc01"
sagp = "6.13.0"
# Compile-time only, for the AGP types the build-logic convention plugins use. The AGP that
# actually runs the build comes from the root buildscript (Config.AGP, overridable via VERSION_AGP).
# The AGP matrix job overrides this with the VERSION_AGP env var, through each build's settings.
agp = "9.4.0"
sqlite = "2.6.2"
sqliteRc = "2.7.0-rc01" # Required by Room3 3.0.0-rc*
Expand All @@ -62,6 +61,7 @@ compileSdkMinor = "2"
minSdk = "21"

[plugins]
android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-spring = { id = "org.jetbrains.kotlin.plugin.spring", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
Expand Down
2 changes: 1 addition & 1 deletion scripts/test-ui-android.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ out_dir=$1
device_dir=/sdcard/Download/sentry_replay_snapshots

test_status=0
./gradlew sentry-android-integration-tests:sentry-uitest-android:connectedReleaseAndroidTest || test_status=$?
./gradlew -p sentry-android-integration-tests :sentry-uitest-android:connectedReleaseAndroidTest || test_status=$?

mkdir -p "$out_dir"
if adb shell test -d "$device_dir"; then
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
@@ -1,4 +1,5 @@
import io.gitlab.arturbosch.detekt.Detekt
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion

plugins {
id("com.android.application")
Expand All @@ -8,6 +9,8 @@ plugins {
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 @@ -37,20 +40,18 @@ android {
buildFeatures { compose = true }
composeOptions { kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() }
androidComponents.beforeVariants {
it.enable = !Config.Android.shouldSkipDebugVariant(it.buildType)
it.enable = it.buildType != "debug"
}
}

dependencies {
implementation(
kotlin(Config.kotlinStdLib, org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
Comment thread
runningcode marked this conversation as resolved.
Resolved
)
implementation(kotlin("stdlib-jdk8", getKotlinPluginVersion()))
implementation(libs.androidx.activity.compose)
implementation(libs.androidx.compose.foundation)
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
Loading
Loading