diff --git a/.craft.yml b/.craft.yml index cce5557d9..3c14ba9df 100644 --- a/.craft.yml +++ b/.craft.yml @@ -13,3 +13,4 @@ targets: sdks: maven:io.sentry:sentry-android-gradle-plugin: maven:io.sentry:sentry-kotlin-compiler-plugin: + maven:io.sentry:sentry-snapshots-runtime: diff --git a/CHANGELOG.md b/CHANGELOG.md index 117f17c78..e05b270fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Features + +- Add `@SentrySnapshot` runtime annotation for configuring the per-snapshot diff threshold, published as `io.sentry:sentry-snapshots-runtime` ([EME-1055](https://linear.app/getsentry/issue/EME-1055)) + ## 6.4.0 ### Dependencies diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 46d2472bb..5cde3d1f6 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -31,6 +31,7 @@ composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version = "2.1. [libraries] junit = { group = "junit", name = "junit", version = "4.13.2" } +androidxAnnotation = { group = "androidx.annotation", name = "annotation", version = "1.9.1" } proguard = { group = "com.guardsquare", name = "proguard-gradle", version = "7.5.0" } # this allows us to develop against a fixed version of Gradle, as opposed to depending on the # locally available version. kotlin-gradle-plugin follows the same approach. diff --git a/sentry-snapshots-runtime/Makefile b/sentry-snapshots-runtime/Makefile new file mode 100644 index 000000000..8cc671a3f --- /dev/null +++ b/sentry-snapshots-runtime/Makefile @@ -0,0 +1,10 @@ +.PHONY: compile all dist + +compile: + ./gradlew assemble + +# build distribution artifacts +dist: + ./gradlew distZip --no-parallel + +all: compile dist diff --git a/sentry-snapshots-runtime/build.gradle.kts b/sentry-snapshots-runtime/build.gradle.kts new file mode 100644 index 000000000..28e54139c --- /dev/null +++ b/sentry-snapshots-runtime/build.gradle.kts @@ -0,0 +1,58 @@ +plugins { + alias(libs.plugins.kotlin) + id("distribution") + alias(libs.plugins.mavenPublish) + alias(libs.plugins.spotless) +} + +spotless { + kotlin { + ktfmt(libs.versions.ktfmt.get()).googleStyle() + target("**/*.kt") + } + kotlinGradle { + target("**/*.kts") + ktfmt(libs.versions.ktfmt.get()).googleStyle() + } +} + +val sep = File.separator + +distributions { + main { + contents { + from("build${sep}libs") + from("build${sep}publications${sep}maven") + } + } +} + +listOf("distZip", "distTar").forEach { taskName -> + tasks.named(taskName) { + dependsOn("publishToMavenLocal") + onlyIf { inputs.sourceFiles.isEmpty.not().also { require(it) { "No distribution to zip." } } } + } +} + +dependencies { compileOnly(libs.androidxAnnotation) } + +plugins.withId("com.vanniktech.maven.publish.base") { + configure { + repositories { + maven { + name = "mavenTestRepo" + url = file("${rootProject.projectDir}/../build/mavenTestRepo").toURI() + } + maven { + name = "mavenCentralSnapshots" + url = uri("https://central.sonatype.com/repository/maven-snapshots/") + credentials { + username = findProperty("mavenCentralUsername")?.toString() + password = findProperty("mavenCentralPassword")?.toString() + } + } + } + } +} + +kotlin { jvmToolchain(11) } diff --git a/sentry-snapshots-runtime/gradle.properties b/sentry-snapshots-runtime/gradle.properties new file mode 100644 index 000000000..96056cc73 --- /dev/null +++ b/sentry-snapshots-runtime/gradle.properties @@ -0,0 +1,24 @@ +org.gradle.jvmargs=-Xmx4g -XX:MaxMetaspaceSize=1536m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -XX:+UseParallelGC -XX:+CrashOnOutOfMemoryError +org.gradle.caching=true +org.gradle.parallel=true + +GROUP = io.sentry +POM_ARTIFACT_ID = sentry-snapshots-runtime +VERSION_NAME = 6.4.0 + +# publication pom properties +POM_NAME=Sentry Snapshots Runtime +POM_DESCRIPTION=Runtime annotations for configuring Sentry snapshot tests +POM_URL=https://github.com/getsentry/sentry-android-gradle-plugin +POM_SCM_URL=https://github.com/getsentry/sentry-android-gradle-plugin +POM_SCM_CONNECTION=scm:git:git://github.com/getsentry/sentry-android-gradle-plugin.git +POM_SCM_DEV_CONNECTION=scm:git:ssh://git@github.com/getsentry/sentry-android-gradle-plugin.git + +POM_LICENCE_NAME=MIT +POM_LICENCE_URL=https://github.com/getsentry/sentry-android-gradle-plugin/blob/main/LICENSE + +POM_DEVELOPER_ID=getsentry +POM_DEVELOPER_NAME=Sentry Team and Contributors +POM_DEVELOPER_URL=https://github.com/getsentry/ + +RELEASE_SIGNING_ENABLED=false diff --git a/sentry-snapshots-runtime/settings.gradle.kts b/sentry-snapshots-runtime/settings.gradle.kts new file mode 100644 index 000000000..491d12970 --- /dev/null +++ b/sentry-snapshots-runtime/settings.gradle.kts @@ -0,0 +1,10 @@ +rootProject.name = ("sentry-snapshots-runtime") + +dependencyResolutionManagement { + repositories { + google() + mavenCentral() + } + versionCatalogs.create("libs") { from(files("../gradle/libs.versions.toml")) } + repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) +} diff --git a/sentry-snapshots-runtime/src/main/kotlin/io/sentry/snapshots/runtime/SentrySnapshot.kt b/sentry-snapshots-runtime/src/main/kotlin/io/sentry/snapshots/runtime/SentrySnapshot.kt new file mode 100644 index 000000000..6c821abb1 --- /dev/null +++ b/sentry-snapshots-runtime/src/main/kotlin/io/sentry/snapshots/runtime/SentrySnapshot.kt @@ -0,0 +1,22 @@ +package io.sentry.snapshots.runtime + +import androidx.annotation.FloatRange + +/** + * Configures how Sentry compares this preview snapshot against the baseline. + * + * Apply alongside `@Preview` on a composable to override the global diff threshold on a + * per-snapshot basis. + */ +@Retention(AnnotationRetention.BINARY) +@Target(AnnotationTarget.FUNCTION) +annotation class SentrySnapshot( + /** + * Minimum pixel-difference percentage required to report this snapshot as changed. Differences + * below this value are treated as unchanged. + * + * Range: `0.0`..`1.0`. Example: `0.01f` reports a change only when at least 1% of pixels differ. + * Defaults to `0f` (report any difference). + */ + @FloatRange(from = 0.0, to = 1.0) val diffThreshold: Float = 0f +) diff --git a/settings.gradle.kts b/settings.gradle.kts index 300a0b391..0e8912dac 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -46,3 +46,9 @@ includeBuild("sentry-kotlin-compiler-plugin") { substitute(module("io.sentry:sentry-kotlin-compiler-plugin")).using(project(":")) } } + +includeBuild("sentry-snapshots-runtime") { + dependencySubstitution { + substitute(module("io.sentry:sentry-snapshots-runtime")).using(project(":")) + } +}