diff --git a/sentry/src/main/java/io/sentry/util/DebugMetaPropertiesApplier.java b/sentry/src/main/java/io/sentry/util/DebugMetaPropertiesApplier.java index 236e962682..a6ff901b90 100644 --- a/sentry/src/main/java/io/sentry/util/DebugMetaPropertiesApplier.java +++ b/sentry/src/main/java/io/sentry/util/DebugMetaPropertiesApplier.java @@ -17,6 +17,7 @@ public static void apply( if (debugMetaProperties != null) { applyToOptions(options, debugMetaProperties); applyBuildTool(options, debugMetaProperties); + applyDistributionOptions(options, debugMetaProperties); } } @@ -89,4 +90,79 @@ private static void applyBuildTool( final @NotNull Properties debugMetaProperties) { return debugMetaProperties.getProperty("io.sentry.build-tool-version"); } + + private static void applyDistributionOptions( + final @NotNull SentryOptions options, final @NotNull List debugMetaProperties) { + for (Properties properties : debugMetaProperties) { + final @Nullable String orgSlug = getDistributionOrgSlug(properties); + final @Nullable String projectSlug = getDistributionProjectSlug(properties); + final @Nullable String orgAuthToken = getDistributionAuthToken(properties); + final @Nullable String buildConfiguration = getDistributionBuildConfiguration(properties); + + if (orgSlug != null + || projectSlug != null + || orgAuthToken != null + || buildConfiguration != null) { + final @NotNull SentryOptions.DistributionOptions distributionOptions = + options.getDistribution(); + + if (orgSlug != null && !orgSlug.isEmpty() && distributionOptions.orgSlug.isEmpty()) { + options.getLogger().log(SentryLevel.DEBUG, "Distribution org slug found: %s", orgSlug); + distributionOptions.orgSlug = orgSlug; + } + + if (projectSlug != null + && !projectSlug.isEmpty() + && distributionOptions.projectSlug.isEmpty()) { + options + .getLogger() + .log(SentryLevel.DEBUG, "Distribution project slug found: %s", projectSlug); + distributionOptions.projectSlug = projectSlug; + } + + if (orgAuthToken != null + && !orgAuthToken.isEmpty() + && distributionOptions.orgAuthToken.isEmpty()) { + options.getLogger().log(SentryLevel.DEBUG, "Distribution org auth token found"); + distributionOptions.orgAuthToken = orgAuthToken; + } + + if (buildConfiguration != null + && !buildConfiguration.isEmpty() + && distributionOptions.buildConfiguration == null) { + options + .getLogger() + .log( + SentryLevel.DEBUG, + "Distribution build configuration found: %s", + buildConfiguration); + distributionOptions.buildConfiguration = buildConfiguration; + } + + // We only process the first properties file that contains distribution options + // to maintain consistency with other properties like proguardUuid + break; + } + } + } + + private static @Nullable String getDistributionOrgSlug( + final @NotNull Properties debugMetaProperties) { + return debugMetaProperties.getProperty("io.sentry.distribution.org-slug"); + } + + private static @Nullable String getDistributionProjectSlug( + final @NotNull Properties debugMetaProperties) { + return debugMetaProperties.getProperty("io.sentry.distribution.project-slug"); + } + + private static @Nullable String getDistributionAuthToken( + final @NotNull Properties debugMetaProperties) { + return debugMetaProperties.getProperty("io.sentry.distribution.auth-token"); + } + + private static @Nullable String getDistributionBuildConfiguration( + final @NotNull Properties debugMetaProperties) { + return debugMetaProperties.getProperty("io.sentry.distribution.build-configuration"); + } } diff --git a/sentry/src/test/java/io/sentry/util/DebugMetaPropertiesApplierTest.kt b/sentry/src/test/java/io/sentry/util/DebugMetaPropertiesApplierTest.kt new file mode 100644 index 0000000000..63c8a62c91 --- /dev/null +++ b/sentry/src/test/java/io/sentry/util/DebugMetaPropertiesApplierTest.kt @@ -0,0 +1,141 @@ +package io.sentry.util + +import io.sentry.SentryOptions +import java.util.Properties +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertNull + +class DebugMetaPropertiesApplierTest { + + @Test + fun `applies distribution options from properties`() { + val properties = Properties() + properties.setProperty("io.sentry.distribution.org-slug", "test-org") + properties.setProperty("io.sentry.distribution.project-slug", "test-project") + properties.setProperty("io.sentry.distribution.auth-token", "test-token") + properties.setProperty("io.sentry.distribution.build-configuration", "debug") + + val options = SentryOptions() + DebugMetaPropertiesApplier.apply(options, listOf(properties)) + + assertEquals("test-org", options.distribution.orgSlug) + assertEquals("test-project", options.distribution.projectSlug) + assertEquals("test-token", options.distribution.orgAuthToken) + assertEquals("debug", options.distribution.buildConfiguration) + } + + @Test + fun `applies partial distribution options from properties`() { + val properties = Properties() + properties.setProperty("io.sentry.distribution.org-slug", "test-org") + properties.setProperty("io.sentry.distribution.project-slug", "test-project") + + val options = SentryOptions() + DebugMetaPropertiesApplier.apply(options, listOf(properties)) + + assertEquals("test-org", options.distribution.orgSlug) + assertEquals("test-project", options.distribution.projectSlug) + assertEquals("", options.distribution.orgAuthToken) + assertNull(options.distribution.buildConfiguration) + } + + @Test + fun `does not override existing distribution options`() { + val properties = Properties() + properties.setProperty("io.sentry.distribution.org-slug", "properties-org") + properties.setProperty("io.sentry.distribution.project-slug", "properties-project") + properties.setProperty("io.sentry.distribution.auth-token", "properties-token") + properties.setProperty("io.sentry.distribution.build-configuration", "properties-config") + + val options = SentryOptions() + options.distribution.orgSlug = "existing-org" + options.distribution.projectSlug = "existing-project" + options.distribution.orgAuthToken = "existing-token" + options.distribution.buildConfiguration = "existing-config" + + DebugMetaPropertiesApplier.apply(options, listOf(properties)) + + assertEquals("existing-org", options.distribution.orgSlug) + assertEquals("existing-project", options.distribution.projectSlug) + assertEquals("existing-token", options.distribution.orgAuthToken) + assertEquals("existing-config", options.distribution.buildConfiguration) + } + + @Test + fun `applies distribution options from first properties file with values`() { + val properties1 = Properties() + val properties2 = Properties() + val properties3 = Properties() + + // properties1 has non-distribution properties so is ignored: + properties1.setProperty("io.sentry.unrelated", "unrelated") + + // properties2 should end up being the ones set + properties2.setProperty("io.sentry.distribution.project-slug", "project-from-second") + + // properties3 also has distribution properties but since properties2 was first they are + // ignored. + properties3.setProperty("io.sentry.distribution.project-slug", "project-from-third") + + val options = SentryOptions() + DebugMetaPropertiesApplier.apply(options, listOf(properties1, properties2, properties3)) + + assertEquals("project-from-second", options.distribution.projectSlug) + } + + @Test + fun `does nothing when properties list is empty`() { + val options = SentryOptions() + val originalOrgSlug = options.distribution.orgSlug + val originalProjectSlug = options.distribution.projectSlug + + DebugMetaPropertiesApplier.apply(options, emptyList()) + + assertEquals(originalOrgSlug, options.distribution.orgSlug) + assertEquals(originalProjectSlug, options.distribution.projectSlug) + } + + @Test + fun `does nothing when properties list is null`() { + val options = SentryOptions() + val originalOrgSlug = options.distribution.orgSlug + val originalProjectSlug = options.distribution.projectSlug + + DebugMetaPropertiesApplier.apply(options, null) + + assertEquals(originalOrgSlug, options.distribution.orgSlug) + assertEquals(originalProjectSlug, options.distribution.projectSlug) + } + + @Test + fun `applies buildConfiguration only when it is the only property set`() { + val properties = Properties() + properties.setProperty("io.sentry.distribution.build-configuration", "debug") + + val options = SentryOptions() + DebugMetaPropertiesApplier.apply(options, listOf(properties)) + + assertEquals("debug", options.distribution.buildConfiguration) + assertEquals("", options.distribution.orgSlug) + assertEquals("", options.distribution.projectSlug) + assertEquals("", options.distribution.orgAuthToken) + } + + @Test + fun `does not apply empty string values`() { + val properties = Properties() + properties.setProperty("io.sentry.distribution.org-slug", "") + properties.setProperty("io.sentry.distribution.project-slug", "") + properties.setProperty("io.sentry.distribution.auth-token", "") + properties.setProperty("io.sentry.distribution.build-configuration", "") + + val options = SentryOptions() + DebugMetaPropertiesApplier.apply(options, listOf(properties)) + + assertEquals("", options.distribution.orgSlug) + assertEquals("", options.distribution.projectSlug) + assertEquals("", options.distribution.orgAuthToken) + assertNull(options.distribution.buildConfiguration) + } +}