From 22b3ebf543c54413cf363b22286c076523685c19 Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Wed, 12 Jun 2024 15:59:49 +0200 Subject: [PATCH 1/9] dev version to 1.1.3-SNAPSHOT --- buildSrc/src/main/kotlin/Versions.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index aa29b78..787103c 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -1,6 +1,6 @@ @Suppress("ConstPropertyName", "MemberVisibilityCanBePrivate") object Versions { - const val project = "1.1.2" + const val project = "1.1.3-SNAPSHOT" object Plugins { const val licenseReport = "2.5" From 13cc873891a2912e8faabcddd7a87ffb59c04eca Mon Sep 17 00:00:00 2001 From: Bastiaan Date: Wed, 12 Jun 2024 15:59:49 +0200 Subject: [PATCH 2/9] Fix set project version to 1.1.3-SNAPSHOT --- radar-commons-gradle/build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/radar-commons-gradle/build.gradle.kts b/radar-commons-gradle/build.gradle.kts index 5d9a9d2..b24acd5 100644 --- a/radar-commons-gradle/build.gradle.kts +++ b/radar-commons-gradle/build.gradle.kts @@ -176,7 +176,7 @@ tasks.withType { // They should be copied from the Versions.kt file directly to maintain consistency. @Suppress("ConstPropertyName", "MemberVisibilityCanBePrivate") object Versions { - const val project = "1.1.3" + const val project = "1.1.3-SNAPSHOT" object Plugins { const val licenseReport = "2.5" From 08c63b4d12195643850aa4012c1641e8b56f7e63 Mon Sep 17 00:00:00 2001 From: pvannierop Date: Mon, 2 Sep 2024 09:50:41 +0200 Subject: [PATCH 3/9] Fix pgp secret key name for publish GitHub action --- .github/workflows/publish_snapshots.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish_snapshots.yml b/.github/workflows/publish_snapshots.yml index 8113752..a0d0829 100644 --- a/.github/workflows/publish_snapshots.yml +++ b/.github/workflows/publish_snapshots.yml @@ -36,7 +36,7 @@ jobs: env: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - run: ./gradlew -Psigning.gnupg.keyName=CBEF2CF0 -Psigning.gnupg.executable=gpg -Psigning.gnupg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} publish + run: ./gradlew -Psigning.gnupg.keyName=${{ secrets.OSSRH_GPG_SECRET_KEY_NAME }} -Psigning.gnupg.executable=gpg -Psigning.gnupg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} publish - name: Plugin has SNAPSHOT version run: ./gradlew :radar-commons-gradle:properties | grep '^version:.*-SNAPSHOT$' @@ -45,4 +45,4 @@ jobs: env: OSSRH_USER: ${{ secrets.OSSRH_USER }} OSSRH_PASSWORD: ${{ secrets.OSSRH_PASSWORD }} - run: ./gradlew -Psigning.gnupg.keyName=CBEF2CF0 -Psigning.gnupg.executable=gpg -Psigning.gnupg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} :radar-commons-gradle:publish + run: ./gradlew -Psigning.gnupg.keyName=${{ secrets.OSSRH_GPG_SECRET_KEY_NAME }} -Psigning.gnupg.executable=gpg -Psigning.gnupg.passphrase=${{ secrets.OSSRH_GPG_SECRET_KEY_PASSWORD }} :radar-commons-gradle:publish From 68980f31950b2adf1b1b34c2934fee53f7e44318 Mon Sep 17 00:00:00 2001 From: pvannierop Date: Fri, 13 Sep 2024 17:25:29 +0200 Subject: [PATCH 4/9] Impl. support for Sentry monitoring --- radar-commons-gradle/README.md | 118 ++++++++++++++++++ radar-commons-gradle/build.gradle.kts | 2 + .../gradle/plugin/RadarKotlinPlugin.kt | 31 +++++ 3 files changed, 151 insertions(+) diff --git a/radar-commons-gradle/README.md b/radar-commons-gradle/README.md index a860f24..c0f674c 100644 --- a/radar-commons-gradle/README.md +++ b/radar-commons-gradle/README.md @@ -2,6 +2,17 @@ A Gradle plugin to do some common RADAR-base tasks. + +* [radar-commons-gradle](#radar-commons-gradle) + * [Usage](#usage) + * [radar-commons-gradle plugin](#radar-commons-gradle-plugin) + * [radarKotlin extension](#radarkotlin-extension) + * [Enable logging with log4j2](#enable-logging-with-log4j2) + * [Enable monitoring with Sentry](#enable-monitoring-with-sentry) + * [Enable Sentry source context](#enable-sentry-source-context) + * [Customizing Sentry configuration](#customizing-sentry-configuration) + + ## Usage Add the following block to `settings.gradle.kts` to get access to the RADAR-base plugins. @@ -51,6 +62,13 @@ subprojects { kotlinVersion.set(Versions.Plugins.kotlin) // already has a default value junitVersion.set(Versions.junit) // already has a default value ktlintVersion.set(Versions.ktlint) // already has a default value + slf4jVersion.set(Versions.slf4j) // already has a default value + // log4j2Version.set(Versions.log4j2) // setting this will enable log4j2 + // sentryVersion.set(Versions.sentry) // setting this will enable Sentry monitoring + // sentryEnabled.set(false) // setting this to true will enable Sentry monitoring + // sentrySourceContextToken.set("") // setting this will upload the source code context to Sentry + // sentryOrganization.set("radar-base") // already has a default value, only needed when setting 'sentrySourceContextToken' + // sentryProject.set("") // already has a default value, only needed when setting 'sentrySourceContextToken' } // Both values are required to be set to use radar-publishing. @@ -68,3 +86,103 @@ subprojects { } } ``` + +## radar-commons-gradle plugin + +This plugin provides the basics for RADAR-base projects. + +### radarKotlin extension + +#### Enable logging with log4j2 + +By default, no logging implementation is added to projects (only the slf4j interface is included). To enable log4j2, add +the following to your root project configurations: + +```gradle +... +subprojects { + ... + radarKotlin { + log4j2Version.set(Versions.log4j2) + } + ... +} +``` + +#### Enable monitoring with Sentry + +1. Activate log4j2 logging (see [above](#enable-logging-with-log4j2)) +2. Activate Sentry in the _radarKotlin_ extension: + +```gradle +... +subprojects { + ... + radarKotlin { + sentryEnabled.set(true) + } + ... +} +``` + +3. Add a Sentry log Appender to the `log4j2.xml` configuration file to `src/main/resources`. For example: + +```xml + + + + + + + + + + + + + + + + +``` + +4. Set the `SENTRY_DSN` environment variable at runtime to the DSN of your Sentry project. + +#### Enable Sentry source context + +Sentry can be configured to show the source code context of the error. For this to work, source code can be uploaded +to the target sentry organization and project during the build phase. To enable this, set the following values: + +```gradle +... +subprojects { + ... + radarKotlin { + sentrySourceContextToken.set("my-token") + sentryOrganization.set("my-organization") + sentryProject.set("my-project") + } + ... +} +``` + +NOTE: The organization and project must correspond to the values for the monitoring environment in Sentry. The +organization and project are encooded in Sentry OAuth token. + +#### Customizing Sentry configuration + +In a project that uses radar-commons-gradle, the Sentry configuration can be customized by using the _sentry_ extension +like for instance: + +build.gradle.kts + +```gradle +sentry { + debug = true + ... +} +... + +Additional information on config options: https://docs.sentry.io/platforms/java/guides/log4j2/gradle/ diff --git a/radar-commons-gradle/build.gradle.kts b/radar-commons-gradle/build.gradle.kts index b24acd5..aa0919f 100644 --- a/radar-commons-gradle/build.gradle.kts +++ b/radar-commons-gradle/build.gradle.kts @@ -30,6 +30,7 @@ dependencies { implementation("io.github.gradle-nexus:publish-plugin:${Versions.Plugins.publishPlugin}") implementation("org.jlleitschuh.gradle:ktlint-gradle:${Versions.ktlint}") implementation("com.github.jk1.dependency-license-report:com.github.jk1.dependency-license-report.gradle.plugin:${Versions.Plugins.licenseReport}") + implementation("io.sentry.jvm.gradle:io.sentry.jvm.gradle.gradle.plugin:${Versions.sentry}") } gradlePlugin { @@ -209,4 +210,5 @@ object Versions { const val guava = "32.1.1-jre" const val gradleVersionsPlugin = "0.50.0" const val ktlint = "12.0.3" + const val sentry = "4.10.0" } diff --git a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt index b3c4f05..4beebc8 100644 --- a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt +++ b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt @@ -1,6 +1,8 @@ package org.radarbase.gradle.plugin import com.github.jk1.license.LicenseReportPlugin +import io.sentry.android.gradle.extensions.SentryPluginExtension +import io.sentry.jvm.gradle.SentryJvmPlugin import org.gradle.api.Plugin import org.gradle.api.Project import org.gradle.api.plugins.ApplicationPlugin @@ -42,6 +44,10 @@ interface RadarKotlinExtension { val log4j2Version: Property val slf4jVersion: Property val ktlintVersion: Property + val sentryEnabled: Property + val sentryOrganization: Property + val sentryProject: Property + val sentrySourceContextToken: Property } class RadarKotlinPlugin : Plugin { @@ -53,11 +59,18 @@ class RadarKotlinPlugin : Plugin { junitVersion.convention(Versions.junit) ktlintVersion.convention(Versions.ktlint) slf4jVersion.convention(Versions.ktlint) + sentryEnabled.convention(false) + sentryOrganization.convention("radar-base") + sentryProject.convention(project.name) + sentrySourceContextToken.convention("") } apply(plugin = "kotlin") apply() + // SentryJvmPlugin will be removed in afterEvaluate when sentryEnabled == false. + apply() + repositories { mavenCentral { mavenContent { @@ -162,6 +175,20 @@ class RadarKotlinPlugin : Plugin { implementation("org.slf4j:slf4j-api:${extension.slf4jVersion.get()}") } } + if (extension.sentryEnabled.get()) { + val sentry = extensions.get("sentry") as SentryPluginExtension + sentry.org.set(extension.sentryOrganization) + sentry.projectName.set(extension.sentryProject) + if (extension.sentrySourceContextToken.isPresent && + extension.sentrySourceContextToken.get().isNotEmpty() + ) { + // Passing the source context token will activate upload of our source code to Sentry. + sentry.includeSourceContext.set(true) + sentry.authToken.set(extension.sentrySourceContextToken) + } + } else { + plugins.removeIf({ it is SentryJvmPlugin }) + } if (extension.log4j2Version.isPresent) { dependencies { val log4j2Version = extension.log4j2Version.get() @@ -171,6 +198,10 @@ class RadarKotlinPlugin : Plugin { runtimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl:$log4j2Version") runtimeOnly("org.apache.logging.log4j:log4j-core:$log4j2Version") runtimeOnly("org.apache.logging.log4j:log4j-jul:$log4j2Version") + if (extension.sentryEnabled.get()) { + val annotationProcessor by configurations + annotationProcessor("org.apache.logging.log4j:log4j-core:$log4j2Version") + } } else { val testRuntimeOnly by configurations testRuntimeOnly("org.apache.logging.log4j:log4j-slf4j2-impl:$log4j2Version") From 6a82a0d35991f7f9855245dfeae3ea10330116cc Mon Sep 17 00:00:00 2001 From: pvannierop Date: Mon, 23 Sep 2024 15:13:02 +0200 Subject: [PATCH 5/9] Fix import --- .../radarbase/data/AvroDatumEncoderTest.java | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/radar-commons/src/test/java/org/radarbase/data/AvroDatumEncoderTest.java b/radar-commons/src/test/java/org/radarbase/data/AvroDatumEncoderTest.java index 410ea22..8a110cc 100644 --- a/radar-commons/src/test/java/org/radarbase/data/AvroDatumEncoderTest.java +++ b/radar-commons/src/test/java/org/radarbase/data/AvroDatumEncoderTest.java @@ -16,10 +16,6 @@ package org.radarbase.data; -import java.io.IOException; -import java.util.Arrays; -import java.util.UUID; -import java.util.concurrent.ThreadLocalRandom; import junit.framework.TestCase; import org.apache.avro.specific.SpecificData; import org.radarbase.topic.AvroTopic; @@ -29,9 +25,22 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; +import java.util.UUID; +import java.util.concurrent.ThreadLocalRandom; + +import static org.junit.Assert.assertArrayEquals; + public class AvroDatumEncoderTest extends TestCase { private static final Logger logger = LoggerFactory.getLogger(AvroDatumEncoderTest.class); + public static String byteArrayToHex(byte[] a) { + StringBuilder sb = new StringBuilder(a.length * 2); + for (byte b : a) + sb.append(String.format("%02x", b & 0xff)); + return sb.toString(); + } + public void testJson() throws IOException { AvroDatumEncoder encoder = new AvroDatumEncoder(SpecificData.get(), false); AvroTopic topic = new AvroTopic<>("keeeeys", ObservationKey.getClassSchema(), EmpaticaE4BloodVolumePulse.getClassSchema(), ObservationKey.class, EmpaticaE4BloodVolumePulse.class); @@ -58,20 +67,13 @@ public void testBinary() throws IOException { byte[] expectedKey = {2, 8, 116, 101, 115, 116, 2, 97, 2, 98}; System.out.println("key: 0x" + byteArrayToHex(key)); System.out.println("expected: 0x" + byteArrayToHex(expectedKey)); - assertTrue(Arrays.equals(expectedKey, key)); + assertArrayEquals(expectedKey, key); byte[] value = valueEncoder.encode(new EmpaticaE4BloodVolumePulse(0d, 0d, 0f)); // 8 bytes, 8 bytes, 4 bytes, all zero byte[] expectedValue = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; System.out.println("value: 0x" + byteArrayToHex(value)); System.out.println("expected: 0x" + byteArrayToHex(expectedValue)); - assertTrue(Arrays.equals(expectedValue, value)); - } - - public static String byteArrayToHex(byte[] a) { - StringBuilder sb = new StringBuilder(a.length * 2); - for(byte b: a) - sb.append(String.format("%02x", b & 0xff)); - return sb.toString(); + assertArrayEquals(expectedValue, value); } public void testSize() throws IOException { From fe0034454051da86562de0667e1edcf995df3fe7 Mon Sep 17 00:00:00 2001 From: pvannierop Date: Mon, 23 Sep 2024 16:06:09 +0200 Subject: [PATCH 6/9] Fix jackson vulnerability in avro --- buildSrc/src/main/kotlin/Versions.kt | 2 +- radar-commons-gradle/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 787103c..796f8d5 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -17,7 +17,7 @@ object Versions { const val slf4j = "2.0.13" const val confluent = "7.6.0" const val kafka = "${confluent}-ce" - const val avro = "1.11.3" + const val avro = "1.12.0" const val jackson = "2.15.3" const val okhttp = "4.12.0" const val junit = "5.10.0" diff --git a/radar-commons-gradle/build.gradle.kts b/radar-commons-gradle/build.gradle.kts index aa0919f..00a0c5e 100644 --- a/radar-commons-gradle/build.gradle.kts +++ b/radar-commons-gradle/build.gradle.kts @@ -194,7 +194,7 @@ object Versions { const val slf4j = "2.0.13" const val confluent = "7.6.0" const val kafka = "${confluent}-ce" - const val avro = "1.11.3" + const val avro = "1.12.0" const val jackson = "2.15.3" const val okhttp = "4.12.0" const val junit = "5.10.0" From 8d25fa9782f3c4dacb0714df669bed374d0bdd41 Mon Sep 17 00:00:00 2001 From: pvannierop Date: Wed, 11 Sep 2024 09:35:49 +0200 Subject: [PATCH 7/9] Fix ktlint versions used for default slf4j version --- .../kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt | 2 +- .../src/main/kotlin/org/radarbase/gradle/plugin/Versions.kt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt index 4beebc8..e6fc4b5 100644 --- a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt +++ b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/RadarKotlinPlugin.kt @@ -58,7 +58,7 @@ class RadarKotlinPlugin : Plugin { kotlinApiVersion.convention("") junitVersion.convention(Versions.junit) ktlintVersion.convention(Versions.ktlint) - slf4jVersion.convention(Versions.ktlint) + slf4jVersion.convention(Versions.slf4j) sentryEnabled.convention(false) sentryOrganization.convention("radar-base") sentryProject.convention(project.name) diff --git a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/Versions.kt b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/Versions.kt index fb7e4bb..40ae020 100644 --- a/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/Versions.kt +++ b/radar-commons-gradle/src/main/kotlin/org/radarbase/gradle/plugin/Versions.kt @@ -6,4 +6,5 @@ object Versions { const val ktlint = "0.50.0" const val java = 11 const val junit = "5.10.0" + const val slf4j = "2.0.16" } From c0f4bafe7cda7f3d981c068ae395e2995c48280e Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 28 Nov 2024 11:40:01 +0000 Subject: [PATCH 8/9] Add support for additional parms for client credentials ktor oauth --- .../kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt | 1 + .../main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt | 3 +++ 2 files changed, 4 insertions(+) diff --git a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt index b1ba8a7..0f7b8ad 100644 --- a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt +++ b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt @@ -6,6 +6,7 @@ data class ClientCredentialsConfig( val tokenUrl: String, val clientId: String? = null, val clientSecret: String? = null, + val additionalParameters: Map? = null, ) { /** * Fill in the client ID and client secret from environment variables. The variables are diff --git a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt index 9a2fd00..750a237 100644 --- a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt +++ b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt @@ -56,6 +56,9 @@ fun Auth.clientCredentials( append("grant_type", "client_credentials") append("client_id", authConfig.clientId) append("client_secret", authConfig.clientSecret) + authConfig.additionalParameters?.forEach { (key, value) -> + append(key, value) + } }, ) { accept(ContentType.Application.Json) From f237a9a488670b3a056a07e91fb69d373a1742b6 Mon Sep 17 00:00:00 2001 From: Pauline Date: Thu, 28 Nov 2024 12:07:09 +0000 Subject: [PATCH 9/9] Explicitly specify scope and audience in client credentials config --- .../org/radarbase/ktor/auth/ClientCredentialsConfig.kt | 3 ++- .../kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt | 5 ++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt index 0f7b8ad..17797d9 100644 --- a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt +++ b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/ClientCredentialsConfig.kt @@ -6,7 +6,8 @@ data class ClientCredentialsConfig( val tokenUrl: String, val clientId: String? = null, val clientSecret: String? = null, - val additionalParameters: Map? = null, + val scope: String? = null, + val audience: String? = null, ) { /** * Fill in the client ID and client secret from environment variables. The variables are diff --git a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt index 750a237..18a8e8a 100644 --- a/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt +++ b/radar-commons-kotlin/src/main/kotlin/org/radarbase/ktor/auth/OAuthClientProvider.kt @@ -56,9 +56,8 @@ fun Auth.clientCredentials( append("grant_type", "client_credentials") append("client_id", authConfig.clientId) append("client_secret", authConfig.clientSecret) - authConfig.additionalParameters?.forEach { (key, value) -> - append(key, value) - } + authConfig.scope?.let { append("scope", it) } + authConfig.audience?.let { append("audience", it) } }, ) { accept(ContentType.Application.Json)